feat!: Implemented improved first and second derivatives for the

corresponding methods of the Corr class. The parameter which
distinguishes between the variant is now a string instead of a bool
which may break current analyses.
This commit is contained in:
Fabian Joswig 2022-01-31 10:50:00 +00:00
parent fbb98e05f6
commit 8165479846
2 changed files with 75 additions and 30 deletions

View file

@ -460,25 +460,16 @@ class Corr:
return (self + T_partner) / 2 return (self + T_partner) / 2
def deriv(self, symmetric=True): def deriv(self, variant="symmetric"):
"""Return the first derivative of the correlator with respect to x0. """Return the first derivative of the correlator with respect to x0.
Parameters Parameters
---------- ----------
symmetric : bool variant : str
decides whether symmetric of simple finite differences are used. Default: True decides which definition of the finite differences derivative is used.
Available choice: symmetric, forward, improved, default: symmetric
""" """
if not symmetric: if variant == "symmetric":
newcontent = []
for t in range(self.T - 1):
if (self.content[t] is None) or (self.content[t + 1] is None):
newcontent.append(None)
else:
newcontent.append(self.content[t + 1] - self.content[t])
if(all([x is None for x in newcontent])):
raise Exception("Derivative is undefined at all timeslices")
return Corr(newcontent, padding=[0, 1])
if symmetric:
newcontent = [] newcontent = []
for t in range(1, self.T - 1): for t in range(1, self.T - 1):
if (self.content[t - 1] is None) or (self.content[t + 1] is None): if (self.content[t - 1] is None) or (self.content[t + 1] is None):
@ -488,18 +479,60 @@ class Corr:
if(all([x is None for x in newcontent])): if(all([x is None for x in newcontent])):
raise Exception('Derivative is undefined at all timeslices') raise Exception('Derivative is undefined at all timeslices')
return Corr(newcontent, padding=[1, 1]) return Corr(newcontent, padding=[1, 1])
elif variant == "forward":
newcontent = []
for t in range(self.T - 1):
if (self.content[t] is None) or (self.content[t + 1] is None):
newcontent.append(None)
else:
newcontent.append(self.content[t + 1] - self.content[t])
if(all([x is None for x in newcontent])):
raise Exception("Derivative is undefined at all timeslices")
return Corr(newcontent, padding=[0, 1])
elif variant == "improved":
newcontent = []
for t in range(2, self.T - 2):
if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
newcontent.append(None)
else:
newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
if(all([x is None for x in newcontent])):
raise Exception('Derivative is undefined at all timeslices')
return Corr(newcontent, padding=[2, 2])
else:
raise Exception("Unknown variant.")
def second_deriv(self): def second_deriv(self, variant="symmetric"):
"""Return the second derivative of the correlator with respect to x0.""" """Return the second derivative of the correlator with respect to x0.
newcontent = []
for t in range(1, self.T - 1): Parameters
if (self.content[t - 1] is None) or (self.content[t + 1] is None): ----------
newcontent.append(None) variant : str
else: decides which definition of the finite differences derivative is used.
newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1])) Available choice: symmetric, improved, default: symmetric
if(all([x is None for x in newcontent])): """
raise Exception("Derivative is undefined at all timeslices") if variant == "symmetric":
return Corr(newcontent, padding=[1, 1]) newcontent = []
for t in range(1, self.T - 1):
if (self.content[t - 1] is None) or (self.content[t + 1] is None):
newcontent.append(None)
else:
newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
if(all([x is None for x in newcontent])):
raise Exception("Derivative is undefined at all timeslices")
return Corr(newcontent, padding=[1, 1])
elif variant == "improved":
newcontent = []
for t in range(2, self.T - 2):
if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
newcontent.append(None)
else:
newcontent.append((1 / 12) * (-self.content[t + 2] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * self.content[t - 1] - self.content[t - 2]))
if(all([x is None for x in newcontent])):
raise Exception("Derivative is undefined at all timeslices")
return Corr(newcontent, padding=[2, 2])
else:
raise Exception("Unknown variant.")
def m_eff(self, variant='log', guess=1.0): def m_eff(self, variant='log', guess=1.0):
"""Returns the effective mass of the correlator as correlator object """Returns the effective mass of the correlator as correlator object

View file

@ -45,7 +45,7 @@ def test_modify_correlator():
exponent = np.random.normal(3, 5) exponent = np.random.normal(3, 5)
corr_content.append(pe.pseudo_Obs(2 + 10 ** exponent, 10 ** (exponent - 1), 't')) corr_content.append(pe.pseudo_Obs(2 + 10 ** exponent, 10 ** (exponent - 1), 't'))
corr = pe.correlators.Corr(corr_content) corr = pe.Corr(corr_content)
with pytest.warns(RuntimeWarning): with pytest.warns(RuntimeWarning):
corr.symmetric() corr.symmetric()
@ -53,14 +53,26 @@ def test_modify_correlator():
corr.anti_symmetric() corr.anti_symmetric()
for pad in [0, 2]: for pad in [0, 2]:
corr = pe.correlators.Corr(corr_content, padding=[pad, pad]) corr = pe.Corr(corr_content, padding=[pad, pad])
corr.roll(np.random.randint(100)) corr.roll(np.random.randint(100))
corr.deriv(symmetric=True) corr.deriv(variant="forward")
corr.deriv(symmetric=False) corr.deriv(variant="symmetric")
corr.deriv(variant="improved")
corr.deriv().deriv() corr.deriv().deriv()
corr.second_deriv() corr.second_deriv(variant="symmetric")
corr.second_deriv(variant="improved")
corr.second_deriv().second_deriv() corr.second_deriv().second_deriv()
for i, e in enumerate(corr.content):
corr.content[i] = None
for func in [pe.Corr.deriv, pe.Corr.second_deriv]:
for variant in ["symmetric", "improved", "forward", "gibberish", None]:
with pytest.raises(Exception):
func(corr, variant=variant)
def test_m_eff(): def test_m_eff():
for padding in [0, 4]: for padding in [0, 4]: