.. _discrete:
Matsubara fitting for data generated by discrete poles
========================================================
In this note, let us illustrate how to perform Matsubara fitting using
test data generated by discrete poles with random weights.
Let us first define the inverse temperature :math:`\beta` and Matsubara
frequencies :math:`\{Z_n\}`:
.. math::
Z_n = \mathrm i \frac{(2n+1)\pi}{\beta}.
.. code:: ipython3
import numpy as np
import matplotlib.pyplot as plt
from adapol import hybfit
beta = 20
N = 55
Z = 1j *(np.linspace(-N, N, N + 1)) * np.pi / beta
We will generate Matsubara data evaluated on :math:`\{Z_n\}` using the
following formula:
.. math::
\begin{aligned}
G(\mathrm i\nu_n)& = \sum_{k=1}^{N_p} \frac{|v_k\rangle\langle v_k|}{\mathrm i\nu_n - E_k},
\end{aligned}
Where :math:`|v_k\rangle` is a :math:`N_{\text{orb}}\times 1` vector,
where :math:`N_{\text{orb}}` is the number of orbitals.
Below is the code for making a :math:`N_{\text{orb}}`-dimensional
Matsubara data on Matsubara frequencies :math:`Z`, by summing with
:math:`N_p` discrete poles.
.. code:: ipython3
def make_Delta_with_random_discrete_pole(Norb, Np, Z):
np.random.seed(0)
pol = np.cos((2*np.arange(Np)+1) * np.pi / (2*Np) )
vec = np.random.randn(Norb, Np) + 1j * np.random.randn(Norb, Np)
weight = np.array(
[vec[:, i, None] * np.transpose(np.conj(vec[:, i])) for i in range(Np)]
)
pol_t = np.reshape(pol, [pol.size, 1])
M = 1 / ( Z - pol_t)
M = M.transpose()
if len(weight.shape) == 1:
weight = weight / sum(weight)
Delta = M @ weight
else:
Nw = len(Z)
Delta = (M @ (weight.reshape(Np, Norb * Norb))).reshape(Nw, Norb, Norb)
return pol, weight, Delta
An example Matsubara data would look like the following:
.. code:: ipython3
pol, weight, Delta = make_Delta_with_random_discrete_pole(Norb=1, Np = 10, Z=Z)
plt.plot(Z.imag, Delta[:, 0, 0].real, label='real')
plt.plot(Z.imag, Delta[:, 0, 0].imag, label='imag')
plt.legend()
plt.title("Matsubara data")
.. parsed-literal::
Text(0.5, 1.0, 'Matsubara data')
.. image:: output_6_1.png
Let us first test the Matsubara fitting for scalar-valued Matsubara
functions.
.. code:: ipython3
tol = 1e-6 #Fitting tolerance
for Np in range(2, 21):
pol, weight, Delta = make_Delta_with_random_discrete_pole(Norb=1, Np = Np, Z=Z)
bathenergy, bathhyb, final_error, func = hybfit(Delta, Z, tol=tol)
assert(final_error < tol)
plt.plot(Np, len(bathenergy),"ro")
plt.xlabel("Number of acutal poles")
plt.ylabel("Number of bath orbitals required")
plt.title("Num. of bath orbitals to reach accuracy 1e-6 vs Num. of acutal poles")
plt.xticks(range(2, 21,3))
plt.show()
.. image:: output_8_0.png
Similarly, we can test for matrix-valued Matsubara functions:
.. code:: ipython3
tol = 1e-6
Norb = 4
for Np in range(2, 10):
pol, weight, G = make_Delta_with_random_discrete_pole(Norb=Norb, Np = Np, Z=Z)
bathenergy, bathhyb, final_error, func = hybfit(G, Z, tol=tol)
assert(final_error < tol)
One can also conduct Matsubara fitting via specifying number of modes
:math:`N_p` in the hybfit function:
.. code:: ipython3
pol, weight, G = make_Delta_with_random_discrete_pole(Norb=4, Np = 10, Z=Z)
bathenergy, bathhyb, final_error, func = hybfit(G, Z, Np=15)
print("Numer of bath orbitals is ", len(bathenergy))
print("Final error is ", final_error)
.. parsed-literal::
Numer of bath orbitals is 10
Final error is 6.189103600097627e-10
.. raw:: html
Triqs Interface
.. raw:: html
Let us demonstrate how to use our code if the Matsubara functions are
given using the TRIQS data structure.
In trqis, the Matsubara frequencies are defined using ``MeshImFreq``:
.. code:: ipython3
from triqs.gf import MeshImFreq
Norb = 1
iw_mesh = MeshImFreq(beta=beta, S='Fermion', n_iw=Z.shape[0]//2)
The ``hybfit_triqs`` function could handle TRIQS Green’s functions
object ``GF`` and ``BlockGf``:
.. code:: ipython3
from triqs.gf import Gf, BlockGf
from adapol import hybfit_triqs
Norb = 1
for Np in range(2, 21):
pol, weight, Delta = make_Delta_with_random_discrete_pole(Norb=Norb, Np = Np, Z=Z)
#Construct Gf object
delta_iw = Gf(mesh=iw_mesh, target_shape=[Norb, Norb])
delta_iw.data[:] = Delta
#Construct BlockGf object
delta_blk = BlockGf(name_list=['up', 'down'], block_list=[delta_iw, delta_iw], make_copies=True)
# Gf interface for hybridization fitting
bathhyb, bathenergy, delta_fit, final_error = hybfit_triqs(delta_iw, tol=tol, maxiter=50, debug=True)
assert final_error < tol
# BlockGf interface for hybridization fitting
bathhyb, bathenergy, delta_fit, final_error = hybfit_triqs(delta_blk, tol=tol, maxiter=50, debug=True)
assert final_error[0] < tol and final_error[1] < tol
.. parsed-literal::
optimization finished with fitting error 2.701e-15
optimization finished with fitting error 2.701e-15
optimization finished with fitting error 2.701e-15
optimization finished with fitting error 1.081e-14
optimization finished with fitting error 1.081e-14
optimization finished with fitting error 1.081e-14
optimization finished with fitting error 1.099e-14
optimization finished with fitting error 1.099e-14
optimization finished with fitting error 1.099e-14
optimization finished with fitting error 2.220e-14
optimization finished with fitting error 2.220e-14
optimization finished with fitting error 2.220e-14
optimization finished with fitting error 2.892e-14
optimization finished with fitting error 2.892e-14
optimization finished with fitting error 2.892e-14
optimization finished with fitting error 1.905e-14
optimization finished with fitting error 1.905e-14
optimization finished with fitting error 1.905e-14
optimization finished with fitting error 4.401e-07
optimization finished with fitting error 4.401e-07
optimization finished with fitting error 4.401e-07
optimization finished with fitting error 7.920e-08
optimization finished with fitting error 7.920e-08
optimization finished with fitting error 7.920e-08
optimization finished with fitting error 7.742e-07
optimization finished with fitting error 7.742e-07
optimization finished with fitting error 7.742e-07
optimization finished with fitting error 1.444e-10
optimization finished with fitting error 1.444e-10
optimization finished with fitting error 1.444e-10
optimization finished with fitting error 2.079e-09
optimization finished with fitting error 2.079e-09
optimization finished with fitting error 2.079e-09
optimization finished with fitting error 7.408e-10
optimization finished with fitting error 7.408e-10
optimization finished with fitting error 7.408e-10
optimization finished with fitting error 1.092e-09
optimization finished with fitting error 1.092e-09
optimization finished with fitting error 1.092e-09
optimization finished with fitting error 2.791e-09
optimization finished with fitting error 2.791e-09
optimization finished with fitting error 2.791e-09
optimization finished with fitting error 1.611e-09
optimization finished with fitting error 1.611e-09
optimization finished with fitting error 1.611e-09
optimization finished with fitting error 1.047e-09
optimization finished with fitting error 1.047e-09
optimization finished with fitting error 1.047e-09
optimization finished with fitting error 1.827e-09
optimization finished with fitting error 1.827e-09
optimization finished with fitting error 1.827e-09
optimization finished with fitting error 3.379e-09
optimization finished with fitting error 3.379e-09
optimization finished with fitting error 3.379e-09
optimization finished with fitting error 1.989e-09
optimization finished with fitting error 1.989e-09
optimization finished with fitting error 1.989e-09