def print_amplitudes(self): t1 = self.t1.real.copy() # unpack tensor, remove zeros, sort and select top 10 t = np.ravel(t1) t = sorted(t[np.nonzero(t)],key=abs,reverse=True) if len(t) > 10: t = t[:10] # Disentangle degenerate amplitudes indeces = [] amplitudes = [] for amplitude in t: index = np.argwhere(t1==amplitude) if index.shape[0]==1: indeces.append(index[0]) amplitudes.append(amplitude) else: n = index.shape[0] for i in range(n): if not next((True for elem in indeces if elem.size == index[i].size and np.allclose(elem, index[i])), False): indeces.append(index[i]) amplitudes.append(amplitude) Print(green+'Largest t(I,A) amplitudes'+end) for i in range(len(amplitudes)): index = indeces[i] amplitude = amplitudes[i] Print(cyan+'\t{:2d}{:2d}{:>24.10f}'.format(index[0]+1,index[1]+1,amplitude)+end) t2 = self.t2.real.copy() # unpack tensor, remove zeros, sort and select top 10 t = np.ravel(t2) t = sorted(t[np.nonzero(t)],key=abs,reverse=True) if len(t) > 10: t = t[:10] # Disentangle degenerate amplitudes indeces = [] amplitudes = [] for amplitude in t: index = np.argwhere(t2==amplitude) if index.shape[0]==1: indeces.append(index[0]) amplitudes.append(amplitude) else: n = index.shape[0] for i in range(n): if not next((True for elem in indeces if elem.size == index[i].size and np.allclose(elem, index[i])), False): indeces.append(index[i]) amplitudes.append(amplitude) Print(green+'Largest t(I,j,A,b) amplitudes'+end) for i in range(len(amplitudes)): index = indeces[i] amplitude = amplitudes[i] Print(cyan+'\t{:2d}{:2d}{:2d}{:2d}{:>20.10f}'.format(index[0]+1,index[1]+1,index[2]+1,index[3]+1,amplitude)+end)
def __init__(self,ccsd): Print(yellow+"\nInitializing Lambda object..."+end) # Start timer time_init = time.time() # Read relevant data from ccsd class self.n_occ = ccsd.n_occ self.n_virt = ccsd.n_virt self.o = ccsd.o self.v = ccsd.v self.TEI = ccsd.TEI self.Dia = ccsd.Dia.swapaxes(0,1) self.Dijab = ccsd.Dijab.swapaxes(0,2).swapaxes(1,3) self.t1 = ccsd.t1 self.t2 = ccsd.t2 self.F = ccsd.F # Initialize l1 and l2 to the transpose of t1 and t2, respectively self.l1 = self.t1.swapaxes(0,1).copy() self.l2 = self.t2.swapaxes(0,2).swapaxes(1,3).copy() # Build intermediates independent of Lambda self.Fov = ccsd.build_Fov() self.Foo = self.transform_Foo(ccsd) self.Fvv = self.transform_Fvv(ccsd) self.Woooo = self.transform_Woooo(ccsd) self.Wvvvv = self.transform_Wvvvv(ccsd) self.Wvoov = self.transform_Wovvo(ccsd) self.Wooov = self.build_Wooov(ccsd) self.Wvvvo = self.build_Wvvvo(ccsd)
def check_trace(self, M, t): trace = np.trace(M).real if trace - t > 1e-14: Print( red + 'Warning: Trace of density matrix deviated from expected value' + end) print(trace) return
bold = '\033[1m' underline = '\033[4m' red = '\033[31m' green = '\033[92m' yellow = '\033[93m' blue = '\033[94m' purple = '\033[95m' cyan = '\033[96m' end = '\033[0m' colors = [red,green,yellow,blue,purple,cyan] print_data = True localize = False use_hbar = True # flag to be used later for some testing Print(blue+'\nTime Dependent CCSD Program'+end) Print(blue+'-- Written by Alexandre P. Bazante, 2017\n'+end) psi4.set_memory(int(2e9), False) psi4.core.set_output_file('output.dat', False) numpy_memory = 2 class rtcc(object): def __init__(self,memory=2): psi4.set_module_options('SCF', {'SCF_TYPE':'PK'}) psi4.set_module_options('SCF', {'E_CONVERGENCE':1e-14}) psi4.set_module_options('SCF', {'D_CONVERGENCE':1e-14}) psi4.set_module_options('CCENERGY', {'E_CONVERGENCE':1e-16}) psi4.set_module_options('CCLAMBDA', {'R_CONVERGENCE':1e-16})
def __init__(self, ccsd, Lambda, prop, options, memory=2): Print(yellow + "\nStarting time propagation with 4th order Runge Kutta...\n" + end) # Start timer time_init = time.time() # read CCSD data t1 = ccsd.t1.copy() t2 = ccsd.t2.copy() l1 = Lambda.l1.copy() l2 = Lambda.l2.copy() F = ccsd.F.copy() self.F = F # this is to be implicitly passed downstream to check for spin integration e_conv = psi4.core.get_option('CCENERGY', 'E_CONVERGENCE') energy = ccsd.compute_corr_energy() dipole = prop.compute_ccsd_dipole() # build the electric dipole operator (this is where the electric field orientation is set) ints = ccsd.mints.ao_dipole() axis = 2 # z-axis self.mu = contract('ui,uv,vj->ij', ccsd.npC, np.asarray(ints[axis]), ccsd.npC) # read options & prepare data output self.options = options np.set_printoptions(precision=14, linewidth=200, suppress=True) def save_data(): # create amplitude group root = zarr.open('data.zarr', mode='w') amplitudes = root.create_group('amplitudes') arr = amplitudes.zeros('t1 (real)', shape=t1.shape, chunks=(1000, 1000), dtype='f8') arr[:] = t1.real print('done') print(t1.real) return # TESTS test = True if test: print('\ntest update T convergence') t1 = t1 * 0 t2 = t2 * 0 converged = False counter = 0 while not converged: r_t1 = ccsd.residual_t1(F, t1, t2) r_t2 = ccsd.residual_t2(F, t1, t2) t1 += r_t1 * ccsd.Dia t2 += r_t2 * ccsd.Dijab if np.linalg.norm(r_t1) < 1e-14 and np.linalg.norm( r_t2) < 1e-14: converged = True counter += 1 if np.allclose(t1 - ccsd.t1, 0 * t1): print('t1 has converged to the CCSD result in %s steps' % counter) if np.allclose(t2 - ccsd.t2, 0 * t2): print('t2 has converged to the CCSD result in %s steps' % counter) print('\ntest update Lambda convergence') l1 = l1 * 0 l2 = l2 * 0 converged = False counter = 0 while not converged: r_l1 = Lambda.residual_l1(ccsd, F, t1, t2, l1, l2) r_l2 = Lambda.residual_l2(ccsd, F, t1, t2, l1, l2) l1 += r_l1 * Lambda.Dia l2 += r_l2 * Lambda.Dijab if np.linalg.norm(r_l1) < 1e-14 and np.linalg.norm( r_l2) < 1e-14: converged = True counter += 1 if np.allclose(l1 - Lambda.l1, 0 * l1): print('l1 has converged to the CCSD result in %s steps' % counter) if np.allclose(l2 - Lambda.l2, 0 * l2): print('l2 has converged to the CCSD result in %s steps' % counter) print('\ntest Lambda correlation energy') t1 = ccsd.t1.copy() t2 = ccsd.t2.copy() l1 = Lambda.l1.copy() l2 = Lambda.l2.copy() F = ccsd.F.copy() r_t1 = ccsd.residual_t1(F, t1, t2) r_t2 = ccsd.residual_t2(F, t1, t2) l_e = contract('ai,ia->', l1, r_t1) l_e += contract('abij,ijab->', l2, r_t2) print(l_e.real) print('\ntest imaginary time propagation T') t1 = t1 * 0 t2 = t2 * 0 t = 0.0 h = 0.01 converged = False counter = 0 while not converged: dt1, dt2 = self.prop_t(ccsd, t, h, F, self.zero, t1, t2) t1 += dt1 * (-1.0j) t2 += dt2 * (-1.0j) t += h if np.linalg.norm(dt1) < 1e-8 and np.linalg.norm(dt2) < 1e-8: converged = True counter += 1 if np.allclose(t1 - ccsd.t1, 0 * t1, 1e-6): print('t1 has converged to the CCSD result in %s steps' % counter) else: print( 'after %s steps, t1 differs from the CCSD result by ' % counter, np.linalg.norm(t1 - ccsd.t1)) if np.allclose(t2 - ccsd.t2, 0 * t2, 1e-6): print('t2 has converged to the CCSD result in %s steps' % counter) else: print( 'after %s steps, t2 differs from the CCSD result by ' % counter, np.linalg.norm(t2 - ccsd.t2)) print('\ntest imaginary time propagation Lambda') l1 = l1 * 0 l2 = l2 * 0 t = 0.0 h = 0.01 converged = False counter = 0 while not converged: dl1, dl2 = self.prop_l(ccsd, Lambda, t, h, F, self.zero, t1, t2, l1, l2) l1 += dl1 * (1.0j) l2 += dl2 * (1.0j) t += h if np.linalg.norm(dl1) < 1e-8 and np.linalg.norm(dl2) < 1e-8: converged = True counter += 1 if np.allclose(l1 - Lambda.l1, 0 * l1, 1e-6): print('l1 has converged to the CCSD result in %s steps' % counter) else: print( 'after %s steps, l1 differs from the CCSD result by ' % counter, np.linalg.norm(l1 - Lambda.l1)) if np.allclose(l2 - Lambda.l2, 0 * l2, 1e-6): print('l2 has converged to the CCSD result in %s steps' % counter) else: print( 'after %s steps, l2 differs from the CCSD result by ' % counter, np.linalg.norm(l2 - Lambda.l2)) raise SystemExit data = {} data['parameters'] = options data['time'] = [] data['t1 (real part)'] = [] data['t1 (imag part)'] = [] data['t2 (real part)'] = [] data['t2 (imag part)'] = [] data['l1 (real part)'] = [] data['l1 (imag part)'] = [] data['l2 (real part)'] = [] data['l2 (imag part)'] = [] data['dipole (real part)'] = [] data['dipole (imag part)'] = [] data['energy (real)'] = [] data['energy (imag)'] = [] data['time'].append(0) data['t1 (real part)'].append(t1.real.tolist()) data['t1 (imag part)'].append(t1.imag.tolist()) data['t2 (real part)'].append(t2.real.tolist()) data['t2 (imag part)'].append(t2.imag.tolist()) data['l1 (real part)'].append(l1.real.tolist()) data['l1 (imag part)'].append(l1.imag.tolist()) data['l2 (real part)'].append(l2.real.tolist()) data['l2 (imag part)'].append(l2.imag.tolist()) data['dipole (real part)'].append(dipole[2].real) data['dipole (imag part)'].append(dipole[2].imag) data['energy (real)'].append(energy.real) data['energy (imag)'].append(energy.imag) h = options['timestep'] N = options['number of steps'] T = options['timelength'] t = 0.0 Print(blue + '{:>6s}{:8.4f}'.format('t = ', t) + cyan + '\t{:>15s}{:10.5f}{:>15s}{:12.3E}'.format( 'mu (Real):', dipole[2].real, 'mu (Imag):', dipole[2].imag) + end) #Print(blue+'{:>6s}{:8.4f}'.format('t = ',t)+cyan+'\t{:>15s}{:10.5f}{:>15s}{:12.3E}' .format('e (Real):',energy.real,'e (Imag):',energy.imag)+end) for i in range(N): dt1, dt2 = self.prop_t(ccsd, t, h, F, self.Vt, t1, t2) dl1, dl2 = self.prop_l(ccsd, Lambda, t, h, F, self.Vt, t1, t2, l1, l2) dt1 = np.around(dt1, decimals=-int(np.log10(e_conv))) dt2 = np.around(dt2, decimals=-int(np.log10(e_conv))) dl1 = np.around(dl1, decimals=-int(np.log10(e_conv))) dl2 = np.around(dl2, decimals=-int(np.log10(e_conv))) t1 += dt1 t2 += dt2 l1 += dl1 l2 += dl2 t += h energy = ccsd.compute_corr_energy(F, t1, t2) dipole = prop.compute_ccsd_dipole(t1, t2, l1, l2) if abs(energy.real) > 1000: Print( red + '\nThe propagation is unstable, restart with a smaller time step' + end) raise SystemExit data['time'].append(t) data['t1 (real part)'].append(t1.real.tolist()) data['t1 (imag part)'].append(t1.imag.tolist()) data['t2 (real part)'].append(t2.real.tolist()) data['t2 (imag part)'].append(t2.imag.tolist()) data['l1 (real part)'].append(l1.real.tolist()) data['l1 (imag part)'].append(l1.imag.tolist()) data['l2 (real part)'].append(l2.real.tolist()) data['l2 (imag part)'].append(l2.imag.tolist()) data['dipole (real part)'].append(dipole[2].real) data['dipole (imag part)'].append(dipole[2].imag) data['energy (real)'].append(energy.real) data['energy (imag)'].append(energy.imag) Print(blue + '{:>6s}{:8.4f}'.format('t = ', t) + cyan + '\t{:>15s}{:10.5f}{:>15s}{:12.3E}'.format( 'mu (Real):', dipole[2].real, 'mu (Imag):', dipole[2].imag) + end) #Print(blue+'{:>6s}{:8.4f}'.format('t = ',t)+cyan+'\t{:>15s}{:10.5f}{:>15s}{:12.3E}' .format('e (Real):',energy.real,'e (Imag):',energy.imag)+end) if time.time() > T: Print(yellow + '\nEnd of propagation reached: time = %s seconds' % T + end) break elif t > 0 and round(t / h) % 1000 == 0: # write checkpoint init = time.time() #with open('data.json','w') as outfile: # json.dump(data,outfile,indent=2) Print( yellow + '\n\t checkpoint: saving data to json in %.1f seconds\n' % (time.time() - init) + end) elif round(time.time() - time_init) > 1 and round( time.time() - time_init) % 3600 == 0: # write checkpoint init = time.time() #with open('data.json','w') as outfile: # json.dump(data,outfile,indent=2) Print( yellow + '\n\t checkpoint: saving data to json in %.1f seconds\n' % (time.time() - init) + end) Print(yellow + '\n End of propagation reached: steps = %s' % N + end) Print(yellow + '\t time elapsed: time = %.1f seconds' % (time.time() - time_init) + end) save_data() with open('data.json', 'w') as outfile: json.dump(data, outfile, indent=2)
def print_amplitudes(self): # untile L1 for alpha/beta spin l1 = self.l1.real.copy() n = len(l1.shape) for i in range(n): l1 = np.delete(l1, list(range(1, l1.shape[i], 2)), axis=i) # unpack tensor, remove zeros, sort and select top 10 l = np.ravel(l1) l = sorted(l[np.nonzero(l)],key=abs,reverse=True) if len(l) > 10: l = l[:10] # Disentangle degenerate amplitudes indeces = [] amplitudes = [] for amplitude in l: index = np.argwhere(l1==amplitude) if index.shape[0]==1: indeces.append(index[0]) amplitudes.append(amplitude) else: n = index.shape[0] for i in range(n): if not next((True for elem in indeces if elem.size == index[i].size and np.allclose(elem, index[i])), False): indeces.append(index[i]) amplitudes.append(amplitude) Print(green+'Largest lambda(A,I) amplitudes'+end) for i in range(len(amplitudes)): index = indeces[i] amplitude = amplitudes[i] Print(cyan+'\t{:2d}{:2d}{:>24.10f}'.format(index[0]+1,index[1]+1,amplitude)+end) # untile L2 for alpha/beta spin l2 = self.l2.real.copy() l2 = np.delete(l2, list(range(1, l2.shape[0], 2)), axis=0) l2 = np.delete(l2, list(range(0, l2.shape[1], 2)), axis=1) l2 = np.delete(l2, list(range(1, l2.shape[2], 2)), axis=2) l2 = np.delete(l2, list(range(0, l2.shape[3], 2)), axis=3) # unpack tensor, remove zeros, sort and select top 10 l = np.ravel(l2) l = sorted(l[np.nonzero(l)],key=abs,reverse=True) if len(l) > 10: l = l[:10] # Disentangle degenerate amplitudes indeces = [] amplitudes = [] for amplitude in l: index = np.argwhere(l2==amplitude) if index.shape[0]==1: indeces.append(index[0]) amplitudes.append(amplitude) else: n = index.shape[0] for i in range(n): if not next((True for elem in indeces if elem.size == index[i].size and np.allclose(elem, index[i])), False): indeces.append(index[i]) amplitudes.append(amplitude) Print(green+'Largest lambda(A,b,I,j) amplitudes'+end) for i in range(len(amplitudes)): index = indeces[i] amplitude = amplitudes[i] Print(cyan+'\t{:2d}{:2d}{:2d}{:2d}{:>20.10f}'.format(index[0]+1,index[1]+1,index[2]+1,index[3]+1,amplitude)+end)
def __init__(self,mol,memory=2): Print(yellow+"\nInitializing CCSD object..."+end) ##------------------------------------------------------ ## SCF Procedures ##------------------------------------------------------ ## E_X : Total energy of method X (e.g., E_ccsd = ccsd total energy) ## e_x : Method X specific energy (e.g., e_ccsd = ccsd correlation energy) ## ## P : AO Density matrix ## F_ao: AO fock matrix ## ## F : Canonical MO fock matrix # Start timer time_init = time.time() np.set_printoptions(precision=10,linewidth=200,suppress=True) # Read molecule data psi4.core.set_active_molecule(mol) N_atom = mol.natom() self.n_e = int(sum(mol.Z(A) for A in range(N_atom))-mol.molecular_charge()) self.ndocc = int(self.n_e / 2) # can also be read as self.wfn.doccpi()[0] after an scf instance self.e_nuc = mol.nuclear_repulsion_energy() self.e_scf,self.wfn = psi4.energy('scf',return_wfn=True) # This makes psi4 run the scf calculation Print(blue+'The SCF energy is'+end) Print(cyan+'\t%s\n'%self.e_scf+end) self.memory = memory self.nmo = self.wfn.nmo() self.nso = self.nmo * 2 self.n_occ = self.ndocc * 2 self.n_virt = self.nso - self.n_occ # Make slices self.o = slice(self.n_occ) self.v = slice(self.n_occ,self.nso) # Read SCF data self.mints = psi4.core.MintsHelper(self.wfn.basisset()) self.TEI_ao = np.asarray(self.mints.ao_eri()) self.S_ao = np.asarray(self.mints.ao_overlap()) self.pot = np.asarray(self.mints.ao_potential()) self.kin = np.asarray(self.mints.ao_kinetic()) self.H = self.pot + self.kin self.C = self.wfn.Ca_subset('AO','ALL') self.npC = np.asarray(self.C) #localize_occupied(self) # Build AO density and fock matrix self.P = self.build_P() self.F = self.build_F() # check scf energy matches psi4 result e_scf_plugin = ndot('vu,uv->',self.P,self.H+self.F,prefactor=0.5) if not abs(e_scf_plugin+self.e_nuc-self.e_scf)<1e-7: Print(red+"Warning! There is a mismatch in the scf energy") Print("\tthis could be due to Density-Fitting - switch SCF type to direct or PK"+end) Print("the psi4 scf energy is %s" %self.e_scf) Print("the plugin scf energy is %s" %(e_scf_plugin+self.e_nuc)) raise Exception # Transform to MO basis Print(yellow+"\n..Starting AO -> MO transformation..."+end) ERI_size = (self.nmo**4) * 128e-9 memory_footPrint = ERI_size * 5 if memory_footPrint > self.memory: psi.clean() Print(red+"Estimated memory utilization (%4.2f GB) exceeds numpy_memory \ limit of %4.2f GB." % (memory_footPrint, self.memory)+end) raise Exception self.F_ao = self.F.copy() self.F = contract('up,uv,vq->pq',self.npC,self.F,self.npC) # Tile for alpha/beta spin self.F = np.repeat(self.F,2,axis=0) self.F = np.repeat(self.F,2,axis=1) spin_ind = np.arange(self.F.shape[0], dtype=np.int) % 2 self.F *= (spin_ind.reshape(-1, 1) == spin_ind) # Two Electron Integrals are stored as (left out,right out | left in,right in) self.TEI = np.asarray(self.mints.mo_spin_eri(self.C, self.C)) print("Size of the ERI tensor is %4.2f GB, %d basis functions." % (ERI_size, self.nmo)) # Build denominators eps = np.diag(self.F) self.Dia = 1/(eps[self.o].reshape(-1,1) - eps[self.v]) self.Dijab = 1/(eps[self.o].reshape(-1,1,1,1) + eps[self.o].reshape(-1,1,1) - eps[self.v].reshape(-1,1) - eps[self.v]) # Build MBPT(2) initial guess (complex) Print(yellow+"\n..Building CCSD initial guess from MBPT(2) amplitudes...") self.t1 = np.zeros((self.n_occ,self.n_virt)) + 1j*0.0 # t1 (ia) <- 0 self.t2 = self.TEI[self.o,self.o,self.v,self.v] * self.Dijab + 1j*0.0 # t2 (iJaB) <- (ia|JB) * D(iJaB) Print(yellow+"\n..Initialized CCSD in %.3f seconds." %(time.time() - time_init)+end)
def compute_ccsd(self,maxiter=50,max_diis=8,start_diis=1): ccsd_tstart = time.time() self.e_mp2 = self.compute_corr_energy().real Print('\n\t Summary of iterative solution of the CC equations') Print('\t------------------------------------------------------') Print('\t\t\tCorrelation\t RMS') Print('\t Iteration\tEnergy\t\t error') Print('\t------------------------------------------------------') Print('\t{:4d}{:26.15f}{:>25s}' .format(0,self.e_ccsd,'MBPT(2)')) e_conv = psi4.core.get_option('CCENERGY','E_CONVERGENCE') # Set up DIIS before iterations begin diis_object = helper_diis(self.t1,self.t2,max_diis) # Iterate for iter in range(1,maxiter+1): e_old = self.e_ccsd self.update() e_ccsd = self.compute_corr_energy().real rms = e_ccsd - e_old Print('\t{:4d}{:26.15f}{:15.5E} DIIS={:d}' .format(iter,e_ccsd,rms,diis_object.diis_size)) # Check convergence if abs(rms)<e_conv: Print('\t------------------------------------------------------') Print(yellow+"\n..The CCSD equations have converged in %.3f seconds" %(time.time()-ccsd_tstart)+end) Print(blue+'The ccsd correlation energy is'+end) Print(cyan+'\t%s \n' %e_ccsd+end) self.print_amplitudes() return # Add the new error vector diis_object.add_error_vector(self.t1,self.t2) if iter >= start_diis: self.t1, self.t2 = diis_object.extrapolate(self.t1,self.t2)
def __init__(self,ccsd,Lambda,memory=2): Print(yellow+"\nInitializing CCSD density object..."+end) # Start timer time_init = time.time() # Read relevant data self.n_occ = ccsd.n_occ self.n_virt = ccsd.n_virt self.o = ccsd.o self.v = ccsd.v self.ints = ccsd.mints.ao_dipole() self.P = ccsd.P self.npC = ccsd.npC self.t1 = ccsd.t1 self.t2 = ccsd.t2 self.l1 = Lambda.l1 self.l2 = Lambda.l2 D = self.compute_ccsd_density() Print(yellow+"\n..Density constructed in %.3f seconds\n" %(time.time()-time_init)+end) # Get nuclear dipole moments mol = psi4.core.get_active_molecule() dipoles_nuc = mol.nuclear_dipole() dipoles = self.compute_hf_dipole(self.P) Print(blue+'Dipole moment computed at the HF level'+end) Print(blue+'\tNuclear component (a.u.)'+end) Print(cyan+'\t{:>6s}{:10.5f}{:>6s}{:10.5f}{:>6s}{:10.5f}' .format('X:',dipoles_nuc[0],'Y:',dipoles_nuc[1],'Z:',dipoles_nuc[2])+end) Print(blue+'\tElectronic component (a.u.)'+end) Print(cyan+'\t{:>6s}{:10.5f}{:>6s}{:10.5f}{:>6s}{:10.5f}' .format('X:',dipoles[0],'Y:',dipoles[1],'Z:',dipoles[2])+end) dipoles = np.asarray([dipoles[i] + dipoles_nuc[i] for i in range(3)]) Print(green+'\tTotal electric dipole (a.u.)'+end) Print(cyan+'\t{:>6s}{:10.5f}{:>6s}{:10.5f}{:>6s}{:10.5f}' .format('X:',dipoles[0],'Y:',dipoles[1],'Z:',dipoles[2])+end) dipoles *= 1/0.393456 Print(green+'\tTotal electric dipole (Debye)'+end) Print(cyan+'\t{:>6s}{:10.5f}{:>6s}{:10.5f}{:>6s}{:10.5f}\n' .format('X:',dipoles[0],'Y:',dipoles[1],'Z:',dipoles[2])+end) dipoles = self.compute_ccsd_dipole() Print(blue+'Dipole moment computed at the CCSD level'+end) Print(blue+'\tNuclear component (a.u.)'+end) Print(cyan+'\t{:>6s}{:10.5f}{:>6s}{:10.5f}{:>6s}{:10.5f}' .format('X:',dipoles_nuc[0],'Y:',dipoles_nuc[1],'Z:',dipoles_nuc[2])+end) Print(blue+'\tElectronic component (a.u.)'+end) Print(cyan+'\t{:>6s}{:10.5f}{:>6s}{:10.5f}{:>6s}{:10.5f}' .format('X:',dipoles[0].real,'Y:',dipoles[1].real,'Z:',dipoles[2].real)+end) self.mu = dipoles.copy() dipoles = np.asarray([dipoles[i] + dipoles_nuc[i] for i in range(3)]) Print(green+'\tTotal electric dipole (a.u.)'+end) Print(cyan+'\t{:>6s}{:10.5f}{:>6s}{:10.5f}{:>6s}{:10.5f}' .format('X:',dipoles[0].real,'Y:',dipoles[1].real,'Z:',dipoles[2].real)+end) dipoles *= 1/0.393456 Print(green+'\tTotal electric dipole (Debye)'+end) Print(cyan+'\t{:>6s}{:10.5f}{:>6s}{:10.5f}{:>6s}{:10.5f}\n' .format('X:',dipoles[0].real,'Y:',dipoles[1].real,'Z:',dipoles[2].real)+end)
def compute_lambda(self,maxiter=50,max_diis=8,start_diis=1): lambda_tstart = time.time() e_ccsd_p = self.compute_pseudoenergy().real Print('\n\t Summary of iterative solution of the ACC equations') Print('\t------------------------------------------------------') Print('\t\t\tPseudo\t\t RMS') Print('\t Iteration\tEnergy\t\t error') Print('\t------------------------------------------------------') Print('\t{:4d}{:26.15f}{:>22s}' .format(0,e_ccsd_p,'CCSD')) # Setup DIIS diis_object = helper_diis(self.l1,self.l2,max_diis) e_conv = psi4.core.get_option('CCLAMBDA','R_CONVERGENCE') # Iterate for iter in range(1,maxiter+1): e_old_p = e_ccsd_p self.update() e_ccsd_p = self.compute_pseudoenergy().real rms = e_ccsd_p - e_old_p Print('\t{:4d}{:26.15f}{:15.5E} DIIS={:d}' .format(iter,e_ccsd_p,rms,diis_object.diis_size)) # Check convergence if abs(rms)<e_conv: Print('\t------------------------------------------------------') Print(yellow+"\n..The Lambda CCSD equations have converged in %.3f seconds" %(time.time()-lambda_tstart)+end) Print(blue+'The lambda pseudo-energy is'+end) Print(cyan+'\t%s \n' %e_ccsd_p+end) self.print_amplitudes() return # Add the new error vector diis_object.add_error_vector(self.l1,self.l2) if iter >= start_diis: self.l1,self.l2 = diis_object.extrapolate(self.l1,self.l2)
def __init__(self,ccsd): Print(yellow+"\nInitializing Lambda object..."+end) ##------------------------------------------------------ ## CCSD Lambda equations ##------------------------------------------------------ ## ## The equations follow reference 1, but are spin integrated using the unitary group approach. ## ## i,j -> target occupied indeces ## a,b -> target virtual indeces ## ## m,n,o -> implicit (summed-over) occupied indeces ## e,f,g -> implicit (summed-over) virtual indeces ## ## G: effective 1-particle intermediate ## W,Tau: effective 2 particle intermediates ## ## ## Because equations are spin integrated, we only compute the necessary spin combinations of amplitudes: ## l1 -> alpha block -> l1 (ai) ## l2 -> alpha/beta block -> l2 (aBiJ) ## # Start timer time_init = time.time() # Read relevant data from ccsd class self.n_occ = ccsd.n_occ self.n_virt = ccsd.n_virt self.o = ccsd.o self.v = ccsd.v self.TEI = ccsd.TEI #self.Dia = ccsd.Dia.swapaxes(0,1) #self.Dijab = ccsd.Dijab.swapaxes(0,2).swapaxes(1,3) self.Dia = ccsd.Dia self.Dijab = ccsd.Dijab self.t1 = ccsd.t1 self.t2 = ccsd.t2 self.F = ccsd.F # Initialize l1 and l2 to the transpose of t1 and t2 respectively #self.l1 = self.t1.swapaxes(0,1).copy() #self.l2 = self.t2.swapaxes(0,2).swapaxes(1,3).copy() self.l1 = 2*self.t1.copy() self.l2 = 4*self.t2.copy() self.l2 -= 2*self.t2.swapaxes(2,3) # Build intermediates independent of Lambda # the following Hbar elements are similar to CCSD intermediates; in spin orpbitals, they are easily obtained from the CCSD intermediates directly # When spin integrated, it's easier to recompute them from scratch. self.Fme = ccsd.build_Fme() self.Fmi = self.build_Fmi(ccsd) self.Fae = self.build_Fae(ccsd) self.Wmnij = ccsd.build_Wmnij() self.Wabef = self.build_Wabef(ccsd) self.Wmbej = self.build_Wmbej(ccsd) self.Wmbje = self.build_Wmbje(ccsd) # the following Hbar elements have to be computed from scratch as they don't correspond to transformed CCSD intermediates. self.Wmnie = self.build_Wmnie(ccsd) self.Wamef = self.build_Wamef(ccsd) self.Wmbij = self.build_Wmbij(ccsd) self.Wabei = self.build_Wabei(ccsd)