Here we give a basic example demonstrating some of the functionality of the SmoQySynthAC.jl package.

using SmoQySynthAC
using Distributions
using CairoMakie

# render figures using SVG backend so they are sharp
CairoMakie.activate!(type = "svg")

In this example we will work with the single-particle imaginary time fermion Green's function which is given by

\[G(\tau) = \int_{-\infty}^\infty K_\beta(\omega,\tau) A(\omega)\]

where $A(\omega)$ is the spectral function and

\[K_\beta(\omega,\tau) = \frac{e^{-\tau \omega}}{1 + e^{-\beta \omega}}\]

is the kernel function where $\beta = 1/T$ is the inverse temperature and it is assumed that $\tau \in [0, \beta)$.

As a first step in demonstrating the functionality of SmoQySynthAC.jl package, let us define a synthetic spectral function $A(\omega)$. For convenience we will do this using the Distributions.jl package. Here we define the spectral function as Lorentzian (Cauchy) distribution in between two Normal distributions.

# define spectral function distribution
spectral_dist = MixtureModel(
    [Normal(-2.0,0.7), Cauchy(0.0, 0.3), Normal(+2.0,0.7)],
    [0.2, 0.4, 0.4]
)

# define method to evaluate spectral function
spectral_function = ω -> pdf(spectral_dist, ω)
#1 (generic function with 1 method)

Now let us quickly plot our spectral function so we can see what it looks like.

ωmin = -6.0
ωmax = 6.0
ω = collect(range(start = ωmin, stop = ωmax, length = 1000))
A = spectral_function.(ω)

fig = Figure(
    size = (700, 400),
    fonts = (; regular= "CMU Serif"),
    figure_padding = 10
)

ax = Axis(
    fig[1, 1],
    aspect = 7/4,
    xlabel = L"\omega", ylabel = L"A(\omega)",
    xlabelsize = 30, ylabelsize = 30,
    xticklabelsize = 24, yticklabelsize = 24,
)

lines!(
    ω, A,
    linewidth = 2,
    alpha = 1.0,
    color = :black,
    linestyle = :solid
)

xlims!(ax, ωmin, ωmax)
ylims!(ax, 0.0, 1.05*maximum(A))

fig
Example block output

The next step is to define the inverse temperature $\beta$, discretization in imaginary $\Delta\tau$ and corresponding $\tau$ grid.

# Set inverse temperature.
β = 10.0

# Set discretization in imaginary time.
Δτ = 0.05

# Calculate corresponding imaginary time grid.
τ = collect(range(start = 0.0, stop = β, step = Δτ));

Now we can calculate $G(\tau)$ using the spectral_to_imaginary_time_correlation_function method and appropriate kernel function kernel_tau_fermi.

# Calculate imaginary time Green's function.
Gτ = spectral_to_imaginary_time_correlation_function(
    τ = τ,
    β = β,
    spectral_function = spectral_function,
    kernel_function = kernel_tau_fermi,
    tol = 1e-10
);

We can similary calculate the Matsubara Green's function $G(\text{i}\omega_n)$ using the function spectral_to_matsubara_correlation_function function with the kernel function kernel_mat_fermi.

# Define Matsubara frequency grid in terms of integers n where ωₙ = (2n+1)π/β.
n = collect(-250:250)

# Calculate Matsubara Green's function.
Gn = spectral_to_matsubara_correlation_function(;
    n = n,
    β = β,
    spectral_function = spectral_function,
    kernel_function = kernel_mat_fermi,
    tol = 1e-10,
);

The resulting real and imaginary parts of $G(\text{i}\omega_n)$ are plotted below.

ωn = @. (2*n+1)*π/β

fig = Figure(
    size = (700, 500),
    fonts = (; regular= "CMU Serif"),
    figure_padding = 10
)

ax = Axis(fig[1, 1],
    aspect = 7/5,
    xlabel = L"\omega_n",
    ylabel = L"G_\sigma(\text{i}\omega_n)",
    xlabelsize = 30, ylabelsize = 30,
    xticklabelsize = 24, yticklabelsize = 24,
)

xlims!(ax, minimum(ωn), maximum(ωn))

lines!(
    ωn, real.(Gn),
    linewidth = 2, alpha = 2.0, color = :red, linestyle = :solid, label = L"\text{Re}[G_\sigma(\text{i}\omega_n)]"
)

lines!(
    ωn, imag.(Gn),
    linewidth = 2, alpha = 1.5, color = :green, linestyle = :solid, label = L"\text{Im}[G_\sigma(\text{i}\omega_n)]"
)

axislegend(
    ax, halign = :left, valign = :top, labelsize = 30
)

fig
Example block output

Having calculated the exact $G(\tau)$ function, let us now add some noise to it using the add_noise method.

Gτ_noisy = add_noise(
    Cτ_exact = Gτ,
    τ = τ,
    σ = 1.0e-2,
    ξ = 0.5,
    sum_rule = C0 -> 1 - C0, # enforces fermionic boundary condition that C(τ=β) = 1 - C(τ=0)
    noise_type = :TruncatedNormal
);

Let us now plot what both $G(\tau)$ and $G_{\rm noisy}(\tau)$.

fig = Figure(
    size = (700, 500),
    fonts = (; regular= "CMU Serif"),
    figure_padding = 10
)

ax = Axis(fig[1, 1],
    aspect = 7/5,
    xlabel = L"\tau",
    ylabel = L"G_\sigma(\tau)",
    xlabelsize = 30, ylabelsize = 30,
    xticklabelsize = 24, yticklabelsize = 24,
)

xlims!(ax, 0.0, β)
ylims!(ax, 0.0, 1.0)

lines!(
    τ, Gτ,
    linewidth = 2, alpha = 2.0, color = :black, linestyle = :solid, label = "Exact"
)

lines!(
    τ, Gτ_noisy,
    linewidth = 2, alpha = 1.5, color = :red, linestyle = :solid, label = "Noisy"
)

axislegend(
    ax, halign = :left, valign = :top, labelsize = 30
)

fig
Example block output