NWChem/contrib/python/pes_scan.py

130 lines
3.5 KiB
Python
Raw Permalink Normal View History

2003-04-17 04:45:09 +00:00
from nwchem import *
from math import *
2003-04-17 04:45:09 +00:00
def pes_scan(input,start,end,nstep,theory,task):
#
# Does a true multidimensional potential energy surface
# scan, with user input specifying the minimum and maximum
# values of each variable, and number of times to step each.
# The number of calculations done SCALES QUICKLY; according
# to (nstep+1)^(# of variables to scan). This code can handle
# any computationally feasible number of variables, including
# just one.
#
# Theory selects the electronic wavefunction and task can be
# any defined task but most likely is one of task_energy or
# task_optimize. If task optimize is selected, then it makes
# most sense for one or more of the parameters to be frozen
# in a geometry.
#
# Calculations ARE performed at the end points so specifying
# nstep=1 does one calculation at the start point, and one at
# the end point.
#
# Returned is the tuple
#
# [(param-1,results-1), (param-2,results-2), ...]
#
# where param-n are the parameters of the n-th step and
# results-n are the corresponding results returned by task()
#
# Example. Scan a bond & angle computing the SCF energy
#
# geom = '''
# geometry noprint adjust
# zcoord
# bond 3 2 %f oh
# angle 3 2 1 %f hon constant
# end
# end
# '''
# results = pes_scan(geom, \
# [0.967, 103.3],
# [2.109, 26.96],
# 10, 'scf', task_energy)
#
# in this example using pes_scan, over 120 single point energy
# calculations would be done. using scan_input, only 10 would
# be done.
results = []
if (len(start) != len(end)):
raise NWChemError('pes_scan: inconsistent #parameters')
npoint = (nstep+1)**len(start)
if (ga_nodeid() == 0):
print(' ')
print(' Doing a PES Scan on input ')
print(' -------------------------')
print(' ')
print(input)
print(' ')
print(' Number of points ', npoint)
print(' Minimum values ', start)
print(' Maximum values ', end)
print(' ')
step = []
for i in range (0, len(start)):
step.append((end[i]-start[i])/nstep)
ylist = []
for i in range (0, len(start)):
xlist=[]
for j in range (0, nstep+1):
xlist.append(start[i]+j*step[i])
ylist.append(xlist)
zlist = []
indexes = len(ylist) * [0]
base = len(ylist[0])
while 1:
elt = []
for i in range(0, len(indexes)):
elt.append(ylist[i][indexes[i]])
zlist.append(elt)
for i in range(len(indexes)-1, -1, -1):
if indexes[i] < base-1:
indexes[i] = indexes[i]+1
for j in range(i+1, len(indexes)):
indexes[j] = 0
break
else: break
for i in range(0,len(zlist)):
new = zlist[i]
if (ga_nodeid() == 0):
print(' ')
print(' Scanning NWChem input - point %d of %d ' % (i+1,npoint))
print(' ')
print(input % tuple(new))
print(' ')
input_parse(input % tuple(new))
result = task(theory)
if (ga_nodeid() == 0):
print(' ')
print(' Scanning NWChem input - results from point ', i+1)
print(' ')
print(result)
print(' ')
results.append((new,result));
if (ga_nodeid() == 0):
print(' ')
print(' Python Scan Output ')
print(' ')
for i in range(0,len(results)):
print(results[i][0], results[i][1])
print(' ')
print(' Python Scan Output Finished ')
return tuple(results)