Within some approximation a system has the ground state \(|\tilde{\psi}_0 \rangle\) and an excited state \(|\tilde{\psi}_1 \rangle = \hat{O}|\tilde{\psi}_0 \rangle \) that is connected via the operator \(\hat{O}\), which is known.
I now did a DMRG calculation for that system, obtaining the real ground state \(|\psi_0 \rangle\). As a first guess, I want to try to apply this operator to the real ground state (knowing that the operator is not the 'real' operator anymore) and then compare the spectrum in k-space. Performing a calculation on L sites I want to calculate the energy of the Fourier transformed, excited MPS \(|\psi_1 \rangle_k = \sum_{i=0}^{L-1} e^{ikr_i}\hat{O}_i|\psi_0 \rangle\).
What's the most efficient way to compute these energies? I can apply \(\hat{O}\) using mps.apply_local_op(), but the '+' operator is not overloaded for the mps class, so I wonder if there's a method to construct \(|\psi_0 \rangle_k \), or whether I have to calculate the energy for all the different combinations of the summands in \(|\psi_1 \rangle_k \) and \( \langle\psi_1 |_k \).
Concerning the energy calculation of \(|\psi_1 \rangle_k \), I haven't found an 'energy()' method in the mps-class. Should I use the mps.expectation_value() method, and if yes, is there some predefined Energy operator that I can pass as a string (like 'Sx' or 'Sp'), or is there a better way?
Fourier Transform Product state
Re: Fourier Transform Product state
The MPS does not know about the Hamiltonian, so it can't have an "energy" per se. Instead, you have a model you ran DMRG with, and you can compute the energy from the MPO of that model as
\(E = \langle \psi | H |\psi \rangle\).
(For a NearestNeighborModel, you can also use
From the context, I infer that the \(\hat O_i\) you talk about is an onsite operator.
In that case, I would actually suggest to write \(\hat O_k \equiv \frac{1}{\sqrt{L}} \sum_i e^{ik r_i} \hat{O}_i \) as an MPO and apply it to the state. (Double-check if this is the normalization you want!)
You can try something along these lines:
For the
E = model.H_MPO.expectation_value(psi)
giving you the value \(E = \langle \psi | H |\psi \rangle\).
(For a NearestNeighborModel, you can also use
E = np.sum(model.bond_energies())
.)From the context, I infer that the \(\hat O_i\) you talk about is an onsite operator.
In that case, I would actually suggest to write \(\hat O_k \equiv \frac{1}{\sqrt{L}} \sum_i e^{ik r_i} \hat{O}_i \) as an MPO and apply it to the state. (Double-check if this is the normalization you want!)
You can try something along these lines:
Code: Select all
from tenpy.networks.terms import TermList
from tenpy.networks.mpo import MPOGraph
def get_op_k(k, op, sites, bc):
L = len(sites)
x = np.arange(L)
Sk_terms = TermList([[(op, i)] for i in range(L)], np.exp(1.j*k*x)/np.sqrt(L))
return MPOGraph.from_term_list(Sk_terms, sites, bc).build_MPO()
psi0, model = ... # from DMRG
options = {'compression_method': 'SVD', 'trunc_params: {'chi_max': 100}}
for k in np.linspace(0, 2*np.pi, L, False):
psi_k = psi0.copy()
O_k = get_op_k(k, 'Sp', psi.sites, psi.bc) # assuming your local `O` is just `Sp`
O_k.apply(psi_k, options)
E_k = model.H_MPO.expectation_value(O_k)
print(f"k={k:.3f}: E_k={E_k:.8f}")
options
, see apply.