def get_ddt_corr1RDM( self ): #Subroutine to calculate first time-derivative of correlated 1RDM #Only calculated in the necessary impurity-bath space Ctil = applyham_pyscf.apply_ham_pyscf_fully_complex( self.CIcoeffs, self.h_emb, self.V_emb, self.Nimp, self.Nimp, 2*self.Nimp, self.Ecore ) rdmtil = fci_mod.get_trans1RDM( self.CIcoeffs, Ctil, 2*self.Nimp, 2*self.Nimp ) self.ddt_corr1RDM = -1j*( rdmtil - utils.adjoint( rdmtil ) )
def one_rk_step_mf(self, nproc): #Subroutine to calculate one change in a runge-kutta step of any order #Using EOM that integrates CI coefficients and MF 1RDM #embedding orbitals obtained by diagonalizing MF 1RDM at each step #Prior to calling this routine need to update MF 1RDM and CI coefficients #Calculate embedding orbitals maintaining same phase from previous step prev_rotmat = [] for frag in self.tot_system.frag_list: prev_rotmat.append(np.copy(frag.rotmat)) self.tot_system.get_frag_rotmat() for cnt, frag in enumerate(self.tot_system.frag_list): phase = np.diag( np.diag( np.real( np.dot(utils.adjoint(prev_rotmat[cnt]), frag.rotmat)))) frag.rotmat = np.dot(frag.rotmat, phase) #Calculate the rest of the terms needed for time-derivative of MF-1RDM self.tot_system.get_frag_corr1RDM() self.tot_system.get_glob1RDM() self.tot_system.get_nat_orbs() print(self.tot_system.NOevals) exit() #Calculate embedding hamiltonian self.tot_system.get_frag_Hemb() #Make sure Ecore for each fragment is 0 for dynamics for frag in self.tot_system.frag_list: frag.Ecore = 0.0 #Calculate change in mf1RDM change_mf1RDM = self.delt * mf1rdm_timedep_mod.get_ddt_mf1rdm_serial( self.tot_system, int(self.tot_system.Nele / 2)) #Calculate change in CI coefficients in parallel if (nproc == 1): change_CIcoeffs_list = [] for frag in self.tot_system.frag_list: change_CIcoeffs_list.append( -1j * self.delt * applyham_pyscf.apply_ham_pyscf_fully_complex( frag.CIcoeffs, frag.h_emb, frag.V_emb, frag.Nimp, frag.Nimp, 2 * frag.Nimp, frag.Ecore)) else: frag_pool = multproc.Pool(nproc) change_CIcoeffs_list = frag_pool.starmap( applyham_wrapper, [(frag, self.delt) for frag in self.tot_system.frag_list]) frag_pool.close() return change_mf1RDM, change_CIcoeffs_list
def applyham_wrapper(frag, delt): #Subroutine to call pyscf to apply FCI hamiltonian onto FCI vector in dynamics #Includes the -1j*timestep term #The wrapper is necessary to parallelize using Pool and must be separate from #the class because the class includes IO file types (annoying and ugly but it works) return -1j * delt * applyham_pyscf.apply_ham_pyscf_fully_complex( frag.CIcoeffs, frag.h_emb, frag.V_emb, frag.Nimp, frag.Nimp, 2 * frag.Nimp, frag.Ecore)
def applyham_wrapper(frag, delt): #Subroutine to call pyscf to apply FCI hamiltonian onto FCI vector in dynamics #Includes the -1j*timestep term and the addition of bath-bath terms of X-matrix to embedding Hamiltonian #The wrapper is necessary to parallelize using Pool and must be separate from #the class because the class includes IO file types (annoying and ugly but it works) Xmat_sml = np.zeros([2 * frag.Nimp, 2 * frag.Nimp], dtype=complex) Xmat_sml[frag.Nimp:, frag.Nimp:] = frag.Xmat[frag.bathrange[:, None], frag.bathrange] return -1j * delt * applyham_pyscf.apply_ham_pyscf_fully_complex( frag.CIcoeffs, frag.h_emb - Xmat_sml, frag.V_emb, frag.Nimp, frag.Nimp, 2 * frag.Nimp, frag.Ecore)
def one_rk_step_orb(self, nproc): #Subroutine to calculate one change in a runge-kutta step of any order #Using EOM that explicitly integrate embedding orbitals and CI coefficients using X-matrix #Prior to calling this routine need to update rotation matrices and CI coefficients #of each fragment up to appropriate point #Calculate terms needed for X-matrix self.tot_system.get_frag_corr1RDM() self.tot_system.get_glob1RDM() self.tot_system.get_nat_orbs() #Calculate embedding hamiltonian self.tot_system.get_frag_Hemb() #mrar for frag in self.tot_system.frag_list: #frag.Ecore = -fci_mod.get_FCI_E( frag.h_emb, frag.V_emb, 0.0, frag.CIcoeffs, 2*frag.Nimp, frag.Nimp, frag.Nimp ) frag.Ecore = 0.0 #Calculate X-matrix self.tot_system.get_Xmats(round(self.tot_system.Nele / 2), nproc) #Calculate change in rotation matrices new_rotmat_list = [] for frag in self.tot_system.frag_list: new_rotmat_list.append(-1j * self.delt * np.dot(frag.rotmat, frag.Xmat)) #Calculate change in CI coefficients in parallel if (nproc == 1): new_CIcoeffs_list = [] for frag in self.tot_system.frag_list: new_CIcoeffs_list.append( -1j * self.delt * applyham_pyscf.apply_ham_pyscf_fully_complex( frag.CIcoeffs, frag.h_emb, frag.V_emb, frag.Nimp, frag.Nimp, 2 * frag.Nimp, frag.Ecore)) else: frag_pool = multproc.Pool(nproc) new_CIcoeffs_list = frag_pool.starmap( applyham_wrapper, [(frag, self.delt) for frag in self.tot_system.frag_list]) frag_pool.close() return new_rotmat_list, new_CIcoeffs_list
def get_ddt_corr1RDM( self ): #Subroutine to calculate first time-derivative of correlated 1RDM #Only calculated in the necessary impurity-bath space t1 = time.time() #grr Ctil = applyham_pyscf.apply_ham_pyscf_fully_complex( self.CIcoeffs, self.h_emb, self.V_emb, self.Nimp, self.Nimp, 2*self.Nimp, self.Ecore ) t2 = time.time() #grr rdmtil = fci_mod.get_trans1RDM( self.CIcoeffs, Ctil, 2*self.Nimp, 2*self.Nimp ) t3 = time.time() #grr #print() #print( 'Ctil = ',t2-t1 ) #grr #print( 'rdm = ',t3-t2 ) #grr #print() self.ddt_corr1RDM = -1j*( rdmtil - utils.adjoint( rdmtil ) )
def one_rk_step2(mf1RDM, CIcoeffs, Nsites, Nele, h_site, Nimp, delt, rotmat): iddt_mf1RDM = utils.commutator(h_site, mf1RDM) change_mf1RDM = -1j * delt * iddt_mf1RDM evals = np.copy( np.real( np.diag(utils.rot1el(mf1RDM[Nimp:, Nimp:], rotmat[Nimp:, Nimp:])))) #####grr#### #chk1, chk2 = get_rotmat( mf1RDM, Nsites, Nimp ) #print(rotmat[Nimp:,Nimp:]) #print() #print(chk1[Nimp:,Nimp:]) #print() #print(evals) #print() #print(chk2) #print() #print('------------------') #print() ############ Xmat, Xmat_sml = get_Xmat(mf1RDM, iddt_mf1RDM, rotmat, evals, Nsites, Nele, Nimp) change_rotmat = -1j * delt * np.dot(rotmat, Xmat) h_emb, Ecore = get_Hemb(h_site, rotmat, Nimp, Nsites, Nele) V_emb = np.zeros([2 * Nimp, 2 * Nimp, 2 * Nimp, 2 * Nimp], dtype=complex) Ecore = 0.0 change_CIcoeffs = -1j * delt * applyham_pyscf.apply_ham_pyscf_fully_complex( CIcoeffs, h_emb - Xmat_sml, V_emb, Nimp, Nimp, 2 * Nimp, Ecore) return change_mf1RDM, change_CIcoeffs, change_rotmat
def one_rk_step(mf1RDM, CIcoeffs, Nsites, Nele, h_site, Nimp, delt, rotmat_old): iddt_mf1RDM = utils.commutator(h_site, mf1RDM) change_mf1RDM = -1j * delt * iddt_mf1RDM rotmat, evals = get_rotmat(mf1RDM, Nsites, Nimp) phase = np.diag( np.round(np.diag(np.real(np.dot(utils.adjoint(rotmat_old), rotmat))))) rotmat = np.dot(rotmat, phase) h_emb, Ecore = get_Hemb(h_site, rotmat, Nimp, Nsites, Nele) V_emb = np.zeros([2 * Nimp, 2 * Nimp, 2 * Nimp, 2 * Nimp], dtype=complex) Xmat, Xmat_sml = get_Xmat(mf1RDM, iddt_mf1RDM, rotmat, evals, Nsites, Nele, Nimp) Ecore = 0.0 change_CIcoeffs = -1j * delt * applyham_pyscf.apply_ham_pyscf_fully_complex( CIcoeffs, h_emb - Xmat_sml, V_emb, Nimp, Nimp, 2 * Nimp, Ecore) return change_mf1RDM, change_CIcoeffs, rotmat
def get_FCI_E(h, V, Econst, CIcoeffs, Norbs, Nalpha, Nbeta): #Subroutine to calculate the FCI electronic energy for given Hamiltonian and FCI vector #Works with complex Hamitlonian and FCI vector Hpsi = applyham_pyscf.apply_ham_pyscf_fully_complex( CIcoeffs, h, V, Nalpha, Nbeta, Norbs, Econst) Re_Hpsi = np.copy(Hpsi.real) Im_Hpsi = np.copy(Hpsi.imag) Re_CIcoeffs = np.copy(CIcoeffs.real) Im_CIcoeffs = np.copy(CIcoeffs.imag) FCI_E = pyscf.fci.addons.overlap(Re_CIcoeffs, Re_Hpsi, Norbs, (Nalpha, Nbeta)) FCI_E += pyscf.fci.addons.overlap(Im_CIcoeffs, Im_Hpsi, Norbs, (Nalpha, Nbeta)) FCI_E += 1j * pyscf.fci.addons.overlap(Re_CIcoeffs, Im_Hpsi, Norbs, (Nalpha, Nbeta)) FCI_E -= 1j * pyscf.fci.addons.overlap(Im_CIcoeffs, Re_Hpsi, Norbs, (Nalpha, Nbeta)) return FCI_E.real
def one_rk_step_mf(self, nproc): #Subroutine to calculate one change in a runge-kutta step of any order #Using EOM that integrates CI coefficients and MF 1RDM #embedding orbitals obtained by diagonalizing MF 1RDM at each step #Prior to calling this routine need to update MF 1RDM and CI coefficients #calculate embedding orbitals maintaining same phase from previous step prev_rotmat = [] for frag in self.tot_system.frag_list: prev_rotmat.append(np.copy(frag.rotmat)) self.tot_system.get_frag_rotmat() for cnt, frag in enumerate(self.tot_system.frag_list): phase = np.diag( np.round( np.diag( np.real( np.dot(utils.adjoint(prev_rotmat[cnt]), frag.rotmat))))) frag.rotmat = np.dot(frag.rotmat, phase) #calculate the rest of the terms needed for time-derivative of mf-1rdm self.tot_system.get_frag_corr1RDM() self.tot_system.get_glob1RDM() self.tot_system.get_nat_orbs() #calculate embedding hamiltonian self.tot_system.get_frag_Hemb() #Make sure Ecore for each fragment is 0 for dynamics for frag in self.tot_system.frag_list: frag.Ecore = 0.0 #Calculate change in mf1RDM change_mf1RDM = self.delt * mf1rdm_timedep_mod.get_ddt_mf1rdm_serial( self.tot_system, round(self.tot_system.Nele / 2)) ############ #print( np.allclose( mf1rdm_timedep_mod.get_ddt_mf1rdm_serial( self.tot_system, round(self.tot_system.Nele/2) ), -1j*utils.commutator( self.tot_system.h_site, self.tot_system.mf1RDM ), rtol=0.0, atol=1e-12 ) ) #print() #print( mf1rdm_timedep_mod.get_ddt_mf1rdm_serial( self.tot_system, round(self.tot_system.Nele/2) ) ) #print() #print( -1j*utils.commutator( self.tot_system.h_site, self.tot_system.mf1RDM ) ) #print() #print('--------------------------------------') #print() #exit() #msh #Calculate bath-bath terms of X-matrix necessary for CI propagation Xmat_list = [] for frag in self.tot_system.frag_list: X_small = np.zeros([frag.Nimp, frag.Nimp], dtype=complex) for b in frag.bathrange: for a in frag.bathrange: if (b != a): ib = b - frag.Nimp - frag.Nvirt ia = a - frag.Nimp - frag.Nvirt X_small[ib, ia] = 1.0 / ( frag.env1RDM_evals[a - frag.Nimp] - frag.env1RDM_evals[b - frag.Nimp]) * utils.matprod( utils.adjoint(frag.rotmat)[b, :], 1j * change_mf1RDM / self.delt, frag.rotmat[:, a]) X = np.zeros([2 * frag.Nimp, 2 * frag.Nimp], dtype=complex) X[frag.Nimp:, frag.Nimp:] = np.copy(X_small) Xmat_list.append(X) #Calculate change in CI coefficients in parallel if (nproc == 1): change_CIcoeffs_list = [] for ifrag, frag in enumerate(self.tot_system.frag_list): #change_CIcoeffs_list.append( -1j * self.delt * applyham_pyscf.apply_ham_pyscf_fully_complex( frag.CIcoeffs, frag.h_emb, frag.V_emb, frag.Nimp, frag.Nimp, 2*frag.Nimp, frag.Ecore ) ) change_CIcoeffs_list.append( -1j * self.delt * applyham_pyscf.apply_ham_pyscf_fully_complex( frag.CIcoeffs, frag.h_emb - Xmat_list[ifrag], frag.V_emb, frag.Nimp, frag.Nimp, 2 * frag.Nimp, frag.Ecore)) #grr else: frag_pool = multproc.Pool(nproc) change_CIcoeffs_list = frag_pool.starmap( applyham_wrapper, [(frag, self.delt) for frag in self.tot_system.frag_list]) frag_pool.close() return change_mf1RDM, change_CIcoeffs_list