def rhfenergy(alpha_old, coef2, xyz, l, charges, xyz_atom, natoms, nbasis, contr_list, ne, max_scf, max_d, log, eigen, printguess, readguess, name, write, dtype): ''' This function returns the rhf function Parameters: alpha_old : array Gaussian exponents coef2 : array Contraction coeffients xyz : array 3N Gaussian centers l : array 3N Angular momentum each entry is a vector eg. s orbital (0,0,0) or pz (1,0,0) charges : array Atom charges nbasis : int Number of basis contr_list: list of integers Specify the number of orbitals in each atom ne : int Number of electrons max_scf : int maximum number of scf cycles log : bool The exponents are given in log printguess: str or None File to print coeff matrix initial guess readguess : str or None File that contains coeff matrix initial guess name : str Output file name write : bool True if printing dtype : type of output This is the directive to know if algopy will be used or not np.float64(1.0) if it is a single point calculation otherwise, it specify the size of the UTMP, autodifferentiation Returns: energy : float RHF energy ''' tool_D = 1e-8 tool = 1e-8 if log: alpha = algopy.exp(alpha_old) else: alpha = alpha_old if type(xyz_atom) != np.ndarray: ## Cover the case of diff xyz atom coef = normalization(alpha, coef2, l, contr_list, dtype=np.float64(1.0)) V = nuclearmatrix(alpha, coef, xyz, l, nbasis, charges, xyz_atom, natoms, contr_list, dtype=dtype) S = overlapmatrix(alpha, coef, xyz, l, nbasis, contr_list, dtype=np.float64(1.0)) T = kineticmatrix(alpha, coef, xyz, l, nbasis, contr_list, dtype=np.float64(1.0)) Eri = erivector(alpha, coef, xyz, l, nbasis, contr_list, dtype=np.float(1.0)) else: coef = normalization(alpha, coef2, l, contr_list, dtype=dtype) S = overlapmatrix(alpha, coef, xyz, l, nbasis, contr_list, dtype=dtype) V = nuclearmatrix(alpha, coef, xyz, l, nbasis, charges, xyz_atom, natoms, contr_list, dtype=dtype) T = kineticmatrix(alpha, coef, xyz, l, nbasis, contr_list, dtype=dtype) Eri = erivector(alpha, coef, xyz, l, nbasis, contr_list, dtype=dtype) Hcore = T + V if eigen: eigsys = eigensolver(S) SqrtLambda = algopy.diag(1. / algopy.sqrt(eigsys[0])) L = eigsys[1] LT = algopy.transpose(L) SqrtS = algopy.dot(algopy.dot(L, SqrtLambda), LT) SqrtST = algopy.transpose(SqrtS) else: Sinv = np.linalg.inv(S) if readguess != None: C = np.load(readguess) D = np.zeros((nbasis, nbasis)) for i in range(nbasis): for j in range(nbasis): tmp = 0.0 for k in range(ne): tmp = tmp + C[i, k] * C[j, k] D[i, j] = tmp F = fockmatrix(Hcore, Eri, D, nbasis, alpha, dtype) else: F = Hcore OldE = 1e8 status = False E_step = [] for scf_iter in range(max_scf): if eigen: Fprime = algopy.dot(algopy.dot(SqrtST, F), SqrtS) eigsysFockOp = eigensolver(Fprime) Cprime = eigsysFockOp[1] C = algopy.dot(SqrtS, Cprime) Fprime = algopy.dot(algopy.dot(SqrtST, F), SqrtS) eigsysFockOp = eigensolver(Fprime) Cprime = eigsysFockOp[1] C = algopy.dot(SqrtS, Cprime) D = algopy.zeros((nbasis, nbasis), dtype=dtype) for i in range(nbasis): for j in range(nbasis): tmp = 0.0 for k in range(ne): tmp = tmp + C[i, k] * C[j, k] D[i, j] = tmp else: D = newdensity(F, Sinv, nbasis, ne) for i in range(max_d): D = cannonicalputication(D, S) err = np.linalg.norm(D - np.dot(np.dot(D, S), D)) if err < tool_D: break F = fockmatrix(Hcore, Eri, D, nbasis, alpha, dtype) E_elec = algopy.sum(np.multiply(D, Hcore + F)) E_step.append(E_elec) E_nuc = nuclearrepulsion(xyz_atom, charges, natoms) if np.absolute(E_elec - OldE) < tool: status = True break OldE = E_elec E_nuc = nuclearrepulsion(xyz_atom, charges, natoms) if printguess != None: np.save(printguess, C) def update_system(): mol.energy = E_elec + E_nuc mol.erepulsion = Eri mol.hcore = Hcore mol.mo_coeff = C return def write_molden(): import Data from Data import select_atom ## Details of calculation tape.write('[Energy] \n') tape.write('E_elec: ' + str(E_elec) + '\n') tape.write('E_nuc: ' + str(E_nuc) + '\n') tape.write('E_tot: ' + str(E_nuc + E_elec) + '\n') tape.write('SCF Details\n') line = 'Eigen: ' if eigen: tape.write(line + 'True') else: tape.write(line + 'False') tape.write('\n') for i, step in enumerate(E_step): line = 'Step: ' + str(i) + ' ' + str(step) tape.write(line + '\n') ### C Matrix tape.write('[CM] \n') tape.write('C AO times MO\n') printmatrix(C, tape) ### D Matrix tape.write('[DM] \n') tape.write('D \n') printmatrix(D, tape) ### D Matrix tape.write('[NMO] \n') tape.write('NMO \n') printmatrix(mo_naturalorbital(D), tape) ### MO energies tape.write('[MOE] \n') tape.write('MOE \n') for i, energ in enumerate(eigsysFockOp[0]): tape.write(str(i) + ' ' + str(energ) + '\n') ### MO energies tape.write('[INPUT] \n') line = 'mol = [' for i, coord in enumerate(xyz_atom): line += '(' + str(charges[i]) + ',' line += '(' + str(coord[0]) + ',' + str(coord[1]) + ',' + str( coord[2]) + ')),\n' tape.write(line) cont = 0 line = 'basis = [' for i, ci in enumerate(contr_list): line += '[' line += '(' + str(l[i][0]) + ',' + str(l[i][1]) + ',' + str( l[i][2]) + '),' for ii in range(ci): line += str(alpha[cont]) + ',' + str(coef[i]) line += ',(' + str(xyz[i, 0]) + ',' + str( xyz[i, 1]) + ',' + str(xyz[i, 2]) + ')],\n' cont += 1 line += ']\n' tape.write(line) ### Atom coordinates tape.write('[Atoms]\n') for i, coord in enumerate(xyz_atom): line = select_atom.get(charges[i]) line += ' ' + str(i + 1) + ' ' + str(charges[i]) line += ' ' + str(coord[0]) + ' ' + str(coord[1]) + ' ' + str( coord[2]) + '\n' tape.write(line) ### Basis coordinates for i, coord in enumerate(xyz): line = 'XX' line += ' ' + str(i + natoms + 1) + ' ' + str(0) line += ' ' + str(coord[0]) + ' ' + str(coord[1]) + ' ' + str( coord[2]) + '\n' tape.write(line) ### Basis set cont = 0 tape.write('[GTO]\n') for i, ci in enumerate(contr_list): tape.write(' ' + str(i + 1 + natoms) + ' 0\n') if np.sum(l[i]) == 0: tape.write(' s ' + str(ci) + ' 1.0 ' + str(l[i][0]) + ' ' + str(l[i][1]) + ' ' + str(l[i][2]) + '\n') else: tape.write(' p ' + str(ci) + ' 1.0 ' + str(l[i][0]) + ' ' + str(l[i][1]) + ' ' + str(l[i][2]) + '\n') #tape.write(' p '+str(1)+' 1.0 '+ str(l[i])+'\n') for ii in range(ci): line = ' ' + str(alpha[cont]) + ' ' + str(coef[cont]) + '\n' tape.write(line) cont += 1 line = ' \n' tape.write(line) ### MOs tape.write('[MO]\n') for j in range(nbasis): tape.write(' Sym= None\n') tape.write(' Ene= ' + str(eigsysFockOp[0][j]) + '\n') tape.write(' Spin= Alpha\n') if j > ne: tape.write(' Occup= 0.0\n') else: tape.write(' Occup= 2.0\n') for i in range(nbasis): tape.write(str(i + 1 + natoms) + ' ' + str(C[i, j]) + '\n') if status: if write: tape = open(name + '.molden', "w") write_molden() tape.close() return E_elec + E_nuc else: print('E_elec: ' + str(E_elec) + '\n') print('E_nuc: ' + str(E_nuc) + '\n') print('E_tot: ' + str(E_nuc + E_elec) + '\n') print('SCF DID NOT CONVERGED') return 99999 return E_elec + E_nuc
def mo_naturalorbital(D): eigsys = eigensolver(D) return [eigsys[0]]