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
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
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)
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)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
def ao2mo(M, C): return simx(M, C)
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
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'
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
def ao2mo(M,C): return simx(M,C) def mo2ao(M,C,S):
def mo2ao(M,C,S): SC = matrixmultiply(S,C) return simx(M,SC,'t')