def ph_onsite(cls, mol_list: MolList, opera: str, mol_idx:int, ph_idx=0): assert opera in ["b", r"b^\dagger", r"b^\dagger b"] mpo = cls() mpo.mol_list = mol_list for imol, mol in enumerate(mol_list): if mol_list.scheme < 4: mpo.append(xp.eye(2).reshape(1, 2, 2, 1)) elif mol_list.scheme == 4: if len(mpo) == mol_list.e_idx(): n = mol_list.mol_num mpo.append(xp.eye(n).reshape(1, n, n, 1)) else: assert False iph = 0 for ph in mol.dmrg_phs: for iqph in range(ph.nqboson): ph_pbond = ph.pbond[iqph] if imol == mol_idx and iph == ph_idx: mt = ph_op_matrix(opera, ph_pbond) else: mt = ph_op_matrix("Iden", ph_pbond) mpo.append(mt.reshape(1, ph_pbond, ph_pbond, 1)) iph += 1 mpo.build_empty_qn() return mpo
def exact_propagator(cls, mol_list: MolList, x, space="GS", shift=0.0): """ construct the GS space propagator e^{xH} exact MPO H=\\sum_{in} \\omega_{in} b^\\dagger_{in} b_{in} fortunately, the H is local. so e^{xH} = e^{xh1}e^{xh2}...e^{xhn} the bond dimension is 1 shift is the a constant for H+shift """ assert space in ["GS", "EX"] mpo = cls() if np.iscomplex(x): mpo.to_complex(inplace=True) mpo.mol_list = mol_list for imol, mol in enumerate(mol_list): if mol_list.scheme < 4: mo = np.eye(2).reshape(1, 2, 2, 1) mpo.append(mo) elif mol_list.scheme == 4: if len(mpo) == mol_list.e_idx(): n = mol_list.mol_num mpo.append(np.eye(n).reshape(1, n, n, 1)) else: assert False for ph in mol.dmrg_phs: if space == "EX": # for the EX space, with quasiboson algorithm, the b^\dagger + b # operator is not local anymore. assert ph.nqboson == 1 ph_pbond = ph.pbond[0] # construct the matrix exponential by diagonalize the matrix first phop = construct_ph_op_dict(ph_pbond) h_mo = ( phop[r"b^\dagger b"] * ph.omega[0] + phop[r"(b^\dagger + b)^3"] * ph.term30 + phop[r"b^\dagger + b"] * (ph.term10 + ph.term11) + phop[r"(b^\dagger + b)^2"] * (ph.term20 + ph.term21) + phop[r"(b^\dagger + b)^3"] * (ph.term31 - ph.term30) ) w, v = scipy.linalg.eigh(h_mo) h_mo = np.diag(np.exp(x * w)) h_mo = v.dot(h_mo) h_mo = h_mo.dot(v.T) mo = h_mo.reshape(1, ph_pbond, ph_pbond, 1) mpo.append(mo) elif space == "GS": anharmo = False # for the ground state space, yet doesn't support 3rd force # potential quasiboson algorithm ph_pbond = ph.pbond[0] for i in range(len(ph.force3rd)): anharmo = not np.allclose( ph.force3rd[i] * ph.dis[i] / ph.omega[i], 0.0 ) if anharmo: break if not anharmo: for iboson in range(ph.nqboson): d = np.exp( x * ph.omega[0] * ph.base ** (ph.nqboson - iboson - 1) * np.arange(ph_pbond) ) mo = np.diag(d).reshape(1, ph_pbond, ph_pbond, 1) mpo.append(mo) else: assert ph.nqboson == 1 # construct the matrix exponential by diagonalize the matrix first phop = construct_ph_op_dict(ph_pbond) h_mo = ( phop[r"b^\dagger b"] * ph.omega[0] + phop[r"(b^\dagger + b)^3"] * ph.term30 ) w, v = scipy.linalg.eigh(h_mo) h_mo = np.diag(np.exp(x * w)) h_mo = v.dot(h_mo) h_mo = h_mo.dot(v.T) mo = np.zeros([1, ph_pbond, ph_pbond, 1]) mo[0, :, :, 0] = h_mo mpo.append(mo) else: assert False # shift the H by plus a constant mpo.qn = [[0]] * (len(mpo) + 1) mpo.qnidx = len(mpo) - 1 mpo.qntot = 0 # np.exp(shift * x) is usually very large mpo = mpo.scale(np.exp(shift * x), inplace=True) return mpo