Source code for dgamore.matsubara_frequencies

# SPDX-FileCopyrightText: 2025-2026 Julian Peil <julian.peil@tuwien.ac.at>
# SPDX-License-Identifier: MIT
#
# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) &
#           Eliashberg Equation Solver for Strongly Correlated Electron Systems
"""
Helpers for Matsubara frequency arithmetic. :class:`MFHelper` builds the integer index grids and the
corresponding real bosonic/fermionic Matsubara frequencies used throughout the code, and converts
particle-hole (ph) frequency triples to particle-particle (pp) notation.
"""

from enum import Enum

import numpy as np
from multimethod import multimethod


[docs] class FrequencyShift(Enum): """ Enum for the direction of an asymptotic frequency shift (used when extending a quantity beyond its core box). :cvar MINUS: Shift towards negative frequencies. :cvar PLUS: Shift towards positive frequencies. :cvar CENTER: Centered (symmetric) shift. :cvar NONE: No shift. """ MINUS: str = "minus" PLUS: str = "plus" CENTER: str = "center" NONE: str = "none"
[docs] class MFHelper: """ Collection of static helpers for Matsubara frequency index and grid arithmetic. """ @multimethod @staticmethod def wn(niw: int, shift: int = 0, return_only_positive: bool = False) -> np.ndarray: r""" Returns the integer bosonic Matsubara indices in the closed interval :math:`[-\mathrm{niw}, \mathrm{niw}]`, optionally shifted. This is the index-only overload (no temperature dependence). :param niw: Half-width of the bosonic frequency box (number of positive bosonic frequencies). :param shift: Integer offset added to the whole index range. :param return_only_positive: If True, return only the non-negative indices :math:`[0, \mathrm{niw}]`. :return: 1D integer array of bosonic Matsubara indices. """ if return_only_positive: return np.arange(shift, niw + shift + 1) return np.arange(-niw + shift, niw + shift + 1)
[docs] @multimethod @staticmethod def wn(niw: int, beta: float, shift: int = 0, return_only_positive: bool = False) -> np.ndarray: r""" Returns the real bosonic Matsubara frequencies :math:`\omega_n = 2 n \pi / \beta` for the index range :math:`n \in [-\mathrm{niw}, \mathrm{niw}]`, optionally shifted. :param niw: Half-width of the bosonic frequency box (number of positive bosonic frequencies). :param beta: Inverse temperature :math:`\beta`. :param shift: Integer offset added to the whole index range before scaling. :param return_only_positive: If True, return only the non-negative frequencies. :return: 1D real array of bosonic Matsubara frequencies. """ return np.pi / beta * 2 * MFHelper.wn(niw, shift, return_only_positive)
@multimethod @staticmethod def vn(niv: int, shift: int = 0, return_only_positive: bool = False) -> np.ndarray: r""" Returns the integer fermionic Matsubara indices in the half-open interval :math:`[-\mathrm{niv}, \mathrm{niv})`, optionally shifted. This is the index-only overload (no temperature dependence). :param niv: Half-width of the fermionic frequency box (number of positive fermionic frequencies). :param shift: Integer offset added to the whole index range. :param return_only_positive: If True, return only the non-negative indices :math:`[0, \mathrm{niv})`. :return: 1D integer array of fermionic Matsubara indices. """ if return_only_positive: return np.arange(shift, niv + shift) return np.arange(-niv + shift, niv + shift)
[docs] @multimethod @staticmethod def vn(niv: int, beta: float, shift: int = 0, return_only_positive: bool = False) -> np.ndarray: r""" Returns the real fermionic Matsubara frequencies :math:`\nu_n = (2 n + 1) \pi / \beta` for the index range :math:`n \in [-\mathrm{niv}, \mathrm{niv})`, optionally shifted. :param niv: Half-width of the fermionic frequency box (number of positive fermionic frequencies). :param beta: Inverse temperature :math:`\beta`. :param shift: Integer offset added to the whole index range before scaling. :param return_only_positive: If True, return only the positive frequencies. :return: 1D real array of fermionic Matsubara frequencies. """ return np.pi / beta * (2 * MFHelper.vn(niv, shift, return_only_positive) + 1)
[docs] @staticmethod def get_frequencies_for_ph_to_pp_w0_channel_conversion( niw: int, niv: int ) -> tuple[np.ndarray, np.ndarray, np.ndarray]: r""" Returns the index arrays that map a particle-hole quantity onto the :math:`\omega = 0` particle-particle notation, i.e. the :math:`(\omega', \nu_1', \nu_2')` indices such that :math:`F_{pp}[\omega, \nu_1, \nu_2] = F_{ph}[\omega', \nu_1', \nu_2']` with the frequency shift :math:`(\omega = 0, \nu_1, \nu_2) \to (\nu_1 + \nu_2, \nu_1, \nu_2)`. The returned arrays are already offset so they can be used to index directly into the full (positive-and-negative) ph frequency axes. :param niw: Half-width of the bosonic frequency box of the source ph quantity. :param niv: Half-width of the fermionic frequency box of the source ph quantity. :return: Tuple ``(wn_pp, vn_pp, vpn_pp)`` of index arrays for the bosonic and the two fermionic axes. """ niv_pp = min(niw // 2, niv) vn = MFHelper.vn(niv_pp) vn_pp, vpn_pp = np.meshgrid(vn, vn, indexing="ij") wn_pp = niw + vn_pp + vpn_pp + 1 vn_pp += niv vpn_pp += niv return wn_pp, vn_pp, vpn_pp