From b18f1fc85e323957525b45d50748ab1a3780867d Mon Sep 17 00:00:00 2001 From: Matej Hudec Date: Wed, 3 Feb 2021 19:34:01 +0100 Subject: [PATCH 1/6] Fix the bug causing errors in "BR(KS->emu,mue)" The calculation actually still proceeds incorrectly, but it is a matter of physics, not of programming, and will be solved in next commits. --- flavio/physics/kdecays/kll.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flavio/physics/kdecays/kll.py b/flavio/physics/kdecays/kll.py index 2d873b31..2262c6d0 100644 --- a/flavio/physics/kdecays/kll.py +++ b/flavio/physics/kdecays/kll.py @@ -59,7 +59,7 @@ def amplitudes_eff(par, wc, K, l1, l2, ld=True): PLD = 0 else: SLD, PLD = amplitudes_LD(par, K, l1) - if K == 'KS' and l1 == l2: + if K == 'KS': Peff = P.imag Seff = S.real + SLD if K == 'KL': From 71c3f34c9d9f944910cd1a3574f6dfcd088d00a4 Mon Sep 17 00:00:00 2001 From: Matej Hudec Date: Wed, 3 Feb 2021 19:48:30 +0100 Subject: [PATCH 2/6] Unify m_K0 in amplitudes_LD in bll.py Like almost everywhere else, there is no need to distinguish between mass of KL and KS in the prefactors in amplitudes_LD. --- flavio/physics/kdecays/kll.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flavio/physics/kdecays/kll.py b/flavio/physics/kdecays/kll.py index 2262c6d0..39548aec 100644 --- a/flavio/physics/kdecays/kll.py +++ b/flavio/physics/kdecays/kll.py @@ -40,7 +40,7 @@ def amplitudes(par, wc, l1, l2): def amplitudes_LD(par, K, l): r"""Long-distance amplitudes entering the $K\to\ell^+\ell^-$ observables.""" ml = par['m_' + l] - mK = par['m_' + K] + mK = par['m_K0'] s2w = par['s2w'] pre = 2 * ml / mK / s2w # numbers extracted from arXiv:1711.11030 From ec148e71b8249c7e45bb7468d6660e604a3e2a03 Mon Sep 17 00:00:00 2001 From: Matej Hudec Date: Wed, 3 Feb 2021 22:19:47 +0100 Subject: [PATCH 3/6] Improve comments in Kll.py --- flavio/physics/kdecays/kll.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flavio/physics/kdecays/kll.py b/flavio/physics/kdecays/kll.py index 39548aec..c9590b77 100644 --- a/flavio/physics/kdecays/kll.py +++ b/flavio/physics/kdecays/kll.py @@ -17,14 +17,13 @@ def amplitudes(par, wc, l1, l2): - `par`: parameter dictionary - `wc`: Wilson coefficient dictionary - - `K`: should be `'KL'` or `'KS'` - `l1` and `l2`: should be `'e'` or `'mu'` """ # masses ml1 = par['m_'+l1] ml2 = par['m_'+l2] mK = par['m_K0'] - # Wilson coefficients + # Wilson coefficient postfix qqll = 'sd' + l1 + l2 # For LFV expressions see arXiv:1602.00881 eq. (5) C9m = wc['C9_'+qqll] - wc['C9p_'+qqll] # only relevant for l1 != l2 @@ -33,6 +32,7 @@ def amplitudes(par, wc, l1, l2): CSm = wc['CS_'+qqll] - wc['CSp_'+qqll] P = (ml2 + ml1)/mK * C10m + mK * CPm # neglecting mu, md S = (ml2 - ml1)/mK * C9m + mK * CSm # neglecting mu, md + # Include complex part of the eff. operator prefactor. Phases matter. xi_t = ckm.xi('t', 'sd')(par) return xi_t * P, xi_t * S @@ -95,7 +95,7 @@ def br_kll(par, wc_obj, K, l1, l2, ld=True): mK = par['m_K0'] tauK = par['tau_'+K] fK = par['f_K0'] - # appropriate CKM elements + # CKM part of the eff. operator prefactor N is included in Peff and Seff N = 4 * GF / sqrt(2) * alphaem / (4 * pi) beta = sqrt(lambda_K(mK**2, ml1**2, ml2**2)) / mK**2 beta_p = sqrt(1 - (ml1 + ml2)**2 / mK**2) From 6957590c6778ffa6747de30696422a754ac1da9e Mon Sep 17 00:00:00 2001 From: Matej Hudec Date: Wed, 3 Feb 2021 22:49:34 +0100 Subject: [PATCH 4/6] Improved implementation of amplitudes_LD for K->ll Originally, the function `amplitudes_LD(par, K, l)` would send both long-distance coefficients - for KL and KS, despite the fact that it takes `K` as an argument; `amplitudes_eff` then always thrown one of them away. The new implementation should be more transparent. --- flavio/physics/kdecays/kll.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/flavio/physics/kdecays/kll.py b/flavio/physics/kdecays/kll.py index c9590b77..fd39f1d0 100644 --- a/flavio/physics/kdecays/kll.py +++ b/flavio/physics/kdecays/kll.py @@ -44,11 +44,15 @@ def amplitudes_LD(par, K, l): s2w = par['s2w'] pre = 2 * ml / mK / s2w # numbers extracted from arXiv:1711.11030 - ASgaga = 2.49e-4 * (-2.821 + 1.216j) - ALgaga = 2.02e-4 * (par['chi_disp(KL->gammagamma)'] - 5.21j) - S = pre * ASgaga - P = -pre * ALgaga - return S, P + if K == 'KS': + ASgaga = 2.49e-4 * (-2.821 + 1.216j) + SLD = +pre * ASgaga + PLD = 0 + elif K == 'KL': + ALgaga = 2.02e-4 * (par['chi_disp(KL->gammagamma)'] - 5.21j) + SLD = 0 + PLD = -pre * ALgaga + return SLD, PLD def amplitudes_eff(par, wc, K, l1, l2, ld=True): @@ -60,11 +64,11 @@ def amplitudes_eff(par, wc, K, l1, l2, ld=True): else: SLD, PLD = amplitudes_LD(par, K, l1) if K == 'KS': - Peff = P.imag + Peff = P.imag + PLD Seff = S.real + SLD if K == 'KL': Peff = P.real + PLD - Seff = S.imag + Seff = S.imag + SLD return Peff, Seff From e67ea14566b02e883082260d9380b7470498d32c Mon Sep 17 00:00:00 2001 From: Matej Hudec Date: Fri, 5 Feb 2021 12:13:43 +0100 Subject: [PATCH 5/6] Correct calculation of LFV decays KL,KS->l1+l2- * The original `amplitudes` function renamed to `amplitudes_weak_eigst` as it actually yields amplitudes for K0, K0bar, not KL or KS. * A new `amplitudes` function, which newly takes also `K` (to be `'KL'` or `'KS'`) as an argument, has been implemented. It makes proper linear combinations of amplitudes for K0 and K0bar and changes by sqrt(2) the normalization of the amplitudes (cf. arXiv:1602.00881 with 1711.11030). * For l1=l2, `amplitudes` yields the imag/real parts of the S, P weak_eigs coefficients, as it should. Thus, taking real/imag parts is no longer tackled in `amplitudes_eff`, which now serves merely to add up short- and long-distance contributions, as it should. * Relative signs between SD and LD contributions now tackled in `amplitudes_eff`. It is in accordance with the original version of this file; looks differently than in arXiv:1711.11030, but it is due to different WC conventions (see my notes for details). --- flavio/physics/kdecays/kll.py | 65 +++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/flavio/physics/kdecays/kll.py b/flavio/physics/kdecays/kll.py index fd39f1d0..26daddb7 100644 --- a/flavio/physics/kdecays/kll.py +++ b/flavio/physics/kdecays/kll.py @@ -9,8 +9,8 @@ from math import pi, sqrt -def amplitudes(par, wc, l1, l2): - r"""Amplitudes P and S entering the $K\to\ell_1^+\ell_2^-$ observables. +def amplitudes_weak_eigst(par, wc, l1, l2): + r"""Amplitudes P and S for the decay $\bar K^0\to\ell_1^+\ell_2^-$. Parameters ---------- @@ -37,6 +37,41 @@ def amplitudes(par, wc, l1, l2): return xi_t * P, xi_t * S +def amplitudes(par, wc, K, l1, l2): + r"""Amplitudes P and S entering the $K_{L,S}\to\ell_1^+\ell_2^-$ observables. + + Parameters + ---------- + + - `par`: parameter dictionary + - `wc`: Wilson coefficient dictionary + - `K`: should be `'KL'` or `'KS'` + - `l1` and `l2`: should be `'e'` or `'mu'` + """ + # KL, KS are linear combinations of K0, K0bar. So are the amplitudes. + # Normalization differs by sqrt(2) from `amplitudes_weak_eigst`. + P_K0bar, S_K0bar = amplitudes_weak_eigst(par, wc, l1, l2) + if l1 != l2: + P_aux, S_aux = amplitudes_weak_eigst(par, wc, l2, l1) + S_K0 = -S_aux.conjugate() + P_K0 = P_aux.conjugate() + if K == 'KL': + sig = +1 + elif K == 'KS': + sig = -1 + S = (S_K0 + sig * S_K0bar) / 2 + P = (P_K0 + sig * P_K0bar) / 2 + # Simplified expressions for special cases. See also arXiv:1711.11030. + elif l1 == l2: + if K == 'KL': + S = -1j * S_K0bar.imag + P = P_K0bar.real + elif K == 'KS': + S = -S_K0bar.real + P = -1j * P_K0bar.imag + return P, S + + def amplitudes_LD(par, K, l): r"""Long-distance amplitudes entering the $K\to\ell^+\ell^-$ observables.""" ml = par['m_' + l] @@ -46,43 +81,43 @@ def amplitudes_LD(par, K, l): # numbers extracted from arXiv:1711.11030 if K == 'KS': ASgaga = 2.49e-4 * (-2.821 + 1.216j) - SLD = +pre * ASgaga + SLD = pre * ASgaga PLD = 0 elif K == 'KL': ALgaga = 2.02e-4 * (par['chi_disp(KL->gammagamma)'] - 5.21j) SLD = 0 - PLD = -pre * ALgaga + PLD = pre * ALgaga return SLD, PLD def amplitudes_eff(par, wc, K, l1, l2, ld=True): r"""Effective amplitudes entering the $K\to\ell_1^+\ell_2^-$ observables.""" - P, S = amplitudes(par, wc, l1, l2) + P, S = amplitudes(par, wc, K, l1, l2) if l1 != l2 or not ld: SLD = 0 PLD = 0 else: SLD, PLD = amplitudes_LD(par, K, l1) - if K == 'KS': - Peff = P.imag + PLD - Seff = S.real + SLD - if K == 'KL': - Peff = P.real + PLD - Seff = S.imag + SLD + # The relative sign due to different conventions. Cf. my notes. + Peff = P - PLD + Seff = S - SLD return Peff, Seff def get_wc(wc_obj, par, l1, l2): scale = config['renormalization scale']['kdecays'] - label = 'sd' + l1 + l2 - wcnp = wc_obj.get_wc(label, scale, par) - if l1 == l2: + if l1 == l2: # (l1,l2) == ('e','e') or ('mu','mu') + label = 'sd' + l1 + l2 + wcnp = wc_obj.get_wc(label, scale, par) # include SM contributions for LF conserving decay _c = wilsoncoefficients_sm_sl(par, scale) xi_t = ckm.xi('t', 'sd')(par) xi_c = ckm.xi('c', 'sd')(par) wcsm = {'C10_sd' + l1 + l2: _c['C10_t'] + xi_c / xi_t * _c['C10_c']} - else: + elif {l1,l2} == {'e','mu'}: + # Both flavor combinations relevant due to K0-K0bar mixing + wcnp = {**wc_obj.get_wc('sdemu', scale, par), + **wc_obj.get_wc('sdmue', scale, par)} wcsm = {} return add_dict((wcsm, wcnp)) From 0c1865b6f3a50911b90722a175140d96acfc0e62 Mon Sep 17 00:00:00 2001 From: Matej Hudec Date: Mon, 8 Feb 2021 19:01:23 +0100 Subject: [PATCH 6/6] Avoid repeating LFV calculations in kll.py As long as we neglect indirect CPV in kaons (which we do in kll.py), WET predicts BR(KL,KS->e+mu-) = BR(KL,KS->mu+e-), so we do don't calculate twice anymore at `br_kll_fct_lsum`. --- flavio/physics/kdecays/kll.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flavio/physics/kdecays/kll.py b/flavio/physics/kdecays/kll.py index 26daddb7..71f14e1c 100644 --- a/flavio/physics/kdecays/kll.py +++ b/flavio/physics/kdecays/kll.py @@ -152,7 +152,8 @@ def f(wc_obj, par): def br_kll_fct_lsum(K, l1, l2): def f(wc_obj, par): - return br_kll(par, wc_obj, K, l1, l2) + br_kll(par, wc_obj, K, l2, l1) + # Neglecting indirect CPV in kaons, BR(KL,KS->e+mu-) = BR(KL,KS->mu+e-) + return 2 * br_kll(par, wc_obj, K, l1, l2) return f