def test_dynamics(dissipation, dt, nsteps): tentative_mpo = Mpo(band_limit_mol_list) gs_mp = MpDm.max_entangled_gs(band_limit_mol_list) # subtract the energy otherwise might cause numeric error because of large offset * dbeta energy = Quantity(gs_mp.expectation(tentative_mpo)) mpo = Mpo(band_limit_mol_list, offset=energy) tp = ThermalProp(gs_mp, mpo, exact=True, space="GS") tp.evolve(None, 50, low_t.to_beta() / 2j) gs_mp = tp.latest_mps center_mol_idx = band_limit_mol_list.mol_num // 2 creation_operator = Mpo.onsite( band_limit_mol_list, r"a^\dagger", mol_idx_set={center_mol_idx} ) mpdm = creation_operator.apply(gs_mp) mpdm_full = MpDmFull.from_mpdm(mpdm) # As more compression is involved higher threshold is necessary mpdm_full.compress_config = CompressConfig(threshold=1e-4) liouville = SuperLiouville(mpo, dissipation) r_square_list = [calc_r_square(mpdm_full.e_occupations)] time_series = [0] for i in range(nsteps - 1): logger.info(mpdm_full) mpdm_full = mpdm_full.evolve(liouville, dt) r_square_list.append(calc_r_square(mpdm_full.e_occupations)) time_series.append(time_series[-1] + dt) time_series = np.array(time_series) if dissipation == 0: assert np.allclose(get_analytical_r_square(time_series), r_square_list, rtol=1e-2, atol=1e-3) else: # not much we can do, just basic sanity check assert (np.array(r_square_list)[1:] < get_analytical_r_square(time_series)[1:]).all()
def test_FT_dynamics_hybrid_TDDMRG_TDH(n_dmrg_phs, scheme): mol_list = parameter_PBI.construct_mol(4, n_dmrg_phs, 10 - n_dmrg_phs).switch_scheme(scheme) mpdm = MpDm.max_entangled_gs(mol_list) tentative_mpo = Mpo(mol_list) temperature = Quantity(2000, "K") tp = ThermalProp(mpdm, tentative_mpo, exact=True, space="GS") tp.evolve(None, 1, temperature.to_beta() / 2j) mpdm = ( Mpo.onsite(mol_list, r"a^\dagger", mol_idx_set={0}).apply(tp.latest_mps).normalize(1.0) ) mpdm.compress_config = CompressConfig(threshold=5e-4) offset = mpdm.expectation(tentative_mpo) mpo = Mpo(mol_list, offset=Quantity(offset, "a.u.")) # do the evolution # nsteps = 90 # too many steps, may take hours to finish nsteps = 40 dt = 10.0 occ = [mpdm.e_occupations] for i in range(nsteps): mpdm = mpdm.evolve(mpo, dt) occ.append(mpdm.e_occupations) # make it compatible with std data occ = np.array(occ[:nsteps]).transpose() with open(os.path.join(cur_dir, "FT_occ" + str(n_dmrg_phs) + ".npy"), "rb") as f: std = np.load(f) assert np.allclose(occ[:, :nsteps], std[:, :nsteps], atol=1e-3, rtol=1e-3)
def init_mps(self): tentative_mpo = Mpo(self.model) if self.temperature == 0: gs_mp = Mps.ground_state(self.model, max_entangled=False) else: if self._defined_output_path: gs_mp = load_thermal_state(self.model, self._thermal_dump_path) else: gs_mp = None if gs_mp is None: gs_mp = MpDm.max_entangled_gs(self.model) # subtract the energy otherwise might cause numeric error because of large offset * dbeta energy = Quantity(gs_mp.expectation(tentative_mpo)) mpo = Mpo(self.model, offset=energy) tp = ThermalProp(gs_mp, mpo, exact=True, space="GS") tp.evolve(None, max(20, len(gs_mp)), self.temperature.to_beta() / 2j) gs_mp = tp.latest_mps if self._defined_output_path: gs_mp.dump(self._thermal_dump_path) init_mp = self.create_electron(gs_mp) energy = Quantity(init_mp.expectation(tentative_mpo)) self.mpo = Mpo(self.model, offset=energy) logger.info(f"mpo bond dims: {self.mpo.bond_dims}") logger.info(f"mpo physical dims: {self.mpo.pbond_list}") init_mp.evolve_config = self.evolve_config init_mp.compress_config = self.compress_config if self.evolve_config.is_tdvp: init_mp = init_mp.expand_bond_dimension(self.mpo) init_mp.canonicalise() return init_mp
def init_mps(self): tentative_mpo = Mpo(self.mol_list) if self.temperature == 0: gs_mp = Mps.gs(self.mol_list, max_entangled=False) if self.dissipation != 0: gs_mp = MpDm.from_mps(gs_mp) else: gs_mp = MpDm.max_entangled_gs(self.mol_list) # subtract the energy otherwise might cause numeric error because of large offset * dbeta energy = Quantity(gs_mp.expectation(tentative_mpo)) mpo = Mpo(self.mol_list, offset=energy) tp = ThermalProp(gs_mp, mpo, exact=True, space="GS") tp.evolve(None, len(gs_mp), self.temperature.to_beta() / 2j) gs_mp = tp.latest_mps init_mp = self.create_electron(gs_mp) if self.dissipation != 0: init_mp = MpDmFull.from_mpdm(init_mp) energy = Quantity(init_mp.expectation(tentative_mpo)) self.mpo = Mpo(self.mol_list, offset=energy) logger.info(f"mpo bond dims: {self.mpo.bond_dims}") logger.info(f"mpo physical dims: {self.mpo.pbond_list}") if self.dissipation != 0: self.mpo = SuperLiouville(self.mpo, self.dissipation) init_mp.canonicalise() init_mp.evolve_config = self.evolve_config # init the compress config if not using threshold and not set if self.compress_config.criteria is not CompressCriteria.threshold\ and self.compress_config.max_dims is None: self.compress_config.set_bonddim(length=len(init_mp) + 1) init_mp.compress_config = self.compress_config # init_mp.invalidate_cache() return init_mp
def test_mpo(): gs_dm = MpDm.max_entangled_gs(mol_list) beta = Quantity(10, "K").to_beta() tp = ThermalProp(gs_dm, Mpo(gs_dm.mol_list), exact=True, space="GS") tp.evolve(None, 500, beta / 1j) gs_dm = tp.latest_mps mp = creation_operator.apply(gs_dm) check_property(mp)
def init_mps_abs(self): dipole_mpo = Mpo.onsite(self.mol_list, r"a^\dagger", dipole=True) i_mpo = MpDm.max_entangled_gs(self.mol_list) beta = self.temperature.to_beta() tp = ThermalProp(i_mpo, self.h_mpo, exact=True, space="GS") tp.evolve(None, 1, beta / 2j) ket_mpo = tp.latest_mps ket_mpo.evolve_config = self.evolve_config a_ket_mpo = dipole_mpo.apply(ket_mpo, canonicalise=True) a_ket_mpo.canonical_normalize() a_bra_mpo = a_ket_mpo.copy() return BraKetPairAbsFiniteT(a_bra_mpo, a_ket_mpo)
def test_bogoliubov(): # REF: JCP, 2016, 145, 224101 evolve_config = EvolveConfig(EvolveMethod.tdvp_ps) # evolve_config = EvolveConfig() omega = 1 D = 1 nlevel = 10 T = Quantity(1) ph1 = Phonon.simple_phonon(Quantity(omega), Quantity(D), nlevel) mol1 = Mol(Quantity(0), [ph1]) mlist = MolList([mol1] * 2, Quantity(1), scheme=4) mpdm1 = MpDm.max_entangled_gs(mlist) mpdm1.evolve_config = evolve_config mpo1 = Mpo(mlist) tp = ThermalProp(mpdm1, mpo1, exact=True) tp.evolve(nsteps=20, evolve_time=T.to_beta() / 2j) mpdm2 = tp.latest_mps e1 = mpdm2.expectation(mpo1) mpdm3 = (Mpo.onsite(mlist, r"a^\dagger", False, {0}) @ mpdm2).expand_bond_dimension(mpo1) es1 = [mpdm3.e_occupations] for i in range(40): mpdm3 = mpdm3.evolve(mpo1, 0.1) es1.append(mpdm3.e_occupations) theta = np.arctanh(np.exp(-T.to_beta() * omega / 2)) ph2 = Phonon.simple_phonon(Quantity(omega), Quantity(D * np.cosh(theta)), nlevel) ph3 = Phonon.simple_phonon(Quantity(-omega), Quantity(-D * np.sinh(theta)), nlevel) mol2 = Mol(Quantity(0), [ph2, ph3]) mlist2 = MolList([mol2] * 2, Quantity(1), scheme=4) mps1 = Mps.gs(mlist2, False) mps1.evolve_config = evolve_config mpo2 = Mpo(mlist2) e2 = mps1.expectation(mpo2) mps2 = (Mpo.onsite(mlist2, r"a^\dagger", False, {0}) @ mps1).expand_bond_dimension(mpo2) es2 = [mps2.e_occupations] for i in range(20): mps2 = mps2.evolve(mpo2, 0.2) es2.append(mps2.e_occupations) assert np.allclose(es1[::2], es2, atol=5e-3)
def test_mpdm_full(nmols, phonon_freq): ph = Phonon.simple_phonon(Quantity(phonon_freq), Quantity(1), 2) m = Mol(Quantity(0), [ph]) mol_list = MolList([m] * nmols, Quantity(1)) gs_dm = MpDm.max_entangled_gs(mol_list) beta = Quantity(1000, "K").to_beta() tp = ThermalProp(gs_dm, Mpo(mol_list), exact=True, space="GS") tp.evolve(None, 50, beta / 1j) gs_dm = tp.latest_mps assert np.allclose(gs_dm.e_occupations, [0] * nmols) e_gs_dm = Mpo.onsite(mol_list, r"a^\dagger", mol_idx_set={0}).apply(gs_dm, canonicalise=True) assert np.allclose(e_gs_dm.e_occupations, [1] + [0] * (nmols - 1)) mpdm_full = MpDmFull.from_mpdm(e_gs_dm) assert np.allclose(mpdm_full.e_occupations, e_gs_dm.e_occupations) assert np.allclose(mpdm_full.ph_occupations, e_gs_dm.ph_occupations, rtol=1e-3)
def init_mps(self): beta = self.temperature.to_beta() self.h_mpo = Mpo(self.mol_list) if self.spectratype == "abs": dipole_mpo = Mpo.onsite(self.mol_list, r"a^\dagger", dipole=True) i_mpo = MpDm.max_entangled_gs(self.mol_list) tp = ThermalProp(i_mpo, self.h_mpo, exact=True, space='GS') tp.evolve(None, 1, beta / 2j) ket_mpo = tp.latest_mps else: impo = MpDm.max_entangled_ex(self.mol_list) dipole_mpo = Mpo.onsite(self.mol_list, "a", dipole=True) if self.job_name is None: job_name = None else: job_name = self.job_name + "_thermal_prop" impo.compress_config = self.compress_config tp = ThermalProp(impo, self.h_mpo, evolve_config=self.evolve_config, dump_dir=self.dump_dir, job_name=job_name) self._defined_output_path = tp._defined_output_path if tp._defined_output_path: try: logger.info( f"load density matrix from {self._thermal_dump_path}") ket_mpo = MpDm.load(self.mol_list, self._thermal_dump_path) logger.info(f"density matrix loaded: {ket_mpo}") except FileNotFoundError: logger.debug(f"no file found in {self._thermal_dump_path}") tp.evolve(None, self.insteps, beta / 2j) ket_mpo = tp.latest_mps ket_mpo.dump(self._thermal_dump_path) self.a_ket_mpo = dipole_mpo.apply(ket_mpo, canonicalise=True) self.cv_mpo = Mpo.finiteT_cv(self.mol_list, 1, self.m_max, self.spectratype, percent=1.0) self.cv_mps = self.cv_mpo
def init_b_mpo(self): # get the right hand site vector b, Ax=b # b = -eta * dipole * \psi_0 # only support Holstien model 0/1 exciton manifold beta = self.temperature.to_beta() if self.spectratype == "abs": dipole_mpo = Mpo.onsite(self.model, r"a^\dagger", dipole=True) i_mpo = MpDm.max_entangled_gs(self.model) tp = ThermalProp(i_mpo, self.h_mpo, exact=True, space='GS') tp.evolve(None, 1, beta / 2j) ket_mpo = tp.latest_mps elif self.spectratype == "emi": dipole_mpo = Mpo.onsite(self.model, "a", dipole=True) if self._defined_output_path: ket_mpo = \ load_thermal_state(self.model, self._thermal_dump_path) else: ket_mpo = None if ket_mpo is None: impo = MpDm.max_entangled_ex(self.model) impo.compress_config = self.compress_config if self.job_name is None: job_name = None else: job_name = self.job_name + "_thermal_prop" tp = ThermalProp(impo, self.h_mpo, evolve_config=self.evolve_config, dump_dir=self.dump_dir, job_name=job_name) tp.evolve(None, self.insteps, beta / 2j) ket_mpo = tp.latest_mps if self._defined_output_path: ket_mpo.dump(self._thermal_dump_path) else: assert False ket_mpo = dipole_mpo.apply(ket_mpo.scale(-self.eta)) return ket_mpo, None
def test_ft(): model = get_model() mpo = Mpo(model) impdm = MpDm.max_entangled_gs(model) impdm.compress_config = CompressConfig(threshold=1e-6) temperature = Quantity(3) evolve_config = EvolveConfig(adaptive=True, guess_dt=-0.001j) tp = ThermalProp(impdm, mpo, evolve_config=evolve_config) tp.evolve(nsteps=1, evolve_time=temperature.to_beta() / 2j) mpdm = tp.latest_mps mpdm = Mpo(model, Op("sigma_x", "spin")).contract(mpdm) mpdm.evolve_config = EvolveConfig(adaptive=True, guess_dt=0.1) time_series = [0] sigma_z_oper = Mpo(model, Op("sigma_z", "spin")) spin = [mpdm.expectation(sigma_z_oper)] for i in range(29): dt = mpdm.evolve_config.guess_dt mpdm = mpdm.evolve(mpo, evolve_dt=dt) time_series.append(time_series[-1] + dt) spin.append(mpdm.expectation(sigma_z_oper)) qutip_res = get_qutip_ft(model, temperature, time_series) assert np.allclose(qutip_res, spin, atol=1e-3)
def test_ft(): mol = get_mol() mol_list = MolList([mol], Quantity(0)) mpo = Mpo(mol_list) impdm = MpDm.max_entangled_gs(mol_list) impdm.compress_config = CompressConfig(threshold=1e-6) impdm.use_dummy_qn = True temperature = Quantity(3) evolve_config = EvolveConfig(adaptive=True, guess_dt=-0.001j) tp = ThermalProp(impdm, mpo, evolve_config=evolve_config) tp.evolve(nsteps=1, evolve_time=temperature.to_beta() / 2j) mpdm = tp.latest_mps mpdm = Mpo.onsite(mol_list, r"sigma_x").contract(mpdm) mpdm.evolve_config = EvolveConfig(adaptive=True, guess_dt=0.1) time_series = [0] spin = [1 - 2 * mpdm.e_occupations[0]] for i in range(30): dt = mpdm.evolve_config.guess_dt mpdm = mpdm.evolve(mpo, evolve_dt=dt) time_series.append(time_series[-1] + dt) spin.append(1 - 2 * mpdm.e_occupations[0]) exact = get_exact_ft(mol, temperature, time_series) assert np.allclose(exact, spin, atol=1e-3)