from nwchem import * from math import * 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)