Beispiel #1
0
    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:])
Beispiel #2
0
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)
Beispiel #3
0
 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()
Beispiel #4
0
 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)
Beispiel #5
0
 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)
Beispiel #6
0
 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)
Beispiel #7
0
    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)
Beispiel #8
0
 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()
Beispiel #9
0
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
Beispiel #10
0
 def read(self):
     self.mol.read_from_xyzc(filename=self.filename)
     self.modes = VibModes(self.mol.nmodes, self.mol)
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
 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()
Beispiel #16
0
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