def test2(): '''测试right相关的''' right = first_rightblock(10) cudown = create_operator_of_site(right.fock_basis, OperFactory.create_spindown()) print(cudown) #扩展right rightext = extend_rightblock(right) cuup2 = create_operator_of_site(rightext.stbss, OperFactory.create_spinup()) #扩展rightext上面的两个算符 cudownext = rightblock_extend_oper(rightext, cudown) print(cudownext) cuup2ext = rightsite_extend_oper(rightext, cuup2) print(cuup2ext) #将扩展完的两个算符收缩到新的right上 phival = random_phival([16, 16], rightext) newright = update_to_rightblock(rightext, phival) print(newright) #print(newright.fock_dict) newcudown = update_rightblockextend_oper(newright, cudownext, phival) newcuup2 = update_rightblockextend_oper(newright, cuup2ext, phival) print(newcudown) print(newcuup2) #再给right扩展一个 newrightext = extend_rightblock(newright) print(newrightext) #, newrightext._fock_basis) #扩展newright上面的算符 newcudownext = rightblock_extend_oper(newrightext, newcudown) phival = random_phival([8, 64], newrightext) newnewright = update_to_rightblock(newrightext, phival) newnewcudown = update_rightblockextend_oper(newnewright, newcudownext, phival) print(newnewcudown)
def init_first_site(model: BaseModel, nrg_maxkeep: int, meass: List[Tuple[str, int]]): '''初始化第一个site\n 这个时候只有1和N上面的block,创建这两个block上面的升降算符\n 还有以后观测要用的算符。 meass中应该是[(1, 'sz'), (N, 'sz')](N是最后一个格子的编号)\n 这样的内容 ''' conf = DMRGConfig(model, nrg_maxkeep) # left = first_leftblock(model.sites[0]) #创建第一个格子上的哈密顿量,还有第一个格子的产生算符 hamleft = create_hamiltonian_of_site(left.fock_basis, model.coef_u, model.get_coef_mu(model.sites[0])) cup1 = create_operator_of_site(left.fock_basis, OperFactory.create_spinup()) cdn1 = create_operator_of_site(left.fock_basis, OperFactory.create_spindown()) #把现在的结果暂存到dconf conf.left_tmp_reset(model.sites[0], left, hamleft) conf.left_tmp_add_oper(cup1) conf.left_tmp_add_oper(cdn1) # right = first_rightblock(model.sites[-1]) #创建最后一个格子上的哈密顿量,还有最后一个格子的产生算符 hamright = create_hamiltonian_of_site(right.fock_basis, model.coef_u, model.get_coef_mu(model.sites[-1])) cuplast = create_operator_of_site(right.fock_basis, OperFactory.create_spinup()) cdnlast = create_operator_of_site(right.fock_basis, OperFactory.create_spindown()) #把右侧的结果也暂存到dconf conf.right_tmp_reset(model.sites[-1], right, hamright) conf.right_tmp_add_oper(cuplast) conf.right_tmp_add_oper(cdnlast) #把block上面的算符存储到tmp里,以后需要的是ext上面的算符 leftstor = conf.get_leftblock_storage(model.sites[0]) rightstor = conf.get_rightblock_storage(model.sites[-1]) for prefix, idx in meass: if idx == model.sites[0]: stor = leftstor basis = left elif idx == model.sites[-1]: stor = rightstor basis = right else: raise ValueError('这个算符不在第一个或最后一个格子') measop = create_operator_of_site(basis.fock_basis, OperFactory.create_by_name(prefix)) stor.storage_meas(prefix, measop) return conf
def test1(): '''测试leftblock''' #first_block中的phi有四个分量,内容和一个格子是一致的 left = first_leftblock(1) cuop = create_operator_of_site(left.fock_basis, OperFactory.create_spinup()) #nuop = create_operator_of_site(left.fock_basis, OperFactory.number_spinup()) leftext = extend_leftblock(left) print(left) print(cuop) #print(nuop) #print('验证:', numpy.matmul(cuop.mat, cuop.mat.transpose())) cuopext = leftblock_extend_oper(leftext, cuop) #nuopext = leftblock_extend_oper(leftext, nuop) print(cuopext) #print('验证2:', nuopext) #print(numpy.matmul(cuopext.mat,cuopext.mat.transpose())) # print('site上的算符更新') # cuop2 = create_operator_of_site(leftext.stbss, OperFactory.create_spinup()) #nuop2 = create_operator_of_site(leftext.stbss, OperFactory.number_spinup()) print(cuop2) cuop2ext = leftsite_extend_oper(leftext, cuop2) #nuop2ext = leftsite_extend_oper(leftext, nuop2) print(cuop2ext) #print('验证3:', nuop2ext) #print(numpy.matmul(cuop2ext.mat, cuop2ext.mat.transpose())) # phival = random_phival([4, 16], leftext) newleft = update_to_leftblock(leftext, phival) print(newleft) # newcuop = update_leftblockextend_oper(newleft, cuopext, phival) #newnuop = update_leftblockextend_oper(newleft, nuopext, phival) print(newcuop) #print('验证4', newnuop) #print(numpy.matmul(newnuop.mat, newnuop.mat.transpose())) # newleftext = extend_leftblock(newleft) newcuopext = leftblock_extend_oper(newleftext, newcuop) phival = random_phival([8, 16], newleftext) newnewleft = update_to_leftblock(newleftext, phival) newnewcuop = update_leftblockextend_oper(newnewleft, newcuopext, phival) print(newnewcuop)
def leftblock_to_next( conf: DMRGConfig, phi_idx: int, newbonds: List[int], extoper_storage: List[int], tmpoper_storage: List[int], measuer_storage: List[Tuple[str, int]] ): '''将leftblock向前推进一个格子\n left是需要推进的block\n phi_idx是新的left的idx,这个和block_len不一定是一个东西\n conf是程序运行时的句柄\n newbonds是新加的这个site和哪些site有bond(新的site是left.fock_basis.site[-1]+1)\n extoper_storage是指|phi^phi_idx-1, s^phi_idx>这个基上有哪些算符需要保存\n 村下来的extoper以后要用到superblock上。\n tmpoper_storage是指在|phi^phi_idx>这个基上要临时存储的算符,用在下一次递推\n 时的哈密顿量计算,以及下一次的迭代中需要保存的ext\n measure_storage是指以后dmrg需要观测的过程中要计算的算符,需要保存到leftstorage中\n leftext[phi_idx-1]上面的观测算符也需要保存,由于leftext[phi_idx-1]和\n leftblock[phi_idx]实际上是一个block_len这里用一个参数指定就可以了\n ''' leftstorage = conf.get_leftblock_storage(phi_idx-1) left = leftstorage.block hamleft = leftstorage.hamiltonian ### 开始处理leftext在leftext上面工作的内容 #把left扩展一个格子 leftext = extend_leftblock(left) #给leftext进行初始化,leftext[phi_idx-1]中存的就是leftblock[phi_idx-1]的extend conf.leftext_reset(phi_idx-1, leftext) #把哈密顿量扩展一个格子 hamleft = extend_leftblock_hamiltonian(hamleft, leftext) #把扩展基上的哈密顿量存下来 conf.storage_leftext_ham(phi_idx-1, hamleft) #存储需要进行扩展的算符 maintain_opers = {} #创建新的格子上厄的两个算符并且扩展 newup = create_operator_of_site(leftext.stbss, OperFactory.create_spinup()) newup = leftsite_extend_oper(leftext, newup) newdown = create_operator_of_site(leftext.stbss, OperFactory.create_spindown()) newdown = leftsite_extend_oper(leftext, newdown) #if leftext.stbss.sites[0] in tmpoper_storage: maintain_opers[leftext.stbss.sites[0]] = (newup, newdown) #把left_tmp中所有的算符扩展 #注意这个时候leftstorage.oper_storage_list会被修改, #不能在这个上面进行循环 while len(leftstorage.oper_storage_list) > 0: #for stidx in leftstorage.oper_storage_list: stidx = leftstorage.oper_storage_list[0] #把left上面的两个算符弹出 stup, stdown = leftstorage.pop_oper(stidx) #将两个算符扩展 stup = leftblock_extend_oper(leftext, stup) stdown = leftblock_extend_oper(leftext, stdown) maintain_opers[stidx] = (stup, stdown) #把需要保存到leftext中的算符保存下来 for stidx in extoper_storage: conf.storage_leftext_oper(phi_idx-1, maintain_opers[stidx][0]) conf.storage_leftext_oper(phi_idx-1, maintain_opers[stidx][1]) #找到构成bond的算符,把新的hopping添加到哈密顿量 for bstidx in newbonds: coef_t = conf.model.get_t_coef(bstidx, newup.siteidx) #自旋上部分 tar_up = maintain_opers[bstidx][0] hamleft.add_hopping_term(newup, tar_up, coef_t) #自旋下部分 tar_down = maintain_opers[bstidx][1] hamleft.add_hopping_term(newdown, tar_down, coef_t) #构建U项并扩展,然后添加到哈密顿量 newiu = create_operator_of_site(leftext.stbss, OperFactory.create_u()) newiu = leftsite_extend_oper(leftext, newiu) hamleft.add_u_term(newiu, conf.model.coef_u) #构建Mu项并扩展,然后添加到哈密顿量 coef_mu = conf.model.get_coef_mu(phi_idx) if coef_mu != 0: newnu = create_operator_of_site(leftext.stbss, OperFactory.create_numup()) newnu = leftsite_extend_oper(leftext, newnu) hamleft.add_mu_term(newnu, coef_mu) newnd = create_operator_of_site(leftext.stbss, OperFactory.create_numdown()) newnd = leftsite_extend_oper(leftext, newnd) hamleft.add_mu_term(newnd, coef_mu) ### 开始从leftext升级到下一个left #调用get_phival_from_hamleft,得到能量本正值 #获得相应的自旋sector限制 if phi_idx <= numpy.floor_divide(conf.model.size, 2): sector = None else: sector = [] sp1min = conf.spin_sector[0] - (conf.model.size - phi_idx) if sp1min < 0: sp1min = 0 sp1max = conf.spin_sector[0] sp2min = conf.spin_sector[1] - (conf.model.size - phi_idx) if sp2min < 0: sp2min = 0 sp2max = conf.spin_sector[1] for se1 in range(sp1min, sp1max + 1): for se2 in range(sp2min, sp2max + 1): sector.append((se1, se2)) phival = get_phival_from_hamleft( hamleft, leftext, conf.nrg_max_keep, restrict_sector=sector ) #给leftext升级成新的基,这个时候phival其实没什么用 #但fermionic在DEBUG_MODE下会解出basis在fock_basis下的系数,这个是需要的 newleft = update_to_leftblock(leftext, phival) #给哈密顿量进行更新 hamleft = update_leftblockextend_hamiltonian(newleft, hamleft, phival) #把tmp中保存的leftblock[phi_idx-1]的观测算符取出来,并扩展到 #leftext[phi_idx-1] ext_measops = {} for meas in measuer_storage: if meas[1] == phi_idx:#如果是这次新加的格子,就创建一个而不是读取 meaop = create_operator_of_site( leftext.stbss, OperFactory.create_by_name(meas[0]) ) meaop = leftsite_extend_oper(leftext, meaop) else: meaop = leftstorage.get_meas(meas[0], meas[1]) meaop = leftblock_extend_oper(leftext, meaop) ext_measops['%s,%d' % meas] = meaop #给conf中的left_tmp重置,现在left_tmp应该保存phi_idx的哈密顿量和算符了 conf.left_tmp_reset(phi_idx, newleft, hamleft) #给下一次运算需要保存的算符更新 for stidx in tmpoper_storage: up_ext, down_ext = maintain_opers[stidx] up_upd = update_leftblockextend_oper(newleft, up_ext, phival) down_upd = update_leftblockextend_oper(newleft, down_ext, phival) conf.left_tmp_add_oper(up_upd) conf.left_tmp_add_oper(down_upd) #给以后需要观测的算符进行保存 leftext_stor = conf.get_leftext_storage(phi_idx-1) leftstorage = conf.get_leftblock_storage(phi_idx) for prefix, stidx in measuer_storage: #如果这个site是之前的block上面的,已经扩展到了leftext[phi_idx-1] #保存到leftext[phi_idx-1] #升级到leftblock[phi_idx],存到left_tmp meaop = ext_measops['%s,%d' % (prefix, stidx)] leftext_stor.storage_meas(prefix, meaop) #升级 meaop = update_leftblockextend_oper(newleft, meaop, phival) leftstorage.storage_meas(prefix, meaop) return newleft
def leftblockextend_to_next(conf: DMRGConfig, phi_idx: int, extrabonds: List[int], newbonds: List[int], extoper_storage: List[int], measure_storage: List[Tuple[str, int]], spin_sector, maxkeep: int): '''在右侧的rightext迭代到位以后,开始左侧的迭代\n 这个时候的phi_idx是新的leftblockext的idx,新加的site就是phi_idx+1,\n 相对应的rightblockext的idx就是phi_idx+2 ''' leftstorage = conf.get_leftext_storage(phi_idx - 1) rightstorage = conf.get_rightext_storage(phi_idx + 2) #首先要把superblock拼出来 sector_idxs, mat, superext = get_superblock_ham(conf.model, leftstorage, rightstorage, spin_sector, extrabonds) #把基态解出来 eigvals, eigvecs = scipy.sparse.linalg.eigsh(mat, k=1, which='SA') #numpy.linalg.eigh(mat) ground = eigvecs[:, 0] ground_erg = eigvals[0] #把基态的信息保留下来 conf.ground_vec = ground conf.ground_secidx = sector_idxs conf.ground_superext = superext #构造密度矩阵 lidxs, ridxs, mat = get_density_root( #pylint: disable=unused-variable leftstorage, rightstorage, sector_idxs, ground) #这个mat行是phi^phi_idx-1,s^phi_idx,列是s^phi_idx+1,phi^phi_idx+2 #lidxs是mat上的行到leftext的基的指标 #利用矩阵乘法收缩掉列 denmat = numpy.matmul(mat, mat.transpose()) #把密度矩阵再分成相同粒子数在一起的小块 #这时就不需要到superblock上面的idx了,需要从phi^phi_idx-1,s^phi_idx #到leftext的idx spsec_mat_dict = get_density_in_sector(leftstorage, lidxs, denmat) #获得更新基的phival #这个过程就是给每一个denmat的subblock对角化,注意phival最后会 #放到整个leftext的基上面去 phival = get_phival_from_density_sector(leftstorage, spsec_mat_dict, maxkeep) #现在给leftblockext升级成新的位置上面的ext #先从leftblkext升级到left + 1 leftext = leftstorage.block newleftblk = update_to_leftblock(leftext, phival) #然后升级哈密顿量 newham = update_leftblockextend_hamiltonian(newleftblk, leftstorage.hamiltonian, phival) #调整一下tmp中的idx,没有实际的价值 conf.left_tmp_reset(phi_idx, newleftblk, None) #先把newleftblk上面的算符升级,然后再扩展 maintain_dict = {} for extidx in leftstorage.oper_storage_list: extup = leftstorage.get_oper(extidx, 1) newup = update_leftblockextend_oper(newleftblk, extup, phival) extdn = leftstorage.get_oper(extidx, -1) newdn = update_leftblockextend_oper(newleftblk, extdn, phival) maintain_dict[extidx] = (newup, newdn) #完成phi_idx位置上的leftblock,开始扩展它到leftblockextend newleftext = extend_leftblock(newleftblk) #把哈密顿量也扩展 newhamext = extend_leftblock_hamiltonian(newham, newleftext) #以后的观测需要的算符,从leftext[phi_idx-1]中拿到,再升级扩展 #以后放到leftext[phi_idx]中 ext_meaops = {} for prefix, stidx in measure_storage: if stidx == phi_idx + 1: #如果是新加的格子上的算符,不需要升级 #新建一个观测用的算符 meaop = create_operator_of_site(newleftext.stbss, OperFactory.create_by_name(prefix)) #扩展到leftext[phi_idx]上 meaop = leftsite_extend_oper(newleftext, meaop) else: #得到meaop meaop = leftstorage.get_meas(prefix, stidx) #升级meaop到leftblock[phi_idx] meaop = update_leftblockextend_oper(newleftblk, meaop, phival) #扩展 meaop = leftblock_extend_oper(newleftext, meaop) ext_meaops['%s,%d' % (prefix, stidx)] = meaop #把现在的缓存进去 conf.leftext_reset(phi_idx, newleftext) conf.storage_leftext_ham(phi_idx, newhamext) #获得新加的格子的两个算符并且扩展 newsiteup = create_operator_of_site(newleftext.stbss, OperFactory.create_spinup()) newsitedn = create_operator_of_site(newleftext.stbss, OperFactory.create_spindown()) newsiteup = leftsite_extend_oper(newleftext, newsiteup) newsitedn = leftsite_extend_oper(newleftext, newsitedn) #把之前存的升级到newleftblk上的算符也扩展了 for idx in maintain_dict: extup, extdn = maintain_dict[idx] extup = leftblock_extend_oper(newleftext, extup) extdn = leftblock_extend_oper(newleftext, extdn) maintain_dict[idx] = (extup, extdn) #新加的site是phi_idx + 1 maintain_dict[phi_idx + 1] = (newsiteup, newsitedn) #把新的hopping项加进去 for bnd in newbonds: coef_t = conf.model.get_t_coef(bnd, newsiteup.siteidx) newhamext.add_hopping_term(maintain_dict[bnd][0], newsiteup, coef_t) newhamext.add_hopping_term(maintain_dict[bnd][1], newsitedn, coef_t) #把新的格子的U项添加进去 newiu = create_operator_of_site(newleftext.stbss, OperFactory.create_u()) newiu = leftsite_extend_oper(newleftext, newiu) newhamext.add_u_term(newiu, conf.model.coef_u) #把新的格子的Mu项添加进去 coef_mu = conf.model.get_coef_mu(phi_idx + 1) if coef_mu != 0: newnu = create_operator_of_site(newleftext.stbss, OperFactory.create_numup()) newnu = leftsite_extend_oper(newleftext, newnu) newhamext.add_mu_term(newnu, coef_mu) newnd = create_operator_of_site(newleftext.stbss, OperFactory.create_numdown()) newnd = leftsite_extend_oper(newleftext, newnd) newhamext.add_mu_term(newnd, coef_mu) #保存需要保存的算符 for extidx in extoper_storage: conf.storage_leftext_oper(phi_idx, maintain_dict[extidx][0]) conf.storage_leftext_oper(phi_idx, maintain_dict[extidx][1]) #把需要保存的观测用的算符保存到leftext[phi_idx]当中 leftstor_phiidx = conf.get_leftext_storage(phi_idx) for prefix, stidx in measure_storage: meaop = ext_meaops['%s,%d' % (prefix, stidx)] leftstor_phiidx.storage_meas(prefix, meaop) return ground_erg
def prepare_rightblockextend(conf: DMRGConfig, phi_idx: int, newbonds: List[int], extoper_storage: List[int], measure_storage: List[Tuple[str, int]]): '''把最右边的一个格子的扩展计算出来,这个扩展要包括新增的hopping\n 以后要用来构成superblock ''' #这个过程不会更新conf中的right_tmp rightstorage = conf.get_rightblock_storage(phi_idx) right = rightstorage.block rightham = rightstorage.hamiltonian #扩展right rightext = extend_rightblock(right) #给conf中的rightext进行初始化 conf.rightext_reset(phi_idx, rightext) #扩展哈密顿量 rightham = extend_rightblock_hamiltonian(rightham, rightext) #把扩展以后的哈密顿量存下来 conf.storage_rightext_ham(phi_idx, rightham) #把需要扩展的算符扩展 maintain_opers = {} #首先考虑这次新加进来的两个 newup = create_operator_of_site(rightext.stbss, OperFactory.create_spinup()) newup = rightsite_extend_oper(rightext, newup) newdown = create_operator_of_site(rightext.stbss, OperFactory.create_spindown()) newdown = rightsite_extend_oper(rightext, newdown) #先把他放到maintain_opers当中 maintain_opers[rightext.stbss.sites[0]] = (newup, newdown) #然后把现在暂存的这些都扩展并保存到maintain_oper #中,这些可能会去要计算bond,还有可能会保存到rightext while len(rightstorage.oper_storage_list) > 0: stidx = rightstorage.oper_storage_list[0] #弹出这两个算符 stup, stdown = rightstorage.pop_oper(stidx) #扩展这两个算符,然后放到maintain_opers stup = rightblock_extend_oper(rightext, stup) stdown = rightblock_extend_oper(rightext, stdown) maintain_opers[stidx] = (stup, stdown) #把需要保存到ext中的算符都保存下来 for stidx in extoper_storage: conf.storage_rightext_oper(phi_idx, maintain_opers[stidx][0]) conf.storage_rightext_oper(phi_idx, maintain_opers[stidx][1]) #把新的bond添加进去 #rightext中保存的是rightham的实例,在这时修改也是可以的 for bstidx in newbonds: coef_t = conf.model.get_t_coef(bstidx, newup.siteidx) #自旋向上部分 tar_up = maintain_opers[bstidx][0] rightham.add_hopping_term(tar_up, newup, coef_t) #自旋向下部分 tar_down = maintain_opers[bstidx][1] rightham.add_hopping_term(tar_down, newdown, coef_t) #把新的U添加进去 newu = create_operator_of_site(rightext.stbss, OperFactory.create_u()) newu = rightsite_extend_oper(rightext, newu) rightham.add_u_term(newu, conf.model.coef_u) #把新的Mu项添加进去 coef_mu = conf.model.get_coef_mu(phi_idx - 1) if coef_mu != 0: newnu = create_operator_of_site(rightext.stbss, OperFactory.create_numup()) newnu = rightsite_extend_oper(rightext, newnu) rightham.add_mu_term(newnu, coef_mu) newnd = create_operator_of_site(rightext.stbss, OperFactory.create_numdown()) newnd = rightsite_extend_oper(rightext, newnd) rightham.add_mu_term(newnd, coef_mu) #把扩展后的算符存储到rightext[N]上面,用来给以后的观测使用 #之前的过程并没有调整right_tmp,直接用就可以了 rightext_stor = conf.get_rightext_storage(phi_idx) for prefix, idx in measure_storage: if idx == phi_idx - 1: #如果是新加的格子,就新建这个算符 meaop = create_operator_of_site(rightext.stbss, OperFactory.create_by_name(prefix)) meaop = rightsite_extend_oper(rightext, meaop) else: meaop = rightstorage.get_meas(prefix, idx) meaop = rightblock_extend_oper(rightext, meaop) rightext_stor.storage_meas(prefix, meaop) return rightext
def test1(): '''测试一维链上面的NRG,DMRG''' hc6 = HubbardChain(6, 0.0) #print(hc6) dconf = DMRGConfig(hc6, 1000) # left1 = first_leftblock(1) #创建第一个格子上的哈密顿量,还有第一个格子的产生算符 hamleft = create_hamiltonian_of_site(left1.fock_basis, hc6.coef_u, 0) cup1 = create_operator_of_site(left1.fock_basis, OperFactory.create_spinup()) cdn1 = create_operator_of_site(left1.fock_basis, OperFactory.create_spindown()) #把现在的结果暂存到dconf dconf.left_tmp_reset(1, left1, hamleft) dconf.left_tmp_add_oper(cup1) dconf.left_tmp_add_oper(cdn1) print(dconf) #新的格子的bonds,只需要比自己小的 allbonds = hc6.get_site_bonds(2) newbonds = [bond for bond in allbonds if bond < 2] print(newbonds) #如果之前的这些site中依旧和更大的site有bond #需要在left_tmp中保留他们的算符,在下一次中扩展 site_need_tmp = [] for site in range(1, left1.block_len + 2): allbonds = hc6.get_site_bonds(site) for bond in allbonds: if bond > left1.block_len + 1: site_need_tmp.append(site) break print(site_need_tmp) left2 = leftblock_to_next(dconf, 2, newbonds, [], site_need_tmp, []) print(dconf) #继续向下一个格子 allbonds = hc6.get_site_bonds(3) newbonds = [bond for bond in allbonds if bond < 3] print(newbonds) site_need_tmp = [] for site in range(1, left2.block_len + 2): allbonds = hc6.get_site_bonds(site) for bond in allbonds: if bond > left2.block_len + 1: site_need_tmp.append(site) break print(site_need_tmp) ##加上一个2用来检测结果 #left3 = leftblock_to_next(left2, 2, dconf, newbonds, [], site_need_tmp + [2]) ##检查算符 #left_tmp = dconf.get_leftblock_storage(3) #cu1 = left_tmp.get_oper(1, 1) #cd1 = left_tmp.get_oper(1, -1) #cu2 = left_tmp.get_oper(2, 1) #cd2 = left_tmp.get_oper(2, -1) #for ridx in range(left3.dim): # for lidx in range(left3.dim): # print('右侧的基') # print(left3.idx_to_state(ridx)) # #在fock_basis上面的分量 # sitebss_arr = left3.fock_dict[ridx] # template = '' # for idx2 in range(left3.fock_basis.dim): # if (idx2 % 4) == 0: # template += '\n' # template += '%.4f |%s>\t' %\ # (sitebss_arr[idx2], left3.fock_basis.idx_to_state(idx2)) # print(template) # print('左侧的基') # #再fock_basis上面的分量 # sitebss_arr = left3.fock_dict[lidx] # template = '' # for idx2 in range(left3.fock_basis.dim): # if (idx2 % 4) == 0: # template += '\n' # template += '%.4f |%s>\t' %\ # (sitebss_arr[idx2], left3.fock_basis.idx_to_state(idx2)) # print(template) # print('算符的数值') # print(cu1.mat[lidx, ridx]) # print(cd1.mat[lidx, ridx]) # print(cu2.mat[lidx, ridx]) # print(cd2.mat[lidx, ridx]) # left3 = leftblock_to_next(dconf, 3, newbonds, [], site_need_tmp, []) #继续向下一个格子 allbonds = hc6.get_site_bonds(4) newbonds = [bond for bond in allbonds if bond < 4] print(newbonds) #newbonds = newbonds + [1]#PBC的时候加一个4-1之间的链接 site_need_tmp = [] for site in range(1, left3.block_len + 2): allbonds = hc6.get_site_bonds(site) for bond in allbonds: if bond > left3.block_len + 1: site_need_tmp.append(site) break print(site_need_tmp) left4 = leftblock_to_next(dconf, 4, newbonds, [], site_need_tmp, []) print(left4) lst4 = dconf.get_leftblock_storage(4) ham4 = lst4.hamiltonian print(ham4) print(ham4.basis.dim) eigvs = numpy.linalg.eigvalsh(ham4.mat) print(numpy.sort(eigvs)) #半满四个格子的时候的精确解是-4.47213595(OBC)可以调节max_keep来验证 #半满四个格子的时候的精确解是-4.0(PBC)可以去掉之前的注释验证 #注意这里的解是没有限制sector的,可以看ham4.basis第一个分量是不是半满 print(ham4.basis.spin_nums[0])
def rightblockextend_to_next(conf: DMRGConfig, phi_idx: int, extrabonds: List[int], newbonds: List[int], extoper_storage: List[int], measure_storage: List[Tuple[str, int]], spin_sector, maxkeep: int): '''这时候的phi_idx是新的rightext的idx,leftext的idx就是他减去2\n spin_sector是在superblock上面的粒子数的要求\n extrabond在get_superblock_ham中要使用,而newbonds是值扩展 ''' #首先要将superblock得到,这个时候左边和右边之间的 #extrabond也要考虑上 leftstorage = conf.get_leftext_storage(phi_idx - 2) rightstorage = conf.get_rightext_storage(phi_idx + 1) #scrtor_idxs中保存的是满足粒子数要求的所有superblock上的基的idx #mat是这个sector上的矩阵 sector_idxs, mat, superext = get_superblock_ham(conf.model, leftstorage, rightstorage, spin_sector, extrabonds) #将基态解出来 eigvals, eigvecs = scipy.sparse.linalg.eigsh(mat, k=1, which='SA') #numpy.linalg.eigh(mat) ground = eigvecs[:, 0] ground_erg = eigvals[0] #把基态的信息保留下来 conf.ground_vec = ground conf.ground_secidx = sector_idxs conf.ground_superext = superext #print('g', ground_erg) #从基态构造密度矩阵 #这里需要sector_idx来判断有哪些位置上是有数值的 #这个方法主要是将基态的C(alpha,s^j,s^j+1,beta)这个写成 #M(a,b),lidxs就是将a变成(alpha,s^j)的列表, #ridxs是b到(s^j+1,beta)的,这在以后计算phival的时候有作用 #因为phival的列是在(s^j+1,beta)的 lidxs, ridxs, mat = get_density_root( #pylint: disable=unused-variable leftstorage, rightstorage, sector_idxs, ground) #right上面的密度矩阵的获得 denmat = numpy.matmul(mat.transpose(), mat) #这个方法主要目的是把density matrix划分成小块 spsec_mat_dict = get_density_in_sector(rightstorage, ridxs, denmat) #获得phival phival = get_phival_from_density_sector(rightstorage, spsec_mat_dict, maxkeep) #在获得了phival以后,就可以通过这个phival更新基 #rightblock^phi_idx里面的内容全部都在rightblockextend^phi_idx+1里面 #不需要添加,只需要升级就行了,在DMRG sweep的过程中,rightblock上面的 #算符或者哈密顿量都是用不到的,不进行保存 rightext = rightstorage.block newrightblk = update_to_rightblock(rightext, phival) newham = update_rightblockextend_hamiltonian(newrightblk, rightstorage.hamiltonian, phival) #设置一下现在的idx,不保存哈密顿量,以后用不到 conf.right_tmp_reset(phi_idx, newrightblk, None) #用来保存newrightblk上面的算符 maintain_dict = {} #把需要放到新的rightext上面的算符,先升级到新的right上面 for extidx in rightstorage.oper_storage_list: #extoper_storage: #上一次迭代的时候,包含小于phi_val的bond的site都被存在 #conf里面了 extup = rightstorage.get_oper(extidx, 1) newup = update_rightblockextend_oper(newrightblk, extup, phival) extdn = rightstorage.get_oper(extidx, -1) newdn = update_rightblockextend_oper(newrightblk, extdn, phival) maintain_dict[extidx] = (newup, newdn) #把新的rightblock扩展一个格子 newrightext = extend_rightblock(newrightblk) #把哈密顿量也扩展一个格子 newhamext = extend_rightblock_hamiltonian(newham, newrightext) #以后的观测需要的算符,从leftext[phi_idx-1]中拿到,再升级扩展 #以后放到leftext[phi_idx]中 ext_meaops = {} for prefix, stidx in measure_storage: if stidx == phi_idx - 1: #如果是新加的格子上的算符,不需要升级 #新建一个观测用的算符 meaop = create_operator_of_site(newrightext.stbss, OperFactory.create_by_name(prefix)) #扩展到leftext[phi_idx]上 meaop = rightsite_extend_oper(newrightext, meaop) else: #得到meaop meaop = rightstorage.get_meas(prefix, stidx) #升级meaop到leftblock[phi_idx] meaop = update_rightblockextend_oper(newrightblk, meaop, phival) #扩展 meaop = rightblock_extend_oper(newrightext, meaop) ext_meaops['%s,%d' % (prefix, stidx)] = meaop #更新缓存的ext,现在存进去就行了,后面在add_hopping_term #也是加在这个newhamext上面的 conf.rightext_reset(phi_idx, newrightext) conf.storage_rightext_ham(phi_idx, newhamext) #获得新加的格子上面的两个算符 newsiteup = create_operator_of_site(newrightext.stbss, OperFactory.create_spinup()) newsitedn = create_operator_of_site(newrightext.stbss, OperFactory.create_spindown()) #扩展到新的基上 newsiteup = rightsite_extend_oper(newrightext, newsiteup) newsitedn = rightsite_extend_oper(newrightext, newsitedn) #maintain_dict[phi_idx-1] = (newsiteup, newsitedn) #把maintain_dict中的其他算符也扩展到新的基上 for idx in maintain_dict: extup, extdn = maintain_dict[idx] extup = rightblock_extend_oper(newrightext, extup) extdn = rightblock_extend_oper(newrightext, extdn) maintain_dict[idx] = (extup, extdn) maintain_dict[phi_idx - 1] = (newsiteup, newsitedn) #加入新的hopping项 for bnd in newbonds: coef_t = conf.model.get_t_coef(bnd, newsiteup.siteidx) newhamext.add_hopping_term(maintain_dict[bnd][0], newsiteup, coef_t) newhamext.add_hopping_term(maintain_dict[bnd][1], newsitedn, coef_t) #把新的格子的U项添加进去 newiu = create_operator_of_site(newrightext.stbss, OperFactory.create_u()) newiu = rightsite_extend_oper(newrightext, newiu) newhamext.add_u_term(newiu, conf.model.coef_u) #把新的格子的Mu项添加进去 coef_mu = conf.model.get_coef_mu(phi_idx - 1) if coef_mu != 0: newnu = create_operator_of_site(newrightext.stbss, OperFactory.create_numup()) newnu = rightsite_extend_oper(newrightext, newnu) newhamext.add_mu_term(newnu, coef_mu) newnd = create_operator_of_site(newrightext.stbss, OperFactory.create_numdown()) newnd = rightsite_extend_oper(newrightext, newnd) newhamext.add_mu_term(newnd, coef_mu) #保存需要保存的新的ext上面的算符 for extidx in extoper_storage: conf.storage_rightext_oper(phi_idx, maintain_dict[extidx][0]) conf.storage_rightext_oper(phi_idx, maintain_dict[extidx][1]) #把需要保存的观测用的算符保存到leftext[phi_idx]当中 rightstor_phiidx = conf.get_rightext_storage(phi_idx) for prefix, stidx in measure_storage: meaop = ext_meaops['%s,%d' % (prefix, stidx)] rightstor_phiidx.storage_meas(prefix, meaop) return ground_erg
def test1(): '''测试superblock 测试在5个格子时候的哈密顿量是否正确,验证自旋上的部分 ''' # left1 = first_leftblock(1) #现在只有第一个格子,创建第一个格子的哈密顿量和产生算符 hamleft = create_hamiltonian_of_site(left1.fock_basis, -1., 0) print('U', hamleft) cup_in_1 = create_operator_of_site(left1.fock_basis, OperFactory.create_spinup()) #将第一个格子扩展到第二个 left1ext = extend_leftblock(left1) #在扩展过的格子上的C^+_1 cup_in_1 = leftblock_extend_oper(left1ext, cup_in_1) #扩展以后有C^+_2 cup_in_2 = create_operator_of_site(left1ext.stbss, OperFactory.create_spinup()) cup_in_2 = leftsite_extend_oper(left1ext, cup_in_2) #扩展以后的U2 ciu_in_2 = create_operator_of_site(left1ext.stbss, OperFactory.create_u()) ciu_in_2 = leftsite_extend_oper(left1ext, ciu_in_2) #现在C^+_1和C^+_2都在|phi^1, s^2>这个left1ext基上,整合进哈密顿量 #先把哈密顿量也放到|phi^1, s^2>这个基上 hamleft = extend_leftblock_hamiltonian(hamleft, left1ext) hamleft.add_hopping_term(cup_in_1, cup_in_2, 1.0) hamleft.add_u_term(ciu_in_2, -1.0) print('U', hamleft) #然后升级left1ext到left2 |phi^2> phival = numpy.eye(16) left2 = update_to_leftblock(left1ext, phival) hamleft = update_leftblockextend_hamiltonian(left2, hamleft, phival) cup_in_1 = update_leftblockextend_oper(left2, cup_in_1, phival) cup_in_2 = update_leftblockextend_oper(left2, cup_in_2, phival) #将|phi^2>扩展到|phi^2, s^3> left2ext = extend_leftblock(left2) #把哈密顿量和第二个算符也扩展过去 hamleft = extend_leftblock_hamiltonian(hamleft, left2ext) cup_in_2 = leftblock_extend_oper(left2ext, cup_in_2) #创建第三个格子的算符,然后放到|phi^2, s^3> cup_in_3 = create_operator_of_site(left2ext.stbss, OperFactory.create_spinup()) cup_in_3 = leftsite_extend_oper(left2ext, cup_in_3) #把2-3之间的hopping放到哈密顿量里 hamleft.add_hopping_term(cup_in_2, cup_in_3, 1.0) #把|phi^2, s^3>这个东西以后要用来生成supoerblock print(hamleft) print(cup_in_3) # # right = first_rightblock(5) #现在只有第5个格子 hamright = create_hamiltonian_of_site(right.fock_basis, -1.0, 0) print('rU', hamright) cup_in_5 = create_operator_of_site(right.fock_basis, OperFactory.create_spinup()) #将第5个格子扩展到第4个 |s^4, phi^1> rightext = extend_rightblock(right) #把第5个格子的算符扩展 cup_in_5 = rightblock_extend_oper(rightext, cup_in_5) #创建第四个格子的算符并且扩展 cup_in_4 = create_operator_of_site(rightext.stbss, OperFactory.create_spinup()) cup_in_4 = rightsite_extend_oper(rightext, cup_in_4) #第四个格子上的U ciu_in_4 = create_operator_of_site(rightext.stbss, OperFactory.create_u()) ciu_in_4 = rightsite_extend_oper(rightext, ciu_in_4) #把哈密顿量扩展到|s^4, phi^1> hamright = extend_rightblock_hamiltonian(hamright, rightext) #添加4-5的hopping hamright.add_hopping_term(cup_in_4, cup_in_5, 1.0) hamright.add_u_term(ciu_in_4, -1.0) print('rU', hamright) print(cup_in_4) # #创建superblock superblock = extend_merge_to_superblock(left2ext, rightext) print(superblock) #把左边的哈密顿量扩展到superblock上面 hamleft = leftext_hamiltonian_to_superblock(superblock, hamleft) cup_in_3_e = leftext_oper_to_superblock(superblock, cup_in_3) print(hamleft) print(cup_in_3_e) # #for ridx in superblock.iter_idx(): # for lidx in superblock.iter_idx(): # if hamleft.mat[lidx, ridx] == 0: # continue # idx1, idx2, idx3, idx4 = superblock.idx_to_idxtuple(ridx) # rsta = '%s,%s,%s,%s' %\ # (left1ext.idx_to_state(idx1),\ # superblock.leftblockextend.stbss.idx_to_state(idx2),\ # superblock.rightblockextend.stbss.idx_to_state(idx3),\ # superblock.rightblockextend.rblk.idx_to_state(idx4)) # idx1, idx2, idx3, idx4 = superblock.idx_to_idxtuple(lidx) # lsta = '%s,%s,%s,%s' %\ # (left1ext.idx_to_state(idx1),\ # superblock.leftblockextend.stbss.idx_to_state(idx2),\ # superblock.rightblockextend.stbss.idx_to_state(idx3),\ # superblock.rightblockextend.rblk.idx_to_state(idx4)) # print(rsta, lsta, hamleft.mat[lidx, ridx]) #for ridx in superblock.iter_idx(): # for lidx in superblock.iter_idx(): # if cup_in_3.mat[lidx, ridx] == 0: # continue # idx1, idx2, idx3, idx4 = superblock.idx_to_idxtuple(ridx) # rsta = '%s,%s,%s,%s' %\ # (left1ext.idx_to_state(idx1),\ # superblock.leftblockextend.stbss.idx_to_state(idx2),\ # superblock.rightblockextend.stbss.idx_to_state(idx3),\ # superblock.rightblockextend.rblk.idx_to_state(idx4)) # idx1, idx2, idx3, idx4 = superblock.idx_to_idxtuple(lidx) # lsta = '%s,%s,%s,%s' %\ # (left1ext.idx_to_state(idx1),\ # superblock.leftblockextend.stbss.idx_to_state(idx2),\ # superblock.rightblockextend.stbss.idx_to_state(idx3),\ # superblock.rightblockextend.rblk.idx_to_state(idx4)) # print(rsta, lsta, cup_in_3.mat[lidx, ridx]) # #把右边的哈密顿量扩展到superblock上面 hamright = rightext_hamiltonian_to_superblock(superblock, hamright) print(hamright) #for ridx in superblock.iter_idx(): # for lidx in superblock.iter_idx(): # if hamright.mat[lidx, ridx] == 0: # continue # idx1, idx2, idx3, idx4 = superblock.idx_to_idxtuple(ridx) # rsta = '%s,%s,%s,%s' %\ # (left1ext.idx_to_state(idx1),\ # superblock.leftblockextend.stbss.idx_to_state(idx2),\ # superblock.rightblockextend.stbss.idx_to_state(idx3),\ # superblock.rightblockextend.rblk.idx_to_state(idx4)) # idx1, idx2, idx3, idx4 = superblock.idx_to_idxtuple(lidx) # lsta = '%s,%s,%s,%s' %\ # (left1ext.idx_to_state(idx1),\ # superblock.leftblockextend.stbss.idx_to_state(idx2),\ # superblock.rightblockextend.stbss.idx_to_state(idx3),\ # superblock.rightblockextend.rblk.idx_to_state(idx4)) # print(rsta, lsta, hamright.mat[lidx, ridx]) # #把右边的算符扩展到superblock上面 cup_in_4_e = rightext_oper_to_superblock(superblock, cup_in_4) print(cup_in_4_e) #for ridx in superblock.iter_idx(): # for lidx in superblock.iter_idx(): # if cup_in_4.mat[lidx, ridx] == 0: # continue # idx1, idx2, idx3, idx4 = superblock.idx_to_idxtuple(ridx) # rsta = '%s,%s,%s,%s' %\ # (left1ext.idx_to_state(idx1),\ # superblock.leftblockextend.stbss.idx_to_state(idx2),\ # superblock.rightblockextend.stbss.idx_to_state(idx3),\ # superblock.rightblockextend.rblk.idx_to_state(idx4)) # idx1, idx2, idx3, idx4 = superblock.idx_to_idxtuple(lidx) # lsta = '%s,%s,%s,%s' %\ # (left1ext.idx_to_state(idx1),\ # superblock.leftblockextend.stbss.idx_to_state(idx2),\ # superblock.rightblockextend.stbss.idx_to_state(idx3),\ # superblock.rightblockextend.rblk.idx_to_state(idx4)) # print(rsta, lsta, cup_in_4.mat[lidx, ridx]) hamsuper = plus_two_hamiltonian(hamleft, hamright) res1 = hamsuper.add_hopping_term(cup_in_3_e, cup_in_4_e, 1.0) res2 = hamsuper.superblock_add_hopping_term(cup_in_3, cup_in_4, 1.0) print('superblock_add_hopping_term: ', numpy.allclose(res1, res2)) print(hamsuper)
def test2(): '''测试superblock 测试在5个格子时候的哈密顿量是否正确,验证自旋下的部分 ''' # left1 = first_leftblock(1) #现在只有第一个格子,创建第一个格子的哈密顿量和产生算符 hamleft = create_hamiltonian_of_site(left1.fock_basis, 0, 0) cdn_in_1 = create_operator_of_site(left1.fock_basis, OperFactory.create_spindown()) #将第一个格子扩展到第二个 left1ext = extend_leftblock(left1) #在扩展过的格子上的C^+_1 cdn_in_1 = leftblock_extend_oper(left1ext, cdn_in_1) #扩展以后有C^+_2 cdn_in_2 = create_operator_of_site(left1ext.stbss, OperFactory.create_spindown()) cdn_in_2 = leftsite_extend_oper(left1ext, cdn_in_2) #现在C^+_1和C^+_2都在|phi^1, s^2>这个left1ext基上,整合进哈密顿量 #先把哈密顿量也放到|phi^1, s^2>这个基上 hamleft = extend_leftblock_hamiltonian(hamleft, left1ext) hamleft.add_hopping_term(cdn_in_1, cdn_in_2, 1.0) #然后升级left1ext到left2 |phi^2> phival = numpy.eye(16) left2 = update_to_leftblock(left1ext, phival) hamleft = update_leftblockextend_hamiltonian(left2, hamleft, phival) cdn_in_1 = update_leftblockextend_oper(left2, cdn_in_1, phival) cdn_in_2 = update_leftblockextend_oper(left2, cdn_in_2, phival) #将|phi^2>扩展到|phi^2, s^3> left2ext = extend_leftblock(left2) #把哈密顿量和第二个算符也扩展过去 hamleft = extend_leftblock_hamiltonian(hamleft, left2ext) cdn_in_2 = leftblock_extend_oper(left2ext, cdn_in_2) #创建第三个格子的算符,然后放到|phi^2, s^3> cdn_in_3 = create_operator_of_site(left2ext.stbss, OperFactory.create_spindown()) cdn_in_3._mat = numpy.random.randn(cdn_in_3.mat.shape[0], cdn_in_3.mat.shape[1]) cdn_in_3 = leftsite_extend_oper(left2ext, cdn_in_3) #把2-3之间的hopping放到哈密顿量里 hamleft.add_hopping_term(cdn_in_2, cdn_in_3, 1.0) #把|phi^2, s^3>这个东西以后要用来生成supoerblock print(hamleft) print(cdn_in_3) # # right = first_rightblock(5) #现在只有第5个格子 hamright = create_hamiltonian_of_site(right.fock_basis, 0, 0) cdn_in_5 = create_operator_of_site(right.fock_basis, OperFactory.create_spindown()) #将第5个格子扩展到第4个 |s^4, phi^1> rightext = extend_rightblock(right) #把第5个格子的算符扩展 cdn_in_5 = rightblock_extend_oper(rightext, cdn_in_5) #创建第四个格子的算符并且扩展 cdn_in_4 = create_operator_of_site(rightext.stbss, OperFactory.create_spindown()) #Issue #16:用一个随机的矩阵来验证优化的正确性 cdn_in_4._mat = numpy.random.randn(cdn_in_4.mat.shape[0], cdn_in_4.mat.shape[1]) cdn_in_4 = rightsite_extend_oper(rightext, cdn_in_4) #把哈密顿量扩展到|s^4, phi^1> hamright = extend_rightblock_hamiltonian(hamright, rightext) #添加4-5的hopping hamright.add_hopping_term(cdn_in_4, cdn_in_5, 1.0) print(hamright) print(cdn_in_4) # #创建superblock superblock = extend_merge_to_superblock(left2ext, rightext) print(superblock) #把左边的哈密顿量扩展到superblock上面 hamleft = leftext_hamiltonian_to_superblock(superblock, hamleft) cdn_in_3_e = leftext_oper_to_superblock(superblock, cdn_in_3) print(hamleft) print(cdn_in_3_e) #把右边的哈密顿量扩展到superblock上面 hamright = rightext_hamiltonian_to_superblock(superblock, hamright) print(hamright) #把右边的算符扩展到superblock上面 cdn_in_4_e = rightext_oper_to_superblock(superblock, cdn_in_4) print(cdn_in_4_e) # hamsuper = plus_two_hamiltonian(hamleft, hamright) res1 = hamsuper.add_hopping_term(cdn_in_3_e, cdn_in_4_e, 1.0) res2 = hamsuper.superblock_add_hopping_term(cdn_in_3, cdn_in_4, 1.0) print('superblock_add_hopping_term: ', numpy.allclose(res1, res2)) print(hamsuper)