Esempio n. 1
0
    def __getAtoms(self):
        """Build the atom list for the molecule
		"""
        molecule = self.__molecule
        file = self.__fd
        file.toBOF()
        ret = file.findString("Atoms and basis sets")
        if ret == '':
            raise ParseError("Keyword not found 'Atoms and basis sets'")
        file.skipLines(2)
        line = file.readline()
        molecule.numOfAtomTypes = int(
            re.compile("Number of atom types:\s*([0-9]+)").search(line).group(
                1))
        line = file.readline()
        molecule.numOfAtoms = int(
            re.compile("Total number of atoms:\s*([0-9]+)").search(line).group(
                1))
        #  O           1       8      42      30      [10s5p2d1f|4s3p2d1f]
        file.skipLines(3)
        regexp = re.compile(
            "^\s*(.+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\[.*\])\s+")
        for i in xrange(0, self.__molecule.numOfAtomTypes):
            line = file.readline()
            res = regexp.match(line)
            numForThisAtomType = int(res.group(2))
            for j in xrange(0, numForThisAtomType):
                atom = Atom()
                atom.symbol = res.group(1)
                atom.charge = int(res.group(3))
                atom.primitives = int(res.group(4))
                atom.contracted = int(res.group(5))
                atom.basis = res.group(6)
                molecule.atomList.append(atom)
Esempio n. 2
0
	def __readSymmetry(self):
		self.__symmetries=[]
		check=['X','Y','Z','XY','XZ','YZ','XYZ']
		f = self.__infile
		f.toBOF()
		f.findString("&symmetry")
		if f.isAtEOF():
			# no symmetry section
			return
		line=f.readline()
			
		self.__symmetries=line.upper().split()

		for k in self.__symmetries:
			if k not in check:
				raise ParseError('Unknown symmetry key %s' % k, f.name,f.currentPos()+1)
	def __readBasis(self):
# {{{
		basOptions=[] # no options for now
		self.__basis={}
		f = self.__infile
		f.toBOF()
		linetuple=f.findRegexp("^\s*\[\s*basis.*\]\s*$")
		line=linetuple[0]
		if f.isAtEOF():
			# no basis section ? how weird
			return
		optionsDict = self.__buildOptionsDict(line,basOptions)
		
		regexp1 = re.compile("^\s*(\d*)\s+(.*)\s*$")
		regexp2 = re.compile("^\s*([a-zA-Z]\w*)\s+(.*)\s*$")
		regexp3 = re.compile("^\s*"+re.escape("*")+"\s+(.*)\s*$")
		line = f.readline()
		while not (f.isAtEOF() or line.strip()[0] == '['):
			line=string.strip(line)
			if line == '' or line[0] == "#":
				line = f.readline()
				continue
			match1 = regexp1.match(line)
			match2 = regexp2.match(line)
			match3 = regexp3.match(line)
			if match1 != None: # the assignment to an id
				theid = int(match1.group(1))
				if theid > len(self.__zmatrixparser.zmatrix()) or theid < 1:
					raise ParseError('Wrong id parameter %d' % int(theid), f.name,f.currentPos()+1)
				if not self.__basis.has_key(theid):
					self.__basis[theid]=match1.group(2)
			elif match2 != None:
				theatom = match2.group(1)
				list=[]
				for atom in self.__zmatrixparser:
					if atom[self.AtomListSymbol].lower() == theatom.lower():
						list.append(int(atom[self.AtomListId]))
				for i in list:
					if not self.__basis.has_key(i):
						self.__basis[i]=match2.group(2)
			elif match3 != None:
				#print "matched all"
				for i in xrange(1,len(self.__zmatrixparser.zmatrix())+1):
					if not self.__basis.has_key(i):
						self.__basis[i]=match3.group(1)
			line = f.readline()
Esempio n. 4
0
	def __readBasis(self):
		f = self.__infile
		f.toBOF()
		f.findString("&basis")
		if f.isAtEOF():
			# no basis section
			return
		# this re search for key = anything
		self.__basis={}
		
		regexp1 = re.compile("^\s*(\d*)\s+(.*)\s*$")
		regexp2 = re.compile("^\s*([a-zA-Z]\w*)\s+(.*)\s*$")
		regexp3 = re.compile("^\s*"+re.escape("*")+"\s+(.*)\s*$")
		line = f.readline()
		while not (f.isAtEOF() or line[0] == '&'):
			line=string.strip(line)
			if line == '' or line[0] == "#":
				line = f.readline()
				continue
			match1 = regexp1.match(line)
			match2 = regexp2.match(line)
			match3 = regexp3.match(line)
			if match1 != None: # the assignment to an id
				theid = int(match1.group(1))
				if theid > len(self.__zmatrix) or theid < 1:
					raise ParseError('Wrong id parameter %d' % int(theid), f.name,f.currentPos()+1)
				if not self.__basis.has_key(theid):
					self.__basis[theid]=match1.group(2)
			elif match2 != None:
				theatom = match2.group(1)
				list=[]
				for atom in self.__zmatrix:
					if atom[self.AtomListSymbol].lower() == theatom.lower():
						list.append(int(atom[self.AtomListId]))
				for i in list:
					if not self.__basis.has_key(i):
						self.__basis[i]=match2.group(2)
			elif match3 != None:
				#print "matched all"
				for i in xrange(1,len(self.__zmatrix)+1):
					if not self.__basis.has_key(i):
						self.__basis[i]=match3.group(1)
			line = f.readline()
	def __readSymmetry(self):
# {{{
		self.__symmetries=[]
		check=['X','Y','Z','XY','XZ','YZ','XYZ']
		f = self.__infile
		f.toBOF()
		linetuple=f.findRegexp("^\s*\[\s*symmetry.*\]\s*$")
		line=linetuple[0]
		if f.isAtEOF():
			# no symmetry section
			return
		symOptions=[] # no options for now
		optionsDict = self.__buildOptionsDict(line,symOptions)

		line=f.readline()
			
		self.__symmetries=line.upper().split()

		for k in self.__symmetries:
			if k not in check:
				raise ParseError('Unknown symmetry key %s' % k, f.name,f.currentPos()+1)
	def __readSymmetry(self):
		self.__symmetries=[]
		check=['X','Y','Z','XY','XZ','YZ','XYZ']
		f = self.__infile
		f.toBOF()
		f.findString("[symmetry")
		if f.isAtEOF():
			# no symmetry section
			return

		line=f.readline()
			
		while not (f.isAtEOF() or line[0] == '['):
			line=string.strip(line)
			if line == '' or line[0] == "#":
				line = f.readline()
				continue
			self.__symmetries=line.upper().split()

			for k in self.__symmetries:
				if k not in check:
					raise ParseError('Unknown symmetry key %s' % k, f.name,f.currentPos()+1)
			line=f.readline()
	def __cartesianCoords(self):
		cart=[]
		
		for currentAtom in self.__zmatrix:
			carttmp=[]
			if self.__zmatrix.index(currentAtom) == 0:
				# first atom, place in the center
				if self.__basis.has_key( int(currentAtom[self.AtomListId]) ):
					basis = self.__basis[ int(currentAtom[self.AtomListId] ) ]
				else:
					basis = ''
				#print '-> basis ',basis,' ', int(currentAtom[self.AtomListId]) 
				cart.append( (currentAtom[self.AtomListSymbol], Vector(0.0,0.0,0.0),  basis))
			elif self.__zmatrix.index(currentAtom) == 1:
				# the second atom. Place along the z axis at the bond distance
				if self.__basis.has_key( int(currentAtom[self.AtomListId]) ):
					basis = self.__basis[ int(currentAtom[self.AtomListId] ) ]
				else:
					basis = ''
				#print '-> basis ',basis,' ', int(currentAtom[self.AtomListId]) 
				cart.append( (currentAtom[self.AtomListSymbol], Vector(0.0, 0.0, float(currentAtom[self.AtomListBondValue])), basis))
			elif self.__zmatrix.index(currentAtom) == 2:
				# {{{
				# third atom. copy into a temporary buffer the cart position of 1 and 2
				# WARNING: atom 1 for zmatrix enumeration is element 0 in the cartesian list
				# so always decrease indexes by one. Also remember that zmatrix storagement is
				# per-string. Id's are strings, distances and angles too... always convert to
				# int or float to manage
				idx = int(currentAtom[self.AtomListBondId])-1
				carttmp.append( deepcopy(cart[idx]) )
				idx = int(currentAtom[self.AtomListAngleId])-1
				carttmp.append( deepcopy(cart[idx]) ) 
				# center the bond reference angle
				# now carttmp holds:
				# in position 0 the bond lenght reference atom
				# in position 1 the angle reference atom

				# choose the first atom and set as the center of the world
				# create a new tuple object with the cartesian parameters

				firstAtom=carttmp[0]
				firstAtomCoords=firstAtom[1]
				secondAtom=carttmp[1]
				secondAtomCoords=secondAtom[1]
				newcenter = (firstAtomCoords.x(), firstAtomCoords.y(), firstAtomCoords.z())
				# remember: newcenter is a tuple for xyz

				# translate each atom by carttmp
				for atom in carttmp:
					atom[1].translate(-newcenter[0],-newcenter[1],-newcenter[2])

				# keep the translated transformation, to revert it later

				translation=(newcenter[0],newcenter[1],newcenter[2])

				# done... now carttmp holds the translated elements.
				# please note that firstAtom and secondAtom are a reference in the
				# list carttmp, so they get updated too.
				# now work on the second atom, rotate the whole carttmp so to have
				# the second atom on z

				# the length of zy
				ryz=math.sqrt(secondAtomCoords.y()**2+secondAtomCoords.z()**2)
				if ryz > 1e-10:
					# the cosine of the angle
					rapp=secondAtomCoords.z()/ryz
					# choose the correct quadrant
					sign=1
					if secondAtomCoords.y() < 0:
						sign=-1
					xangle=sign*math.acos(rapp)
				else:
					if secondAtomCoords.y() < 0:
						xangle=math.pi
					else:
						xangle=0.0
					
				# now rotate along x
				for atom in carttmp[:]:
					atom[1].rotateX(-xangle)

				# do the same on the y axis
				# the lenght of xz
				rxz=math.sqrt(secondAtomCoords.x()**2+secondAtomCoords.z()**2)

				if rxz > 1e-10 :
					# the cosine of the angle
					rapp=secondAtomCoords.z()/rxz
					# choose the correct quadrant
					sign=1
					if secondAtomCoords.x() < 0:
						sign=-1
					yangle=sign*math.acos(rapp)
				else:
					if secondAtomCoords.x() < 0:
						yangle=math.pi
					else:
						yangle=0.0
	
				# now rotate along y
				for atom in carttmp:
					atom[1].rotateY(-yangle)
				
				# keep the rotation transformation close at hand, to revert it later
				rotation=(xangle, yangle, 0.0)
				
				# it's time to place our new atom

				vec=Vector(0.0, 0.0, float(currentAtom[self.AtomListBondValue]))
				angle=float(currentAtom[self.AtomListAngleValue])*math.pi/180
				vec.rotateX(angle)
				
				# ok.. time to backtransform and regain the position against the
				# original system. Rotate only the current atom vector, since
				# we no longer care about the other atoms.

				vec.rotateY(rotation[1])
				vec.rotateX(rotation[0])
				vec.translate(translation[0],translation[1],translation[2])

				# time to add the atom to our cartesian list
				if self.__basis.has_key( int(currentAtom[self.AtomListId]) ):
					basis = self.__basis[ int(currentAtom[self.AtomListId] ) ]
				else:
					basis = ''
				#print '-> basis ',basis,' ', int(currentAtom[self.AtomListId]) 
				cart.append( (currentAtom[self.AtomListSymbol], vec, basis))
				# }}}
			elif self.__zmatrix.index(currentAtom) >= 3:
				# {{{
				# ok... the same as for index = 2, plus the dihedral rotation
				# cut and paste of the previous section, stripped of the comments
				# should we merge with the previous case ?
				idx = int(currentAtom[self.AtomListBondId])-1
				carttmp.append( deepcopy(cart[idx]) )
				idx = int(currentAtom[self.AtomListAngleId])-1
				carttmp.append( deepcopy(cart[idx]) ) 

				# add the dihedral reference angle
				idx = int(currentAtom[self.AtomListDihedralId])-1
				carttmp.append( deepcopy(cart[idx]) ) 

				# now carttmp holds:
				# in position 2 the dihedral reference atom

				firstAtom=carttmp[0]
				firstAtomCoords=firstAtom[1]
				secondAtom=carttmp[1]
				secondAtomCoords=secondAtom[1]
				thirdAtom=carttmp[2]
				thirdAtomCoords=thirdAtom[1]
				newcenter = (firstAtomCoords.x(), firstAtomCoords.y(), firstAtomCoords.z())

				for atom in carttmp:
					atom[1].translate(-newcenter[0],-newcenter[1],-newcenter[2])

				translation=(newcenter[0],newcenter[1],newcenter[2])

				ryz=math.sqrt(secondAtomCoords.y()**2+secondAtomCoords.z()**2)
				if ryz > 1e-10:
					rapp=secondAtomCoords.z()/ryz
					sign=1
					if secondAtomCoords.y() < 0:
						sign=-1
					xangle=sign*math.acos(rapp)
				else:
					if secondAtomCoords.y() < 0:
						xangle=math.pi
					else:
						xangle=0.0
					
				for atom in carttmp:
					atom[1].rotateX(-xangle)

				rxz=math.sqrt(secondAtomCoords.x()**2+secondAtomCoords.z()**2)

				if rxz > 1e-10 :
					rapp=secondAtomCoords.z()/rxz
					sign=1
					if secondAtomCoords.x() < 0:
						sign=-1
					yangle=sign*math.acos(rapp)
				else:
					if secondAtomCoords.x() < 0:
						yangle=math.pi
					else:
						yangle=0.0
	
				for atom in carttmp:
					atom[1].rotateY(-yangle)
				# now we need to rotate the atoms along the z axis so the third
				# atom is on the yz plane

				rxy=math.sqrt(thirdAtomCoords.x()**2+thirdAtomCoords.y()**2)
				if rxy > 1e-10 :
					rapp=thirdAtomCoords.y()/rxy
					sign=1
					if thirdAtomCoords.x() < 0:
						sign=-1
					zangle=sign*math.acos(rapp)
				else:
					raise ParseError('Third atom %d is collinear with %d and %d at specification for atom %d' % (int(currentAtom[self.AtomListDihedralId]), int(currentAtom[self.AtomListBondId]), int(currentAtom[self.AtomListAngleId]), int(currentAtom[self.AtomListId])) ,None,None)
	
				for atom in carttmp:
					atom[1].rotateZ(-zangle)
				
				rotation=(xangle, yangle, zangle)

				# it's time to place our new atom

				vec=Vector(0.0, 0.0, float(currentAtom[self.AtomListBondValue]))
				angle=float(currentAtom[self.AtomListAngleValue])*math.pi/180
				vec.rotateX(angle)
				angle=float(currentAtom[self.AtomListDihedralValue])*math.pi/180
				vec.rotateZ(angle)

				vec.rotateZ(rotation[2])
				vec.rotateY(rotation[1])
				vec.rotateX(rotation[0])
				vec.translate(translation[0],translation[1],translation[2])
				if self.__basis.has_key( int(currentAtom[self.AtomListId]) ):
					basis = self.__basis[ int(currentAtom[self.AtomListId] ) ]
				else:
					basis = ''
				#print '-> basis ',basis,' ', int(currentAtom[self.AtomListId]) 

				cart.append( (currentAtom[self.AtomListSymbol], vec, basis))

		# }}}
				
		return cart
	def __readZMat(self):
		pt=ptable.PTable()
		self.__zmatrix=[]
		f = self.__infile
		currentRead=0

		f.toBOF()
		f.findString("[zmatrix")
		if f.isAtEOF():
			raise ParseError('Unable to find [zmatrix] section',f.name,f.currentPos()+1)

		line = f.readline()
		# AtomSymbol IdentifierNum [id distance [id angle [id dihedral]]]
		while not (f.isAtEOF() or line[0] == '['):
			line=string.strip(line)
			if line == '' or line[0] == "#":
				# the line is empty or a comment... skip
				line = f.readline()
				continue
			currentRead=currentRead+1

			# call the replacement function. It replaces occurences of parameters into the
			# zmatrix. btw.. what about this sub into the parameters list itself?

			line = self.__parseParameters(line)

			elems=line.split()
			expectedElems=currentRead*2
			if expectedElems > 8:
				expectedElems = 8

			if len(elems) != expectedElems:
					print line
					raise ParseError('Wrong format. Expected elements %d found %d' % (expectedElems, len(elems)),f.name,f.currentPos()+1)

			# parse the consistency of the line
			# does the atomtype exists?
			if pt.getElementBySymbol(elems[self.AtomListSymbol]) == None:
				raise ParseError('Unknown atom type %s' % elems[self.AtomListSymbol],f.name,f.currentPos()+1)
			
			# the current identifier must match the currentRead parameter
			try:
				theid=int(elems[self.AtomListId])
			except ValueError:
				raise ParseError('Non integer value as id at field 2' ,f.name,f.currentPos()+1)

			if int(elems[self.AtomListId]) != currentRead:
				raise ParseError('Error in identifier. Expected %d, found %d.' % (currentRead, int(elems[self.AtomListId])),f.name,f.currentPos()+1)

			# for each identifier  check if its' integer and lower than the
			# current identifier num (but greater than one! :)), and also if
			# the associated data is numeric
			temp=[]
			for i in range(2,expectedElems,2):
				try:
					theid=int(elems[i])
				except ValueError:
					raise ParseError('Non integer value as id at field %d' % (i+1) ,f.name,f.currentPos()+1)
				
				# check if there's no duplicated id in this line
				try:
					temp.index(theid)
				except ValueError:
					pass
				else:
					raise ParseError('Duplicated id at field %d' % (i+1) ,f.name,f.currentPos()+1)
				
				temp.append(theid)
				
				try:
					theval=float(elems[i+1])
				except ValueError:
					raise ParseError('Non numeric value given as parameter at field %d' % (i+2), f.name,f.currentPos()+1)
				
				if theid < 1 or theid >= currentRead:
					raise ParseError('Wrong id parameter at field %d' % (i+1), f.name,f.currentPos()+1)
				
			
			
			# ok... the line seems valid.
			# Pack the line in a tuple and add to an array
			
			self.__zmatrix.append(tuple(elems))
			#print tuple(elems)
			
			# new line and restart
			line = f.readline()
	def __readZMat(self):
		# {{{
		# the mighty parser object. He knows everything
		self.__zmatrixparser = zmatrixparser.ZMatrixParser()

		f = self.__infile

		f.toBOF()
		linetuple=f.findRegexp("^\s*\[\s*zmatrix.*\]\s*$")
		line=linetuple[0]
		if f.isAtEOF():
			raise ParseError('Unable to find [zmatrix] section',f.name,f.currentPos()+1)
		zmatOptions=("distanceunit", "angleunit", "dihedralunit", "format")
		optionsDict = self.__buildOptionsDict(line,zmatOptions)

		zmatrixbegin = f.currentPos()+1

		# {{{ check the distance unit flag
		if optionsDict.has_key('distanceunit'):
			if optionsDict['distanceunit'] == 'angstrom':
				self.__zmatrixparser.setDistanceUnit(zmatrixparser.ZMatrixParser.Unit_DistanceAngstrom)
			elif optionsDict['distanceunit'] == 'bohr':
				self.__zmatrixparser.setDistanceUnit(zmatrixparser.ZMatrixParser.Unit_DistanceBohr)
			else:
				raise ParseError('Unknown value for key distanceunit in [zmatrix] section',f.name,f.currentPos()+1)
		else:
			self.__zmatrixparser.setDistanceUnit(zmatrixparser.ZMatrixParser.Unit_DistanceBohr)
		# }}}
		# {{{ check the angle unit flag
		if optionsDict.has_key('angleunit'):
			if optionsDict['angleunit'] == 'radians':
				self.__zmatrixparser.setAngleUnit(zmatrixparser.ZMatrixParser.Unit_AngleRadians)
			elif optionsDict['angleunit'] == 'degrees':
				self.__zmatrixparser.setAngleUnit(zmatrixparser.ZMatrixParser.Unit_AngleDegrees)
			else:
				raise ParseError('Unknown value for key angleunit in [zmatrix] section',f.name,f.currentPos()+1)
		else:
			self.__zmatrixparser.setAngleUnit(zmatrixparser.ZMatrixParser.Unit_AngleDegrees)
		# }}}
		# {{{ check the dihedral unit flag
		if optionsDict.has_key('dihedralunit'):
			if optionsDict['dihedralunit'] == 'radians':
				self.__zmatrixparser.setDihedralUnit(zmatrixparser.ZMatrixParser.Unit_DihedralRadians)
			elif optionsDict['dihedralunit'] == 'degrees':
				self.__zmatrixparser.setDihedralUnit(zmatrixparser.ZMatrixParser.Unit_DihedralDegrees)
			else:
				raise ParseError('Unknown value for key dihedralunit in [zmatrix] section',f.name,f.currentPos()+1)
		else:
			self.__zmatrixparser.setDihedralUnit(zmatrixparser.ZMatrixParser.Unit_DihedralDegrees)
		# }}}
		# {{{ check the format flag
		if optionsDict.has_key('format'):
			if optionsDict['format'] == 'internal':
				self.__zmatrixparser.setFormat(zmatrixparser.ZMatrixParser.Format_Internal)
			elif optionsDict['format'] == 'gaussian':
				self.__zmatrixparser.setFormat(zmatrixparser.ZMatrixParser.Format_Gaussian)
			elif optionsDict['format'] == 'dalton':
				self.__zmatrixparser.setFormat(zmatrixparser.ZMatrixParser.Format_Dalton)
			else:
				raise ParseError('Unknown value for key format in [zmatrix] section',f.name,f.currentPos()+1)
		else:
			self.__zmatrixparser.setFormat(zmatrixparser.ZMatrixParser.Format_Internal)
		# }}}

		zmat=[]
		line = f.readline().strip()
		while not (f.isAtEOF() or line[0] == '['):
			if line == '' or line[0] == "#":
				# the line is empty or a comment... skip
				line = f.readline().strip()
				continue

			# call the replacement function. It replaces occurences of 
			# parameters into the zmatrix.

			line = self.__parseParameters(line)

			# append the line in a tuple that will be fed into our parser object
			zmat = zmat + [line]
			line = f.readline().strip()

		try:
			self.__zmatrixparser.parse(zmat)
		except ZMatrixParser.ParseException, e:
			raise ParseError('Error type %d in [zmatrix] section: %s' % (e.code, e.message),f.name,zmatrixbegin+e.line+1)
Esempio n. 10
0
    def __getVibrational(self):
        """ 
		parse and read the vibrational section for the current molecule.
		Note that the format of this section in dalton 1.2 is

		            Eigenvalues of mass-weighted Hessian
		            ------------------------------------
		
		
		        Column   1     Column   2     Column   3     Column   4
		1     1.279649E-42   1.279649E-42   4.094095E-04   9.790871E-44
		
		        Column   5     Column   6
		1     9.790871E-44  -1.212226E-21
		
		
		           Normal coordinates in Cartesian basis
		           -------------------------------------
		
		
		        Column   1     Column   2     Column   3     Column   4
		1       0.02333068     0.00000000     0.00000000     0.00000000
		2       0.00000000     0.02333068     0.00000000     0.00000000
		3       0.00000000     0.00000000     0.02273544     0.00000000
		4       0.00000000     0.00000000     0.00000000     0.00537355
		6       0.00000000     0.00000000    -0.00120607     0.00000000
		
		        Column   5     Column   6
		3       0.00000000     0.00523645
		5       0.00537355     0.00000000
		6       0.00000000     0.00523645
	
		So note that
		- informations are represented in blocks of 4 columns at a time.
		- rows which have zero values for each column aren't written
		"""

        file = self.__fd
        file.toEOF()
        line = file.findString("Eigenvalues of mass-weighted Hessian", 1, 1)
        if line == '':
            return
        file.skipLines(4)

        degOfFreedom = self.__molecule.numOfAtoms * 3
        # in the above example, 2 blocks, one made with 4 columns,
        # the other made of 2 columns
        numOfBlocks = (degOfFreedom + 3) / 4
        # how many columns make the last block, in the above case 2
        # (the columns 5 and 6)
        lastLineEntries = degOfFreedom % 4
        if lastLineEntries == 0:
            lastLineEntries = 4

        eigenvalues = []
        for i in xrange(0, numOfBlocks):
            columns = 4
            if i == numOfBlocks - 1:  # is the last block
                columns = lastLineEntries
            restring = "^\s+\d*\s+"
            for j in xrange(0, columns):
                restring = restring + "(-?\d\.\d+[DdEe][+-]\d\d)"
                if j == columns - 1:
                    restring = restring + "\s*$"
                else:
                    restring = restring + "\s+"

            regexp = re.compile(restring)
            line = file.readline()
            res = regexp.search(line)
            transl = string.maketrans('dD', 'ee')
            for j in xrange(0, columns):
                eigenvalues.append(
                    float(string.translate(res.group(j + 1), transl)))
            file.skipLines(2)

        # get the normal modes

        line = file.findString("Normal coordinates in Cartesian basis")
        if line == '':
            raise ParseError(
                "Unable to find keyword 'Normal coordinates in Cartesian basis'"
            )

        file.skipLines(4)

        eigenvectors = []
        for i in xrange(0, numOfBlocks):
            columns = 4
            eig = []
            if i == numOfBlocks - 1:  # is the last block
                columns = lastLineEntries
            restring = "^\s+(\d+)\s+"
            for j in xrange(0, columns):
                restring = restring + "(-?\d\.\d+)"
                if j == columns - 1:
                    restring = restring + "\s*$"
                else:
                    restring = restring + "\s+"

            regexp = re.compile(restring)
            for j in xrange(0, columns):
                eig.append([])

            lastExistingEntry = 0
            j = 0
            while j < degOfFreedom:
                line = file.readline()
                res = regexp.search(line)
                if res == None:
                    # this means that we are at the end but some of the
                    # remaining data misses 'cause they are zero
                    for k in xrange(lastExistingEntry, degOfFreedom):
                        for l in xrange(0, columns):
                            eig[l].append(0.0)
                    break
                else:
                    if int(res.group(1)) != j + 1:
                        # a number was skipped in the dalton printout,
                        # because the printing routine automatically
                        # eat lines with all zeroes. We need the zeroes,
                        # so we take control over the line-by-line reading
                        # routine and place the missing zeroes
                        for k in xrange(lastExistingEntry + 1,
                                        int(res.group(1))):
                            for l in xrange(0, columns):
                                eig[l].append(0.0)
                            j = j + 1
                    for l in xrange(0, columns):
                        eig[l].append(
                            float(string.translate(res.group(l + 2), transl)))
                    lastExistingEntry = int(res.group(1))
                    j = j + 1

            # finished reading the block... put the eigenvectors
            # in the array
            for l in xrange(0, columns):
                eigenvectors.append(eig[l])
            # and step to the next block
            file.skipLines(2)

        # pack them into normalMode objects

        for i in xrange(0, degOfFreedom):
            normalmode = NormalMode()
            normalmode.frequency = math.sqrt(abs(eigenvalues[i]))
            if eigenvalues[i] < 0:
                normalmode.frequency = -normalmode.frequency
            normalmode.coordinates = eigenvectors[i]
            self.__molecule.normalModeList.append(normalmode)

        # sort the NormalMode list

        self.__molecule.normalModeList.sort(normalModeSort)
Esempio n. 11
0
    def __getGeometry(self):

        # get the starting geometry
        file = self.__fd
        file.toBOF()
        ret = file.findString("Cartesian Coordinates")
        if ret == '':
            raise ParseError("Keyword not found 'Cartesian Coordinates'")
        file.skipLines(5)
        # catches    1   O        x      0.0000000000
        # and also   7   H    1   x      0.0000000000
        regexp1 = re.compile("^\s+\d+\s+.+\s+.+\s+x\s+(-?\d+\.\d+)\s*")
        # catches    2            y      0.0000000000
        regexp2 = re.compile("^\s+\d+\s+[yz]\s*(-?\d+\.\d+)\s*")
        geometry = Geometry()
        self.__molecule.geometryList.append(geometry)
        for i in xrange(0, self.__molecule.numOfAtoms):
            pos = Position()

            line = file.readline()
            res = regexp1.search(line)
            pos.x = float(res.group(1))

            line = file.readline()
            res = regexp2.search(line)
            pos.y = float(res.group(1))

            line = file.readline()
            res = regexp2.search(line)
            pos.z = float(res.group(1))

            geometry.posList.append(pos)

            file.readline()

        # get the energy

        ret = file.findRegexp("^\s*Final\s+.*\senergy:\s*(-\d+\.\d+)\s*$")

        if ret[0] == '':
            raise ParseError('No Final energy in this output')

        geometry.energy = float(ret[1][0])

        # try to get other geometries from the optimization

        save = file.currentPos()
        ret = file.findString("Next geometry (au)")
        if ret == '':
            # there are no other geometries
            return
        file.toPos(save)

        geolist = file.occurrences("Next geometry (au)")

        for i in geolist:
            file.toPos(i)
            file.skipLines(2)
            regexp = re.compile(
                "^\s+.*\s+\d*\s+(-?\d+\.\d+)\s+(-?\d+\.\d+)\s+(-?\d+\.\d+)\s*$"
            )
            geometry = Geometry()
            self.__molecule.geometryList.append(geometry)
            for j in xrange(0, self.__molecule.numOfAtoms):
                pos = Position()
                line = file.readline()
                res = regexp.search(line)
                pos.x = float(res.group(1))
                pos.y = float(res.group(2))
                pos.z = float(res.group(3))
                geometry.posList.append(pos)
            # catch the subsequent energy
            ret = file.findRegexp("^\s*Final\s+.*\senergy:\s*(-\d+\.\d+)\s*$")
            if ret[0] == '':
                raise ParseError(
                    'No Final energy in this output during optimization, pos %d'
                    % i)

            geometry.energy = float(ret[1][0])