Source code for mqed.Lindblad.coupling_filter
# mqed/Lindblad/coupling_filter.py
import numpy as np
[docs]
def _mask_within_hops(N: int, hop_radius: int, *, include_on_site: bool) -> np.ndarray:
"""Boolean mask for sites within a hop distance on a 1D chain.
Condition: ``abs(i - j) <= hop_radius``. Example: ``hop_radius=1`` keeps
nearest neighbours (and on-site when ``include_on_site=True``); ``hop_radius=2``
keeps up to next-nearest neighbours.
"""
i = np.arange(N)
M = (np.abs(i[:, None] - i[None, :]) <= hop_radius)
if not include_on_site:
np.fill_diagonal(M, False)
return M
[docs]
def enforce_coupling_range(
V: np.ndarray, Gamma: np.ndarray, *,
V_hop_radius: int | None = None,
keep_V_on_site: bool = False,
Gamma_rule: str = "leave", # "leave" | "same_as_V" | "diagonal_only" | "limit_by_hops"
Gamma_hop_radius: int | None = None,
keep_Gamma_on_site: bool = True,
) -> tuple[np.ndarray, np.ndarray]:
"""Zero out V and Γ beyond a chosen hop range.
Args:
V: (N, N) coherent coupling matrix.
Gamma: (N, N) dissipative coupling matrix.
V_hop_radius: If set, keep pairs with ``abs(i-j) <= V_hop_radius``.
keep_V_on_site: If False, zero the diagonal of V.
Gamma_rule: How to mask Γ ("leave", "same_as_V", "diagonal_only", "limit_by_hops").
Gamma_hop_radius: Hop limit for Γ when ``Gamma_rule="limit_by_hops"``.
keep_Gamma_on_site: If False, zero the diagonal of Γ where applicable.
Returns:
tuple[np.ndarray, np.ndarray]: Filtered, symmetrized copies of V and Γ.
"""
N = V.shape[0]
V_new, G_new = V.copy(), Gamma.copy()
# --- V (coherent)
if V_hop_radius is not None:
MV = _mask_within_hops(N, V_hop_radius, include_on_site=keep_V_on_site)
else:
MV = np.ones_like(V_new, dtype=bool)
V_new[~MV] = 0.0
# --- Γ (dissipative)
if Gamma_rule == "leave":
pass
elif Gamma_rule == "same_as_V":
G_new[~MV] = 0.0
if not keep_Gamma_on_site:
np.fill_diagonal(G_new, 0.0)
elif Gamma_rule == "diagonal_only":
G_new[:] = 0.0
if keep_Gamma_on_site:
np.fill_diagonal(G_new, np.diag(Gamma))
elif Gamma_rule == "limit_by_hops":
if Gamma_hop_radius is None:
raise ValueError("Gamma_hop_radius required for Gamma_rule='limit_by_hops'.")
MG = _mask_within_hops(N, Gamma_hop_radius, include_on_site=keep_Gamma_on_site)
G_new[~MG] = 0.0
else:
raise ValueError(f"Unknown Gamma_rule '{Gamma_rule}'.")
# Symmetrize to clean tiny FP asymmetries
V_new = 0.5 * (V_new + V_new.T)
G_new = 0.5 * (G_new + G_new.T)
return V_new, G_new