def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms normalmodes = numpy.zeros((0,)) freqs = [] for i, l in enumerate(lines): if "FREQUENCY:" in l: freqs.extend(l.split()[1:]) block = lines[i+5:i+5+3*natoms] array = [] for blockline in block: pattern = r"-?\d+\.\d+" alist = re.findall(pattern, blockline) array.append([float(fl) for fl in alist]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) freqs = numpy.array([float(fl) for fl in freqs]) # redmass=numpy.array([float (fl) for fl in redmass]) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0,): print("No normal modes found") else: normalmodes = normalmodes.reshape((3*natoms, 3*natoms)) self.modes.set_modes_c(normalmodes[self.mol.ntransrot:]) self.modes.set_freqs(freqs[self.mol.ntransrot:])
class SNFOutputFile(object): def __init__(self, filename='snf.out'): self.modes = None self.lwl = None self.filename = filename def read(self, mol): natoms = mol.natoms self.modes = VibModes(mol.nmodes, mol) f = open(self.filename, 'r') lines = f.readlines() f.close() first = 0 last = 0 for i, l in enumerate(lines): if (first == 0) and ('root no.' in l): first = i if 'Generate fake outputs for' in l: last = i break if 'W A R N I N G' in l: last = i - 1 break if 'Raman Optical Activity properties for freq.' in l: self.lwl = float(l[46:57]) lines = lines[first:last] lines = [l for l in lines if not len(l.strip()) == 0] lines = [l for l in lines if not l.startswith('1')] normalmodes = numpy.zeros((self.modes.nmodes, 3 * natoms)) freqs = numpy.zeros((self.modes.nmodes)) ncol = len(lines[2][10:].split()) icol = -ncol for i, l in enumerate(lines): irow = i % (3 * natoms + 2) - 2 if irow == -2: if 'root' not in l: raise Exception('wrong number of lines for normal modes') icol += ncol else: line = [float(fl) for fl in l[10:].split()] if irow == -1: freqs[icol:icol + ncol] = line else: normalmodes[icol:icol + ncol, irow] = line self.modes.set_modes_mw(normalmodes) self.modes.set_freqs(freqs)
def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms freqs = [] normalmodes = numpy.zeros((0, )) for i, l in enumerate(lines): if "Wavenumbers [cm-1]" in l: freqs.extend(l.split()[2:]) elif "X1 " in l: block = lines[i:i + 3 * natoms] array = [] for blockline in block: array.append([float(fl) for fl in blockline.split()[1:]]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0, ): print("No normal modes found") return freqs = numpy.array([float(fl) for fl in freqs]) normalmodes = normalmodes.reshape((3 * natoms, 3 * natoms)) modes_wtr = VibModes(3 * natoms, self.mol) modes_wtr.set_freqs(freqs) modes_wtr.set_modes_c(normalmodes) self.modes = modes_wtr.remove_trans_rot() self.modes.sort_by_freq()
def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms freqs = numpy.zeros((self.modes.nmodes)) redmass = numpy.zeros((self.modes.nmodes)) normalmodes = numpy.zeros((0, )) first1 = 0 last1 = 0 first2 = 0 last2 = 0 for i, l in enumerate(lines): if "Vib-E2" in l: pattern = r"\d+" size = int(re.findall(pattern, l)[1]) first1 = i + 1 last1 = i + 1 + (size - 1) // 5 + 1 elif "Vib-Modes" in l: pattern = r"\d+" size = int(re.findall(pattern, l)[0]) first2 = i + 1 last2 = i + 1 + (size - 1) // 5 + 1 lines1 = lines[first1:last1] lines2 = lines[first2:last2] data = [] self.modes = VibModes(self.mol.nmodes, self.mol) if len(lines1) == 0: print( "No Normal modes found in fchk. Ask saveNM in the calculation." ) print("Compute from hessian instead") prop = Property(self) hessian_mw = prop.get_hessian_mw() if hessian_mw is not None: self.modes.ComputeModes_without_TR(hessian_mw) return for i, sline in enumerate(lines1): line = [float(fl) for fl in sline.split()] data.extend(line) for i in range(self.modes.nmodes): freqs[i] = data[i] redmass[i] = data[i + self.modes.nmodes] for sline in lines2: array = [float(fl) for fl in sline.split()] array = numpy.array(array) normalmodes = numpy.append(normalmodes, array) self.modes.set_modes_c_norm( normalmodes.reshape((self.modes.nmodes, 3 * natoms)), redmass) self.modes.set_freqs(freqs)
def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms # find the block of date containing the normal modes first = 0 last = 0 for i, l in enumerate(lines): if "[Vibrational Normal Modes]" in l: first = i + 2 elif (first != 0) and "[" in l: last = i break elif (first != 0) and i == len(lines) - 1: last = i + 1 break lines = lines[first:last] freqs = [] redmass = [] normalmodes = numpy.zeros((0, )) for i, l in enumerate(lines): if "Frequencies " in l: freqs.extend(l.split()[1:]) elif "Reduced-masses" in l: redmass.extend(l.split()[1:]) elif "Coord" in l: block = lines[i + 1:i + 3 * natoms + 1] array = [] for blockline in block: array.append([float(fl) for fl in blockline.split()[3:]]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) freqs = numpy.array([float(fl) for fl in freqs]) redmass = numpy.array([float(fl) for fl in redmass]) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0, ): print("No normal modes found") print("Compute from hessian instead") from VibTools import Properties prop = Properties.Property(self) hessian_mw = prop.get_hessian_mw() if hessian_mw is not None: self.modes.ComputeModes_without_TR(hessian_mw) return else: self.modes.set_modes_c_norm( normalmodes.reshape((self.modes.nmodes, 3 * natoms)), redmass) self.modes.set_freqs(freqs)
def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms # find the block of date containing the normal modes first = 0 last = 0 for i, l in enumerate(lines): if "[Modes de vibration]" in l: first = i + 2 elif "[Vibrational modes]" in l: first = i + 2 elif (first != 0) and "[" in l: last = i break elif (first != 0) and i == len(lines) - 1: last = i + 1 break lines = lines[first:last] freqs = [] redmass = [] normalmodes = numpy.zeros((0, )) for i, l in enumerate(lines): if "Frequencies " in l: freqs.extend(l.split()[1:]) elif "Reduced-masses" in l: redmass.extend(l.split()[1:]) elif "Coord NA Element:" in l: block = lines[i + 1:i + 3 * natoms + 1] array = [] for blockline in block: array.append([float(fl) for fl in blockline.split()[3:]]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) freqs = numpy.array([float(fl) for fl in freqs]) redmass = numpy.array([float(fl) for fl in redmass]) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0, ): print("No normal modes found") else: self.modes.set_modes_c_norm( normalmodes.reshape((self.modes.nmodes, 3 * natoms)), redmass) self.modes.set_freqs(freqs)
def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms normalmodes = numpy.zeros((0, )) start = 0 stop = 0 freqs = [] for i, l in enumerate(lines): if "Vibrational Frequencies and IR Intensities" in l: block = lines[i + 10:i + 10 + self.modes.nmodes] freqs = [float(l.split()[2]) for l in block] elif "Normal Coordinates" in l: start = i + 2 elif "Dipole Gradient in Normal Coordinate Basis" in l: stop = i break lines = lines[start:stop] lines = [l for l in lines if not len(l.strip()) == 0] while len(lines) > 0: block = lines[2:3 * natoms + 2] lines = lines[3 * natoms + 2:] array = [] for line in block: array.append([float(fl) for fl in line.split()[2:]]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) freqs = numpy.array(freqs) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0, ): print("No normal modes found") else: self.modes.set_modes_c( normalmodes.reshape(self.modes.nmodes, 3 * natoms)) self.modes.set_freqs(freqs)
def read(self): self.mol.read_from_dalton(filename=self.filename) self.modes = VibModes(self.mol.nmodes, self.mol) if self.lwl is None: self.lwl = self.get_pulsation()
class Dalton(object): def __init__(self, logname='dalton.out', w=None): self.mol = VibToolsMolecule() self.modes = None self.filename = logname self.lwl = w freqs = property(lambda self: self.modes.freqs) def read(self): self.mol.read_from_dalton(filename=self.filename) self.modes = VibModes(self.mol.nmodes, self.mol) if self.lwl is None: self.lwl = self.get_pulsation() def get_pulsation(self): """ Get the w value used in the TDHF(or equivalent) approach """ f = open(self.filename, 'r') lines = f.readlines() f.close() pattern = r"-?\d+\.\d*[ED]?[+\-]?\d*" # lwls=None lwl = None for l in lines: if "Frequencies :" in l: alist = re.findall(pattern, l) lwl = float(alist[0]) break elif "OMEGA=" in l: alist = re.findall(pattern, l) lwl = float("%.6f" % float(alist[0])) break # lwls=[float(vl) for vl in alist] # # Only take the first non-zero pulsation in the followings # if lwls is not None: # for puls in lwls: # if puls > 0.0: # lwl=puls # print "Pulsations in the calculations:", lwls # print "Pulsation used:", lwl return lwl def get_forces(self): natoms = self.mol.natoms f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of date containing the gradient first = 0 last = 0 for i, l in enumerate(lines): if "Molecular gradient (au)" in l: first = i + 3 elif (first != 0) and ("Molecular Hessian (au)" in l): last = i break lines = lines[first:last] if len(lines) == 0: return None # remove blank lines lines = [l for l in lines if not len(l.strip()) == 0] if len(lines) > 0 and len(lines) != natoms: raise RuntimeError( 'The number of line in the block of the forces should be equal to the number of atoms' ) gradient = numpy.zeros((natoms, 3)) for i, line in enumerate(lines): pattern = r"-?\d+\.\d*[ED]?[+\-]?\d*" alist = re.findall(pattern, line) gradient[i] = [float(x) for x in alist] return -gradient def get_hessian(self): natoms = self.mol.natoms f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of date containing the Hessian first = 0 last = 0 for i, l in enumerate(lines): if "Molecular Hessian (au)" in l: first = i + 3 elif (first != 0) and ("Dipole moment" in l): last = i break lines = lines[first:last] if len(lines) == 0: return None # remove blank lines lines = [l for l in lines if not len(l.strip()) == 0] # read the data (triangular matrix divided into different block) hessian = numpy.zeros((3 * natoms, 3 * natoms)) iblock = 0 while len(lines) > 0: end = 3 * natoms + 1 - iblock * 6 #skip the first line that are the label of the columns block = lines[1:end] lines = lines[end:] for irow, blockline in enumerate(block): line = [ float(fl.replace('D', 'E')) for fl in blockline.split()[2:] ] hessian[irow + iblock * 6, iblock * 6:iblock * 6 + len(line)] = line iblock = iblock + 1 # fill the other half of the hessian matrix hessian = hessian + hessian.transpose() - numpy.diag( hessian.diagonal()) return hessian def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms normalmodes = numpy.zeros((0, )) start = 0 stop = 0 freqs = [] for i, l in enumerate(lines): if "Vibrational Frequencies and IR Intensities" in l: block = lines[i + 10:i + 10 + self.modes.nmodes] freqs = [float(l.split()[2]) for l in block] elif "Normal Coordinates" in l: start = i + 2 elif "Dipole Gradient in Normal Coordinate Basis" in l: stop = i break lines = lines[start:stop] lines = [l for l in lines if not len(l.strip()) == 0] while len(lines) > 0: block = lines[2:3 * natoms + 2] lines = lines[3 * natoms + 2:] array = [] for line in block: array.append([float(fl) for fl in line.split()[2:]]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) freqs = numpy.array(freqs) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0, ): print("No normal modes found") else: self.modes.set_modes_c( normalmodes.reshape(self.modes.nmodes, 3 * natoms)) self.modes.set_freqs(freqs) def read_tensor2(self, string): """ read a tensor 2 from a string: x y z x. 44.263383 2.620191 -1.002017 y. 2.620191 36.377832 -0.803650 z. -1.002017 -0.803650 36.078729 """ tensor2 = numpy.zeros((3, 3)) pattern = r"-?\d+\.\d+" alist = re.findall(pattern, string[1]) tensor2[0, :] = [float(val) for val in alist] alist = re.findall(pattern, string[2]) tensor2[1, :] = [float(val) for val in alist] alist = re.findall(pattern, string[3]) tensor2[2, :] = [float(val) for val in alist] return tensor2 def read_tensor3(self, string): """ read a tensor 3 from a string: x y z x, x. -32.230435 25.466354 7.026991 x, y. 25.466354 18.700157 2.406899 x, z. 7.026991 2.406899 13.530278 y, x. 0.094701 -12.816096 -0.752058 y, y. -12.816096 7.530971 -6.340628 y, z. -0.752058 -6.340628 -7.625672 z, x. 4.075249 0.870322 -19.985933 z, y. 0.870322 -10.312200 19.363558 z, z. -19.985933 19.363558 6.236951 """ string = [l for l in string if not len(l.strip()) == 0] tensor3 = numpy.zeros((3, 3, 3)) pattern = r"-?\d+\.\d+" for i in range(3): for j in range(3): index = i * 3 + j + 1 alist = re.findall(pattern, string[index]) tensor3[i, j, :] = [float(val) for val in alist] return tensor3 def read_tensor4(self, string): """ read a tensor 4 from a string: x y z xxx. 187088.641556 0.000001 -0.000054 xxy. 0.000002 100237.066416 0.000006 xxz. -0.000053 0.000007 79288.069398 xyx. 0.000001 100237.066386 0.000011 xyy. 100237.066369 -0.000007 -0.000021 xyz. 0.000004 -0.000021 0.000031 xzx. -0.000054 0.000006 79288.069401 xzy. 0.000007 -0.000021 0.000039 xzz. 79288.069391 0.000049 -0.000078 yxx. -0.000003 21561.430508 -0.000003 yxy. 21561.430510 0.000000 -0.000001 yxz. -0.000003 -0.000002 0.000055 yyx. 21561.430508 -0.000001 -0.000002 yyy. -0.000002 59145.984721 0.000004 yyz. -0.000002 0.000004 50112.750694 yzx. -0.000003 -0.000003 0.000055 yzy. -0.000002 0.000004 50112.750638 yzz. 0.000055 50112.750678 -0.000018 zxx. 0.000000 0.000000 42279.004942 zxy. 0.000000 0.000000 -0.000004 zxz. 42279.004942 -0.000004 -0.000028 zyx. 0.000000 0.000000 -0.000004 zyy. 0.000000 0.000000 37304.216039 zyz. -0.000004 37304.216039 -0.000011 zzx. 42279.004942 -0.000004 -0.000028 zzy. -0.000004 37304.216039 -0.000011 zzz. -0.000028 -0.000011 47404.495422 """ string = [l for l in string if not len(l.strip()) == 0] tensor4 = numpy.zeros((3, 3, 3, 3)) pattern = r"-?\d+\.\d+" for i in range(3): for j in range(3): for k in range(3): index = i * 9 + j * 3 + k + 1 alist = re.findall(pattern, string[index]) tensor4[i, j, k, :] = [float(val) for val in alist] return tensor4 def get_dipole(self): """ read the dipole """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the dipole dipole = None for i, l in enumerate(lines): if " Dipole moment [in au]" in l: pattern = r"-?\d*\.\d*" alist = [ float(l) for l in re.findall(pattern, lines[i + 2])[0:3] ] dipole = numpy.array(alist) break elif "Total Molecular Dipole Moment" in l: # for CCSD calculation in Dalton pattern = r"-?\d*\.\d*" dipX = float(re.findall(pattern, lines[i + 5])[0]) dipY = float(re.findall(pattern, lines[i + 6])[0]) dipZ = float(re.findall(pattern, lines[i + 7])[0]) dipole = numpy.array([dipX, dipY, dipZ]) return dipole def get_quadrupole(self): """ read the quadrupole """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the quadrupole quadrupole = None for i, l in enumerate(lines): if " Quadrupolar moment [in au]" in l: quadrupole = self.read_tensor2(lines[i + 1:i + 5]) break return quadrupole def get_pollen(self): """ Read Alpha(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability alpha = {} #dictionary with alpha values for different pulsations dipdipSOP = [] # For Second-Order Properties module in dalton nbFreq = 0 freqs = [] pattern = r"-?\d+\.\d*[ED]?[+\-]?\d*" for i, l in enumerate(lines): if "Alpha tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in alpha: alpha[lwl] = self.read_tensor2(lines[i + 1:i + 5]) elif ".FREQUE" in l: nbFreq = int(lines[i + 1]) for ifreq in range(nbFreq): freqs.append(float(lines[i + 2 + ifreq])) elif len(re.findall(r'[XYZ]DIPLEN', l)) == 2: for ifreq in range(nbFreq): dipdipSOP.append( float(re.findall(pattern, lines[i + ifreq])[2])) #check if dipdipSOP was populated if (nbFreq > 0) and (len(dipdipSOP) == nbFreq * 9): dipdipSOP = numpy.array(dipdipSOP).reshape((9, nbFreq)) for ifreq in range(nbFreq): alpha[tuple([freqs[ifreq]])] = dipdipSOP[:, ifreq].reshape(3, 3) if len(alpha) == 0: return None return alpha def get_beta(self): """ Read Beta(-w_sigma;w1, w2) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability beta = {} #dictionary with beta values for different pulsations for i, l in enumerate(lines): if "Beta tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in beta: beta[lwl] = self.read_tensor3(lines[i + 1:i + 11]) if len(beta) == 0: return None return beta def get_gamma(self): """ Read Gamma(-w_sigma;w1, w2) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability gamma = {} #dictionary with gamma values for different pulsations for i, l in enumerate(lines): if "Gamma tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in gamma: gamma[lwl] = self.read_tensor4(lines[i + 1:i + 29]) if len(gamma) == 0: return None return gamma def get_gtenlen(self): """ Read G'(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability Gprime = {} #dictionary with Gprime values for different pulsations for i, l in enumerate(lines): if "G' tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in Gprime: Gprime[lwl] = self.read_tensor2(lines[i + 1:i + 5]) if len(Gprime) == 0: return None return Gprime def get_aten(self): """ read UpperA(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability upperA = {} #dictionary with UpperA values for different pulsations for i, l in enumerate(lines): if "UpperA tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in upperA: upperA[lwl] = self.read_tensor3(lines[i + 2:i + 14]) if len(upperA) == 0: return None return upperA def read_vectorderiv(self, string): """ read the derivative of a vector from a string: param. 1:dx(1) x y z 0.131482 0.000001 0.000000 param. 2:dy(1) x y z -0.000001 0.093156 0.000000 """ vector = numpy.zeros((self.mol.natoms * 3, 3)) iblock = 0 while len(string) > 0: block = string[2] string = string[3:] pattern = r"-?\d+\.\d+" alist = re.findall(pattern, block) vector[iblock, :] = [float(val) for val in alist] iblock = iblock + 1 return vector.reshape((self.mol.natoms, 3, 3)) def read_tensor2deriv(self, string): """ read the derivative of a tensor 2 from a string: param. 1:dx(1) x y z x. 3.779827 -3.897852 -1.792047 y. -3.897852 0.211138 0.578452 z. -1.792047 0.578452 0.060065 param. 2:dy(1) x y z x. -1.386831 2.090519 0.725367 y. 2.090519 -9.454466 -2.132374 z. 0.725367 -2.132374 -0.464399 ... """ tensor2 = numpy.zeros( (self.mol.natoms * 3, 3, 3)) # natoms, x, y, z derivative, 3 elec-field, 3 elec-field iblock = 0 while len(string) > 0: block = string[2:5] string = string[5:] pattern = r"-?\d+\.\d+" for i in range(3): alist = re.findall(pattern, block[i]) tensor2[iblock, i, :] = [float(val) for val in alist] iblock = iblock + 1 return tensor2.reshape((self.mol.natoms, 3, 3, 3)) def read_tensor3deriv(self, string): """ read the derivative of a tensor 3 from a string: param. 1:dx(1)(-0.085645; 0.085645) (from traceless quadrupole:3/2[q_i(r_i r_j - r_i^2/3 delta_ij)]) x y z x, x. 8.252061 -16.010794 -2.972253 x, y. -16.010794 1.072645 5.354106 x, z. -2.972253 5.354106 -9.324706 y, x. -8.727084 16.836621 4.486339 y, y. 16.836621 2.244281 -1.294347 y, z. 4.486339 -1.294347 6.482803 z, x. 1.550365 5.483838 11.028642 z, y. 5.483838 1.856942 -1.047115 z, z. 11.028642 -1.047115 -3.407307 x:24.078216 A(i)=(A(i, j, j) +A(j, i, j) +A(j, j, i)) /3 y:-9.875752 z:-5.115938 VEC:26.522892 norm of A VEC param. 2:dy(1)(-0.085645; 0.085645) (from traceless quadrupole:3/2[q_i(r_i r_j - r_i^2/3 delta_ij)]) x y z x, x. -1.993802 16.690003 4.721374 x, y. 16.690003 -3.407884 0.715354 x, z. 4.721374 0.715354 5.401686 y, x. -16.095652 -29.812332 -2.809342 y, y. -29.812332 27.193908 5.960600 y, z. -2.809342 5.960600 -11.098256 z, x. -2.598681 -4.243842 -1.864990 z, y. -4.243842 -0.739061 14.421986 z, z. -1.864990 14.421986 3.337742 x:-22.447416 A(i)=(A(i, j, j) +A(j, i, j) +A(j, j, i)) /3 y:38.870598 z:9.346477 VEC:45.849390 norm of A VEC ... """ string = [l for l in string if not len(l.strip()) == 0] tensor3 = numpy.zeros( (self.mol.natoms * 3, 3, 3, 3) ) # natoms, x, y, z derivative, 3 elec-field, 9 elec-field gradient iblock = 0 while len(string) > 0: block = string[3:12] string = string[16:] pattern = r"-?\d+\.\d+" for i in range(3): for j in range(3): index = i * 3 + j alist = re.findall(pattern, block[index]) tensor3[iblock, i, j, :] = [float(val) for val in alist] iblock = iblock + 1 return tensor3.reshape((self.mol.natoms, 3, 3, 3, 3)) def get_dipole_deriv_c(self): """ Get dmuDX """ #find the block of data containing the Cartesian derivatives of the dipole f = open(self.filename, 'r') lines = f.readlines() f.close() dmudx = None for i, l in enumerate(lines): if "Dipole derivatives [in au]" in l: # dmudx given by 3*natoms blocks of 3 lines length = 3 * self.mol.natoms * 3 dmudx = self.read_vectorderiv(lines[i + 1:i + 1 + length]) break return dmudx def get_pollen_deriv_c(self): """ Get dALphaDX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dalphadx = { } #dictionary with dalphadx values for different pulsations for i, l in enumerate(lines): if "Alpha derivatives" in l: if "param." in lines[i + 1]: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in dalphadx: # alpha given by 3*natoms blocks of 5 lines length = 3 * self.mol.natoms * 5 dalphadx[lwl] = self.read_tensor2deriv( lines[i + 1:i + length + 1]) if len(dalphadx) == 0: return None return dalphadx def get_gtenlen_deriv_c(self): """ Get dGprimeDX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dgprimedx = { } #dictionary with dgprimedx values for different pulsations for i, l in enumerate(lines): if "G' derivatives" in l: if "param." in lines[i + 1]: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in dgprimedx: # gprime given by 3*natoms blocks of 5 lines length = 3 * self.mol.natoms * 5 dgprimedx[lwl] = self.read_tensor2deriv( lines[i + 1:i + length + 1]) if len(dgprimedx) == 0: return None return dgprimedx def get_aten_deriv_c(self): """ Get dUpperADX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dupperAdx = { } #dictionary with dupperAdx values for different pulsations for i, l in enumerate(lines): if "UpperA derivatives" in l: if "param." in lines[i + 2]: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in dupperAdx: # upperA given by 3*natoms blocks of 21 lines length = 3 * self.mol.natoms * 21 dupperAdx[lwl] = self.read_tensor3deriv( lines[i + 2:i + length + 2]) if len(dupperAdx) == 0: return None return dupperAdx def quadratic_reponse(self): """ Get all the quadratic responses """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find data of the Quadratic Responses response = {} for l in lines: if "@omega B, omega C, QR value" in l: pattern = r"-?\d+\.\d{8}" values = re.findall(pattern, l) lwl = (float(values[0]), float(values[1])) if lwl not in response: response[lwl] = numpy.zeros((0, )) response[lwl] = numpy.append(response[lwl], float(values[2])) else: response[lwl] = numpy.append(response[lwl], float(values[2])) if len(response) == 0: return None return response def get_integrals(self, name, symmetric=None): """ Get any integrals print by proppri """ f = open(self.filename, 'r') lines = f.readlines() f.close() header = "! Integrals of operator: " + name start = 0 end = 0 size = None for i, l in enumerate(lines): if header in l: start = i elif "Total number of orbitals" in l: pattern = r"\d+" size = int(re.findall(pattern, l)[0]) elif (end == 0) and (start > 0) and (i > start + 1) and ( "+---------------------------------+" in l): end = i lines = lines[start:end] if len(lines) == 0: return None lines = [l for l in lines if not len(l.strip()) == 0] lines = [l for l in lines if not l.startswith(' Symmetry of operator')] # print lines integrals = numpy.zeros((size, size)) for l in lines[2:]: if "Zero matrix" in l: return integrals elif "Column" in l: # read the column numbers fo the block of data pattern = r"\d+" columns = re.findall(pattern, l) columns = [int(c) - 1 for c in columns] else: # read the block of data data = l.split() line = int(data[0]) - 1 data = [float(d) for d in data[1:]] integrals[line, columns[0]:columns[0] + len(data)] = data if symmetric is None: return integrals elif symmetric: integrals = integrals + integrals.transpose() - numpy.diag( integrals.diagonal()) else: integrals = integrals - integrals.transpose() return integrals def get_orbitals(self): """ Build a dictionary with the number of orbitals for each type of atom """ f = open(self.filename, 'r') lines = f.readlines() f.close() for i, line in enumerate(lines): if "Number of atom types:" in line: pattern = r"\d+" norbtype = int(re.findall(pattern, line)[0]) elif "label atoms charge prim cont basis" in line: orbitals = lines[i + 2:i + norbtype + 2] nborbitals = int(lines[i + norbtype + 3].split()[4]) break if len(orbitals) == 0: return None, 0 orbital = {} for line in orbitals: alist = line.split() orbital[int(float(alist[2]))] = int(alist[4]) return orbital, nborbitals def get_energy_transition(self): f = open(self.filename, 'r') lines = f.readlines() f.close() start = 0 end = 0 for i, line in enumerate(lines): if "electronic excitation energies" in line: start = i + 7 elif start > 0 and "=========" in line: end = i if end > start: # since "===" is also present in line start+3 break block = lines[start:end] if len(block) == 0: return None energies = [] for line in block: energies.append(float(line.split()[2])) return numpy.array(energies) def get_dipole_transition(self): f = open(self.filename, 'r') lines = f.readlines() f.close() start = 0 end = 0 for i, line in enumerate(lines): if "Electric transition dipole moments" in line: start = i + 6 elif start > 0 and "----" in line: end = i if end > start: # since "---" is also present in line start+1 break block = lines[start:end] if len(block) == 0: return None dipoles = [] for line in block: dipoles.append([float(x) for x in line.split()[6:]]) dipoles = numpy.array(dipoles) dipoles.reshape((-1, 3)) return dipoles
def read(self): self.mol.read_from_xyzc(filename=self.filename) self.modes = VibModes(self.mol.nmodes, self.mol)
class FCHK(object): def __init__(self, fchkname='gaussian.fchk', w=None): self.mol = VibToolsMolecule() self.modes = None self.filename = fchkname self.lwl = w if os.path.splitext(self.filename)[1] in [".bz2", ".BZ2"]: self.bz2 = True else: self.bz2 = False freqs = property(lambda self: self.modes.freqs) def read(self): self.mol.read_from_fchk(filename=self.filename) self.modes = VibModes(self.mol.nmodes, self.mol) if self.lwl is None: self.lwl = self.get_pulsation() def get_pulsation(self): """ Get the w value used in the TDHF(or equivalent) approach """ lwls = self.get_property("Frequencies for FD properties") # Only take the first non-zero pulsation in the followings lwl = None if lwls is not None: for puls in lwls: if puls > 0.0: lwl = float(puls) break print("Pulsations in the calculations:", lwls) print("Pulsation used:", lwl) else: print("No Pulsation found in the file. Assume Zero") lwl = 0.000 return lwl def get_property(self, prop): """ Read a property name "property" in the fchk file return a numpy vector """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block "property" first = 0 last = 0 cols = {"R": 5, "I": 6} numpytype = {"R": "d", "I": "int"} stype = "R" size = 0 for i, l in enumerate(lines): if prop in l: l = l[len(prop):] if "N=" in l: # read array of data pattern = r"\d+" size = int(re.findall(pattern, l)[0]) typepattern = r" [IR] " try: stype = re.findall(typepattern, l)[0].strip() except IndexError: raise Exception( "The type of data in fchk is not recognized") first = i + 1 nlines = (size - 1) // cols[stype] + 1 last = first + nlines break else: # single data typepattern = r" [IR] " try: stype = re.findall(typepattern, l)[0].strip() except IndexError: raise Exception( "The type of data in fchk is not recognized") if stype == 'I': pattern = r"\d+" return int(re.findall(pattern, l)[0]) elif stype == 'R': pattern = r"-?\d+\.\d*[ED]?[+\-]?\d*" return float(re.findall(pattern, l)[0]) lines = lines[first:last] if len(lines) == 0: return None # read the data data = [] for line in lines: data.extend([float(fl) for fl in line.split()]) data = numpy.array(data, numpytype[stype]) if data.size != size: raise Exception( "The number of data recovered [%i] is not the same as the size written in the file [%i]" % (data.size, size)) return data def get_forces(self): natoms = self.mol.natoms data = self.get_property("Cartesian Gradient") if isinstance(data, numpy.ndarray): forces = -data.reshape(natoms, 3) return forces def get_hessian(self): natoms = self.mol.natoms # find the block of date containing the Hessian # get the data (triangular matrix) data = self.get_property("Cartesian Force Constants") if data is None: return None index = 0 hessian = numpy.zeros((3 * natoms, 3 * natoms)) for i in range(3 * natoms): for j in range(i + 1): hessian[i, j] = data[index] index += 1 # fill the other half of the hessian matrix hessian = hessian + hessian.transpose() - numpy.diag( hessian.diagonal()) return hessian def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms freqs = numpy.zeros((self.modes.nmodes)) redmass = numpy.zeros((self.modes.nmodes)) normalmodes = numpy.zeros((0, )) first1 = 0 last1 = 0 first2 = 0 last2 = 0 for i, l in enumerate(lines): if "Vib-E2" in l: pattern = r"\d+" size = int(re.findall(pattern, l)[1]) first1 = i + 1 last1 = i + 1 + (size - 1) // 5 + 1 elif "Vib-Modes" in l: pattern = r"\d+" size = int(re.findall(pattern, l)[0]) first2 = i + 1 last2 = i + 1 + (size - 1) // 5 + 1 lines1 = lines[first1:last1] lines2 = lines[first2:last2] data = [] self.modes = VibModes(self.mol.nmodes, self.mol) if len(lines1) == 0: print( "No Normal modes found in fchk. Ask saveNM in the calculation." ) print("Compute from hessian instead") prop = Property(self) hessian_mw = prop.get_hessian_mw() if hessian_mw is not None: self.modes.ComputeModes_without_TR(hessian_mw) return for i, sline in enumerate(lines1): line = [float(fl) for fl in sline.split()] data.extend(line) for i in range(self.modes.nmodes): freqs[i] = data[i] redmass[i] = data[i + self.modes.nmodes] for sline in lines2: array = [float(fl) for fl in sline.split()] array = numpy.array(array) normalmodes = numpy.append(normalmodes, array) self.modes.set_modes_c_norm( normalmodes.reshape((self.modes.nmodes, 3 * natoms)), redmass) self.modes.set_freqs(freqs) def get_molecularorbitalenergies(self): """ Get the molecular orbital energies """ # get the block with the MO coefficients moen = self.get_property("Alpha Orbital Energies") return moen def get_molecularorbitalcoeffs(self): """ Get the molecular orbitals LCAO coefficients Output = M_ij with i which correspond to a MO and j to a AO Output = C+ """ # get the block with the MO coefficients mo = self.get_property("Alpha MO coefficients") if isinstance(mo, numpy.ndarray): nAO = self.get_property("Number of basis functions") nMO = self.get_property("Number of independent functions") mo = mo.reshape((nMO, nAO)) return mo def get_dipole(self): """ get dipole """ dipole = self.get_property("Dipole Moment") return dipole def get_dipole_deriv_c(self): """ get dmudx """ dmudx = self.get_property("Dipole Derivatives") if isinstance(dmudx, numpy.ndarray): dmudx = dmudx.reshape(self.mol.natoms, 3, 3) return dmudx get_AAT = (lambda self: self.get_magneticdipole_deriv_c()) def get_magneticdipole_deriv_c(self): """ get atomic axial tensor """ aat = self.get_property("AAT") if isinstance(aat, numpy.ndarray): aat = aat.reshape(self.mol.natoms, 3, 3) return aat def get_pollen(self): """ get polarizability """ alpha = {} #dictionary with alpha values for different pulsations frequencies = self.get_property("Frequencies for FD properties") data = self.get_property("Alpha(-w,w)") if data is None: dummy = self.get_property("Polarizability") if isinstance(dummy, numpy.ndarray): data = numpy.zeros((3, 3)) data[0, 0] = dummy[0] data[1, 0] = dummy[1] data[0, 1] = dummy[1] data[1, 1] = dummy[2] data[2, 0] = dummy[3] data[0, 2] = dummy[3] data[2, 1] = dummy[4] data[1, 2] = dummy[4] data[2, 2] = dummy[5] frequencies = [0.00000] if isinstance(data, numpy.ndarray): data = data.reshape((-1, 3, 3)) for lwl, a in zip(frequencies, data): alpha[(lwl, )] = a if len(alpha) == 0: return None return alpha def get_gtenlen(self): """ Read G'(-w;w) """ Gprime = {} #dictionary with Gprime values for different pulsations frequencies = self.get_property("Frequencies for FD properties") data = self.get_property("FD Optical Rotation Tensor") if isinstance(data, numpy.ndarray): data = data.reshape((-1, 3, 3)) for lwl, a in zip(frequencies, data): Gprime[( lwl, )] = a * lwl # gaussian gives the transpose of G'/w if len(Gprime) == 0: return None return Gprime def get_aten(self): """ read UpperA(-w;w) """ UpperA = {} #dictionary with UpperA values for different pulsations frequencies = self.get_property("Frequencies for FD properties") data = self.get_property("D-Q polarizability") if isinstance(data, numpy.ndarray): data = data.reshape((-1, 3, 6)) for lwl, a in zip(frequencies, data): a *= 1.5 # gaussian give the traceless A but not multiply by 3/2 UpperA[(lwl, )] = numpy.zeros((3, 3, 3)) UpperA[(lwl, )][:, 0, 0] = a[:, 0] UpperA[(lwl, )][:, 1, 1] = a[:, 1] UpperA[(lwl, )][:, 2, 2] = a[:, 2] UpperA[(lwl, )][:, 0, 1] = a[:, 3] UpperA[(lwl, )][:, 1, 0] = a[:, 3] UpperA[(lwl, )][:, 0, 2] = a[:, 4] UpperA[(lwl, )][:, 2, 0] = a[:, 4] UpperA[(lwl, )][:, 1, 2] = a[:, 5] UpperA[(lwl, )][:, 2, 1] = a[:, 5] if len(UpperA) == 0: return None return UpperA def get_pollen_deriv_c(self): """ Get dALphaDX """ dalphadx = {} #dictionary with dalphadx frequencies = self.get_property("Frequencies for DFD properties") data = self.get_property("Derivative Alpha(-w,w)") if data is None: dummy = self.get_property("Polarizability Derivatives") if isinstance(dummy, numpy.ndarray): data = numpy.zeros((self.mol.natoms * 3, 3, 3)) data[:, 0, 0] = dummy[0::6] data[:, 1, 0] = dummy[1::6] data[:, 0, 1] = dummy[1::6] data[:, 1, 1] = dummy[2::6] data[:, 2, 0] = dummy[3::6] data[:, 0, 2] = dummy[3::6] data[:, 2, 1] = dummy[4::6] data[:, 1, 2] = dummy[4::6] data[:, 2, 2] = dummy[5::6] frequencies = [0.00000] else: data = None if isinstance(data, numpy.ndarray): data = data.reshape((-1, self.mol.natoms, 3, 3, 3)) for lwl, dadx in zip(frequencies, data): dalphadx[(lwl, )] = dadx if len(dalphadx) == 0: return None return dalphadx def get_gtenlen_deriv_c(self): """ Get dGprimeDX """ dgprimedx = {} #dictionary with dgprimedx frequencies = self.get_property("Frequencies for DFD properties") data = self.get_property("Derivative FD Optical Rotation Tensor") if isinstance(data, numpy.ndarray): data = data.reshape((-1, self.mol.natoms, 3, 3, 3)) for lwl, dadx in zip(frequencies, data): dgprimedx[( lwl, )] = dadx * lwl # gaussian gives the transpose of G'/w if len(dgprimedx) == 0: return None return dgprimedx def get_aten_deriv_c(self): """ Get dUpperADX """ dupperAdx = { } #dictionary with dupperAdx values for different pulsations frequencies = self.get_property("Frequencies for DFD properties") data = self.get_property("Derivative D-Q polarizability") if isinstance(data, numpy.ndarray): data = data.reshape((-1, self.mol.natoms, 3, 3, 6)) for lwl, dadx in zip(frequencies, data): dadx *= 1.5 # gaussian give the traceless A but not multiply by 3/2 dupperAdx[(lwl, )] = numpy.zeros((self.mol.natoms, 3, 3, 3, 3)) dupperAdx[(lwl, )][:, :, :, 0, 0] = dadx[:, :, :, 0] dupperAdx[(lwl, )][:, :, :, 1, 1] = dadx[:, :, :, 1] dupperAdx[(lwl, )][:, :, :, 2, 2] = dadx[:, :, :, 2] dupperAdx[(lwl, )][:, :, :, 0, 1] = dadx[:, :, :, 3] dupperAdx[(lwl, )][:, :, :, 1, 0] = dadx[:, :, :, 3] dupperAdx[(lwl, )][:, :, :, 0, 2] = dadx[:, :, :, 4] dupperAdx[(lwl, )][:, :, :, 2, 0] = dadx[:, :, :, 4] dupperAdx[(lwl, )][:, :, :, 1, 2] = dadx[:, :, :, 5] dupperAdx[(lwl, )][:, :, :, 2, 1] = dadx[:, :, :, 5] if len(dupperAdx) == 0: return None return dupperAdx def get_energy_transition(self): data = self.get_property("ETran state values") GSen = self.get_property("SCF Energy") if (data is None) or (GSen is None): return None data = data.reshape((-1, 16)) # 16 values for each transition # energy, 3x <g|\mu|e>, 3x <g|mu_vel|e>, 3x <g|m|e>, 6 unknown energies = data[:, 0] # Make the difference with the smallest value of energy energies -= GSen return energies def get_dipole_transition(self): diptrans = self.get_property("ETran state values") if isinstance(diptrans, numpy.ndarray): diptrans = diptrans.reshape( (-1, 16)) # 16 values for each transition # energy, 3x <g|\mu|e>, 3x <g|mu_vel|e>, 3x <g|m|e>, 6 unknown diptrans = diptrans[:, 1:4] return diptrans def get_magneticdipole_transition(self): diptrans = self.get_property("ETran state values") if isinstance(diptrans, numpy.ndarray): diptrans = diptrans.reshape( (-1, 16)) # 16 values for each transition # energy, 3x <g|\mu|e>, 3x <g|mu_vel|e>, 3x <g|m|e>, 6 unknown diptrans = diptrans[:, 7:10] return diptrans def get_magneticshielding(self): """ Get GIAO nuclear magnetic shielding """ shielding = self.get_property("NMR shielding") if isinstance(shielding, numpy.ndarray): shielding = shielding.reshape((self.mol.natoms, 3, 3)) # order of the elements: for each atom: XX, YX, ZX, XY, YY, ZY, XZ, YZ, ZZ # reorder the elements for each atom: XX, XY, XZ, YX, YY, YZ, ZX, ZY, ZZ shielding = numpy.transpose(shielding, axes=(0, 2, 1)) shielding = shielding * Constants.a**2 * 1.0e6 return shielding def get_density(self): """ Get the non-perturbed density """ data = self.get_property("Total SCF Density") density = None if isinstance(data, numpy.ndarray): nbasis = self.get_property("Number of basis functions") index = 0 density = numpy.zeros((nbasis, nbasis)) for i in range(nbasis): for j in range(i + 1): density[i, j] = data[index] index += 1 # fill the other half of the density matrix density = density + density.transpose() - numpy.diag( density.diagonal()) return density def get_spindensity(self): """ Get the spin density """ data = self.get_property("Spin SCF Density") density = None if isinstance(data, numpy.ndarray): nbasis = self.get_property("Number of basis functions") index = 0 density = numpy.zeros((nbasis, nbasis)) for i in range(nbasis): for j in range(i + 1): density[i, j] = data[index] index += 1 # fill the other half of the density matrix density = density + density.transpose() - numpy.diag( density.diagonal()) return density def get_density_magnetic(self): """ Get the perturbed density by magnetic field """ data = self.get_property("Magnetic Field P1 (GIAO)") density = None if isinstance(data, numpy.ndarray): nbasis = self.get_property("Number of basis functions") index = 0 density = numpy.zeros((3, nbasis, nbasis)) for idir in range(3): for i in range(nbasis): for j in range(i + 1): density[idir, i, j] = data[index] index += 1 # fill the other half of the density matrix density[idir] = density[idir] - density[idir].transpose() return density def get_basisset(self): """ read the basis set return a list of AO objects """ nshell = self.get_property("Number of contracted shells") shelltype = self.get_property("Shell types") primitive_pershell = self.get_property( "Number of primitives per shell") shell2atom = self.get_property("Shell to atom map") primitive_exp = self.get_property("Primitive exponents") primitive_coeff = self.get_property("Contraction coefficients") primitive_coeff_p = self.get_property( "P(S=P) Contraction coefficients") atomicnumbers = self.get_property("Atomic numbers") # basis set list basisset = [] start = 0 for ishell in range(nshell): nprim = primitive_pershell[ishell] # get the exponents and coeffs for all the primitive of the shell exponents = primitive_exp[start:start + nprim] coefficients = primitive_coeff[start:start + nprim] coefficients_p = None if primitive_coeff_p is not None: if numpy.nonzero( primitive_coeff_p[start:start + nprim])[0].size != 0: coefficients_p = primitive_coeff_p[start:start + nprim] iatom = shell2atom[ishell] an = int(atomicnumbers[iatom - 1]) atype = int(shelltype[ishell]) shell = BasisSet.SHELL(iatom, an, atype, exponents=exponents, coefficients=coefficients, coefficients_p=coefficients_p) basisset.append(shell) start = start + nprim if len(basisset) == 0: basisset = None else: basisset = BasisSet.BasisSet(basisset) # basisset.check_contractedcoeff() return basisset
class Gamess(object): def __init__(self, filename='gamess.log', w=None): self.mol = VibToolsMolecule() self.modes = None self.filename = filename self.lwl = w freqs = property(lambda self: self.modes.freqs) def read(self): self.mol.read_from_gamess(filename=self.filename) self.modes = VibModes(self.mol.nmodes, self.mol) if self.lwl is None: self.lwl = self.get_pulsation() # self.ComputeFreqs() def get_pulsation(self): """ Get the w value used in the TDHF(or equivalent) approach """ f = open(self.filename, 'r') lines = f.readlines() f.close() pattern = r"-?\d+\.\d*[ED]?[+\-]?\d*" # lwls=None lwl = None for l in lines: if "OMEGA=" in l: alist = re.findall(pattern, l) lwl = float("%.6f"%float(alist[0])) break # lwls=[float(vl) for vl in alist] # # Only take the first non-zero pulsation in the followings # if lwls is not None: # for puls in lwls: # if puls > 0.0: # lwl=puls # print "Pulsations in the calculations:", lwls # print "Pulsation used:", lwl return lwl def get_hessian(self): natoms = self.mol.natoms # self.modes = VibModes(mol.nmodes, mol) hessian = numpy.zeros((3*natoms, 3*natoms)) f = open(self.filename, 'r') lines = f.readlines() f.close() indexline = 0 for i, l in enumerate(lines): if 'CARTESIAN FORCE CONSTANT MATRIX' in l: indexline = i+5 nread = int((natoms-1) // 2) +1 # print nread for iread in range(nread): istart = iread*2 istop = min(iread*2+2, natoms) for iparam in range(istart*3, natoms*3): indexline = indexline+1 line = lines[indexline] # print indexline, line pattern = r'[+-]?\d+?\.\d*' alist = re.findall(pattern, line) alist = [float(x) for x in alist] for icol, col in enumerate(range(istart*3, istop*3)): # only fill one-half of the matrix if col <= iparam: hessian[iparam, col] = alist[icol] indexline = indexline+4 break if len(numpy.flatnonzero(hessian)) == 0: return None # fill the other half of the matrix hessian = hessian+hessian.transpose() -numpy.diag(hessian.diagonal()) return hessian def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms normalmodes = numpy.zeros((0,)) freqs = [] for i, l in enumerate(lines): if "FREQUENCY:" in l: freqs.extend(l.split()[1:]) block = lines[i+5:i+5+3*natoms] array = [] for blockline in block: pattern = r"-?\d+\.\d+" alist = re.findall(pattern, blockline) array.append([float(fl) for fl in alist]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) freqs = numpy.array([float(fl) for fl in freqs]) # redmass=numpy.array([float (fl) for fl in redmass]) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0,): print("No normal modes found") else: normalmodes = normalmodes.reshape((3*natoms, 3*natoms)) self.modes.set_modes_c(normalmodes[self.mol.ntransrot:]) self.modes.set_freqs(freqs[self.mol.ntransrot:]) def get_energy_transition(self): f = open(self.filename, 'r') lines = f.readlines() f.close() excitations = [] pattern = r"[+-]?\d+\.\d+" # get the block with transition from the ground state start = None end = 0 for i, l in enumerate(lines): if (start is None) and ("transition from the ground state to" in l.lower()): start = i elif (start is not None) and ("transition between excited states" in l.lower()): end = i break lines = lines[start:end] if len(lines) == 0: return None for l in lines: if "state energies" in l.lower(): val = [float(x) for x in re.findall(pattern, l)] excitations.append(val[1] -val[0]) return numpy.array(excitations) def get_dipole_transition(self): f = open(self.filename, 'r') lines = f.readlines() f.close() diptrans = [] pattern = r"[+-]?\d+\.\d+" # get the block with transition from the ground state start = None end = 0 for i, l in enumerate(lines): if (start is None) and ("transition from the ground state to" in l.lower()): start = i elif (start is not None) and ("transition between excited states" in l.lower()): end = i break lines = lines[start:end] if len(lines) == 0: return None for l in lines: if "e*bohr" in l.lower(): val = [float(x) for x in re.findall(pattern, l)[:3]] diptrans.append(val) diptrans = numpy.array(diptrans).reshape((-1, 3)) return diptrans def get_UV_intensities(self): f = open(self.filename, 'r') lines = f.readlines() f.close() pattern_energy = r'STATE #\s+\d+\s+ENERGY =\s+([+-]?\d*\.\d*)' pattern_oscstrength = r'OSCILLATOR STRENGTH =\s+([+-]?\d*\.\d*)' excitations = [] oscillators = [] for iline, line in enumerate(lines): match = re.search(pattern_energy, line) if match is not None: energy = float(match.group(1)) match = re.search(pattern_oscstrength, lines[iline+1]) osc = float(match.group(1)) excitations.append(energy) oscillators.append(osc) if len(excitations) == 0: return None return numpy.array(excitations), numpy.array(oscillators) def read_tensor2(self, string): """ read a tensor 2 from a string: x y z x. 44.263383 2.620191 -1.002017 y. 2.620191 36.377832 -0.803650 z. -1.002017 -0.803650 36.078729 """ tensor2 = numpy.zeros((3, 3)) pattern = r"-?\d+\.\d+" alist = re.findall(pattern, string[1]) tensor2[0, :] = [float(val) for val in alist] alist = re.findall(pattern, string[2]) tensor2[1, :] = [float(val) for val in alist] alist = re.findall(pattern, string[3]) tensor2[2, :] = [float(val) for val in alist] return tensor2 def read_tensor3(self, string): """ read a tensor 3 from a string: x y z x, x. -32.230435 25.466354 7.026991 x, y. 25.466354 18.700157 2.406899 x, z. 7.026991 2.406899 13.530278 y, x. 0.094701 -12.816096 -0.752058 y, y. -12.816096 7.530971 -6.340628 y, z. -0.752058 -6.340628 -7.625672 z, x. 4.075249 0.870322 -19.985933 z, y. 0.870322 -10.312200 19.363558 z, z. -19.985933 19.363558 6.236951 """ string = [l for l in string if not len(l.strip()) == 0] tensor3 = numpy.zeros((3, 3, 3)) pattern = r"-?\d+\.\d+" for i in range(3): for j in range(3): index = i*3+j+1 alist = re.findall(pattern, string[index]) tensor3[i, j, :] = [float(val) for val in alist] return tensor3 def read_tensor4(self, string): """ read a tensor 4 from a string: x y z xxx. 187088.641556 0.000001 -0.000054 xxy. 0.000002 100237.066416 0.000006 xxz. -0.000053 0.000007 79288.069398 xyx. 0.000001 100237.066386 0.000011 xyy. 100237.066369 -0.000007 -0.000021 xyz. 0.000004 -0.000021 0.000031 xzx. -0.000054 0.000006 79288.069401 xzy. 0.000007 -0.000021 0.000039 xzz. 79288.069391 0.000049 -0.000078 yxx. -0.000003 21561.430508 -0.000003 yxy. 21561.430510 0.000000 -0.000001 yxz. -0.000003 -0.000002 0.000055 yyx. 21561.430508 -0.000001 -0.000002 yyy. -0.000002 59145.984721 0.000004 yyz. -0.000002 0.000004 50112.750694 yzx. -0.000003 -0.000003 0.000055 yzy. -0.000002 0.000004 50112.750638 yzz. 0.000055 50112.750678 -0.000018 zxx. 0.000000 0.000000 42279.004942 zxy. 0.000000 0.000000 -0.000004 zxz. 42279.004942 -0.000004 -0.000028 zyx. 0.000000 0.000000 -0.000004 zyy. 0.000000 0.000000 37304.216039 zyz. -0.000004 37304.216039 -0.000011 zzx. 42279.004942 -0.000004 -0.000028 zzy. -0.000004 37304.216039 -0.000011 zzz. -0.000028 -0.000011 47404.495422 """ string = [l for l in string if not len(l.strip()) == 0] tensor4 = numpy.zeros((3, 3, 3, 3)) pattern = r"-?\d+\.\d+" for i in range(3): for j in range(3): for k in range(3): index = i*9+j*3+k+1 alist = re.findall(pattern, string[index]) tensor4[i, j, k, :] = [float(val) for val in alist] return tensor4 def get_dipole(self): """ read the dipole """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the dipole dipole = None for i, l in enumerate(lines): if " Dipole moment [in au]" in l: pattern = r"-?\d*\.\d*" alist = [float(l) for l in re.findall(pattern, lines[i+2])[0:3]] dipole = numpy.array(alist) break return dipole def get_quadrupole(self): """ read the quadrupole """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the quadrupole quadrupole = None for i, l in enumerate(lines): if " Quadrupolar moment [in au](traceless," in l: quadrupole = self.read_tensor2(lines[i+1:i+5]) break return quadrupole def get_pollen(self): """ Read Alpha(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability alpha = {}#dictionary with alpha values for different pulsations for i, l in enumerate(lines): if "Alpha tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in alpha: alpha[lwl] = self.read_tensor2(lines[i+1:i+5]) if len(alpha) == 0: return None return alpha def get_beta(self): """ Read Beta(-w_sigma;w1, w2) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability beta = {}#dictionary with beta values for different pulsations for i, l in enumerate(lines): if "Beta tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in beta: beta[lwl] = self.read_tensor3(lines[i+1:i+11]) if len(beta) == 0: return None return beta def get_gamma(self): """ Read Gamma(-w_sigma;w1, w2) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability gamma = {}#dictionary with gamma values for different pulsations for i, l in enumerate(lines): if "Gamma tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in gamma: gamma[lwl] = self.read_tensor4(lines[i+1:i+29]) if len(gamma) == 0: return None return gamma def get_gtenlen(self): """ Read G'(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability Gprime = {}#dictionary with Gprime values for different pulsations for i, l in enumerate(lines): if "G' tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in Gprime: Gprime[lwl] = self.read_tensor2(lines[i+1:i+5]) if len(Gprime) == 0: return None return Gprime def get_aten(self): """ read UpperA(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability upperA = {}#dictionary with UpperA values for different pulsations for i, l in enumerate(lines): if "Uppera tensor" in l: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in upperA: uppera = self.read_tensor3(lines[i+1:i+13]) if t3_istraceless(uppera): upperA[lwl] = uppera.reshape((3, 3, 3)) else: print("Warning: aten was not traceless") upperA[lwl] = t3_traceless(uppera).reshape((3, 3, 3)) if len(upperA) == 0: return None return upperA def read_vectorderiv(self, string): """ read the derivative of a vector from a string: param. 1:dx(1) x y z 0.131482 0.000001 0.000000 param. 2:dy(1) x y z -0.000001 0.093156 0.000000 """ vector = numpy.zeros((self.mol.natoms*3, 3)) iblock = 0 while len(string) > 0: block = string[2] string = string[3:] pattern = r"-?\d+\.\d+" alist = re.findall(pattern, block) vector[iblock, :] = [float(val) for val in alist] iblock = iblock+1 return vector.reshape((self.mol.natoms, 3, 3)) def read_tensor2deriv(self, string): """ read the derivative of a tensor 2 from a string: param. 1:dx(1) x y z x. 3.779827 -3.897852 -1.792047 y. -3.897852 0.211138 0.578452 z. -1.792047 0.578452 0.060065 param. 2:dy(1) x y z x. -1.386831 2.090519 0.725367 y. 2.090519 -9.454466 -2.132374 z. 0.725367 -2.132374 -0.464399 ... """ tensor2 = numpy.zeros((self.mol.natoms*3, 3, 3))# natoms, x, y, z derivative, 3 elec-field, 3 elec-field iblock = 0 while len(string) > 0: block = string[2:5] string = string[5:] pattern = r"-?\d+\.\d+" for i in range(3): alist = re.findall(pattern, block[i]) tensor2[iblock, i, :] = [float(val) for val in alist] iblock = iblock+1 return tensor2.reshape((self.mol.natoms, 3, 3, 3)) def read_tensor3deriv(self, string): """ read the derivative of a tensor 3 from a string: param. 1:dx(1)(-0.085645; 0.085645) x y z x, x. 8.252061 -16.010794 -2.972253 x, y. -16.010794 1.072645 5.354106 x, z. -2.972253 5.354106 -9.324706 y, x. -8.727084 16.836621 4.486339 y, y. 16.836621 2.244281 -1.294347 y, z. 4.486339 -1.294347 6.482803 z, x. 1.550365 5.483838 11.028642 z, y. 5.483838 1.856942 -1.047115 z, z. 11.028642 -1.047115 -3.407307 param. 2:dy(1)(-0.085645; 0.085645) x y z x, x. -1.993802 16.690003 4.721374 x, y. 16.690003 -3.407884 0.715354 x, z. 4.721374 0.715354 5.401686 y, x. -16.095652 -29.812332 -2.809342 y, y. -29.812332 27.193908 5.960600 y, z. -2.809342 5.960600 -11.098256 z, x. -2.598681 -4.243842 -1.864990 z, y. -4.243842 -0.739061 14.421986 z, z. -1.864990 14.421986 3.337742 ... """ string = [l for l in string if not len(l.strip()) == 0] tensor3 = numpy.zeros((self.mol.natoms*3, 3, 3, 3))# natoms, x, y, z derivative, 3 elec-field, 9 elec-field gradient iblock = 0 while len(string) > 0: block = string[2:11] string = string[11:] pattern = r"-?\d+\.\d+" for i in range(3): for j in range(3): index = i*3+j alist = re.findall(pattern, block[index]) tensor3[iblock, i, j, :] = [float(val) for val in alist] iblock = iblock+1 return tensor3.reshape((self.mol.natoms, 3, 3, 3, 3)) def get_dipole_deriv_c(self): """ Get dmuDX """ #find the block of data containing the Cartesian derivatives of the dipole f = open(self.filename, 'r') lines = f.readlines() f.close() dmudx = None for i, l in enumerate(lines): if "Dipole derivatives [in au]" in l: # dmudx given by 3*natoms blocks of 3 lines length = 3*self.mol.natoms*3 dmudx = self.read_vectorderiv(lines[i+1:i+1+length]) break return dmudx def get_pollen_deriv_c(self): """ Get dALphaDX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dalphadx = {}#dictionary with dalphadx values for different pulsations for i, l in enumerate(lines): if "Alpha derivatives" in l: if "param." in lines[i+1]: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in dalphadx: # alpha given by 3*natoms blocks of 5 lines length = 3*self.mol.natoms*5 dalphadx[lwl] = self.read_tensor2deriv(lines[i+1:i+length+1]) if len(dalphadx) == 0: return None return dalphadx def get_gtenlen_deriv_c(self): """ Get dGprimeDX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dgprimedx = {}#dictionary with dgprimedx values for different pulsations for i, l in enumerate(lines): if "G' derivatives" in l: if "param." in lines[i+1]: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in dgprimedx: # gprime given by 3*natoms blocks of 5 lines length = 3*self.mol.natoms*5 dgprimedx[lwl] = self.read_tensor2deriv(lines[i+1:i+length+1]) if len(dgprimedx) == 0: return None return dgprimedx def get_aten_deriv_c(self): """ Get dUpperADX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dupperAdx = {}#dictionary with dupperAdx values for different pulsations for i, l in enumerate(lines): if "UpperA derivatives" in l: if "param." in lines[i+1]: pattern = r"[+-]?0\.\d{6}" lwl = tuple([float(x) for x in re.findall(pattern, l)[1:]]) if lwl not in dupperAdx: # upperA given by 3*natoms blocks of 14 lines length = 3*self.mol.natoms*14 uppera = self.read_tensor3deriv(lines[i+1:i+length+1]) if t3_istraceless(uppera): dupperAdx[lwl] = uppera.reshape((self.mol.natoms, 3, 3, 3, 3)) else: print("Warning: aten deriv_c was not traceless") dupperAdx[lwl] = t3_traceless(uppera).reshape((self.mol.natoms, 3, 3, 3, 3)) if len(dupperAdx) == 0: return None return dupperAdx
class DATA(object): def __init__(self, logname='file.data', w=None): self.mol = VibToolsMolecule() self.modes = None self.filename = logname self.lwl = w freqs = property(lambda self: self.modes.freqs) def read(self): self.mol.read_from_data(filename=self.filename) self.modes = VibModes(self.mol.nmodes, self.mol) if self.lwl is None: self.lwl = self.get_pulsation() def get_pulsation(self): """ Get the first Pulsation value in the data file """ f = open(self.filename, 'r') lines = f.readlines() f.close() pattern = r"[+-]?0\.\d{6}" # lwls=None lwl = None for l in lines: if "Pulsation:" in l: alist = re.findall(pattern, l) lwl = float(alist[0]) break # lwls=[float(vl) for vl in alist] # # Only take the first non-zero pulsation in the followings # if lwls is not None: # for puls in lwls: # if puls > 0.0: # lwl=puls # print "Pulsations in the calculations:", lwls # print "Pulsation used:", lwl return lwl def get_hessian(self): natoms = self.mol.natoms f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of date containing the Hessian first = 0 last = 0 for i, l in enumerate(lines): if "[Hessian]" in l: first = i + 2 elif (first != 0) and "[" in l: last = i break elif (first != 0) and i == len(lines) - 1: last = i + 1 break lines = lines[first:last] if len(lines) == 0: return None lines = [l for l in lines if not len(l.strip()) == 0] lines = [l for l in lines if not l.startswith('Param.')] hessian = numpy.zeros((3 * natoms, 3 * natoms)) index = 0 for j in range(3 * natoms): for i in range(natoms): alist = [float(l) for l in lines[index].split()] hessian[i * 3:i * 3 + 3, j] = alist index += 1 return hessian def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms # find the block of date containing the normal modes first = 0 last = 0 for i, l in enumerate(lines): if "[Modes de vibration]" in l: first = i + 2 elif "[Vibrational modes]" in l: first = i + 2 elif (first != 0) and "[" in l: last = i break elif (first != 0) and i == len(lines) - 1: last = i + 1 break lines = lines[first:last] freqs = [] redmass = [] normalmodes = numpy.zeros((0, )) for i, l in enumerate(lines): if "Frequencies " in l: freqs.extend(l.split()[1:]) elif "Reduced-masses" in l: redmass.extend(l.split()[1:]) elif "Coord NA Element:" in l: block = lines[i + 1:i + 3 * natoms + 1] array = [] for blockline in block: array.append([float(fl) for fl in blockline.split()[3:]]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) freqs = numpy.array([float(fl) for fl in freqs]) redmass = numpy.array([float(fl) for fl in redmass]) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0, ): print("No normal modes found") else: self.modes.set_modes_c_norm( normalmodes.reshape((self.modes.nmodes, 3 * natoms)), redmass) self.modes.set_freqs(freqs) def read_tensor2(self, string): """ read a tensor 2 from a string: 44.263383 2.620191 -1.002017 2.620191 36.377832 -0.803650 -1.002017 -0.803650 36.078729 """ tensor2 = numpy.zeros((3, 3)) pattern = r"-?\d+\.\d+" alist = re.findall(pattern, string[0]) tensor2[0, :] = [float(val) for val in alist] alist = re.findall(pattern, string[1]) tensor2[1, :] = [float(val) for val in alist] alist = re.findall(pattern, string[2]) tensor2[2, :] = [float(val) for val in alist] return tensor2 def read_tensor3(self, string): """ read a tensor 3 from a string: x y z x, x. -32.230435 25.466354 7.026991 x, y. 25.466354 18.700157 2.406899 x, z. 7.026991 2.406899 13.530278 y, x. 0.094701 -12.816096 -0.752058 y, y. -12.816096 7.530971 -6.340628 y, z. -0.752058 -6.340628 -7.625672 z, x. 4.075249 0.870322 -19.985933 z, y. 0.870322 -10.312200 19.363558 z, z. -19.985933 19.363558 6.236951 """ tensor3 = numpy.zeros((3, 3, 3)) pattern = r"-?\d+\.\d+" for i in range(3): for j in range(3): index = i * 3 + j + 1 alist = re.findall(pattern, string[index]) tensor3[i, j, :] = [float(val) for val in alist] return tensor3 def get_dipole(self): """ read the dipole """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the dipole dipole = None for i, l in enumerate(lines): if "[Vecteur mu]" in l: pattern = r"-?\d*\.\d*" alist = [ float(l) for l in re.findall(pattern, lines[i + 3])[0:3] ] dipole = numpy.array(alist) break return dipole def get_quadrupole(self): """ read the quadrupole """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the quadrupole quadrupole = None for i, l in enumerate(lines): if "[Tenseur theta]" in l: quadrupole = self.read_tensor2(lines[i + 3:i + 6]) if t2_istraceless(quadrupole): quadrupole = quadrupole.reshape((3, 3)) else: print("Warning: Quadrupole was not traceless") quadrupole = t2_traceless(quadrupole).reshape((3, 3)) break return quadrupole def get_pollen(self): """ Read Alpha(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability alpha = {} #dictionary with alpha values for different pulsations for i, l in enumerate(lines): if "[Tenseur alpha]" in l: pattern = r"[+-]?0\.\d{6}" lwl = (float(re.findall(pattern, lines[i + 1])[0]), ) if lwl not in alpha: alpha[lwl] = self.read_tensor2(lines[i + 4:i + 7]) if len(alpha) == 0: return None return alpha def get_gtenlen(self): """ Read G'(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability Gprime = {} #dictionary with Gprime values for different pulsations for i, l in enumerate(lines): if "[Tenseur gprime]" in l: pattern = r"[+-]?0\.\d{6}" lwl = (float(re.findall(pattern, lines[i + 1])[0]), ) if lwl not in Gprime: Gprime[lwl] = self.read_tensor2(lines[i + 4:i + 7]) if len(Gprime) == 0: return None return Gprime def get_aten(self): """ read UpperA(-w;w) """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the polarizability upperA = {} #dictionary with UpperA values for different pulsations for i, l in enumerate(lines): if "[Tenseur uppera]" in l: pattern = r"[+-]?0\.\d{6}" lwl = (float(re.findall(pattern, lines[i + 1])[0]), ) if lwl not in upperA: uppera = self.read_tensor3(lines[i + 4:i + 14]) if t3_istraceless(uppera): upperA[lwl] = uppera.reshape((3, 3, 3)) else: print("Warning: aten was not traceless") upperA[lwl] = t3_traceless(uppera).reshape((3, 3, 3)) if len(upperA) == 0: return None return upperA def read_vectorderiv(self, string): """ read the derivative of a vector from a string: Param 1 -0.94832100 -0.10494700 -0.05493100 Param 2 -0.25497100 -0.69900900 0.06769500 """ string = [l for l in string if not len(l.strip()) == 0] vector = numpy.zeros((self.mol.natoms * 3, 3)) iblock = 0 while len(string) > 0: block = string[1] string = string[2:] pattern = r"-?\d+\.\d+" alist = re.findall(pattern, block) vector[iblock, :] = [float(val) for val in alist] iblock = iblock + 1 return vector.reshape((self.mol.natoms, 3, 3)) def read_tensor2deriv(self, string): """ read the derivative of a tensor 2 from a string: Param 1 0.00000000 0.00000000 -2.12331100 0.00000000 0.00000000 0.00000000 -2.12331100 0.00000000 0.00000000 Param 2 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 -2.92842600 0.00000000 -2.92842600 0.00000000 ... """ string = [l for l in string if not len(l.strip()) == 0] tensor2 = numpy.zeros( (self.mol.natoms * 3, 3, 3)) # natoms, x, y, z derivative, 3 elec-field, 3 elec-field iblock = 0 while len(string) > 0: block = string[1:4] string = string[4:] pattern = r"-?\d+\.\d+" for i in range(3): alist = re.findall(pattern, block[i]) tensor2[iblock, i, :] = [float(val) for val in alist] iblock = iblock + 1 return tensor2.reshape((self.mol.natoms, 3, 3, 3)) def read_tensor3deriv(self, string): """ read the derivative of a tensor 3 from a string: Param 1 X Y Z XX. 2.50844800 0.00000000 0.00000000 XY. 0.00000000 -2.52377500 0.00000000 XZ. 0.00000000 0.00000000 0.01532700 YX. 0.00000000 0.58814400 0.00000000 YY. 0.58814400 0.00000000 0.00000000 YZ. 0.00000000 0.00000000 0.00000000 ZX. 0.00000000 0.00000000 0.98062900 ZY. 0.00000000 0.00000000 0.00000000 ZZ. 0.98062900 0.00000000 0.00000000 Param 2 X Y Z XX. 0.00000000 -0.07767200 0.00000000 XY. -0.07767200 0.00000000 0.00000000 XZ. 0.00000000 0.00000000 0.00000000 YX. 2.84539400 0.00000000 0.00000000 YY. 0.00000000 -2.34382500 0.00000000 YZ. 0.00000000 0.00000000 -0.50156900 ZX. 0.00000000 0.00000000 0.00000000 ZY. 0.00000000 0.00000000 -0.13819900 ZZ. 0.00000000 -0.13819900 0.00000000 ... """ string = [l for l in string if not len(l.strip()) == 0] tensor3 = numpy.zeros( (self.mol.natoms * 3, 3, 3, 3) ) # natoms, x, y, z derivative, 3 elec-field, 9 elec-field gradient iblock = 0 while len(string) > 0: block = string[2:11] string = string[11:] pattern = r"-?\d+\.\d+" for i in range(3): for j in range(3): index = i * 3 + j alist = re.findall(pattern, block[index]) tensor3[iblock, i, j, :] = [float(val) for val in alist] iblock = iblock + 1 return tensor3.reshape((self.mol.natoms, 3, 3, 3, 3)) def get_dipole_deriv_c(self): """ Get dmuDX """ #find the block of data containing the Cartesian derivatives of the dipole f = open(self.filename, 'r') lines = f.readlines() f.close() dmudx = None for i, l in enumerate(lines): if "[Derivee de mu par rapport a X]" in l: # dmudx given by 3*natoms blocks of 4 lines length = 3 * self.mol.natoms * 4 dmudx = self.read_vectorderiv(lines[i + 1:i + 1 + length]) break return dmudx def get_pollen_deriv_c(self): """ Get dALphaDX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dalphadx = { } #dictionary with dalphadx values for different pulsations for i, l in enumerate(lines): if "[Derivee du tenseur alpha par rapport a X]" in l: pattern = r"[+-]?0\.\d{6}" lwl = (float(re.findall(pattern, lines[i + 1])[0]), ) if lwl not in dalphadx: # alpha given by 3*natoms blocks of 6 lines length = 3 * self.mol.natoms * 6 dalphadx[lwl] = self.read_tensor2deriv(lines[i + 2:i + length + 2]) if len(dalphadx) == 0: return None return dalphadx def get_gtenlen_deriv_c(self): """ Get dGprimeDX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dgprimedx = { } #dictionary with dgprimedx values for different pulsations for i, l in enumerate(lines): if ("[Derivee du tenseur G' par rapport a X]" in l) or ( "[Derivee du tenseur G' par rapport a X numerique]" in l): pattern = r"[+-]?0\.\d{6}" lwl = (float(re.findall(pattern, lines[i + 1])[0]), ) if lwl not in dgprimedx: # gprime given by 3*natoms blocks of 6 lines length = 3 * self.mol.natoms * 6 dgprimedx[lwl] = self.read_tensor2deriv(lines[i + 2:i + length + 2]) if len(dgprimedx) == 0: return None return dgprimedx def get_aten_deriv_c(self): """ Get dUpperADX """ f = open(self.filename, 'r') lines = f.readlines() f.close() #find the block of data containing the Cartesian derivatives of the polarizabiltiy dupperAdx = { } #dictionary with dupperAdx values for different pulsations for i, l in enumerate(lines): if "[Derivee du tenseur DupperA par rapport a X]" in l: pattern = r"[+-]?0\.\d{6}" lwl = (float(re.findall(pattern, lines[i + 1])[0]), ) if lwl not in dupperAdx: # upperA given by 3*natoms blocks of 13 lines length = 3 * self.mol.natoms * 13 uppera = self.read_tensor3deriv(lines[i + 2:i + length + 2]) if t3_istraceless(uppera): dupperAdx[lwl] = uppera.reshape( (self.mol.natoms, 3, 3, 3, 3)) else: print("Warning: aten deriv_c was not traceless") dupperAdx[lwl] = t3_traceless(uppera).reshape( (self.mol.natoms, 3, 3, 3, 3)) if len(dupperAdx) == 0: return None return dupperAdx
class DATA(object): def __init__(self, logname='file.data', w=None): self.mol = VibToolsMolecule() self.modes = None self.filename = logname self.lwl = w freqs = property(lambda self: self.modes.freqs) def read(self): self.mol.read_from_data(filename=self.filename) self.modes = VibModes(self.mol.nmodes, self.mol) if self.lwl is None: self.lwl = self.get_pulsation() def get_pulsation(self): """ Get the first Pulsation value in the data file """ f = open(self.filename, 'r') lines = f.readlines() f.close() pattern = r"[+-]?0\.\d{6}" lwls = [] for l in lines: if "Pulsation:" in l: alist = re.findall(pattern, l) w = [float(x) for x in alist] for puls in w: if puls not in lwls: lwls.append(puls) # # Only take the first non-zero pulsation in the followings lwl = None if len(lwls) != 0: for puls in lwls: if puls > 0.0: lwl = puls break print("Pulsations in the calculations:", lwls) print("Pulsation used:", lwl) return lwl get_forces = (lambda self: self.get_mechproperty("Forces")) get_hessian = (lambda self: self.get_mechproperty("Hessian")) get_cubic_forces = (lambda self: self.get_mechproperty("Cubic Forces")) def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms # find the block of date containing the normal modes first = 0 last = 0 for i, l in enumerate(lines): if "[Vibrational Normal Modes]" in l: first = i + 2 elif (first != 0) and "[" in l: last = i break elif (first != 0) and i == len(lines) - 1: last = i + 1 break lines = lines[first:last] freqs = [] redmass = [] normalmodes = numpy.zeros((0, )) for i, l in enumerate(lines): if "Frequencies " in l: freqs.extend(l.split()[1:]) elif "Reduced-masses" in l: redmass.extend(l.split()[1:]) elif "Coord" in l: block = lines[i + 1:i + 3 * natoms + 1] array = [] for blockline in block: array.append([float(fl) for fl in blockline.split()[3:]]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) freqs = numpy.array([float(fl) for fl in freqs]) redmass = numpy.array([float(fl) for fl in redmass]) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0, ): print("No normal modes found") print("Compute from hessian instead") from VibTools import Properties prop = Properties.Property(self) hessian_mw = prop.get_hessian_mw() if hessian_mw is not None: self.modes.ComputeModes_without_TR(hessian_mw) return else: self.modes.set_modes_c_norm( normalmodes.reshape((self.modes.nmodes, 3 * natoms)), redmass) self.modes.set_freqs(freqs) def read_property(self, lines): """ read the property from a string """ # remove empty lines and lines which start with Param lines = [l for l in lines if not len(l.strip()) == 0] lines = [l for l in lines if not l.startswith('Param')] nblines = len(lines) prop = numpy.zeros((nblines, 3)) for iline, l in enumerate(lines): prop[iline] = [float(x) for x in l.strip().split()] return prop.ravel() def read_property_transition(self, lines): """ read the property transition from a string """ # remove empty lines and lines which start with Param lines = [l for l in lines if not len(l.strip()) == 0] lines = [l for l in lines if not l.startswith('Param')] nblines = len(lines) prop = [] for l in lines: prop.append([float(x) for x in l.strip().split()[1:]]) prop = numpy.array(prop) return prop.reshape((nblines, -1)) def get_mechproperty(self, name): """ get any type of mechanical property param name:name of the property """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the mechanical property prop = None for i, l in enumerate(lines): if "[" + name.strip() + "]" in l: nbelems = int(lines[i + 1].split()[1]) if nbelems == 3 * self.mol.natoms: nblines = self.mol.natoms else: nblines = nbelems // 3 + nbelems // (3 * self.mol.natoms) prop = self.read_property(lines[i + 2:i + 2 + nblines]) break return prop def get_property(self, name): """ get any type of property param name:name of the property using the various operators from the response function add _deriv_c for cartesian first-order derivative add _deriv_c2 for cartesian second-order derivative return: a dictinary with pulsations as keys """ from VibTools import Properties f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the property props = [] list_omegas = [] puls_size = Properties.get_pulsation_size(name) for i, l in enumerate(lines): if "[" + name.strip() + "]" in l: omegas = [] if puls_size > 0: omegas = [ float(x) for x in lines[i + 1].strip().split()[1:] ] print("[%s] found with pulsation %s" % (name.strip(), omegas)) prop_size = Properties.get_property_size(name) nblines = int(prop_size // 3) nparams = 1 # deriv_c? if name.find("_deriv") != -1: try: order = int(name[name.find("_deriv") + 8:]) except ValueError: order = 1 nparams = (3 * self.mol.natoms)**order nblines = (nblines + 1) * nparams prop = self.read_property(lines[i + 2:i + 2 + nblines]) if nparams > 1: prop = prop.reshape((nparams, prop_size)) list_omegas.append(tuple(omegas)) props.append(prop) if len(props) == 0: return None props = dict(zip(list_omegas, props)) if puls_size == 0: props = props[()] return props def get_property_transition(self, name): """ get any type of property transition param name:name of the property using the various operators from the response function add _deriv_c for cartesian first-order derivative add _deriv_c2 for cartesian second-order derivative """ from VibTools import Properties f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the property prop = None for i, l in enumerate(lines): if "[" + name.strip() + "_transition]" in l: # if w is not None: # omegas=[float(x) for x in lines[i+1].strip().split()[1:]] # if tuple(omegas) != w: # continue nstates = int(lines[i + 1].strip().split()[1]) prop_size = Properties.get_property_size(name) nblines = nstates nparams = 1 # deriv_c? if name.find("_deriv") != -1: try: order = int(name[name.find("_deriv") + 8:]) except ValueError: order = 1 nparams = (3 * self.mol.natoms)**order nblines = (nblines + 1) * nparams prop = self.read_property_transition(lines[i + 2:i + 2 + nblines]) if nparams > 1: prop = prop.reshape((-1, nparams, prop_size)) break return prop def get_FCfactors(self, istate): """ get Franck Condon factors for state istate """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the property FCfactors = None tline = "[FC factors of state %i]" % (istate) for i, l in enumerate(lines): if tline in l: nbfc = int(lines[i + 2].strip().split()[1]) FCfactors = [] for line in lines[i + 4:i + 4 + nbfc]: FCfactors.append( [float(x) for x in line.strip().split()[0:2]]) FCfactors = numpy.array(FCfactors).transpose() return FCfactors def get_Delta_factors(self, istate): """ get Dimensionless Delta factors for state istate """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the property Delta = None tline = "[Dimensionless Delta factors for state %i]" % (istate) for i, l in enumerate(lines): if tline in l: nbmodes = int(lines[i + 1].strip().split()[1]) Delta = [] for line in lines[i + 3:i + 3 + nbmodes]: Delta.append(float(line.strip())) Delta = numpy.array(Delta) return Delta def get_HuangRhys_factors(self, istate): """ get HuangRhys factors for state istate """ f = open(self.filename, 'r') lines = f.readlines() f.close() # find the block of data containing the property HR = None tline = "[Huang-Rhys factors for state %i]" % (istate) for i, l in enumerate(lines): if tline in l: nbmodes = int(lines[i + 1].strip().split()[1]) HR = [] for line in lines[i + 3:i + 3 + nbmodes]: HR.append(float(line.strip())) HR = numpy.array(HR) return HR
def read(self): self.mol.read_from_molpro(filename=self.filename, oricoord=True) self.modes = VibModes(self.mol.nmodes, self.mol) if self.lwl is None: self.lwl = self.get_pulsation()
class Molpro(object): def __init__(self, logname='molpro.out', w=None): self.mol = VibToolsMolecule() self.modes = None self.filename = logname self.lwl = w freqs = property(lambda self: self.modes.freqs) def read(self): self.mol.read_from_molpro(filename=self.filename, oricoord=True) self.modes = VibModes(self.mol.nmodes, self.mol) if self.lwl is None: self.lwl = self.get_pulsation() def get_pulsation(self): """ Get the w value used in the TDHF(or equivalent) approach """ # f = open(self.filename, 'r') # lines = f.readlines() # f.close() # pattern = r"[+-]?0\.\d{6}" # lwls = None return None # for l in lines: # if "Using perturbation frequencies:" in l: # list=re.findall(pattern, l) # lwls=[float(vl) for vl in list] # break # elif "Frequencies=" in l: # list=re.findall(pattern, l) # lwls=[float(vl) for vl in list] # break # Only take the first non-zero pulsation in the followings # lwl=None # if lwls is not None: # for puls in lwls: # if puls > 0.0: # lwl=puls # break # print "Pulsations in the calculations:", lwls # print "Pulsation used:", lwl # else : # print "No Pulsation found in the file. Assume Zero" # lwl=0.000 # return lwl def read_normalmodes(self): f = open(self.filename, 'r') lines = f.readlines() f.close() natoms = self.mol.natoms freqs = [] normalmodes = numpy.zeros((0, )) for i, l in enumerate(lines): if "Wavenumbers [cm-1]" in l: freqs.extend(l.split()[2:]) elif "X1 " in l: block = lines[i:i + 3 * natoms] array = [] for blockline in block: array.append([float(fl) for fl in blockline.split()[1:]]) array = numpy.array(array) array = array.transpose() normalmodes = numpy.append(normalmodes, array) self.modes = VibModes(self.mol.nmodes, self.mol) if normalmodes.shape == (0, ): print("No normal modes found") return freqs = numpy.array([float(fl) for fl in freqs]) normalmodes = normalmodes.reshape((3 * natoms, 3 * natoms)) modes_wtr = VibModes(3 * natoms, self.mol) modes_wtr.set_freqs(freqs) modes_wtr.set_modes_c(normalmodes) self.modes = modes_wtr.remove_trans_rot() self.modes.sort_by_freq() def get_energy_transition(self): f = open(self.filename, 'r') lines = f.readlines() f.close() energies = {} for line in lines: if "!MCSCF STATE" in line: # match < | DM(XYZ)| > pattern = r'!MCSCF STATE\s+?(\d+?\.\d+?)\s+?Energy\s+?([+-]?\d*\.\d*)' match = re.search(pattern, line) if match is not None: key = match.group(1) energies[key] = float(match.group(2)) if len(energies) == 0: return None # Make the difference with the smallest value of energy energies = numpy.sort(numpy.array(list(energies.values()))) energies = energies[1:] - energies[0] return energies def get_dipole_transition(self): f = open(self.filename, 'r') lines = f.readlines() f.close() diptrans = {} dir = ["X", "Y", "Z"] for line in lines: if "!MCSCF trans" in line: # match < | DM(XYZ)| > pattern = r'<(\d+?\.\d+?)\|DM([XYZ])\|(\d+?.\d+?)>\s+?([+-]?\d*\.\d*)\s+au' match = re.search(pattern, line) if match is not None: key = match.group(1) + "_" + match.group(3) if key not in diptrans: diptrans[key] = numpy.zeros((3)) diptrans[key][dir.index(match.group(2))] = float( match.group(4)) if len(diptrans) == 0: return None return numpy.array(list(diptrans.values())) def get_forces(self): natoms = self.mol.natoms f = open(self.filename, 'r') lines = f.readlines() f.close() start = 0 end = 0 for iline, line in enumerate(lines): if "GRADIENT FOR STATE" in line: start = iline + 4 end = start + natoms break lines = lines[start:end] if len(lines) == 0: return None forces = numpy.zeros((natoms, 3)) for i, line in enumerate(lines): pattern = r"-?\d+\.\d*" alist = re.findall(pattern, line) forces[i] = [-float(x) for x in alist] return forces