Beispiel #1
0
    def get_gradient(self, b):
        energy = self.get_energy(b)
        Fmoa = simx(self.Fa, self.orbsa)
        Fmob = simx(self.Fb, self.orbsb)

        bp = zeros(2 * self.nbf, 'd')

        for g in xrange(self.nbf):
            # Transform Gij[g] to MOs. This is done over the whole
            #  space rather than just the parts we need. I can speed
            #  this up later by only forming the i,a elements required
            Gmo = simx(self.Gij[g], self.orbsa)

            # Now sum the appropriate terms to get the b gradient
            for i in xrange(self.nalpha):
                for a in xrange(self.nalpha, self.norb):
                    bp[g] += Fmoa[i, a] * Gmo[i, a] / (self.orbea[i] -
                                                       self.orbea[a])

        for g in xrange(self.nbf):
            # Transform Gij[g] to MOs. This is done over the whole
            #  space rather than just the parts we need. I can speed
            #  this up later by only forming the i,a elements required
            Gmo = simx(self.Gij[g], self.orbsb)

            # Now sum the appropriate terms to get the b gradient
            for i in xrange(self.nbeta):
                for a in xrange(self.nbeta, self.norb):
                    bp[self.nbf +
                       g] += Fmob[i, a] * Gmo[i, a] / (self.orbeb[i] -
                                                       self.orbeb[a])

        #logging.debug("EXX  Grad: %10.5f" % (sqrt(dot(bp,bp))))
        return bp
def propagate_dm(D, F, dt, **kwargs):

    _prop_ = 'padme'
    method = kwargs.get('method')

    if method == 'relax':

        # direct diagonalization
        if _prop_ == 'direct':
            '''
			Warning : That doesn't work so well
			But I don't know why
			'''
            lambda_F, U_F = scla.eig(F)

            v = np.exp(1j * dt * lambda_F)
            df = np.diag(simx(D, U_F, 'N'))
            prod = np.diag(v * df * np.conj(v))
            Dq = simx(prod, U_F, 'T')

        # padde approximation
        if _prop_ == 'padme':

            U = expm(1j * F * dt)
            D = np.dot(U, np.dot(D, np.conj(U.T)))
            #print D

    else:
        print 'Propagation method %s not regognized' % method
        sys.exit()

    return D
Beispiel #3
0
    def get_gradient(self,b):
        energy = self.get_energy(b)
        Fmoa = simx(self.Fa,self.orbsa)
        Fmob = simx(self.Fb,self.orbsb)

        bp = zeros(2*self.nbf,'d')

        for g in range(self.nbf):
            # Transform Gij[g] to MOs. This is done over the whole
            #  space rather than just the parts we need. I can speed
            #  this up later by only forming the i,a elements required
            Gmo = simx(self.Gij[g],self.orbsa)

            # Now sum the appropriate terms to get the b gradient
            for i in range(self.nalpha):
                for a in range(self.nalpha,self.norb):
                    bp[g] += Fmoa[i,a]*Gmo[i,a]/(self.orbea[i]-self.orbea[a])

        for g in range(self.nbf):
            # Transform Gij[g] to MOs. This is done over the whole
            #  space rather than just the parts we need. I can speed
            #  this up later by only forming the i,a elements required
            Gmo = simx(self.Gij[g],self.orbsb)

            # Now sum the appropriate terms to get the b gradient
            for i in range(self.nbeta):
                for a in range(self.nbeta,self.norb):
                    bp[self.nbf+g] += Fmob[i,a]*Gmo[i,a]/(self.orbeb[i]-self.orbeb[a])

        #logging.debug("EXX  Grad: %10.5f" % (sqrt(dot(bp,bp))))
        return bp
Beispiel #4
0
 def testOrthog(self):
     from PyQuante.LA2 import CanOrth, SymOrth, CholOrth, simx
     from PyQuante.NumWrap import eigh
     solver = SCF(h2, method="HF")
     h, S = solver.h, solver.S
     X1 = CanOrth(S)
     X2 = SymOrth(S)
     X3 = CholOrth(S)
     h1 = simx(h, X1)
     ha = simx(h, X2)
     h3 = simx(h, X3)
     e1, v1 = eigh(h1)
     e2, v2 = eigh(ha)
     e3, v3 = eigh(h3)
     self.assertAlmostEqual(e1[0], e2[0], 6)
     self.assertAlmostEqual(e1[0], e3[0], 6)
Beispiel #5
0
 def testOrthog(self):
     from PyQuante.LA2 import CanOrth, SymOrth, CholOrth, simx
     from PyQuante.NumWrap import eigh
     solver = SCF(h2,method="HF")
     h,S = solver.h, solver.S
     X1 = CanOrth(S)
     X2 = SymOrth(S)
     X3 = CholOrth(S)
     h1 = simx(h,X1)
     ha = simx(h,X2)
     h3 = simx(h,X3)
     e1,v1 = eigh(h1)
     e2,v2 = eigh(ha)
     e3,v3 = eigh(h3)
     self.assertAlmostEqual(e1[0],e2[0],6)
     self.assertAlmostEqual(e1[0],e3[0],6)
Beispiel #6
0
def geigh(H,A,**opts):
    """\
    Generalized eigenproblem using a symmetric matrix H.
    """
    X = SymOrthCutoff(A)
    val,vec = eigh(simx(H,X))
    vec = matrixmultiply(X,vec)
    return val,vec
Beispiel #7
0
def geigh(H, A, **opts):
    """\
    Generalized eigenproblem using a symmetric matrix H.
    """
    X = SymOrthCutoff(A)
    val, vec = eigh(simx(H, X))
    vec = matrixmultiply(X, vec)
    return val, vec
Beispiel #8
0
    def get_gradient(self,b):
        energy = self.get_energy(b)
        Fmo = simx(self.F,self.orbs)
        bp = zeros(self.nbf,'d')

        for g in xrange(self.nbf):
            # Transform Gij[g] to MOs. This is done over the whole
            #  space rather than just the parts we need. I can speed
            #  this up later by only forming the i,a elements required
            Gmo = simx(self.Gij[g],self.orbs)

            # Now sum the appropriate terms to get the b gradient
            for i in xrange(self.nclosed):
                for a in xrange(self.nclosed,self.norb):
                    bp[g] = bp[g] + Fmo[i,a]*Gmo[i,a]/(self.orbe[i]-self.orbe[a])

        #logging.debug("EXX  Grad: %10.5f" % (sqrt(dot(bp,bp))))
        return bp
Beispiel #9
0
 def iterate(self):
     for self.iter in xrange(self.maxit):
         if self.converged(): break
         self.update()
         self.print_iter_info()
     self.print_iter_end_info()
     if self.do_orth:
         self.D = simx(self.D, self.X, 'T')
     return
Beispiel #10
0
 def iterate(self):
     for self.iter in xrange(self.maxit):
         if self.converged(): break
         self.update()
         self.print_iter_info()
     self.print_iter_end_info()
     if self.do_orth:
         self.D = simx(self.D,self.X,'T')
     return
Beispiel #11
0
def compute_F(P, Hcore, X, Ints, mu=0):

    # get the matrix of 2J-K for a given fixed P
    # P is here given in the non- orthonormal basis
    G = get2JmK(Ints, P)

    # pass the G matrix in the orthonormal basis
    Gp = simx(G, X, 'T')

    # form the Fock matrix in the orthonomral basis
    F = Hcore + _ee_inter_ * Gp + mu

    return F
Beispiel #12
0
 def solve(self, H, **kwargs):
     from PyQuante.LA2 import mkdens_spinavg, simx, geigh
     from PyQuante.NumWrap import matrixmultiply, eigh
     if self.first_iteration:
         self.first_iteration = False
         self.orbe, self.orbs = geigh(H, self.S)
     else:
         Ht = simx(H, self.orbs)
         if self.pass_nroots:
             self.orbe, orbs = self.solver(Ht, self.nroots)
         else:
             self.orbe, orbs = self.solver(Ht)
         self.orbs = matrixmultiply(self.orbs, orbs)
     self.D = mkdens_spinavg(self.orbs, self.nclosed, self.nopen)
     self.entropy = 0
     return self.D, self.entropy
Beispiel #13
0
 def solve(self,H,**opts):
     from PyQuante.LA2 import mkdens_spinavg,simx,geigh
     from PyQuante.NumWrap import matrixmultiply,eigh
     if self.first_iteration:
         self.first_iteration = False
         self.orbe,self.orbs = geigh(H,self.S)
     else:
         Ht = simx(H,self.orbs)
         if self.pass_nroots:
             self.orbe,orbs = self.solver(Ht,self.nroots)
         else:
             self.orbe,orbs = self.solver(Ht)
         self.orbs = matrixmultiply(self.orbs,orbs)
     self.D = mkdens_spinavg(self.orbs,self.nclosed,self.nopen)
     self.entropy = 0
     return self.D,self.entropy
Beispiel #14
0
    def __init__(self, F, Ne, S=None, **opts):
        self.tol = opts.get('tol', 1e-7)
        self.maxit = opts.get('maxit', 100)
        self.do_orth = S is not None

        self.N = F.shape[0]
        self.I = identity(self.N, 'd')
        self.Ne = Ne

        if self.do_orth:
            self.X = SymOrth(S)
            self.F = simx(F, self.X)

        self.emin, self.emax = gershgorin_minmax(self.F)
        self.initialize()
        self.print_init_info()
        return
Beispiel #15
0
    def __init__(self, F, Ne, S=None, **kwargs):
        self.tol = kwargs.get('tol', settings.DMPTolerance)
        self.maxit = kwargs.get('maxit', settings.DMPIterations)
        self.do_orth = S is not None

        self.N = F.shape[0]
        self.I = identity(self.N, 'd')
        self.Ne = Ne

        if self.do_orth:
            self.X = SymOrth(S)
            self.F = simx(F, self.X)

        self.emin, self.emax = gershgorin_minmax(self.F)
        self.initialize()
        self.print_init_info()
        return
Beispiel #16
0
    def __init__(self,F,Ne,S=None,**kwargs):
        self.tol = kwargs.get('tol',settings.DMPTolerance)
        self.maxit = kwargs.get('maxit',settings.DMPIterations)
        self.do_orth = S is not None

        self.N = F.shape[0]
        self.I = identity(self.N,'d')
        self.Ne = Ne

        if self.do_orth:
            self.X = SymOrth(S)
            self.F = simx(F,self.X)

        self.emin, self.emax = gershgorin_minmax(self.F)
        self.initialize()
        self.print_init_info()
        return
Beispiel #17
0
    def __init__(self,F,Ne,S=None,**opts):
        self.tol = opts.get('tol',1e-7)
        self.maxit = opts.get('maxit',100)
        self.do_orth = S is not None

        self.N = F.shape[0]
        self.I = identity(self.N,'d')
        self.Ne = Ne

        if self.do_orth:
            self.X = SymOrth(S)
            self.F = simx(F,self.X)

        self.emin, self.emax = gershgorin_minmax(self.F)
        self.initialize()
        self.print_init_info()
        return
Beispiel #18
0
def SymOrthCutoff(S, scut=1e-5):
    """Symmetric orthogonalization of the real symmetric matrix S.
    This is given by Ut(1/sqrt(lambda))U, where lambda,U are the
    eigenvalues/vectors.

    Only eigenvectors with eigenvalues greater that a cutoff are kept.
    This approximation is useful in cases where the basis set has
    linear dependencies.
    """
    val, vec = eigh(S)
    n = vec.shape[0]
    shalf = identity(n, 'd')
    for i in range(n):
        if val[i] > scut:
            shalf[i, i] /= sqrt(val[i])
        else:
            shalf[i, i] = 0.
    X = simx(shalf, vec, 'T')
    return X
Beispiel #19
0
def SymOrthCutoff(S,scut=1e-5):
    """Symmetric orthogonalization of the real symmetric matrix S.
    This is given by Ut(1/sqrt(lambda))U, where lambda,U are the
    eigenvalues/vectors.

    Only eigenvectors with eigenvalues greater that a cutoff are kept.
    This approximation is useful in cases where the basis set has
    linear dependencies.
    """
    val,vec = eigh(S)
    n = vec.shape[0]
    shalf = identity(n,'d')
    for i in range(n):
        if val[i] > scut:
            shalf[i,i] /= sqrt(val[i])
        else:
            shalf[i,i] = 0.
    X = simx(shalf,vec,'T')
    return X
Beispiel #20
0
def ao2mo(M, C):
    return simx(M, C)
Beispiel #21
0
def pyq1_rohf(atomtuples=[(2, (0, 0, 0))], basis='6-31G**', maxit=10, mult=3):
    from PyQuante import Ints, settings, Molecule
    from PyQuante.hartree_fock import get_energy
    from PyQuante.MG2 import MG2 as MolecularGrid
    from PyQuante.LA2 import mkdens, geigh, trace2, simx
    from PyQuante.Ints import getJ, getK

    print("PyQ1 ROHF run")
    atoms = Molecule('Pyq1', atomlist=atomtuples, multiplicity=mult)

    bfs = Ints.getbasis(atoms, basis=basis)
    S, h, I2e = Ints.getints(bfs, atoms)

    nbf = norbs = len(bfs)
    nel = atoms.get_nel()

    nalpha, nbeta = atoms.get_alphabeta()

    enuke = atoms.get_enuke()
    orbe, orbs = geigh(h, S)
    eold = 0

    for i in range(maxit):
        Da = mkdens(orbs, 0, nalpha)
        Db = mkdens(orbs, 0, nbeta)
        Ja = getJ(I2e, Da)
        Jb = getJ(I2e, Db)
        Ka = getK(I2e, Da)
        Kb = getK(I2e, Db)

        Fa = h + Ja + Jb - Ka
        Fb = h + Ja + Jb - Kb
        energya = get_energy(h, Fa, Da)
        energyb = get_energy(h, Fb, Db)
        eone = (trace2(Da, h) + trace2(Db, h)) / 2
        etwo = (trace2(Da, Fa) + trace2(Db, Fb)) / 2
        energy = (energya + energyb) / 2 + enuke
        print(i, energy, eone, etwo, enuke)
        if abs(energy - eold) < 1e-5: break
        eold = energy

        Fa = simx(Fa, orbs)
        Fb = simx(Fb, orbs)
        # Building the approximate Fock matrices in the MO basis
        F = 0.5 * (Fa + Fb)
        K = Fb - Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0, nbeta)
        so = slice(nbeta, nalpha)
        uo = slice(nalpha, norbs)
        F[do, do] -= K[do, do]
        F[uo, uo] += K[uo, uo]
        F[do, so] += 0.5 * K[do, so]
        F[so, do] += 0.5 * K[so, do]
        F[so, uo] -= 0.5 * K[so, uo]
        F[uo, so] -= 0.5 * K[uo, so]

        orbe, mo_orbs = np.linalg.eigh(F)
        orbs = np.dot(orbs, mo_orbs)
    return energy, orbe, orbs
Beispiel #22
0
def main(argv):

    parser = argparse.ArgumentParser(
        description='Hartree Fock Calculation from scratch')

    # molecule information
    parser.add_argument('mol', help='xyz file of the molecule', type=str)
    parser.add_argument('-basis',
                        default='sto-3g',
                        help='basis set to be used in the calculation',
                        type=str)
    parser.add_argument('-charge',
                        default=0,
                        help='Charge of the system',
                        type=float)
    parser.add_argument('-units',
                        default='angs',
                        help='Units in the xyz file',
                        type=str)

    # HF calculations
    parser.add_argument('-MaxIter',
                        default=100,
                        help='Maximum number of SCF iterations',
                        type=int)
    parser.add_argument('-eps_SCF',
                        default=1E-4,
                        help='Criterion for SCF termination',
                        type=float)

    # field information
    parser.add_argument('-ffreq',
                        default=0.1,
                        help='Frequency of the field',
                        type=float)
    parser.add_argument('-fint',
                        default=0.05,
                        help='Intensity of the field',
                        type=float)
    parser.add_argument('-ft0',
                        default=0.5,
                        help='center of the field for gsin',
                        type=float)
    parser.add_argument('-fsigma',
                        default=0.25,
                        help='sigma of the field for gsin',
                        type=float)
    parser.add_argument('-fform', default='sin', help='field form', type=str)
    parser.add_argument('-fdir',
                        default='x',
                        help='direction of the field',
                        type=str)

    # Propagation
    parser.add_argument('-tmax',
                        default=200,
                        help='maximum evolution time',
                        type=float)
    parser.add_argument('-nT',
                        default=200,
                        help='number of time step',
                        type=int)
    parser.add_argument('-time_unit',
                        default='au',
                        help='unit of tmax',
                        type=str)

    # export
    parser.add_argument('-nb_print_mo',
                        default=10,
                        help='Number of orbitals to be written',
                        type=int)
    '''
	Possible basis
	'3-21g' 'sto3g' 'sto-3g' 'sto-6g'
	'6-31g' '6-31g**' '6-31g(d,p)' '6-31g**++' '6-31g++**' '6-311g**' '6-311g++(2d,2p)'
    '6-311g++(3d,3p)' '6-311g++(3df,3pd)'
    'lacvp'
    
    'ccpvdz' 'cc-pvdz' 'ccpvtz' 'cc-pvtz' 'ccpvqz' 'cc-pvqz' 'ccpv5z' 'cc-pv5z' 'ccpv6z' 'cc-pv6z'

    'augccpvdz' 'aug-cc-pvdz' 'augccpvtz' 'aug-cc-pvtz' 'augccpvqz'
    'aug-cc-pvqz' 'augccpv5z' 'aug-cc-pv5z' 'augccpv6z' 'aug-cc-pv6z'    
    'dzvp':'dzvp',

	'''

    # done
    args = parser.parse_args()

    print '\n\n=================================================='
    print '== PyQuante - Time-dependent hartree-fock       =='
    print '==================================================\n'

    #-------------------------------------------------------------------------------------------
    #
    #									PREPARE SIMULATIONS
    #
    #-------------------------------------------------------------------------------------------

    ##########################################################
    ##					Read Molecule
    ##########################################################

    # read the xyz file of the molecule
    print '\t Read molecule position'

    f = open(args.mol, 'r')
    data = f.readlines()
    f.close

    # get the molecule name
    name_mol = re.split(r'\.|/', args.mol)[-2]

    # create the molecule object
    xyz = []
    for i in range(2, len(data)):
        d = data[i].split()
        xyz.append((d[0], (float(d[1]), float(d[2]), float(d[3]))))

    natom = len(xyz)
    mol = Molecule(name=name_mol, units=args.units)
    mol.add_atuples(xyz)
    mol.set_charge(args.charge)
    nelec = mol.get_nel()

    if np.abs(args.charge) == 1:
        mol.set_multiplicity(2)
    if args.charge > 1:
        print 'charge superior to one are not implemented'

    # get the basis function
    bfs = getbasis(mol, args.basis)
    nbfs = len(bfs)
    nclosed, nopen = mol.get_closedopen()
    nocc = nclosed
    print '\t\t Molecule %s' % args.mol
    print '\t\t Basis %s' % args.basis
    print '\t\t %d basis functions' % (nbfs)

    if _print_basis_:
        for i in range(nbfs):
            print bfs[i]

    # compute all the integrals
    print '\n\t Compute the integrals and form the matrices'
    S, Hcore, Ints = getints(bfs, mol)

    print '\t Compute the transition dipole moments'
    mu_at = compute_dipole_atoms(bfs, args.fdir)

    ##########################################################
    ##			Compute the HF GROUND STATE
    ##########################################################

    print '\n\t Compute the ground state HF Ground State\n\t',
    print '-' * 50
    L, C, Cp, F0, F0p, D, Dp, P, X = rhf(mol,
                                         bfs,
                                         S,
                                         Hcore,
                                         Ints,
                                         MaxIter=args.MaxIter,
                                         eps_SCF=args.eps_SCF)

    print '\t Energy of the HF orbitals\n\t',
    print '-' * 50
    index_homo = nocc - 1
    nb_print = int(min(nbfs, args.nb_print_mo) / 2)
    for ibfs in range(index_homo - nb_print + 1, index_homo + nb_print + 1):
        print '\t\t orb %02d \t occ %1.1f \t\t Energy %1.3f Ha' % (
            ibfs, np.abs(2 * P[ibfs, ibfs].real), L[ibfs].real)

    # store the field free eigenstates
    C0 = np.copy(C)
    C0p = np.copy(Cp)

    # invert of the X matrix
    Xm1 = np.linalg.inv(X)

    ##########################################################
    ##		Transform the matrices in the OB
    ##########################################################

    # pass the other matrices as well
    Hcore_p = simx(Hcore, X, 'T')
    mu_at_p = simx(mu_at, X, 'T')

    # copy the Fock matrix
    Fp = np.copy(F0p)

    # transtion matrix at t=0
    mup = mu_at_p

    # check if everythong is ok
    if _check_ortho_:
        w, u = np.linalg.eigh(F0p)
        if np.sum(np.abs(w - L)) > 1E-3:
            print '\t == Warning orthonormalisation issue'
            sys.exit()

    #-------------------------------------------------------------------------------------------
    #
    #						TEST IF EVERYTHING IS OF SO FAR
    #
    #-------------------------------------------------------------------------------------------

    # verify the basis transformation between
    # Atomic Orbitals and Orthonormal orbitals
    #
    if _test_:

        print '\n\t Run Check on the matrices'

        #print'\n'
        #print'='*40
        print '\t\t Verify the basis transformation from diagonal to AO basis ',

        x = np.dot(np.diag(L), np.linalg.inv(C))
        x = np.dot(C, x)
        x = np.dot(S, x)

        if np.abs(np.sum(x - F0)) < 1E-3:
            print '\t Check'
        else:
            print '\t NOT OK'
        #print'='*40

        if _verbose_:
            print '\t\t reconstructed Fock matrix'
            print x
            print '\t\t original Fock matrix'
            print F0

        #print'\n\t'
        #print'='*40
        print '\t\t Verify the basis transformation from AO to diagonal basis ',

        y = np.dot(F0, C)
        y = np.dot(np.linalg.inv(S), y)
        y = np.dot(np.linalg.inv(C), y)

        if np.abs(np.sum(y - np.diag(L))) < 1E-3:
            print '\t Check'
        else:
            print '\t NOT OK'

        #print'='*40

        if _verbose_:
            print '\t\t reconstructed eigenvalues'
            print y
            print '\t\t original eigenvalues'
            print L

    #
    # verify the basis transformation between
    # Atomic Orbitals and Orthonormal orbitals
    #
    if _test_:
        #print'\n'
        #print'='*40
        print '\t\t Verify the basis transformation from AO basis to ORTHO basis ',
        #print'='*40

        if np.abs(np.sum(D - np.dot(X, np.dot(Dp, X.T)))) < 1E-3:
            print '\t Check'
        else:
            print '\t NOT OK'

        if _verbose_:
            print '\t\t reconstructed density in the AO'
            print np.dot(X, np.dot(Dp, X.T))
            print '\t\t Original density in the AO'
            print D

    #
    # verify the basis transformation between
    # Atomic Orbitals and Orthonormal orbitals
    #
    if _test_:
        #print'\n'
        #print'='*40
        print '\t\t Verify the basis transformation from AO basis to ORTHO basis ',
        #print'='*40

        if np.abs(np.sum(Dp - np.dot(Xm1, np.dot(D, Xm1.T)))) < 1E-3:
            print '\t Check'
        else:
            print '\t NOT OK'

        if _verbose_:
            print '\t\t reconstructed density in the OB'
            print np.dot(Xm1, np.dot(D, Xm1.T))
            print '\t\t original density in the OB'
            print Dp

    # test if the Fock matrix and densitu matrix in OB
    # share the same eigenbasis
    # due to degeneracies in the density matrix only a few
    # eigenvectors might be the same
    if _verbose_:
        print '\t\t verify that the Fock matrix and the density matrix '
        print '\t\t in the ORTHOGONAL BASIS have the same eigenvector',

        lf, cf = scla.eigh(F0p)
        r = 1E-6 * np.random.rand(nbfs, nbfs)
        r += r.T
        ld, cd = scla.eigh(Dp + r)

        x1 = simx(Dp, cf, 'N')
        x2 = simx(F0p, cd, 'N')

        s1 = np.sum(np.abs(x1 - np.diag(np.diag(x1))))
        s2 = np.sum(np.abs(x2 - np.diag(np.diag(x2))))

        if s1 < 1E-6 and s2 < 1E-6:
            print '\t\t Check'
        else:
            print '\t\t NOT OK'
            if _verbose_:
                print '\t\tDensity matrix in eigenbasis of the Fock matrix'
                print np.array_str(x1, suppress_small=True)
                print '\t\t\Fock matrix in eigenbasis of the Density matrix'
                print np.array_str(x2, suppress_small=True)

        print '\n'
        print '\t\t',
        print '=' * 40
        print '\t\teigenvector/eigenvalues of the fock matrix'
        print lf
        print cf
        print ''
        print '\t\teigenvector/eigenvalues of the density matrix'
        print ld
        print cd
        print '\t\t',
        print '=' * 40

    #
    # check the initial population of the molecular orbital
    #
    if _verbose_:

        print '\t\t',
        print '=' * 40
        print '\t\t Initial population of the molecular orbitals'
        print '\t\t ',
        for i in range(len(P)):
            print '%1.3f ' % (P[i, i].real),
        print ''
        print '\t\t',
        print '=' * 40
    #

    #-------------------------------------------------------------------------------------------
    #
    #								SIMUALTIONS
    #
    #-------------------------------------------------------------------------------------------

    ##########################################################
    ##					Define time and outputs
    ##########################################################

    if args.time_unit == 'fs':
        tmax_convert = args.tmax * 1E-15 / au2s
    elif args.time_unit == 'ps':
        tmax_convert = args.tmax * 1E-12 / au2s
    elif args.time_unit == 'au':
        tmax_convert = args.tmax

    # a few shortcut
    ffreq = args.ffreq
    fint = args.fint
    ft0 = args.ft0 * tmax_convert
    fsigma = args.fsigma * tmax_convert
    fform = args.fform

    # readjust the frequency in case it is not specified
    if ffreq < 0:
        ffreq = L[nocc] - L[nocc - 1]
        print '\n\t Field frequency adjusted to %f' % (ffreq)

    T = np.linspace(0, tmax_convert, args.nT)
    Tplot = np.linspace(0, args.tmax, args.nT)
    FIELD = np.zeros(args.nT)
    N = np.zeros((nbfs, args.nT))
    Q = np.zeros((natom, args.nT))
    mu0 = 0
    for i in range(natom):
        Q[i, :] = mol[i].Z
        mu0 += mol[i].Z * mol.atoms[i].r[0]
    MU = mu0 * np.ones(args.nT)

    dt = T[1] - T[0]

    ##########################################################
    ##					Loop over time
    ##########################################################
    print '\n'
    print '\t Compute the TDHF dynamics'
    print '\t Simulation done at %d percent' % (0),
    for iT in range(0, args.nT):

        ################################################################
        ## 					TIMER
        ################################################################
        if iT * 10 % int(args.nT) == 0:
            sys.stdout.write('\r\t Simulation done at %d percent' %
                             (iT * 100 / args.nT))
            sys.stdout.flush()

        ################################################################
        ## Compute the observable
        ################################################################

        # compute the Lowdin atomic charges
        for iorb in range(nbfs):
            atid = bfs[iorb].atid
            Q[atid, iT] -= 2 * Dp[iorb, iorb].real

        # compute the population of the orbitals
        for iorb in range(nbfs):
            N[iorb,
              iT] = (np.dot(C0p[:, iorb], np.dot(Dp.real, C0p[:, iorb].T)) /
                     np.linalg.norm(C0p[:, iorb])**2).real

        # compute the instantaneous dipole
        MU[iT] -= np.trace(np.dot(mu_at, D)).real

        ######################################
        ##	Propagation
        ######################################

        if _predict_ and iT < args.nT - 1:

            # predict the density matrix
            dp = propagate_dm(Dp, Fp, dt, method='relax')

            #predicted dm in AO basis
            d = np.dot(X, np.dot(dp, X.T))

            # value of the field
            fp1 = compute_field(T[iT + 1],
                                ffreq=ffreq,
                                fint=fint,
                                t0=ft0,
                                s=fsigma,
                                fform=fform)
            mup_p1 = mu_at_p * fp1

            # predicted fock matrix
            fp = compute_F(d, Hcore_p, X, Ints, mup_p1)

            # form the intermediate fock matrix
            fm = 0.5 * (Fp + fp)

            # propagte the density matrix with that
            Dp = propagate_dm(Dp, fm, dt, method='relax')

        else:

            # propagte the density matrix with that
            Dp = propagate_dm(Dp, Fp, dt, method='relax')

        ######################################
        ##	New Density Matrix in AO
        ######################################

        # DM in AO basis
        D = np.dot(X, np.dot(Dp, X.T))

        ######################################
        ##	New Field
        ######################################

        # value of the field
        FIELD[iT] = compute_field(T[iT],
                                  ffreq=ffreq,
                                  fint=fint,
                                  t0=ft0,
                                  s=fsigma,
                                  fform=fform)
        mup = mu_at_p * FIELD[iT]

        ######################################
        ##	New Fock Matrix
        ######################################

        # new Fock matrix
        Fp = compute_F(D, Hcore_p, X, Ints, mup)

    sys.stdout.write('\r\t Simulation done at 100 percent')

    # save all the data
    print '\n\t Save data\n'
    np.savetxt('time.dat', Tplot)
    np.savetxt('orb_pops.dat', N)
    np.savetxt('charges.dat', Q)
    np.savetxt('dipole.dat', MU)
    np.savetxt('field.dat', FIELD)

    #-------------------------------------------------------------------------------------------
    #
    #						EXPORT THE RESULTS
    #
    #-------------------------------------------------------------------------------------------

    ##########################################################
    ##			PLOT THE DATA WITH MATPLOTLIB
    ##########################################################
    if _plot_:
        plot(Tplot, FIELD, N, Q, MU, cutlow=0.05, cuthigh=0.9)

    ##########################################################
    ##			Export the MO in VMD Format
    ##########################################################
    if _export_mo_:

        print '\t Export MO Gaussian Cube format'

        index_homo = nocc - 1
        nb_print = int(min(nbfs, args.nb_print_mo) / 2)
        fmo_names = []
        for ibfs in range(index_homo - nb_print + 1,
                          index_homo + nb_print + 1):
            if ibfs <= index_homo:
                motyp = 'occ'
            else:
                motyp = 'virt'
            file_name = mol.name + '_mo' + '_' + motyp + '_%01d.cube' % (index)
            xyz_min, nb_pts, spacing = mesh_orb(file_name, mol, bfs, C0, ibfs)
            fmo_names.append(file_name)

        ##########################################################
        ##					Export the MO
        ##				in bvox Blender format
        ##########################################################

        if _export_blender_:
            print '\t Export MO volumetric data for Blender'
            bvox_files_mo = []
            for fname in fmo_names:
                fn = cube2blender(fname)
                bvox_files_mo.append(fn)

            ##########################################################
            ##					Create the
            ##				Blender script to visualize the orbitals
            ##########################################################
            path_to_files = os.getcwd()
            pdb_file = name_mol + '.pdb'
            create_pdb(pdb_file, args.mol, args.units)

            # create the blender file
            blname = name_mol + '_mo_volumetric.py'
            create_blender_script_mo(blname, xyz_min, nb_pts, spacing,
                                     pdb_file, bvox_files_mo, path_to_files)

    ##########################################################
    ##			Export the MO DYNAMICS in VMD Format
    ##########################################################
    if _export_mo_dynamics_:

        # step increment
        nstep_mo = 4

        # resolution i.e. point per angstrom
        ppa = 1

        # just a test
        norm = 1 - np.min(N[0, :])

        # loop to create all the desired cube files
        fdyn_elec, fdyn_hole = [], []
        for iT in range(0, args.nT, nstep_mo):

            if iT * 10 % int(args.nT) == 0:
                sys.stdout.write(
                    '\r\t Export Cube File \t\t\t\t %d percent done' %
                    (iT * 100 / args.nT))
                sys.stdout.flush()

            felec, fhole, xyz_min, nb_pts, spacing = mesh_exc_dens(
                mol, bfs, N, C0, iT, nocc, resolution=ppa)
            fdyn_elec.append(felec)
            fdyn_hole.append(fhole)

        sys.stdout.write('\r\t Export Cube File \t\t\t\t 100 percent done\n')

        # create the vmd script to animate the voxel
        create_vmd_anim(mol.name, args.nT, nstep_mo)

        ##########################################################
        ##					Export the DYN
        ##				in bvox Blender format
        ##########################################################
        if _export_blender_:
            print '\t Export volumetric data for Blender'

            # create the bvox files for electron
            bvox_files_dyn_elec = []
            for fname in fdyn_elec:
                fn = cube2blender(fname)
                bvox_files_dyn_elec.append(fn)

            # create the bvox files for holes
            bvox_files_dyn_hole = []
            for fname in fdyn_hole:
                fn = cube2blender(fname)
                bvox_files_dyn_hole.append(fn)

            # create the pdb file
            pdb_file = name_mol + '.pdb'
            create_pdb(pdb_file, args.mol, args.units)

            # path to files
            path_to_files = os.getcwd()

            # create the blender script
            blname = name_mol + '_traj_volumetric.py'
            create_blender_script_traj(blname, xyz_min, nb_pts, spacing,
                                       pdb_file, bvox_files_dyn_elec,
                                       bvox_files_dyn_hole, path_to_files)

    print '\n\n=================================================='
    print '==                       Calculation done       =='
    print '==================================================\n'
Beispiel #23
0
def pyq1_rohf(atomtuples=[(2,(0,0,0))],basis = '6-31G**',maxit=10,mult=3):
    from PyQuante import Ints,settings,Molecule
    from PyQuante.hartree_fock import get_energy
    from PyQuante.MG2 import MG2 as MolecularGrid
    from PyQuante.LA2 import mkdens,geigh,trace2,simx
    from PyQuante.Ints import getJ,getK
    
    print ("PyQ1 ROHF run")
    atoms = Molecule('Pyq1',atomlist=atomtuples,multiplicity=mult)

    bfs = Ints.getbasis(atoms,basis=basis)
    S,h,I2e = Ints.getints(bfs,atoms)

    nbf = norbs = len(bfs)
    nel = atoms.get_nel()

    nalpha,nbeta = atoms.get_alphabeta()

    enuke = atoms.get_enuke()
    orbe,orbs = geigh(h,S)
    eold = 0

    for i in range(maxit):
        Da = mkdens(orbs,0,nalpha)
        Db = mkdens(orbs,0,nbeta)
        Ja = getJ(I2e,Da)
        Jb = getJ(I2e,Db)
        Ka = getK(I2e,Da)
        Kb = getK(I2e,Db)

        Fa = h+Ja+Jb-Ka
        Fb = h+Ja+Jb-Kb
        energya = get_energy(h,Fa,Da)
        energyb = get_energy(h,Fb,Db)
        eone = (trace2(Da,h) + trace2(Db,h))/2
        etwo = (trace2(Da,Fa) + trace2(Db,Fb))/2
        energy = (energya+energyb)/2 + enuke
        print (i,energy,eone,etwo,enuke)
        if abs(energy-eold) < 1e-5: break
        eold = energy

        Fa = simx(Fa,orbs)
        Fb = simx(Fb,orbs)
        # Building the approximate Fock matrices in the MO basis
        F = 0.5*(Fa+Fb)
        K = Fb-Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0,nbeta)
        so = slice(nbeta,nalpha)
        uo = slice(nalpha,norbs)
        F[do,do] -= K[do,do]
        F[uo,uo] += K[uo,uo]
        F[do,so] += 0.5*K[do,so]
        F[so,do] += 0.5*K[so,do]
        F[so,uo] -= 0.5*K[so,uo]
        F[uo,so] -= 0.5*K[uo,so]

        orbe,mo_orbs = np.linalg.eigh(F)
        orbs = np.dot(orbs,mo_orbs)
    return energy,orbe,orbs
Beispiel #24
0
def ao2mo(M,C): return simx(M,C)
def mo2ao(M,C,S):
Beispiel #25
0
def mo2ao(M,C,S):
    SC = matrixmultiply(S,C)
    return simx(M,SC,'t')