pyerrors/pyerrors/npr.py
2021-11-07 21:44:22 +00:00

108 lines
3.7 KiB
Python

import warnings
import numpy as np
from .linalg import inv, matmul
from .dirac import gamma, gamma5
L = None
T = None
class Npr_matrix(np.ndarray):
def __new__(cls, input_array, mom_in=None, mom_out=None):
obj = np.asarray(input_array).view(cls)
obj.mom_in = mom_in
obj.mom_out = mom_out
return obj
@property
def g5H(self):
"""Gamma_5 hermitean conjugate
Returns gamma_5 @ M.T.conj() @ gamma_5 and exchanges in and out going
momenta. Works only for 12x12 matrices.
"""
if self.shape != (12, 12):
raise Exception('g5H only works for 12x12 matrices.')
extended_g5 = np.kron(np.eye(3, dtype=int), gamma5)
return Npr_matrix(matmul(extended_g5, self.conj().T, extended_g5),
mom_in=self.mom_out,
mom_out=self.mom_in)
def _propagate_mom(self, other, name):
s_mom = getattr(self, name, None)
o_mom = getattr(other, name, None)
if s_mom is not None and o_mom is not None:
if not np.allclose(s_mom, o_mom):
raise Exception(name + ' does not match.')
return o_mom if o_mom is not None else s_mom
def __matmul__(self, other):
return self.__new__(Npr_matrix,
super().__matmul__(other),
self._propagate_mom(other, 'mom_in'),
self._propagate_mom(other, 'mom_out'))
def __array_finalize__(self, obj):
if obj is None:
return
self.mom_in = getattr(obj, 'mom_in', None)
self.mom_out = getattr(obj, 'mom_out', None)
def _check_geometry():
if L is None:
raise Exception("Spatial extent 'L' not set.")
else:
if not isinstance(L, int):
raise Exception("Spatial extent 'L' must be an integer.")
if T is None:
raise Exception("Temporal extent 'T' not set.")
if not isinstance(T, int):
raise Exception("Temporal extent 'T' must be an integer.")
def inv_propagator(prop):
""" Inverts a 12x12 quark propagator"""
if prop.shape != (12, 12):
raise Exception("Only 12x12 propagators can be inverted.")
return Npr_matrix(inv(prop), prop.mom_in)
def Zq(inv_prop, fermion='Wilson'):
""" Calculates the quark field renormalization constant Zq
Parameters
----------
inv_prop : array
Inverted 12x12 quark propagator
fermion : str
Fermion type for which the tree-level propagator is used
in the calculation of Zq. Default Wilson.
"""
_check_geometry()
mom = np.copy(inv_prop.mom_in)
mom[3] /= T / L
sin_mom = np.sin(2 * np.pi / L * mom)
if fermion == 'Wilson':
p_slash = -1j * (sin_mom[0] * gamma[0] + sin_mom[1] * gamma[1] + sin_mom[2] * gamma[2] + sin_mom[3] * gamma[3]) / np.sum(sin_mom ** 2)
elif fermion == 'Continuum':
p_mom = 2 * np.pi / L * mom
p_slash = -1j * (p_mom[0] * gamma[0] + p_mom[1] * gamma[1] + p_mom[2] * gamma[2] + p_mom[3] * gamma[3]) / np.sum(p_mom ** 2)
elif fermion == 'DWF':
W = np.sum(1 - np.cos(2 * np.pi / L * mom))
s2 = np.sum(sin_mom ** 2)
p_slash = -1j * (sin_mom[0] * gamma[0] + sin_mom[1] * gamma[1] + sin_mom[2] * gamma[2] + sin_mom[3] * gamma[3])
p_slash /= 2 * (W - 1 + np.sqrt((1 - W) ** 2 + s2))
else:
raise Exception("Fermion type '" + fermion + "' not implemented")
res = 1 / 12. * np.trace(matmul(inv_prop, np.kron(np.eye(3, dtype=int), p_slash)))
res.gamma_method()
if not res.imag.is_zero_within_error(5):
warnings.warn("Imaginary part of Zq is not zero within 5 sigma")
return res
return res.real