def test_distance(): mol_list = parameter.custom_mol_list(n_phys_dim=(2, 2)) a = Mps.random(mol_list, 1, 10) b = Mps.random(mol_list, 1, 10) check_distance(a, b) h = Mpo(mol_list) for i in range(100): a = a.evolve(h, 10) b = b.evolve(h, 10) check_distance(a, b)
def test_distance(): model = custom_model(n_phys_dim=(2, 2)) a = Mps.random(model, 1, 10) b = Mps.random(model, 1, 10) check_distance(a, b) h = Mpo(model) for i in range(100): a = a.evolve(h, 10) b = b.evolve(h, 10) check_distance(a, b)
def test_expectations(mpos): random = Mps.random(parameter.mol_list, 1, 20) e1 = random.expectations(mpos) e2 = random.expectations(mpos, opt=False) assert np.allclose(e1, e2)
def test_svd_compress(comp, mp): if mp == "mpo": mps = Mpo(holstein_model) M = 22 else: mps = Mps.random(holstein_model, 1, 10) if mp == "mpdm": mps = MpDm.from_mps(mps) mps.canonicalise().normalize() M = 36 if comp: mps = mps.to_complex(inplace=True) print(f"{mps}") mpo = Mpo(holstein_model) if comp: mpo = mpo.scale(-1.0j) print(f"{mpo.bond_dims}") std_mps = mpo.apply(mps, canonicalise=True).canonicalise() print(f"std_mps: {std_mps}") mps.compress_config.bond_dim_max_value = M mps.compress_config.criteria = CompressCriteria.fixed svd_mps = mpo.contract(mps) dis = svd_mps.distance(std_mps) / std_mps.dmrg_norm print(f"svd_mps: {svd_mps}, dis: {dis}") assert np.allclose(dis, 0.0, atol=1e-3) assert np.allclose(svd_mps.dmrg_norm, std_mps.dmrg_norm, atol=1e-4)
def test_from_mps(): gs = Mps.random(parameter.holstein_model, 1, 20) gs_mpdm = MpDm.from_mps(gs) assert np.allclose(gs.e_occupations, gs_mpdm.e_occupations) gs = gs.canonicalise() gs_mpdm = gs_mpdm.canonicalise() assert np.allclose(gs.e_occupations, gs_mpdm.e_occupations)
def test_expectations(mpos): random = Mps.random(parameter.holstein_model, 1, 20) e1 = random.expectations(mpos) e2 = random.expectations(mpos, opt=False) assert np.allclose(e1, e2)
def init_b_mps(self): # get the right hand site vector b, Ax=b # b = -eta * dipole * \psi_0 # only support Holstine model 0/1 exciton manifold if self.spectratype == "abs": nexciton = 0 dipoletype = r"a^\dagger" elif self.spectratype == "emi": nexciton = 1 dipoletype = "a" # procedure for ground state calculation if self.procedure_gs is None: self.procedure_gs = \ [[10, 0.4], [20, 0.2], [30, 0.1], [40, 0], [40, 0]] # ground state calculation mps = Mps.random( self.model, nexciton, self.procedure_gs[0][0], percent=1.0) mps.optimize_config = OptimizeConfig(procedure=self.procedure_gs) mps.optimize_config.method = "2site" energies, mps = gs.optimize_mps(mps, self.h_mpo) e0 = min(energies) dipole_mpo = \ Mpo.onsite( self.model, dipoletype, dipole=True ) b_mps = dipole_mpo.apply(mps.scale(-self.eta)) return b_mps, e0
def find_highest_energy(h_mpo: Mpo, nexciton, Mmax): logger.debug("begin finding highest energy") model = h_mpo.model mps = Mps.random(model, nexciton, Mmax) mps.optimize_config.inverse = -1.0 energies, _ = optimize_mps(mps, h_mpo) return -energies[-1]
def init_mps(self): mmax = self.optimize_config.procedure[0][0] i_mps = Mps.random(self.h_mpo.model, self.nexciton, mmax, 1) i_mps.optimize_config = self.optimize_config energy, i_mps = gs.optimize_mps(i_mps, self.h_mpo) if self.spectratype == "emi": operator = "a" else: operator = r"a^\dagger" dipole_mpo = Mpo.onsite(self.model, operator, dipole=True) if self.temperature != 0: beta = self.temperature.to_beta() # print "beta=", beta # thermal_mpo = Mpo.exact_propagator(self.model, -beta / 2.0, space=self.space1, shift=self.shift1) # ket_mps = thermal_mpo.apply(i_mps) # ket_mps.normalize() # no test, don't know work or not i_mpdm = MpDm.from_mps(i_mps) tp = ThermalProp(i_mpdm, self.h_mpo, exact=True, space=self.space1) tp.evolve(None, 1, beta / 2j) ket_mps = tp.latest_mps else: ket_mps = i_mps a_ket_mps = dipole_mpo.apply(ket_mps, canonicalise=True) a_ket_mps.canonical_normalize() if self.temperature != 0: a_bra_mps = ket_mps.copy() else: a_bra_mps = a_ket_mps.copy() return BraKetPair(a_bra_mps, a_ket_mps)
def test_zt_init_state(): ph = Phonon.simple_phonon(Quantity(1), Quantity(1), 10) mol_list = MolList([Mol(Quantity(0), [ph])], Quantity(0), scheme=3) mpo = Mpo(mol_list) mps = Mps.random(mol_list, 1, 10) optimize_mps(mps, mpo) ct = ChargeTransport(mol_list) assert mps.angle(ct.latest_mps) == pytest.approx(1)
def check_reduced_density_matrix(basis): model = Model(basis, []) mps = Mps.random(model, 1, 20) rdm = mps.calc_edof_rdm().real assert np.allclose(np.diag(rdm), mps.e_occupations) # only test a sample. Should be enough. mpo = Mpo(model, Op(r"a^\dagger a", [0, 3])) assert rdm[-1][0] == pytest.approx(mps.expectation(mpo))
def find_lowest_energy(h_mpo: Mpo, nexciton, Mmax, with_hartree=True): logger.debug("begin finding lowest energy") if with_hartree: mol_list = h_mpo.mol_list else: mol_list = h_mpo.mol_list.get_pure_dmrg_mollist() mps = Mps.random(mol_list, nexciton, Mmax) energy = optimize_mps(mps, h_mpo) return energy.min()
def init_cv_mps(self): # random guess of cv_mps with same qn as b_mps assert self.b_mps is not None # initialize guess of cv_mps cv_mps = Mps.random( self.model, self.b_mps.qntot, self.m_max, percent=1.0) logger.info(f"cv_mps random guess qntot: {cv_mps.qntot}") return cv_mps
def test_environ(): mps = Mps.random(holstein_model, 1, 10) mpo = Mpo(holstein_model) mps = mps.evolve(mpo, 10) environ = Environ(mps, mpo) for i in range(len(mps) - 1): l = environ.read("L", i) r = environ.read("R", i + 1) e = complex(tensordot(l, r, axes=((0, 1, 2), (0, 1, 2)))).real assert pytest.approx(e) == mps.expectation(mpo)
def check_reduced_density_matrix(order, basis): mol_list = MolList2(order, basis, {}, ModelTranslator.general_model) mps = Mps.random(mol_list, 1, 20) rdm = mps.calc_reduced_density_matrix().real assert np.allclose(np.diag(rdm), mps.e_occupations) # only test a sample. Should be enough. mpo = Mpo.general_mpo(mol_list, model={ (f"e_0", f"e_3"): [(Op(r"a^\dagger", 1), Op("a", -1), 1.0)] }, model_translator=ModelTranslator.general_model) assert rdm[-1][0] == pytest.approx(mps.expectation(mpo))
def test_site_entropy(): mps = Mps.random(parameter.holstein_model, 1, 20) mps.canonicalise().normalize() entropy_1site = mps.calc_entropy("1site") entropy_2site = mps.calc_entropy("2site") entropy_bond = mps.calc_entropy("bond") entropy_mutual = mps.calc_entropy("mutual") assert np.allclose(entropy_bond[0], entropy_1site[0]) assert np.allclose(entropy_bond[-1], entropy_1site[mps.site_num - 1]) assert np.allclose(entropy_bond[1], entropy_2site[(0, 1)]) assert np.allclose(entropy_bond[-2], entropy_2site[(mps.site_num - 2, mps.site_num - 1)]) assert np.allclose( entropy_mutual[0, 1], (entropy_1site[0] + entropy_1site[1] - entropy_2site[(0, 1)]) / 2)
def test_environ_multi_mpo(mpdm): mps = Mps.random(holstein_model, 1, 10) if mpdm: mps = MpDm.from_mps(mps) mpo = Mpo(holstein_model) mps = mps.evolve(mpo, 10) environ = Environ(mps, mpo) environ_multi_mpo = Environ(mps, [mpo]) for i in range(len(mps) - 1): l = environ.read("L", i) r = environ.read("R", i + 1) l2 = environ_multi_mpo.read("L", i) r2 = environ_multi_mpo.read("R", i + 1) assert np.allclose(asnumpy(l), asnumpy(l2)) assert np.allclose(asnumpy(r), asnumpy(r2))
def construct_mps_mpo_2(model, Mmax, nexciton, offset=Quantity(0)): """ MPO/MPS structure 2 e1,ph11,ph12,..e2,ph21,ph22,...en,phn1,phn2... """ """ initialize MPO """ mpo = Mpo(model, offset=offset) """ initialize MPS according to quantum number """ mps = Mps.random(model, nexciton, Mmax, percent=1) # print("initialize left-canonical:", mps.check_left_canonical()) return mps, mpo
def test_VibBasis(basistype): nv = 2 pdim = 6 hessian = np.array([[2, 1], [1, 3]]) e, c = scipy.linalg.eigh(hessian) ham_terms = [] basis = [] for iv in range(nv): op = Op("p^2", f"v_{iv}", factor=0.5, qn=0) ham_terms.append(op) if basistype == "SineDVR": # sqrt(<x^2>) of the highest vibrational basis x_mean = np.sqrt((pdim + 0.5) / np.sqrt(hessian[iv, iv])) bas = Ba.BasisSineDVR(f"v_{iv}", 2 * pdim, -x_mean * 1.5, x_mean * 1.5, endpoint=True) print("x_mean", x_mean, bas.dvr_x) else: if basistype == "SHO": dvr = False else: dvr = True bas = Ba.BasisSHO(f"v_{iv}", np.sqrt(hessian[iv, iv]), pdim, dvr=dvr) basis.append(bas) for iv in range(nv): for jv in range(nv): op = Op("x x", [f"v_{iv}", f"v_{jv}"], factor=0.5 * hessian[iv, jv], qn=[0, 0]) ham_terms.append(op) model = Model(basis, ham_terms) mpo = Mpo(model) mps = Mps.random(model, 0, 10) mps.optimize_config.nroots = 2 energy, mps = gs.optimize_mps(mps, mpo) w1, w2 = np.sqrt(e) std = [(w1 + w2) * 0.5, w1 * 1.5 + w2 * 0.5] print(basistype, "calc:", energy[-1], "exact:", std) assert np.allclose(energy[-1], std)
def test_variational_compress(comp, mp): if mp == "mpo": mps = Mpo(holstein_model) M = 20 else: mps = Mps.random(holstein_model, 1, 10) if mp == "mpdm": mps = MpDm.from_mps(mps) mps.canonicalise().normalize() M = 36 if comp: mps = mps.to_complex(inplace=True) print(f"{mps}") mpo = Mpo(holstein_model) if comp: mpo = mpo.scale(-1.0j) print(f"{mpo.bond_dims}") std_mps = mpo.apply(mps, canonicalise=True).canonicalise() print(f"std_mps: {std_mps}") # 2site algorithm mps.compress_config.vprocedure = [[M, 1.0], [M, 0.2], [M, 0.1]] + [ [M, 0], ] * 10 mps.compress_config.vmethod = "2site" var_mps = mps.variational_compress(mpo, guess=None) dis = var_mps.distance(std_mps) / std_mps.dmrg_norm print(f"var2_mps: {var_mps}, dis: {dis}") assert np.allclose(dis, 0.0, atol=1e-4) assert np.allclose(var_mps.dmrg_norm, std_mps.dmrg_norm, atol=1e-4) # 1site algorithm with 2site result as a guess # 1site algorithm is easy to be trapped in a local minimum var_mps.compress_config.vprocedure = [ [M, 0], ] * 10 var_mps.compress_config.vmethod = "1site" var_mps = mps.variational_compress(mpo, guess=var_mps) dis = var_mps.distance(std_mps) / std_mps.dmrg_norm print(f"var1_mps: {var_mps}, dis: {dis}") assert np.allclose(dis, 0.0, atol=1e-4) assert np.allclose(var_mps.dmrg_norm, std_mps.dmrg_norm, atol=1e-4)
#h2e = 0.5*(h2e+h2e.transpose((2,3,0,1))) model = qc_model(h1e, h2e) order = {} basis = [] for iorb in range(spin_norbs): order[f"e_{iorb}"] = iorb basis.append(ba.BasisHalfSpin(sigmaqn=[0, 1])) mol_list2 = MolList2(order, basis, model, ModelTranslator.general_model) mpo = Mpo(mol_list2) logger.info(f"mpo_bond_dims:{mpo.bond_dims}") nelec = 10 energy_list = {} M = 50 procedure = [[M, 0.4], [M, 0.2], [M, 0.1], [M, 0], [M, 0], [M, 0], [M, 0]] mps = Mps.random(mol_list2, nelec, M, percent=1.0) mps.optimize_config.procedure = procedure mps.optimize_config.method = "2site" energies = solver.optimize_mps_dmrg(mps.copy(), mpo) gs_e = energies.min() + nuc logger.info(f"lowest energy: {gs_e}") # fci result assert np.allclose(gs_e, -75.008697516450) end = time.time() logger.info(f"time cost {end - start}")
def init_mps(self): self.cv_mps = Mps.random( self.mol_list, 1-self.nexciton, self.m_max, percent=1.0)
def test_identity(): identity = Mpo.identity(holstein_model) mps = Mps.random(holstein_model, nexciton=1, m_max=5) assert mps.expectation(identity) == pytest.approx( mps.dmrg_norm) == pytest.approx(1)
def test_H_chain_LDOS(): # local density of states of four H_Chain # Ronca,J. Chem. Theory Comput. 2017, 13, 5560-5571 # example to use Mollist2 to do CV calculation spatial_norbs = 4 spin_norbs = spatial_norbs * 2 h1e, h2e, nuc = h_qc.read_fcidump( os.path.join(cur_dir, "fcidump_lowdin_h4.txt"), spatial_norbs) basis, ham_terms = h_qc.qc_model(h1e, h2e) model = Model(basis, ham_terms) mpo = Mpo(model) nelec = spatial_norbs M = 50 procedure = [[M, 0.4], [M, 0.2]] + [ [M, 0], ] * 6 mps = Mps.random(model, nelec, M, percent=1.0) mps.optimize_config.procedure = procedure mps.optimize_config.method = "2site" energies, mps = gs.optimize_mps(mps, mpo) gs_e = min(energies) + nuc assert np.allclose(gs_e, -2.190384218792706) mps_e = mps.expectation(mpo) def photoelectron_operator(idx): # norbs is the spin orbitals # green function op_list = [Op("sigma_z", iorb, qn=0) for iorb in range(idx)] return Op.product(op_list + [Op("sigma_+", idx, qn=-1)]) dipole_model = photoelectron_operator(nelec - 1) dipole_op = Mpo(model, dipole_model) b_mps = dipole_op.apply(mps) #std #test_freq = np.linspace(0.25, 1.25, 100, endpoint=False).tolist() test_freq = np.linspace(0.25, 1.25, 20, endpoint=False).tolist() eta = 0.05 M = 10 procedure_cv = [0.4, 0.2] + [0] * 6 spectra = SpectraZtCV(model, None, M, eta, h_mpo=mpo, method="2site", procedure_cv=procedure_cv, b_mps=b_mps.scale(-eta), e0=mps_e) result = batch_run(test_freq, 1, spectra) std = np.load(os.path.join(cur_dir, "H_chain_std.npy")) #np.save("res", result) #np.save("freq", test_freq) assert np.allclose(result, std[::5])
def get_imps(self): mmax = self.optimize_config.procedure[0][0] i_mps = Mps.random(self.h_mpo.model, self.nexciton, mmax, 1) i_mps.optimize_config = self.optimize_config energy, i_mps = gs.optimize_mps(i_mps, self.h_mpo) return i_mps
def get_imps(self): mmax = self.optimize_config.procedure[0][0] i_mps = Mps.random(self.h_mpo.mol_list, self.nexciton, mmax, 1) i_mps.optimize_config = self.optimize_config solver.optimize_mps(i_mps, self.h_mpo) return i_mps
def test_tda(): from renormalizer.tests.c2h4_para import ff, omega_std, B, zeta # See J. Chem. Phys. 153, 084118 (2020) for the details of the Hamiltonian # the order is according to the harmonic frequency from small to large. ham_terms = [] nmode = 12 omega = {} nterms = 0 # potential terms for term in ff: mode, factor = term[:-1], term[-1] # ignore the factor smaller than 1e-15 if abs(factor) < 1e-15: continue # ignore the expansion larger than 4-th order #if len(mode) > 4: # continue mode = Counter(mode) # the permutation symmetry prefactor prefactor = 1. for p in mode.values(): prefactor *= scipy.special.factorial(p, exact=True) # check harmonic term if len(mode) == 1 and list(mode.values())[0] == 2: omega[list(mode.keys())[0]] = np.sqrt(factor) dof = [f"v_{i}" for i in mode.keys()] symbol = " ".join([f"x^{i}" for i in mode.values()]) qn = [0 for i in mode.keys()] factor /= prefactor ham_terms.append(Op(symbol, dof, factor=factor, qn=qn)) nterms += 1 # Coriolis terms B = np.array(B) zeta = np.array(zeta) terms = [("x", "partialx", "x", "partialx", 1.), ("x", "partialx", "partialx", "x", -1.), ("partialx", "x", "x", "partialx", -1.), ("partialx", "x", "partialx", "x", 1.)] for j, l in itertools.product(range(nmode), repeat=2): for i, k in itertools.product(range(j), range(l)): dof = [f"v_{i}", f"v_{j}", f"v_{k}", f"v_{l}"] tmp = -np.einsum("i,i,i ->", B, zeta[:, i, j], zeta[:, k, l]) qn = [0, 0, 0, 0] if abs(tmp) < 1e-15: continue for term in terms: symbol, factor = " ".join(term[:-1]), term[-1] * tmp ham_terms.append(Op(symbol, dof, factor=factor, qn=qn)) nterms += 4 # Kinetic terms for imode in range(nmode): ham_terms.append(Op("p^2", f"v_{imode}", 0.5, 0)) nterms += 1 logger.info(f"nterms: {nterms}") logger.info( f"omega: {np.sort(np.array(list(omega.values())),axis=None)*au2cm}") logger.info(f"omega_std: {np.array(omega_std)}") basis = [] for imode in range(nmode): basis.append(ba.BasisSHO(f"v_{imode}", omega[imode], 4, dvr=False)) model = Model(basis, ham_terms) mpo = Mpo(model) logger.info(f"mpo_bond_dims:{mpo.bond_dims}") #assert mpo.is_hermitian() alias = [ "v10", "v8", "v7", "v4", "v6", "v3", "v12", "v2", "v11", "v1", "v5", "v9" ] energy_list = {} M = 10 procedure = [[M, 0.4], [M, 0.2], [M, 0.2], [M, 0.1]] + [[M, 0]] * 100 mps = Mps.random(model, 0, M, percent=1.0) mps.optimize_config.procedure = procedure mps.optimize_config.method = "2site" mps.optimize_config.e_rtol = 1e-6 mps.optimize_config.e_atol = 1e-8 mps.optimize_config.nroots = 1 energies, mps = gs.optimize_mps(mps, mpo) logger.info(f"M: {M}, energy : {np.array(energies[-1])*au2cm}") tda = TDA(model, mpo, mps, nroots=3, algo="primme") e = tda.kernel(include_psi0=False) logger.info(f"tda energy : {(e-energies[-1])*au2cm}") assert np.allclose((e - energies[-1]) * au2cm, [824.74925026, 936.42650242, 951.96826289], atol=1) config, compressed_mps = tda.analysis_dominant_config(alias=alias) # std is calculated with M=200, include_psi0=True; the initial gs is # calculated with 9 state SA-DMRG; physical_bond=6 std = np.load(os.path.join(cur_dir, "c2h4_std.npz"))["200"] assert np.allclose(energies[-1] * au2cm, std[0], atol=2) assert np.allclose(e * au2cm, std[1:4], atol=3)
def find_lowest_energy(h_mpo: Mpo, nexciton, Mmax): logger.debug("begin finding lowest energy") model = h_mpo.model mps = Mps.random(model, nexciton, Mmax) energies, _ = optimize_mps(mps, h_mpo) return energies[-1]
def test_identity(): identity = Mpo.identity(mol_list) mps = Mps.random(mol_list, nexciton=1, m_max=5) assert mps.expectation(identity) == pytest.approx(mps.dmrg_norm) == pytest.approx(1)
h1e = np.random.uniform(-1, 1, size=(spin_norbs, spin_norbs)) h2e = np.random.uniform(-1, 1, size=(spin_norbs, spin_norbs, spin_norbs, spin_norbs)) h1e = 0.5 * (h1e + h1e.T) h2e = 0.5 * (h2e + h2e.transpose((2, 3, 0, 1))) basis, ham_terms = h_qc.qc_model(h1e, h2e) model = Model(basis, ham_terms) mpo = Mpo(model) logger.info(f"mpo_bond_dims:{mpo.bond_dims}") nelec = 10 energy_list = {} M = 50 procedure = [[M, 0.4], [M, 0.2], [M, 0.1], [M, 0], [M, 0], [M, 0], [M, 0]] mps = Mps.random(model, nelec, M, percent=1.0) mps.optimize_config.procedure = procedure mps.optimize_config.method = "2site" energies, mps = gs.optimize_mps(mps.copy(), mpo) gs_e = min(energies) + nuc logger.info(f"lowest energy: {gs_e}") # fci result assert np.allclose(gs_e, -75.008697516450) end = time.time() logger.info(f"time cost {end - start}")