Sie sind auf Seite 1von 2

#!

/usr/bin/python
import sys
import numpy
import math
import string
#--------------------------------------------------------------
# Define some handy functions that will come in useful
# Note that the calculate_normal_modes and mass_weight
# functions are where all the real business happens so
# it's most important to make sure you understand them
#--------------------------------------------------------------
def calculate_normal_modes(hessian,masses):
d2V_mw = mass_weight(hessian,masses)
*** enter the command to diagonalize the mass-weighted second ***
*** derivative matrix, returning the eigenvalues as frequencies ***
*** and eigenvectors as normal_modes ***
# the next line does a bunch of stuff
# 1. transpose normal_modes matrix so normal mode displacement
# vectors are stored in rows not columns
# 2. round all normal mode displacement vector elements to 5 decimal places
# 3. convert numpy array to python list (for much easier handling)
normal_modes = numpy.ndarray.tolist(numpy.around(numpy.transpose(normal_modes),5))
# pair up normal mode displacement vectors with frequencies, and sort by frequency (low ->
high)
frequencies_modes = sort_by_frequency(frequencies,normal_modes)
output = format_output(frequencies_modes)
write_to_file('normal_mode_results.out',output)
def read_from_file(filename):
f = open(filename,'r')
fc = f.readlines()
f.close()
return fc
def write_to_file(filename,data):
f = open(filename,'w')
f.writelines(data)
f.close()
def sort_by_frequency(freqs,modes):
data = []
for i in range(0,len(freqs)):
data.append([freqs[i],modes[i]])
data.sort()
return data
def format_output(freqs_modes):
*** This is not a particularly nice output format ***
*** you may like to play around with it ***
output = []
for i in range(0,len(freqs_modes)):
freq = freqs_modes[i][0]
freq = to_wavenumbers(freq)
output.append('Frequency (cm-1):' + str(freq) + "\n")
mode = freqs_modes[i][1]
output.append('Cartesian displacement vector (1x, 1y, 1z, ... , Nx, Ny, Nz)\n')
output.append(" ".join(map(str,mode)) + "\n")
output.append("\n")
return output
def to_wavenumbers(freq):
au_to_cm = 219474.63
tol = 0.000000000000001
if abs(freq) < tol:
freq = 0.0
else:
if freq < tol:
sign = -1
else:
sign = 1
freq = sign*math.sqrt(abs(freq))*au_to_cm
return freq
def mass_weight(d2V,masses):
d2V_mw = []
for i in range(0,3*len(masses)):
d2V_mw.append([])
for i in range(0,len(masses)):
mi = masses[i]
for j in range(0,len(masses)):
mj = masses[j]
mij = math.sqrt(mi*mj)
xx = d2V[3*i][3*j+0]/mij
xy = d2V[3*i][3*j+1]/mij
xz = d2V[3*i][3*j+2]/mij
yx = d2V[3*i+1][3*j+0]/mij
yy = d2V[3*i+1][3*j+1]/mij
yz = d2V[3*i+1][3*j+2]/mij
zx = d2V[3*i+2][3*j+0]/mij
zy = d2V[3*i+2][3*j+1]/mij
zz = d2V[3*i+2][3*j+2]/mij
d2V_mw[3*i].extend([xx,xy,xz])
d2V_mw[3*i+1].extend([yx,yy,yz])
d2V_mw[3*i+2].extend([zx,zy,zz])
return d2V_mw
#--------------------------------------------------------------
# The main part of the program starts here
#--------------------------------------------------------------
# read in the 2nd derivative matrix line by line
hessian = read_from_file("water_hessian.txt")
# split each line up into individual elements, and convert them to numbers (not just text)
for i in range(0,len(hessian)):
hessian[i] = map(float,hessian[i].split())
# note: masses must be in atomic units NOT atomic mass units
masses = [29166.208,1837.471,1837.471]
calculate_normal_modes(hessian,masses)

Das könnte Ihnen auch gefallen