from nwchem import * from math import * def geom_get_coords(name): # # This routine returns a list with the cartesian # coordinates in user input units for the geometry # of given name # try: actualname = rtdb_get(name) except NWChemError: actualname = name coords = rtdb_get('geometry:' + actualname + ':coords') units = rtdb_get('geometry:'+actualname+':user units') if (units == 'a.u.'): factor = 1.0 elif (units == 'angstroms'): factor = rtdb_get('geometry:'+actualname+':angstrom_to_au') else: raise NWChemError,'unknown units' i = 0 while (i < len(coords)): coords[i] = coords[i] / factor i = i + 1 return coords def geom_set_coords(name,coords): # # This routine, given a list with the cartesian # coordinates in user input units set them in # the geometry of given name. # try: actualname = rtdb_get(name) except NWChemError: actualname = name units = rtdb_get('geometry:'+actualname+':user units') if (units == 'a.u.'): factor = 1.0 elif (units == 'angstroms'): factor = rtdb_get('geometry:'+actualname+':angstrom_to_au') else: raise NWChemError,'unknown units' coords = list(coords) i = 0 while (i < len(coords)): coords[i] = coords[i] * factor i = i + 1 rtdb_put('geometry:' + actualname + ':coords',coords) def bond_length(i,j): # atoms numbered 1,2,... # # Return the distance betwen atoms i and j in user # units in the default geometry # coords = geom_get_coords('geometry') x = coords[(i-1)*3 ]-coords[(j-1)*3 ] y = coords[(i-1)*3+1]-coords[(j-1)*3+1] z = coords[(i-1)*3+2]-coords[(j-1)*3+2] return sqrt(x*x + y*y + z*z) def minimize1d(f, xlo, xhi, xtol, maxeval): from math import * # # Find the minimum value of function(x) in [xlo,xhi] # to a precision in x of xtol. Maxeval specifies # the maximum no. of function evaluations. # # If you want to maximize f() then minimize -f() # # It returns (xmin, fmin) where # xmin = position of lowest value computed # fmin = f(xmin) # Also it guarantees that the last point evaluated # was xmin so any external state is consistent. gold = 0.38197 neval = 0 if (xhi < xlo): tmp = xhi xhi = xlo xlo = tmp if (ga_nodeid() == 0): print ' Mode xlo xmid xhi flo fmid fhi' print ' ------- --------- --------- --------- ------------ ------------ ------------' xmid = xlo + (xhi - xlo)*gold flo = f(xlo) if (ga_nodeid() == 0): print ' startup%10.4f %13.6f' \ % (xlo, flo) fmid = f(xmid) if (ga_nodeid() == 0): print ' startup%10.4f%10.4f %13.6f%13.6f' \ % (xlo, xmid, flo, fmid) fhi = f(xhi) neval = neval + 3 xlast = xhi # Tracks last point of function evaluation # First bracket the minimum while (not ((fmid= maxeval): raise NWChemError,'min1d: too many evaluations' if ((flo>fmid) and (fmid>fhi)): xlo = xmid flo = fmid elif ((fhi>fmid) and (fmid>flo)): xhi = xmid fhi = fmid elif ((fmid>flo) and (fmid>fhi)): if (flo < fhi): xhi = xmid fhi = fmid else: xlo = xmid flo = fmid else: raise NWChemError,'unanticipated' xmid = xlo + (xhi - xlo)*gold fmid = f(xmid) neval = neval + 1 # The minimum is now bracketed. # Parabolic fit or Golden section search. mode = 'search' dx = xhi-xlo while (dx > xtol): if (ga_nodeid() == 0): print ' %s %10.4f%10.4f%10.4f%13.6f%13.6f%13.6f' \ % (mode, xlo, xmid, xhi, flo, fmid, fhi) if (neval >= maxeval): raise NWChemError,'min1d: too many evaluations' # Try a parabolic fit d1 = (fmid - flo) / (xmid-xlo) d2 = (fhi - flo) / (xhi -xlo) a = (d2 - d1) / (xhi - xmid) b = d1 - a*(xmid-xlo) c = flo if (a == 0.0): a = -1.0 xtest = xlo + -b / (2.0*a) ftestp = a*(xtest-xlo)*(xtest-xlo) + b*(xtest-xlo) + c ftest = 0.0 if ((a > 0) and (b < 0) and (xtest>xlo) and (xtest fmid)): print ' Rejecting Newton step due to uphill motion %13.6f' % ftest mode = 'search' elif (xtest > xmid): xlo = xmid flo = fmid xmid= xtest fmid= ftest else: xhi = xmid fhi = fmid xmid= xtest fmid= ftest if (mode == 'search'): mode = 'search' if ((xhi - xmid) > (xmid - xlo)): xtest = xmid + (xhi-xmid)*gold ftest = f(xtest) neval = neval + 1 if (ftest < fmid): xlo = xmid flo = fmid xmid = xtest fmid = ftest else: xhi = xtest fhi = ftest else: xtest = xmid + (xlo-xmid)*gold ftest = f(xtest) neval = neval + 1 if (ftest < fmid): xhi = xmid fhi = fmid xmid = xtest fmid = ftest else: xlo = xtest flo = ftest dx = fabs(xlast-xtest) xlast = xtest print ' %s %10.4f%10.4f%10.4f%13.6f%13.6f%13.6f' \ % (mode, xlo, xmid, xhi, flo, fmid, fhi) if (xlast != xmid): print ' Re-evaluating at final coordinate' fmid = f(xmid) return (xmid, fmid) def scan_input(input,start,end,nstep,theory,task): # # Scan some NWChem input in nsteps from the parameters in # start[] to those in end[]. The parameters are substituted # in order into input. 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 NOT performed at the end points # so specifying nstep=1 does one calculation at the mid 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 = scan_input(geom, \ # [0.967, 103.3], # [2.109, 26.96], # 10, 'scf', task_energy) results = [] if (len(start) != len(end)): raise NWChemError,'scan_input: inconsistent #parameters' if (ga_nodeid() == 0): print ' ' print ' Scanning NWChem input ' print ' ---------------------' print ' ' print input print ' ' print ' Nstep ', nstep print ' Start ', start print ' End ', end print ' ' for i in range(1,nstep+1): alpha = (1.0*i)/(nstep+1) new = [] for j in range(0,len(start)): new.append((1.0-alpha)*start[j] + alpha*end[j]) if (ga_nodeid() == 0): print ' ' print ' Scanning NWChem input - step %d of %d ' % (i,nstep) 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 step ', i print ' ' print result print ' ' results.append((new,result)); return tuple(results)