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 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_optimization(scheme, method): mps, mpo = construct_mps_mpo_2(holstein_model.switch_scheme(scheme), procedure[0][0], nexciton) mps.optimize_config.procedure = procedure mps.optimize_config.method = method energies, mps_opt = optimize_mps(mps.copy(), mpo) assert energies[-1] == pytest.approx(0.08401412 + holstein_model.gs_zpe, rel=1e-5) assert mps_opt.expectation(mpo) == pytest.approx(0.08401412 + holstein_model.gs_zpe, rel=1e-5)
def test_multistate(method, algo): mps, mpo = construct_mps_mpo_2(holstein_model, procedure[0][0], nexciton) mps.optimize_config.procedure = procedure mps.optimize_config.nroots = 4 mps.optimize_config.method = method mps.optimize_config.algo = algo mps.optimize_config.e_atol = 1e-6 mps.optimize_config.e_rtol = 1e-6 energy, mps = optimize_mps(mps, mpo) expectation = [mp.expectation(mpo) for mp in mps] energy_std = np.array([0.08401412, 0.08449771, 0.08449801, 0.08449945 ]) + holstein_model.gs_zpe assert np.allclose(energy[-1], energy_std) assert np.allclose(expectation, energy_std)
def test_ex(method, nroots): mps, mpo = construct_mps_mpo_2(holstein_model, procedure[0][0], nexciton) mps.optimize_config.procedure = procedure mps.optimize_config.nroots = nroots mps.optimize_config.method = method mps.optimize_config.e_atol = 1e-6 mps.optimize_config.e_rtol = 1e-6 omega = 0.084 energy, mps = optimize_mps(mps, mpo, omega=omega) energy_std = np.array([0.08401412, 0.08449771, 0.08449801, 0.08449945 ]) + holstein_model.gs_zpe if nroots == 1: #print("eigenenergy", mps.expectation(mpo)) assert np.allclose(mps.expectation(mpo), energy_std[0]) else: #print("eigenenergy", [ms.expectation(mpo) for ms in mps]) assert np.allclose([ms.expectation(mpo) for ms in mps], energy_std)
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_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 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)
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}")