def get_Hemb( self, h_site, V_site, hamtype=0, hubsite_indx=None ): #Subroutine to the get the 1 and 2 e- terms of the Hamiltonian in the embedding basis #Transformation accounts for interaction with the core #Also calculates 1 e- term with only 1/2 interaction with the core - this is used in calculation of DMET energy #remove the virtual states from the rotation matrix #the rotation matrix is of form ( site basis fcns ) x ( impurities, virtual, bath, core ) rotmat_small = np.delete( self.rotmat, np.s_[self.Nimp:self.Nimp+self.Nvirt], 1 ) #rotate the 1 e- terms, h_emb currently ( impurities, bath, core ) x ( impurities, bath, core ) h_emb = utils.rot1el( h_site, rotmat_small ) #define 1 e- term of size ( impurities, bath ) x ( impurities, bath ) that will only have 1/2 interaction with the core self.h_emb_halfcore = np.copy( h_emb[ :2*self.Nimp, :2*self.Nimp ] ) #rotate the 2 e- terms if( hamtype == 0 ): #General hamiltonian, V_emb currently ( impurities, bath, core ) ^ 4 V_emb = utils.rot2el_chem( V_site, rotmat_small ) elif( hamtype == 1 ): #Hubbard hamiltonian rotmat_vsmall = rotmat_small[ hubsite_indx, :2*self.Nimp ] #remove core states from rotation matrix self.V_emb = V_site*np.einsum( 'ap,cp,pb,pd->abcd', utils.adjoint( rotmat_vsmall ), utils.adjoint( rotmat_vsmall ), rotmat_vsmall, rotmat_vsmall ) #augment the impurity/bath 1e- terms from contribution of coulomb and exchange terms btwn impurity/bath and core #and augment the 1 e- term with only half the contribution from the core to be used in DMET energy calculation if( hamtype == 0 ): #General hamiltonian for core in range( 2*self.Nimp, 2*self.Nimp+self.Ncore ): h_emb[ :2*self.Nimp, :2*self.Nimp ] = h_emb[ :2*self.Nimp, :2*self.Nimp ] + 2*V_emb[ :2*self.Nimp, :2*self.Nimp, core, core ] - V_emb[ :2*self.Nimp, core, core, :2*self.Nimp ] self.h_emb_halfcore += V_emb[ :2*self.Nimp, :2*self.Nimp, core, core ] - 0.5*V_emb[ :2*self.Nimp, core, core, :2*self.Nimp ] elif( hamtype == 1): #Hubbard hamiltonian core_int = V_site * np.einsum( 'ap,pb,p->ab', utils.adjoint( rotmat_vsmall ), rotmat_vsmall, np.einsum( 'pe,ep->p',rotmat_small[hubsite_indx,2*self.Nimp:], utils.adjoint( rotmat_small[hubsite_indx,2*self.Nimp:] ) ) ) h_emb[ :2*self.Nimp, :2*self.Nimp ] += core_int self.h_emb_halfcore += 0.5*core_int #calculate the energy associated with core-core interactions, setting it numerically to a real number since it always will be Ecore = 0 for core1 in range( 2*self.Nimp, 2*self.Nimp+self.Ncore ): Ecore += 2*h_emb[ core1, core1 ] if( hamtype == 0 ): #General hamiltonian for core2 in range( 2*self.Nimp, 2*self.Nimp+self.Ncore ): Ecore += 2*V_emb[ core1, core1, core2, core2 ] - V_emb[ core1, core2, core2, core1 ] if( hamtype == 1): #Hubbard hamiltonian vec = np.einsum( 'pe,ep->p',rotmat_small[hubsite_indx,2*self.Nimp:],utils.adjoint( rotmat_small[hubsite_indx,2*self.Nimp:] ) ) Ecore += V_site * np.einsum( 'p,p', vec, vec ) self.Ecore = Ecore.real #shrink h_emb and V_emb arrays to only include the impurity and bath self.h_emb = h_emb[ :2*self.Nimp, :2*self.Nimp ] if( hamtype == 0 ): #General hamiltonian self.V_emb = V_emb[ :2*self.Nimp, :2*self.Nimp, :2*self.Nimp, :2*self.Nimp ]
def _integrate(self, prev, dt, eta0, q, g0=np.eye(4), intermediate=False): self.xi[0, :] = np.array([0, 0, 0, 0, 0, 1]) self.eta[0, :] = eta0 # integration over the body (don't need the initial point as the initial values are determined already) # g_half = g0 # known initial condition g_half = expm(dt / 2 * se(prev.eta[0, :])) for i in range(self.N - 1): # averaging over steps to get half step values xi_half = (self.xi[i, :] + prev.xi[i, :]) / 2 eta_half = (self.eta[i, :] + prev.eta[i, :]) / 2 # implicit midpoint approximation xi_dot = (self.xi[i, :] - prev.xi[i, :]) / dt eta_dot = (self.eta[i, :] - prev.eta[i, :]) / dt # external loads A_bar = 0 B_bar = 0 # viscosity B_bar += self.V @ xi_dot # other loads for load in self.loads: A, B = load.dist_load(g_half, xi_half, eta_half, xi_dot, eta_dot, self, q) A_bar += A B_bar += B if intermediate and i == self.N - 2: for load in self.loads: W = load.tip_load(g_half, xi_half, eta_half, xi_dot, eta_dot, self, q) B_bar += W # spatial derivatives xi_der = np.linalg.inv(self.K - A_bar) @ ( (self.M @ eta_dot) - (adjoint(eta_half).T @ self.M @ eta_half) + (adjoint(xi_half).T @ self.K @ (xi_half - self.xi_ref)) + B_bar) eta_der = xi_dot - (adjoint(xi_half) @ eta_half) # explicit Euler step xi_half_next = xi_half + self.ds * xi_der eta_half_next = eta_half + self.ds * eta_der g_half = g_half @ expm(se(self.ds * xi_half)) # determine next step from half step value self.xi[i + 1, :] = 2 * xi_half_next - prev.xi[i + 1, :] self.eta[i + 1, :] = 2 * eta_half_next - prev.eta[i + 1, :] # midpoint RKMK to step the g values for i in range(self.N): self.g[i, :] = flatten( unflatten(prev.g[i, :]) @ expm( se(dt * (self.eta[i, :] + prev.eta[i, :]) / 2))) return g_half
def FCI_GS(h, V, Ecore, Norbs, Nele): #Subroutine to perform groundstate FCI calculation using pyscf if (isinstance(Nele, tuple)): Nele = sum(Nele) #Define pyscf molecule mol = gto.M() mol.nelectron = Nele mol.incore_anyway = True #this call is necessary to use user defined hamiltonian in fci step #First perform HF calculation mf = scf.RHF(mol) mf.get_hcore = lambda *args: h mf.get_ovlp = lambda *args: np.eye(Norbs) mf._eri = ao2mo.restore(8, V, Norbs) mf.kernel() #Perform FCI calculation using HF MOs cisolver = pyscf.fci.FCI(mf, mf.mo_coeff) E_FCI, CIcoeffs = cisolver.kernel() #Rotate CI coefficients back to site basis used in DMET calculations CIcoeffs = pyscf.fci.addons.transform_ci_for_orbital_rotation( CIcoeffs, Norbs, Nele, utils.adjoint(mf.mo_coeff)) return CIcoeffs
def calc_Umat( natevals, natorbs, Nsites, Nocc ): #Subroutine to calculate the summed U tensor #First form matrix given by one over the difference in the global 1RDM natural orbital evals #(ie just the evals of the global 1RDM) #This only has to be defined for the occupied - virtual block b/c MF rdm invariant to intra-space rotations #chi = np.zeros( [ Nocc, (Nsites-Nocc) ] ) #for mu in range(Nocc): # for nu in range(Nocc,Nsites): # chi[ mu, nu-Nocc ] = 1.0/(natevals[mu]-natevals[nu]) #grr## chi = np.zeros( [ Nocc, Nsites ] ) for mu in range(Nocc): for nu in range(Nsites): if( mu != nu and natevals[mu]-natevals[nu] > 1e-14 ): chi[ mu, nu ] = 1.0/(natevals[mu]-natevals[nu]) #Adjoint of natural orbitals adj_natorbs = utils.adjoint( natorbs ) #Form U tensor by summing over natural orbitals #PING can calculate U in this form more quickly using its hermiticity #U = np.einsum( 'ij,pj,js,ri,iq -> sqpr', chi, natorbs[:,Nocc:], adj_natorbs[Nocc:,:], natorbs[:,:Nocc], adj_natorbs[:Nocc,:] ) U = np.einsum( 'ij,pj,js,ri,iq -> sqpr', chi, natorbs[:,:], adj_natorbs[:,:], natorbs[:,:Nocc], adj_natorbs[:Nocc,:] ) #grr #Return the total summed U matrix return U + np.einsum( 'sqpr -> qsrp', U )
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 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 print_data(self, current_time): #Subroutine to calculate and print-out observables of interest fmt_str = '%20.8e' ######## CALCULATE OBSERVABLES OF INTEREST ####### #Calculate DMET energy, which also includes calculation of 1 & 2 RDMs and embedding hamiltonian for each fragment self.tot_system.get_DMET_E() #Calculate total number of electrons self.tot_system.get_DMET_Nele() ####msh#### frag = self.tot_system.frag_list[0] #Efci = fci_mod.get_FCI_E( frag.h_emb, frag.V_emb, 0.0, frag.CIcoeffs, 2*frag.Nimp, frag.Nimp, frag.Nimp ) #print( Efci, file=self.file_test ) testdata = np.zeros(3 + self.tot_system.Nsites) testdata[0] = current_time testdata[1] = np.linalg.norm(frag.CIcoeffs)**2 testdata[2] = np.real(np.sum(np.diag(frag.corr1RDM))) testdata[3:] = np.copy( np.real(np.diag(np.dot(utils.adjoint(frag.rotmat), frag.rotmat)))) np.savetxt(self.file_test, testdata.reshape(1, testdata.shape[0]), fmt_str) self.file_test.flush() ########### ######## PRINT OUT EVERYTHING ####### #Print correlated density in the site basis cnt = 0 corrdens = np.zeros(self.tot_system.Nsites) for frag in self.tot_system.frag_list: corrdens[cnt:cnt + frag.Nimp] = np.copy( np.diag(np.real(frag.corr1RDM[:frag.Nimp]))) cnt += frag.Nimp corrdens = np.insert(corrdens, 0, current_time) np.savetxt(self.file_corrdens, corrdens.reshape(1, corrdens.shape[0]), fmt_str) self.file_corrdens.flush() #Print output data output = np.zeros(3) output[0] = current_time output[1] = self.tot_system.DMET_E output[2] = self.tot_system.DMET_Nele np.savetxt(self.file_output, output.reshape(1, output.shape[0]), fmt_str) self.file_output.flush() #Save total system to file for restart purposes using pickle file_system = open('restart_system.dat', 'wb') pickle.dump(self.tot_system, file_system) file_system.close()
def calc_Yvec(Umat, phimat, Nsites): #Subroutine to calculate the Y super-vector #Contract Umat and phimat Yvec = np.einsum('sqpr,sr -> pq', Umat, phimat) #Sum up Y vector Yvec = Yvec - utils.adjoint(Yvec) #Reshape Y vector to be a super-vector return -1j * Yvec.reshape(Nsites**2)
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 calc_Rmat( system ): #Subroutine to calculate the 4-index R tensor R = np.zeros( [ system.Nsites, system.Nsites, system.Nsites, system.Nsites ], dtype=complex ) for r in range( system.Nsites ): #Fragment corresponding to site r frag = system.frag_list[system.site_to_frag_list[r]] #Concatenated list of virtual and core orbitals for fragment virtcore = np.concatenate( ( frag.virtrange, frag.corerange ) ) #First form matrix given by one over the difference in the environment orbital eigenvalues #This only has to be defined for the bath - core/virtual space #Subtract off terms b/c indexing of embedding orbitals goes as imp,virt,bath,core chi = np.zeros( [ frag.Nimp, frag.Ncore+frag.Nvirt ] ) i = 0 for a in frag.bathrange: j = 0 for c in virtcore: chi[i,j] = 1.0/( frag.env1RDM_evals[a-frag.Nimp] - frag.env1RDM_evals[c-frag.Nimp] ) j += 1 i += 1 #Impurity index within fragment corresponding to site r rimp = system.site_to_impindx[r] #Adjoint of rotation matrix adj_rotmat = utils.adjoint( frag.rotmat ) #Form portion of R tensor by summing over embedding orbitals #a is over bath orbitals and c is over virtual and core orbitals R[:,:,:,r] = np.einsum( 'ac,sc,ct,ua,a -> stu', chi, frag.rotmat[:,virtcore], adj_rotmat[virtcore,:], \ frag.rotmat[:,frag.bathrange], frag.corr1RDM[frag.Nimp:,rimp] ) return R
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 integrate(mf1RDM, CIcoeffs, Nsites, Nele, h_site, delt, Nimp, rotmat): l1, k1, rotmat = one_rk_step(mf1RDM, CIcoeffs, Nsites, Nele, h_site, Nimp, delt, rotmat) l2, k2, rotmat = one_rk_step(mf1RDM + 0.5 * l1, CIcoeffs + 0.5 * k1, Nsites, Nele, h_site, Nimp, delt, rotmat) l3, k3, rotmat = one_rk_step(mf1RDM + 0.5 * l2, CIcoeffs + 0.5 * k2, Nsites, Nele, h_site, Nimp, delt, rotmat) l4, k4, rotmat = one_rk_step(mf1RDM + 1.0 * l3, CIcoeffs + 1.0 * k3, Nsites, Nele, h_site, Nimp, delt, rotmat) mf1RDM = mf1RDM + 1.0 / 6.0 * (l1 + 2.0 * l2 + 2.0 * l3 + l4) CIcoeffs = CIcoeffs + 1.0 / 6.0 * (k1 + 2.0 * k2 + 2.0 * k3 + k4) rotmat_old = np.copy(rotmat) 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) return mf1RDM, CIcoeffs, rotmat
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
def integrate(self, nproc): #Subroutine to integrate equations of motion if (self.integ == 'rk1_orb'): #Use 1st order runge-kutta (ie euler's method) to integrate EOMs #Using EOM that explicitly integrate embedding orbitals and CI coefficients using X-matrix #Calculate appropriate changes in rotation matrices and CI coeffients #Note that l and k terms are for the rotation matrices and CI coefficients respectively l1_list, k1_list = self.one_rk_step_orb(nproc) #Update rotation matrices and CI coefficients by full time step for cnt, frag in enumerate(self.tot_system.frag_list): frag.rotmat += l1_list[cnt] frag.CIcoeffs += k1_list[cnt] elif (self.integ == 'rk4_orb'): #Use 4th order runge-kutta to integrate EOMs #Using EOM that explicitly integrate embedding orbitals and CI coefficients using X-matrix #Copy rotation matrices (ie orbitals) and CI coefficients at time t init_rotmat_list = [] init_CIcoeffs_list = [] for frag in self.tot_system.frag_list: init_rotmat_list.append(np.copy(frag.rotmat)) init_CIcoeffs_list.append(np.copy(frag.CIcoeffs)) #Calculate appropriate changes in rotation matrices and CI coeffients #Note that l and k terms are for the rotation matrices and CI coefficients respectively l1_list, k1_list = self.one_rk_step_orb(nproc) for cnt, frag in enumerate(self.tot_system.frag_list): frag.rotmat = init_rotmat_list[cnt] + 0.5 * l1_list[cnt] frag.CIcoeffs = init_CIcoeffs_list[cnt] + 0.5 * k1_list[cnt] l2_list, k2_list = self.one_rk_step_orb(nproc) for cnt, frag in enumerate(self.tot_system.frag_list): frag.rotmat = init_rotmat_list[cnt] + 0.5 * l2_list[cnt] frag.CIcoeffs = init_CIcoeffs_list[cnt] + 0.5 * k2_list[cnt] l3_list, k3_list = self.one_rk_step_orb(nproc) for cnt, frag in enumerate(self.tot_system.frag_list): frag.rotmat = init_rotmat_list[cnt] + 1.0 * l3_list[cnt] frag.CIcoeffs = init_CIcoeffs_list[cnt] + 1.0 * k3_list[cnt] l4_list, k4_list = self.one_rk_step_orb(nproc) #Update rotation matrices and CI coefficients by full time-step for cnt, frag in enumerate(self.tot_system.frag_list): frag.rotmat = init_rotmat_list[cnt] + 1.0 / 6.0 * ( l1_list[cnt] + 2.0 * l2_list[cnt] + 2.0 * l3_list[cnt] + l4_list[cnt]) frag.CIcoeffs = init_CIcoeffs_list[cnt] + 1.0 / 6.0 * ( k1_list[cnt] + 2.0 * k2_list[cnt] + 2.0 * k3_list[cnt] + k4_list[cnt]) elif (self.integ == 'rk4_mf'): #Use 4th order runge-kutta to integrate EOMs #Using EOM that integrates CI coefficients and MF 1RDM #embedding orbitals obtained by diagonalizing MF 1RDM at each step #Copy MF 1RDM and CI coefficients at time t init_mf1RDM = np.copy(self.tot_system.mf1RDM) init_CIcoeffs_list = [] for frag in self.tot_system.frag_list: init_CIcoeffs_list.append(np.copy(frag.CIcoeffs)) #Calculate appropriate changes in MF 1RDM and CI coefficients #Note that l and k terms are for MF 1 RDM and CI coefficients respectively l1, k1_list = self.one_rk_step_mf(nproc) self.tot_system.mf1RDM = init_mf1RDM + 0.5 * l1 for cnt, frag in enumerate(self.tot_system.frag_list): frag.CIcoeffs = init_CIcoeffs_list[cnt] + 0.5 * k1_list[cnt] ###msh## #print() #print('****************************') #print() #print( self.tot_system.mf1RDM ) #print() #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 ) #self.tot_system.get_frag_corr1RDM() #self.tot_system.get_glob1RDM() #self.tot_system.get_nat_orbs() #self.tot_system.get_new_mf1RDM( int(self.tot_system.Nele/2) ) #print( self.tot_system.mf1RDM) #exit() ####### l2, k2_list = self.one_rk_step_mf(nproc) self.tot_system.mf1RDM = init_mf1RDM + 0.5 * l2 for cnt, frag in enumerate(self.tot_system.frag_list): frag.CIcoeffs = init_CIcoeffs_list[cnt] + 0.5 * k2_list[cnt] l3, k3_list = self.one_rk_step_mf(nproc) self.tot_system.mf1RDM = init_mf1RDM + 1.0 * l3 for cnt, frag in enumerate(self.tot_system.frag_list): frag.CIcoeffs = init_CIcoeffs_list[cnt] + 1.0 * k3_list[cnt] l4, k4_list = self.one_rk_step_mf(nproc) #Update MF 1RDM and CI coefficients by full time-step self.tot_system.mf1RDM = init_mf1RDM + 1.0 / 6.0 * (l1 + 2.0 * l2 + 2.0 * l3 + l4) for cnt, frag in enumerate(self.tot_system.frag_list): frag.CIcoeffs = init_CIcoeffs_list[cnt] + 1.0 / 6.0 * ( k1_list[cnt] + 2.0 * k2_list[cnt] + 2.0 * k3_list[cnt] + k4_list[cnt]) #Update rotation matrix at new time-step by diagonalizing MF 1RDM maintaing same phase from previous step #Technically maintaining phase amongst each partial step along RK algorithm 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) elif (self.integ == 'exact'): #Exactly propagate CI coefficients #Only works if have 2 fragments, each spanning full space since then embedding hamiltonian is time-independent #and embedding orbitals are time-independent #Embedding hamiltonian must also be real #Calculate embedding hamiltonian (isnt technically needed since it doesnt change) self.tot_system.get_frag_Hemb() #Form FCI hamiltonian (technically only need to do this at time zero since doesnt change) for frag in self.tot_system.frag_list: dim1 = frag.CIcoeffs.shape[0] dim2 = frag.CIcoeffs.shape[1] Ndet = dim1 * dim2 H_fci = np.zeros([Ndet, Ndet]) for i1 in range(dim1): for i2 in range(dim2): vec1 = np.zeros([dim1, dim2]) vec1[i1, i2] = 1.0 i = i2 + i1 * dim2 for j1 in range(dim1): for j2 in range(dim2): j = j2 + j1 * dim2 vec2 = np.zeros([dim1, dim2]) vec2[j1, j2] = 1.0 H_fci[i, j] = pyscf.fci.addons.overlap( vec1, np.real( applyham_pyscf. apply_ham_pyscf_fully_complex( vec2, frag.h_emb, frag.V_emb, frag.Nimp, frag.Nimp, 2 * frag.Nimp, frag.Ecore)), 2 * frag.Nimp, (frag.Nimp, frag.Nimp)) #Convert matrix of CI coeffs to a vector CIvec = frag.CIcoeffs.flatten('F') #Exactly integrate the CI coefficients using the FCI hamiltonian frag.CIcoeffs = integrators.exact_timeindep_coeff_matrix( CIvec, H_fci, self.delt).reshape((dim1, dim2), order='F') else: print('ERROR: A proper integrator was not specified') print() exit()
A = st.Psitf xhat = tf.constant(0,dtype=tf.float32) MUL = tf.matmul NoverM = tf.constant(float(N)/M,dtype=tf.float32) OneOverM = tf.constant(float(1)/M,dtype=tf.float32) for t in range(st.T): # layers 0 thru T-1 if t==0: # xhat is zero, vt is zero vt = y_ph else: bt = dxdr * NoverM vt = y_ph - MUL( A , xhat ) + bt * vt rvar = tf.reduce_sum(tf.square(vt),0) * OneOverM if t==0 or not st.tieS: Bt = MUL(ut.adjoint(A) ,S[t] ) (xhat,dxdr) = shrink_func( xhat + MUL(Bt,vt),rvar , theta[t] ) # in the case of T==1, at least some of the shrinkage functions (e.g. "soft") # are overparameterized for only a loss on xhat. # To mitigate this, we add an extremely weak penalty on the norm of the next v if st.T == 1 and st.T1weight > 0: bt = dxdr * NoverM vt = y_ph - MUL( A , xhat ) + bt * vt rvar = tf.reduce_sum(tf.square(vt),0) * OneOverM st.add_penalty(st.T1weight * rvar ) st.set_output_node(xhat) print 'nmse_check : %.1fdB' % (10*math.log10(st.current_value(st.nmse_check)) ) st.run()
def _integrate(self, prev, dt, xi0, q, g0=np.eye(4), eta0=np.array([0, 0, 0, 0, 0, 0]), intermediate=False): self.xi[0, :] = xi0 self.eta[0, :] = eta0 # integration over the body (don't need the initial point as the initial values are determined already) g_half = g0 # known initial condition for i in range(self.N - 1): s = i * self.ds # averaging over steps to get half step values xi_half = (self.xi[i, :] + prev.xi[i, :]) / 2 eta_half = (self.eta[i, :] + prev.eta[i, :]) / 2 # implicit midpoint approximation xi_dot = (self.xi[i, :] - prev.xi[i, :]) / dt eta_dot = (self.eta[i, :] - prev.eta[i, :]) / dt # external loads A_bar = 0 B_bar = 0 # viscosity B_bar += self.body.viscosity(xi_dot, s) # other loads for load in self.loads: A, B = load.dist_load(g_half, xi_half, eta_half, xi_dot, eta_dot, self, q, s) A_bar += A B_bar += B if intermediate and i == self.N - 2: for load in self.loads: W = load.tip_load(g_half, xi_half, eta_half, xi_dot, eta_dot, self, q) B_bar += W # spatial derivatives xi_der = np.linalg.inv(self.body.Psi_der(xi_half, s) - A_bar) @ ( (self.body.M(s) @ eta_dot) - (adjoint(eta_half).T @ self.body.M(s) @ eta_half) + ( adjoint(xi_half).T @ self.body.Psi(xi_half, s)) + B_bar - self.body.Psi_prime(xi_half, s)) eta_der = xi_dot - (adjoint(xi_half) @ eta_half) # explicit Euler step xi_half_next = xi_half + self.ds * xi_der eta_half_next = eta_half + self.ds * eta_der R = g_half[:3, :3] p = g_half[:3, 3] p = p + self.ds * R @ xi_half[3:] q = toQuaternion(R) q = q + self.ds / 2 * np.array( [[0, -xi_half[0], -xi_half[1], -xi_half[2]], [xi_half[0], 0, xi_half[2], -xi_half[1]], [xi_half[1], -xi_half[2], 0, xi_half[0]], [xi_half[2], xi_half[1], -xi_half[0], 0]]) @ q g_half = unflatten(np.concatenate([q, p])) # determine next step from half step value self.xi[i + 1, :] = 2 * xi_half_next - prev.xi[i + 1, :] self.eta[i + 1, :] = 2 * eta_half_next - prev.eta[i + 1, :] # midpoint RKMK to step the g values for i in range(self.N): eta_half = (self.eta[i, :] + prev.eta[i, :]) / 2 q = prev.g[i, :4] p = prev.g[i, 4:] q = q + dt / 2 * np.array( [[0, -eta_half[0], -eta_half[1], -eta_half[2]], [eta_half[0], 0, eta_half[2], -eta_half[1]], [eta_half[1], -eta_half[2], 0, eta_half[0]], [eta_half[2], eta_half[1], -eta_half[0], 0]]) @ q p = p + dt * toMatrix((q + prev.g[i, :4]) / 2) @ eta_half[3:] self.g[i, :] = np.concatenate([q, p]) return g_half
({}, 'problem_Giid'), ({ 'kappa': 15. }, 'problem_k15'), ) for kw, base in configurations: # set up the inverse problem basic structure with the configuration-specific kw st = ut.Setup(**kw) y_ph = st.get_input_node() # the structure inside of Setup doesn't create all the fields until `set_output_node` # so set a dummy value ( not really used ) st.set_output_node( tf.Variable(1.0, name='junk', dtype=tf.float32) * tf.matmul(ut.adjoint(st.Psitf), y_ph)) # a dictionary with the problem setup prob = st.get_problem_vars() # save as a numpy archive np.savez(base + '.npz', **prob) print 'saved numpy archive %s.npz' % base try: from scipy.io import savemat savemat(base + '.mat', prob, oned_as='column') print 'saved matlab file %s.mat' % base except ImportError: pass
def contract_natorb_rotmat(self, NOevecs): #Subroutine to contract the rotation matrix of the given fragment with #the natural orbitals of the total system global 1RDM self.NO_rot = utils.matprod(utils.adjoint(NOevecs), self.rotmat)
st.flag('setup', False, 'initialize the last layer greedily') ##### create LISTA graph # start with the input (to the LISTA inference algorithm) y_ph = st.get_input_node() print st if st.setup: import lista_setup lista_setup.Setup(st) Wd = st.noisy_Psi() L = 1.1 * LA.norm(Wd, 2)**2 We_ = ut.adjoint(Wd / L) We = st.variable('We', We_) We_ = st.loaded_state.get('We', We_) def checkS(lS, dS): ls = lS.shape ds = dS.shape if ls == ds: return lS res = lS[:] if ls[0] < ds[0]: # expand with I-We_*Wd Snew = np.identity(st.n, dtype=Wd.dtype) - np.matmul(We_, Wd) ngrow = ds[0] - ls[0] tiledims = (ngrow, 1, 1)