From b00ede9e5191cf3d62598c1f5af9d66dd70b886a Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 28 Apr 2023 17:39:34 +0200 Subject: [PATCH 01/24] init harmonics cache --- src/ekore/harmonics/cache.py | 239 +++++++++++++++++++++++++++++++++++ src/ekore/harmonics/w1.py | 16 +-- src/ekore/harmonics/w2.py | 17 ++- src/ekore/harmonics/w3.py | 14 +- src/ekore/harmonics/w4.py | 14 +- src/ekore/harmonics/w5.py | 14 +- 6 files changed, 279 insertions(+), 35 deletions(-) create mode 100644 src/ekore/harmonics/cache.py diff --git a/src/ekore/harmonics/cache.py b/src/ekore/harmonics/cache.py new file mode 100644 index 000000000..76db5ac63 --- /dev/null +++ b/src/ekore/harmonics/cache.py @@ -0,0 +1,239 @@ +"""Caching harmonic sums across :mod:`ekore`.""" +import numba as nb +import numpy as np +import numpy.typing as npt + +from . import w1, w2, w3, w4, w5 +from .g_functions import mellin_g3 +from .polygamma import recursive_harmonic_sum + +# here a register of all possible functions +S1 = 0 # = S_1(N) +S2 = 1 +S3 = 2 +S4 = 3 +S5 = 4 +Sm1 = 5 +Sm2 = 6 +Sm3 = 7 +Sm4 = 8 +Sm5 = 9 +S21 = 10 +S2m1 = 11 +Sm21 = 12 +Sm2m1 = 13 +S31 = 14 +Sm31 = 15 +Sm22 = 16 +S211 = 17 +Sm211 = 18 +S1h = 19 +S2h = 20 +S3h = 21 +S4h = 22 +S5h = 23 +S1mh = 24 +S2mh = 25 +S3mh = 26 +S4mh = 27 +S5mh = 28 +S1ph = 29 +S2ph = 30 +S3ph = 31 +S4ph = 32 +S5ph = 33 +g3 = 34 +S1p2 = 35 +g3p1 = 36 +g3p2 = 37 + + +@nb.njit(cache=True) +def reset(): + """Return the cache placeholder array.""" + return np.full(38, np.nan, np.complex_) + + +@nb.njit(cache=True) +def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet: bool) -> complex: + r"""Retrieve an element of the cache. + + Parameters + ---------- + key : + harmonic sum key + cache : + cache list holding all elements + n : + complex evaluation point + is_singlet : + symmetry factor: True for singlet like quantities + (:math:`\eta=(-1)^N = 1`), + False for non-singlet like quantities + (:math:`\eta=(-1)^N=-1`) + + Returns + ------- + complex : + requested harmonic sum evaluated at n + + """ + # Maybe improve error + if key < 0 or key > len(cache): + raise RuntimeError + # load the thing + s = cache[key] + # found? i.e. not NaN? + if not np.isnan(s): + return s + # compute it now ... + if key == S1: + s = w1.S1(n) + elif key == S2: + s = w2.S2(n) + elif key == S3: + s = w3.S3(n) + elif key == S4: + s = w4.S4(n) + elif key == S5: + s = w5.S5(n) + elif key == Sm1: + s = w1.Sm1( + n, + get(S1, cache, n, is_singlet), + get(S1mh, cache, n, is_singlet), + get(S1h, cache, n, is_singlet), + is_singlet, + ) + elif key == Sm2: + s = w2.Sm2( + n, + get(S2, cache, n, is_singlet), + get(S2mh, cache, n, is_singlet), + get(S2h, cache, n, is_singlet), + is_singlet, + ) + elif key == Sm3: + s = w3.Sm3( + n, + get(S3, cache, n, is_singlet), + get(S3mh, cache, n, is_singlet), + get(S3h, cache, n, is_singlet), + is_singlet, + ) + elif key == Sm4: + s = w4.Sm4( + n, + get(S4, cache, n, is_singlet), + get(S4mh, cache, n, is_singlet), + get(S4h, cache, n, is_singlet), + is_singlet, + ) + elif key == Sm5: + s = w5.Sm5( + n, + get(S5, cache, n, is_singlet), + get(S5mh, cache, n, is_singlet), + get(S5h, cache, n, is_singlet), + is_singlet, + ) + elif key == S21: + s = w3.S21(n, get(S1, cache, n, is_singlet), get(S2, cache, n, is_singlet)) + elif key == S2m1: + s = w3.S2m1( + n, + get(S2, cache, n, is_singlet), + get(Sm1, cache, n, is_singlet), + get(Sm2, cache, n, is_singlet), + is_singlet, + ) + elif key == Sm21: + s = w3.Sm21( + n, get(S1, cache, n, is_singlet), get(Sm1, cache, n, is_singlet), is_singlet + ) + elif key == Sm2m1: + s = w3.Sm2m1( + n, + get(S1, cache, n, is_singlet), + get(S2, cache, n, is_singlet), + get(Sm2, cache, n, is_singlet), + ) + elif key == S31: + s = w4.S31( + n, + get(S1, cache, n, is_singlet), + get(S2, cache, n, is_singlet), + get(S3, cache, n, is_singlet), + get(S4, cache, n, is_singlet), + ) + elif key == Sm31: + s = w4.Sm31( + n, + get(S1, cache, n, is_singlet), + get(Sm1, cache, n, is_singlet), + get(Sm2, cache, n, is_singlet), + is_singlet, + ) + elif key == Sm22: + s = w4.Sm22( + n, + get(S1, cache, n, is_singlet), + get(S2, cache, n, is_singlet), + get(Sm2, cache, n, is_singlet), + get(Sm31, cache, n, is_singlet), + is_singlet, + ) + elif key == S211: + s = w4.S211( + n, + get(S1, cache, n, is_singlet), + get(S2, cache, n, is_singlet), + get(S3, cache, n, is_singlet), + ) + elif key == Sm211: + s = w4.Sm211( + n, + get(S1, cache, n, is_singlet), + get(S2, cache, n, is_singlet), + get(Sm1, cache, n, is_singlet), + is_singlet, + ) + elif key == S1h: + s = w1.S1(n / 2) + elif key == S2h: + s = w2.S2(n / 2) + elif key == S3h: + s = w3.S3(n / 2) + elif key == S4h: + s = w4.S4(n / 2) + elif key == S5h: + s = w5.S5(n / 2) + elif key == S1mh: + s = w1.S1((n - 1) / 2) + elif key == S2mh: + s = w2.S2((n - 1) / 2) + elif key == S3mh: + s = w3.S3((n - 1) / 2) + elif key == S4mh: + s = w4.S4((n - 1) / 2) + elif key == S5mh: + s = w5.S5((n - 1) / 2) + elif key == S1ph: + s = recursive_harmonic_sum(get(S1mh, cache, n, is_singlet), n, 1, 1) + elif key == S2ph: + s = recursive_harmonic_sum(get(S2mh, cache, n, is_singlet), n, 1, 2) + elif key == S3ph: + s = recursive_harmonic_sum(get(S3mh, cache, n, is_singlet), n, 1, 3) + elif key == S4ph: + s = recursive_harmonic_sum(get(S4mh, cache, n, is_singlet), n, 1, 4) + elif key == S5ph: + s = recursive_harmonic_sum(get(S5mh, cache, n, is_singlet), n, 1, 5) + elif key == g3: + s = mellin_g3(n, get(S1, cache, n, is_singlet)) + elif key == S1p2: + s = recursive_harmonic_sum(get(S1, cache, n, is_singlet), n, 2, 1) + elif key == g3p2: + s = mellin_g3(n + 2, get(S1p2, cache, n, is_singlet)) + # # store and return + cache[key] = s + return s diff --git a/src/ekore/harmonics/w1.py b/src/ekore/harmonics/w1.py index 61b0c1f18..78eecce69 100644 --- a/src/ekore/harmonics/w1.py +++ b/src/ekore/harmonics/w1.py @@ -35,7 +35,7 @@ def S1(N): @nb.njit(cache=True) -def Sm1(N, hS1, is_singlet=None): +def Sm1(N, hS1, hS1mh, hS1h, is_singlet=None): r"""Analytic continuation of harmonic sum :math:`S_{-1}(N)`. .. math:: @@ -47,6 +47,10 @@ def Sm1(N, hS1, is_singlet=None): Mellin moment hS1: complex Harmonic sum :math:`S_{1}(N)` + hS1mh: complex + Harmonic sum :math:`S_{1}((N-1)/2)` + hS1h: complex + Harmonic sum :math:`S_{1}(N/2)` is_singlet: bool, None symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) @@ -62,11 +66,7 @@ def Sm1(N, hS1, is_singlet=None): """ if is_singlet is None: - return ( - (1 - (-1) ** N) / 2 * S1((N - 1) / 2) - + ((-1) ** N + 1) / 2 * S1(N / 2) - - hS1 - ) + return (1 - (-1) ** N) / 2 * hS1mh + ((-1) ** N + 1) / 2 * hS1h - hS1 if is_singlet: - return S1(N / 2) - hS1 - return S1((N - 1) / 2) - hS1 + return hS1h - hS1 + return hS1mh - hS1 diff --git a/src/ekore/harmonics/w2.py b/src/ekore/harmonics/w2.py index e11e3c7f5..e4ba3b2c3 100644 --- a/src/ekore/harmonics/w2.py +++ b/src/ekore/harmonics/w2.py @@ -36,7 +36,7 @@ def S2(N): @nb.njit(cache=True) -def Sm2(N, hS2, is_singlet=None): +def Sm2(N, hS2, hS2mh, hS2h, is_singlet=None): r"""Analytic continuation of harmonic sum :math:`S_{-2}(N)`. .. math:: @@ -48,6 +48,10 @@ def Sm2(N, hS2, is_singlet=None): Mellin moment hS2: complex Harmonic sum :math:`S_{2}(N)` + hS2mh: complex + Harmonic sum :math:`S_{2}((N-1)/2)` + hS2h: complex + Harmonic sum :math:`S_{2}(N/2)` is_singlet: bool, None symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), False for non-singlet like quantities @@ -64,12 +68,7 @@ def Sm2(N, hS2, is_singlet=None): """ if is_singlet is None: - return ( - 1 - / 2 - * ((1 - (-1) ** N) / 2 * S2((N - 1) / 2) + ((-1) ** N + 1) / 2 * S2(N / 2)) - - hS2 - ) + return 1 / 2 * ((1 - (-1) ** N) / 2 * hS2mh + ((-1) ** N + 1) / 2 * hS2h) - hS2 if is_singlet: - return 1 / 2 * S2(N / 2) - hS2 - return 1 / 2 * S2((N - 1) / 2) - hS2 + return 1 / 2 * hS2h - hS2 + return 1 / 2 * hS2mh - hS2 diff --git a/src/ekore/harmonics/w3.py b/src/ekore/harmonics/w3.py index b3ab74406..be245aa72 100644 --- a/src/ekore/harmonics/w3.py +++ b/src/ekore/harmonics/w3.py @@ -37,7 +37,7 @@ def S3(N): @nb.njit(cache=True) -def Sm3(N, hS3, is_singlet=None): +def Sm3(N, hS3, hS3mh, hS3h, is_singlet=None): r"""Analytic continuation of harmonic sum :math:`S_{-3}(N)`. .. math:: @@ -49,6 +49,10 @@ def Sm3(N, hS3, is_singlet=None): Mellin moment hS3: complex Harmonic sum :math:`S_{3}(N)` + hS3mh: complex + Harmonic sum :math:`S_{3}((N-1)/2)` + hS3h: complex + Harmonic sum :math:`S_{3}(N/2)` is_singlet: bool, None symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) @@ -65,14 +69,12 @@ def Sm3(N, hS3, is_singlet=None): """ if is_singlet is None: return ( - 1 - / 2**2 - * ((1 - (-1) ** N) / 2 * S3((N - 1) / 2) + ((-1) ** N + 1) / 2 * S3(N / 2)) + 1 / 2**2 * ((1 - (-1) ** N) / 2 * hS3mh + ((-1) ** N + 1) / 2 * hS3h) - hS3 ) if is_singlet: - return 1 / 2**2 * S3(N / 2) - hS3 - return 1 / 2**2 * S3((N - 1) / 2) - hS3 + return 1 / 2**2 * hS3h - hS3 + return 1 / 2**2 * hS3mh - hS3 @nb.njit(cache=True) diff --git a/src/ekore/harmonics/w4.py b/src/ekore/harmonics/w4.py index d9bb03258..0b6863542 100644 --- a/src/ekore/harmonics/w4.py +++ b/src/ekore/harmonics/w4.py @@ -37,7 +37,7 @@ def S4(N): @nb.njit(cache=True) -def Sm4(N, hS4, is_singlet=None): +def Sm4(N, hS4, hS4mh, hS4h, is_singlet=None): r"""Analytic continuation of harmonic sum :math:`S_{-4}(N)`. .. math:: @@ -49,6 +49,10 @@ def Sm4(N, hS4, is_singlet=None): Mellin moment hS4: complex Harmonic sum :math:`S_{4}(N)` + hS4mh: complex + Harmonic sum :math:`S_{4}((N-1)/2)` + hS4h: complex + Harmonic sum :math:`S_{4}(N/2)` is_singlet: bool, None symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) @@ -65,14 +69,12 @@ def Sm4(N, hS4, is_singlet=None): """ if is_singlet is None: return ( - 1 - / 2**3 - * ((1 - (-1) ** N) / 2 * S4((N - 1) / 2) + ((-1) ** N + 1) / 2 * S4(N / 2)) + 1 / 2**3 * ((1 - (-1) ** N) / 2 * hS4mh + ((-1) ** N + 1) / 2 * hS4h) - hS4 ) if is_singlet: - return 1 / 2**3 * S4(N / 2) - hS4 - return 1 / 2**3 * S4((N - 1) / 2) - hS4 + return 1 / 2**3 * hS4h - hS4 + return 1 / 2**3 * hS4mh - hS4 @nb.njit(cache=True) diff --git a/src/ekore/harmonics/w5.py b/src/ekore/harmonics/w5.py index 26ca81eec..19b52881c 100644 --- a/src/ekore/harmonics/w5.py +++ b/src/ekore/harmonics/w5.py @@ -36,7 +36,7 @@ def S5(N): @nb.njit(cache=True) -def Sm5(N, hS5, is_singlet=None): +def Sm5(N, hS5, hS5mh, hS5h, is_singlet=None): r"""Analytic continuation of harmonic sum :math:`S_{-5}(N)`. .. math:: @@ -48,6 +48,10 @@ def Sm5(N, hS5, is_singlet=None): Mellin moment hS5: complex Harmonic sum :math:`S_{5}(N)` + hS5mh: complex + Harmonic sum :math:`S_{5}((N-1)/2)` + hS5h: complex + Harmonic sum :math:`S_{5}(N/2)` is_singlet: bool, None symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) @@ -64,11 +68,9 @@ def Sm5(N, hS5, is_singlet=None): """ if is_singlet is None: return ( - 1 - / 2**4 - * ((1 - (-1) ** N) / 2 * S5((N - 1) / 2) + ((-1) ** N + 1) / 2 * S5(N / 2)) + 1 / 2**4 * ((1 - (-1) ** N) / 2 * hS5mh + ((-1) ** N + 1) / 2 * hS5h) - hS5 ) if is_singlet: - return 1 / 2**4 * S5(N / 2) - hS5 - return 1 / 2**4 * S5((N - 1) / 2) - hS5 + return 1 / 2**4 * hS5h - hS5 + return 1 / 2**4 * hS5mh - hS5 From 866562bc06dd07c8206a68a492c94bb08255a08e Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Sat, 29 Apr 2023 00:33:32 +0200 Subject: [PATCH 02/24] refactor harmonic tests --- src/ekore/harmonics/__init__.py | 379 +++++++------------- src/ekore/harmonics/cache.py | 15 +- tests/ekore/harmonics/__init__.py | 87 +++++ tests/ekore/harmonics/test_cache.py | 85 +++++ tests/ekore/harmonics/test_g_functions.py | 33 +- tests/ekore/harmonics/test_init.py | 171 ++++----- tests/ekore/harmonics/test_log_functions.py | 8 +- tests/ekore/harmonics/test_polygamma.py | 6 +- 8 files changed, 407 insertions(+), 377 deletions(-) create mode 100644 tests/ekore/harmonics/test_cache.py diff --git a/src/ekore/harmonics/__init__.py b/src/ekore/harmonics/__init__.py index 02cbe78c2..7eeecc581 100644 --- a/src/ekore/harmonics/__init__.py +++ b/src/ekore/harmonics/__init__.py @@ -2,266 +2,131 @@ Definitions are coming from :cite:`MuselliPhD,Bl_mlein_2000,Blumlein:2009ta`. """ -import numba as nb -import numpy as np - -from . import g_functions, polygamma +from . import cache, g_functions, polygamma from .w1 import S1, Sm1 from .w2 import S2, Sm2 from .w3 import S3, S21, S2m1, Sm2m1, Sm3, Sm21 from .w4 import S4, S31, S211, Sm4, Sm22, Sm31, Sm211 from .w5 import S5, Sm5 - -@nb.njit(cache=True) -def base_harmonics_cache(n, is_singlet, max_weight=5, n_max_sums_weight=7): - r"""Get the harmonics sums S basic cache. - - Only single index harmonics are computed and stored - in the first (:math:`S_{n}`) or in the last column (:math:`S_{-n}`). - - Multi indices harmonics sums can be stored in the middle columns. - - Parameters - ---------- - n : complex - Mellin moment - is_singlet : bool - symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), - False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) - max_weight : int - max harmonics weight, max value 5 (default) - n_max_sums_weight : int - max number of harmonics sums for a given weight - - Returns - ------- - np.ndarray - list of harmonics sums: (weights, n_max_sums_weight) - - """ - h_cache = np.zeros((max_weight, n_max_sums_weight), dtype=np.complex_) - h_cache[:, 0] = sx(n, max_weight) - if n_max_sums_weight > 1: - h_cache[:, -1] = smx(n, h_cache[:, 0], is_singlet) - return h_cache - - -@nb.njit(cache=True) -def sx(n, max_weight=5): - """Get the harmonics sums S cache. - - Parameters - ---------- - n : complex - Mellin moment - max_weight : int - max harmonics weight, max value 5 (default) - - Returns - ------- - np.ndarray - list of harmonics sums (:math:`S_{1,..,w}`) - - """ - sx = np.zeros(max_weight, dtype=np.complex_) - if max_weight >= 1: - sx[0] = S1(n) - if max_weight >= 2: - sx[1] = S2(n) - if max_weight >= 3: - sx[2] = S3(n) - if max_weight >= 4: - sx[3] = S4(n) - if max_weight >= 5: - sx[4] = S5(n) - return sx - - -@nb.njit(cache=True) -def smx(n, sx, is_singlet): - r"""Get the harmonics S-minus cache. - - Parameters - ---------- - n : complex - Mellin moment - sx : numpy.ndarray - List of harmonics sums: :math:`S_{1},\dots,S_{w}` - is_singlet : bool - symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), - False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) - - Returns - ------- - np.ndarray - list of harmonics sums (:math:`S_{-1,..,-w}`) - - """ - max_weight = sx.size - smx = np.zeros(max_weight, dtype=np.complex_) - if max_weight >= 1: - smx[0] = Sm1(n, sx[0], is_singlet) - if max_weight >= 2: - smx[1] = Sm2(n, sx[1], is_singlet) - if max_weight >= 3: - smx[2] = Sm3(n, sx[2], is_singlet) - if max_weight >= 4: - smx[3] = Sm4(n, sx[3], is_singlet) - if max_weight >= 5: - smx[4] = Sm5(n, sx[4], is_singlet) - return smx - - -@nb.njit(cache=True) -def s3x(n, sx, smx, is_singlet): - r"""Compute the weight 3 multi indices harmonics sums cache. - - Parameters - ---------- - n : complex - Mellin moment - sx : list - List of harmonics sums: :math:`S_{1},S_{2}` - smx : list - List of harmonics sums: :math:`S_{-1},S_{-2}` - is_singlet : bool - symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), - False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) - - Returns - ------- - np.ndarray - list containing: :math:`S_{2,1},S_{2,-1},S_{-2,1},S_{-2,-1}` - - """ - return np.array( - [ - S21(n, sx[0], sx[1]), - S2m1(n, sx[1], smx[0], smx[1], is_singlet), - Sm21(n, sx[0], smx[0], is_singlet), - Sm2m1(n, sx[0], sx[1], smx[1]), - ] - ) - - -@nb.njit(cache=True) -def s4x(n, sx, smx, is_singlet): - r"""Compute the weight 4 multi indices harmonics sums cache. - - Parameters - ---------- - n : complex - Mellin moment - sx : list - List of harmonics sums: :math:`S_{1},S_{2},S_{3},S_{4}` - smx : list - List of harmonics sums: :math:`S_{-1},S_{-2}` - is_singlet : bool - symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), - False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) - - Returns - ------- - np.ndarray - list containing: :math:`S_{3,1},S_{2,1,1},S_{-2,2},S_{-2,1,1},S_{-3,1}` - - """ - sm31 = Sm31(n, sx[0], smx[0], smx[1], is_singlet) - return np.array( - [ - S31(n, sx[0], sx[1], sx[2], sx[3]), - S211(n, sx[0], sx[1], sx[2]), - Sm22(n, sx[0], sx[1], smx[1], sm31, is_singlet), - Sm211(n, sx[0], sx[1], smx[0], is_singlet), - sm31, - ] - ) - - -@nb.njit(cache=True) -def compute_cache(n, max_weight, is_singlet): - r"""Get the harmonics sums cache. - - Parameters - ---------- - n : complex - Mellin moment - max_weight : int - maximum weight to compute [2,3,4,5] - is_singlet : bool - symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), - False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) - - Returns - ------- - list - harmonic sums cache. At |N3LO| it contains: - - .. math :: - [[S_1,S_{-1}], - [S_2,S_{-2}], - [S_{3}, S_{2,1}, S_{2,-1}, S_{-2,1}, S_{-2,-1}, S_{-3}], - [S_{4}, S_{3,1}, S_{2,1,1}, S_{-2,-2}, S_{-3, 1}, S_{-4}],] - [S_{5}, S_{-5}] - - """ - # max number of harmonics sum of a given weight for a given max weight. - n_max_sums_weight = {2: 1, 3: 3, 4: 7, 5: 7} - sx = base_harmonics_cache(n, is_singlet, max_weight, n_max_sums_weight[max_weight]) - if max_weight == 3: - # Add Sm21 to cache - sx[2, 1] = Sm21(n, sx[0, 0], sx[0, -1], is_singlet) - elif max_weight >= 4: - # Add weight 3 and 4 to cache - sx[2, 1:-2] = s3x(n, sx[:, 0], sx[:, -1], is_singlet) - sx[3, 1:-1] = s4x(n, sx[:, 0], sx[:, -1], is_singlet) - # return list of list keeping the non zero values - return [[el for el in sx_list if el != 0] for sx_list in sx] - - -@nb.njit(cache=True) -def compute_qed_ns_cache(n, s1): - r"""Get the harmonics sums cache needed for the qed non singlet AD. - - Parameters - ---------- - n : complex - Mellin moment - s1 : float - harmonic sum :math:`S_1(N)` - - Returns - ------- - list - harmonic sums cache. It contains: - - .. math :: - [S_1(n/2), - S_2(n/2), - S_{3}(n/2), - S_1((n+1)/2), - S_2((n+1)/2), - S_{3}((n+1)/2), - g_3(n), - g_3(n+2)] - - """ - s1h = S1(n / 2.0) - sx_qed_ns = [s1h] - S2h = S2(n / 2.0) - sx_qed_ns.append(S2h) - S3h = S3(n / 2.0) - sx_qed_ns.append(S3h) - S1p1h = S1((n + 1.0) / 2.0) - sx_qed_ns.append(S1p1h) - S2p1h = S2((n + 1.0) / 2.0) - sx_qed_ns.append(S2p1h) - S3p1h = S3((n + 1.0) / 2.0) - sx_qed_ns.append(S3p1h) - g3N = g_functions.mellin_g3(n, s1) - sx_qed_ns.append(g3N) - S1p2 = polygamma.recursive_harmonic_sum(s1, n, 2, 1) - g3Np2 = g_functions.mellin_g3(n + 2.0, S1p2) - sx_qed_ns.append(g3Np2) - return sx_qed_ns +# TODO: CLEAN +# @nb.njit(cache=True) +# def base_harmonics_cache(n, is_singlet, max_weight=5, n_max_sums_weight=7): +# r"""Get the harmonics sums S basic cache. + +# Only single index harmonics are computed and stored +# in the first (:math:`S_{n}`) or in the last column (:math:`S_{-n}`). + +# Multi indices harmonics sums can be stored in the middle columns. + +# Parameters +# ---------- +# n : complex +# Mellin moment +# is_singlet : bool +# symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), +# False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) +# max_weight : int +# max harmonics weight, max value 5 (default) +# n_max_sums_weight : int +# max number of harmonics sums for a given weight + +# Returns +# ------- +# np.ndarray +# list of harmonics sums: (weights, n_max_sums_weight) + +# """ +# h_cache = np.zeros((max_weight, n_max_sums_weight), dtype=np.complex_) +# h_cache[:, 0] = sx(n, max_weight) +# if n_max_sums_weight > 1: +# h_cache[:, -1] = smx(n, h_cache[:, 0], is_singlet) +# return h_cache + + +# @nb.njit(cache=True) +# def compute_cache(n, max_weight, is_singlet): +# r"""Get the harmonics sums cache. + +# Parameters +# ---------- +# n : complex +# Mellin moment +# max_weight : int +# maximum weight to compute [2,3,4,5] +# is_singlet : bool +# symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), +# False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) + +# Returns +# ------- +# list +# harmonic sums cache. At |N3LO| it contains: + +# .. math :: +# [[S_1,S_{-1}], +# [S_2,S_{-2}], +# [S_{3}, S_{2,1}, S_{2,-1}, S_{-2,1}, S_{-2,-1}, S_{-3}], +# [S_{4}, S_{3,1}, S_{2,1,1}, S_{-2,-2}, S_{-3, 1}, S_{-4}],] +# [S_{5}, S_{-5}] + +# """ +# # max number of harmonics sum of a given weight for a given max weight. +# n_max_sums_weight = {2: 1, 3: 3, 4: 7, 5: 7} +# sx = base_harmonics_cache(n, is_singlet, max_weight, n_max_sums_weight[max_weight]) +# if max_weight == 3: +# # Add Sm21 to cache +# sx[2, 1] = Sm21(n, sx[0, 0], sx[0, -1], is_singlet) +# elif max_weight >= 4: +# # Add weight 3 and 4 to cache +# sx[2, 1:-2] = s3x(n, sx[:, 0], sx[:, -1], is_singlet) +# sx[3, 1:-1] = s4x(n, sx[:, 0], sx[:, -1], is_singlet) +# # return list of list keeping the non zero values +# return [[el for el in sx_list if el != 0] for sx_list in sx] + + +# @nb.njit(cache=True) +# def compute_qed_ns_cache(n, s1): +# r"""Get the harmonics sums cache needed for the qed non singlet AD. + +# Parameters +# ---------- +# n : complex +# Mellin moment +# s1 : float +# harmonic sum :math:`S_1(N)` + +# Returns +# ------- +# list +# harmonic sums cache. It contains: + +# .. math :: +# [S_1(n/2), +# S_2(n/2), +# S_{3}(n/2), +# S_1((n+1)/2), +# S_2((n+1)/2), +# S_{3}((n+1)/2), +# g_3(n), +# g_3(n+2)] + +# """ +# s1h = S1(n / 2.0) +# sx_qed_ns = [s1h] +# S2h = S2(n / 2.0) +# sx_qed_ns.append(S2h) +# S3h = S3(n / 2.0) +# sx_qed_ns.append(S3h) +# S1p1h = S1((n + 1.0) / 2.0) +# sx_qed_ns.append(S1p1h) +# S2p1h = S2((n + 1.0) / 2.0) +# sx_qed_ns.append(S2p1h) +# S3p1h = S3((n + 1.0) / 2.0) +# sx_qed_ns.append(S3p1h) +# g3N = g_functions.mellin_g3(n, s1) +# sx_qed_ns.append(g3N) +# S1p2 = polygamma.recursive_harmonic_sum(s1, n, 2, 1) +# g3Np2 = g_functions.mellin_g3(n + 2.0, S1p2) +# sx_qed_ns.append(g3Np2) +# return sx_qed_ns diff --git a/src/ekore/harmonics/cache.py b/src/ekore/harmonics/cache.py index 76db5ac63..be6d808a6 100644 --- a/src/ekore/harmonics/cache.py +++ b/src/ekore/harmonics/cache.py @@ -44,14 +44,13 @@ S5ph = 33 g3 = 34 S1p2 = 35 -g3p1 = 36 -g3p2 = 37 +g3p2 = 36 @nb.njit(cache=True) def reset(): """Return the cache placeholder array.""" - return np.full(38, np.nan, np.complex_) + return np.full(37, np.nan, np.complex_) @nb.njit(cache=True) @@ -219,15 +218,15 @@ def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet: bool) -> complex elif key == S5mh: s = w5.S5((n - 1) / 2) elif key == S1ph: - s = recursive_harmonic_sum(get(S1mh, cache, n, is_singlet), n, 1, 1) + s = recursive_harmonic_sum(get(S1mh, cache, n, is_singlet), (n - 1) / 2, 1, 1) elif key == S2ph: - s = recursive_harmonic_sum(get(S2mh, cache, n, is_singlet), n, 1, 2) + s = recursive_harmonic_sum(get(S2mh, cache, n, is_singlet), (n - 1) / 2, 1, 2) elif key == S3ph: - s = recursive_harmonic_sum(get(S3mh, cache, n, is_singlet), n, 1, 3) + s = recursive_harmonic_sum(get(S3mh, cache, n, is_singlet), (n - 1) / 2, 1, 3) elif key == S4ph: - s = recursive_harmonic_sum(get(S4mh, cache, n, is_singlet), n, 1, 4) + s = recursive_harmonic_sum(get(S4mh, cache, n, is_singlet), (n - 1) / 2, 1, 4) elif key == S5ph: - s = recursive_harmonic_sum(get(S5mh, cache, n, is_singlet), n, 1, 5) + s = recursive_harmonic_sum(get(S5mh, cache, n, is_singlet), (n - 1) / 2, 1, 5) elif key == g3: s = mellin_g3(n, get(S1, cache, n, is_singlet)) elif key == S1p2: diff --git a/tests/ekore/harmonics/__init__.py b/tests/ekore/harmonics/__init__.py index e69de29bb..49695f099 100644 --- a/tests/ekore/harmonics/__init__.py +++ b/tests/ekore/harmonics/__init__.py @@ -0,0 +1,87 @@ +import numpy as np + +from ekore import harmonics as h + + +def get_harmonic(name): + for h_name, func in h.__dict__.items(): + if callable(func) and h_name == name: + return func + + +def s(j, N): + """S functions shortcut.""" + name = f"S{j}" + h_func = get_harmonic(name) + return h_func(N) + + +def sm(j, N, is_singlet=None): + """Sm functions shortcut.""" + name = f"Sm{j}" + h_func = get_harmonic(name[::2]) + h_minus_func = get_harmonic(name) + return h_minus_func(N, h_func(N), h_func((N - 1) / 2), h_func(N / 2), is_singlet) + + +def sx(n, max_weight=5): + """Get the harmonics sums S cache. + + Parameters + ---------- + n : complex + Mellin moment + max_weight : int + max harmonics weight, max value 5 (default) + + Returns + ------- + np.ndarray + list of harmonics sums (:math:`S_{1,..,w}`) + + """ + sx = np.zeros(max_weight, dtype=np.complex_) + if max_weight >= 1: + sx[0] = h.S1(n) + if max_weight >= 2: + sx[1] = h.S2(n) + if max_weight >= 3: + sx[2] = h.S3(n) + if max_weight >= 4: + sx[3] = h.S4(n) + if max_weight >= 5: + sx[4] = h.S5(n) + return sx + + +def smx(n, sx, is_singlet): + r"""Get the harmonics S-minus cache. + + Parameters + ---------- + n : complex + Mellin moment + sx : numpy.ndarray + List of harmonics sums: :math:`S_{1},\dots,S_{w}` + is_singlet : bool + symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), + False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) + + Returns + ------- + np.ndarray + list of harmonics sums (:math:`S_{-1,..,-w}`) + + """ + max_weight = sx.size + smx = np.zeros(max_weight, dtype=np.complex_) + if max_weight >= 1: + smx[0] = h.Sm1(n, sx[0], is_singlet) + if max_weight >= 2: + smx[1] = h.Sm2(n, sx[1], is_singlet) + if max_weight >= 3: + smx[2] = h.Sm3(n, sx[2], is_singlet) + if max_weight >= 4: + smx[3] = h.Sm4(n, sx[3], is_singlet) + if max_weight >= 5: + smx[4] = h.Sm5(n, sx[4], is_singlet) diff --git a/tests/ekore/harmonics/test_cache.py b/tests/ekore/harmonics/test_cache.py new file mode 100644 index 000000000..e503636bc --- /dev/null +++ b/tests/ekore/harmonics/test_cache.py @@ -0,0 +1,85 @@ +import numpy as np + +from ekore import harmonics as h + +from . import get_harmonic + + +def test_reset(): + c = h.cache.reset() + np.testing.assert_allclose(c, np.full(c.shape, np.nan)) + available_items = np.sum( + [isinstance(val, int) for val in h.cache.__dict__.values()] + ) + assert c.shape == (available_items,) + + +def test_get(): + """Test getter function.""" + N = np.random.rand() + 1j * np.random.rand() + for is_singlet in [True, False]: + c = h.cache.reset() + # loop on cached names + for idx_name, idx in h.cache.__dict__.items(): + if not isinstance(idx, int): + continue + h.cache.get(idx, c, N, is_singlet) + # Sx((N-1)/2) + if "mh" in idx_name: + h_func = get_harmonic(idx_name[:2]) + ref_value = h_func((N - 1) / 2) + # Sx((N+1)/2) + elif "ph" in idx_name: + h_func = get_harmonic(idx_name[:2]) + ref_value = h_func((N + 1) / 2) + # Sx(N/2) + elif idx_name.endswith("h"): + h_func = get_harmonic(idx_name[:2]) + ref_value = h_func(N / 2) + # Smx(N) + elif "Sm" in idx_name and len(idx_name) == 3: + h_func = get_harmonic(idx_name[::2]) + h_minus_func = get_harmonic(idx_name) + ref_value = h_minus_func( + N, h_func(N), h_func((N - 1) / 2), h_func(N / 2), is_singlet + ) + # mellin g3 + elif idx_name == "g3": + ref_value = h.g_functions.mellin_g3( + N, h.cache.get(h.cache.S1, c, N, is_singlet) + ) + elif idx_name == "g3p2": + ref_value = h.g_functions.mellin_g3( + N + 2, h.cache.get(h.cache.S1p2, c, N, is_singlet) + ) + # Sx + elif len(idx_name) == 2: + h_func = get_harmonic(idx_name) + ref_value = h_func(N) + # all the others + S1 = h.S1(N) + S2 = h.S2(N) + Sm1 = h.Sm1(N, S1, h.S1((N - 1) / 2), h.S1(N / 2), is_singlet) + Sm2 = h.Sm2(N, S2, h.S2((N - 1) / 2), h.S2(N / 2), is_singlet) + if idx_name == "S21": + ref_value = h.S21(N, S1, S2) + elif idx_name == "S2m1": + ref_value = h.S2m1(N, S2, Sm1, Sm2, is_singlet) + elif idx_name == "Sm21": + ref_value = h.Sm21(N, S1, Sm1, is_singlet) + elif idx_name == "Sm2m1": + ref_value = h.Sm2m1(N, S1, S2, Sm2) + elif idx_name == "S31": + ref_value = h.S31(N, S1, S2, h.S3(N), h.S4(N)) + elif idx_name == "Sm31": + ref_value = h.Sm31(N, S1, Sm1, Sm2, is_singlet) + elif idx_name == "Sm22": + Sm31 = h.Sm31(N, S1, Sm1, Sm2, is_singlet) + ref_value = h.Sm22(N, S1, S2, Sm2, Sm31, is_singlet) + elif idx_name == "S211": + ref_value = h.S211(N, S1, S2, h.S3(N)) + elif idx_name == "Sm211": + ref_value = h.Sm211(N, S1, S2, Sm1, is_singlet) + elif idx_name == "S1p2": + ref_value = h.S1(N + 2) + np.testing.assert_allclose(c[idx], ref_value, err_msg=f"{idx_name}") diff --git a/tests/ekore/harmonics/test_g_functions.py b/tests/ekore/harmonics/test_g_functions.py index 85dc5be4c..bdf930fd2 100644 --- a/tests/ekore/harmonics/test_g_functions.py +++ b/tests/ekore/harmonics/test_g_functions.py @@ -2,7 +2,6 @@ import numpy as np -from eko.constants import log2, zeta3 from ekore import harmonics as h # Reference values comes form Mathematica, and are @@ -26,9 +25,13 @@ def test_g4(): for N, vals in zip(testN, refvals): is_singlet = (-1) ** N == 1 S1 = h.S1(N) + S1mh = h.S1((N - 1) / 2) + S1h = h.S1(N / 2) S2 = h.S2(N) - Sm1 = h.Sm1(N, S1, is_singlet) - Sm2 = h.Sm2(N, S2, is_singlet) + S2mh = h.S2((N - 1) / 2) + S2h = h.S2(N / 2) + Sm1 = h.Sm1(N, S1, S1mh, S1h, is_singlet) + Sm2 = h.Sm2(N, S2, S2mh, S2h, is_singlet) S2m1 = h.S2m1(N, S2, Sm1, Sm2, is_singlet) np.testing.assert_allclose(S2m1, vals, atol=1e-05) @@ -38,9 +41,13 @@ def test_g6(): for N, vals in zip(testN, refvals): is_singlet = (-1) ** N == 1 S1 = h.S1(N) + S1mh = h.S1((N - 1) / 2) + S1h = h.S1(N / 2) S2 = h.S2(N) - Sm1 = h.Sm1(N, S1, is_singlet) - Sm2 = h.Sm2(N, S2, is_singlet) + S2mh = h.S2((N - 1) / 2) + S2h = h.S2(N / 2) + Sm1 = h.Sm1(N, S1, S1mh, S1h, is_singlet) + Sm2 = h.Sm2(N, S2, S2mh, S2h, is_singlet) Sm31 = h.Sm31(N, S1, Sm1, Sm2, is_singlet) np.testing.assert_allclose(Sm31, vals, atol=1e-05) @@ -50,9 +57,13 @@ def test_g5(): for N, vals in zip(testN, refvals): is_singlet = (-1) ** N == 1 S1 = h.S1(N) + S1mh = h.S1((N - 1) / 2) + S1h = h.S1(N / 2) S2 = h.S2(N) - Sm1 = h.Sm1(N, S1, is_singlet) - Sm2 = h.Sm2(N, S2, is_singlet) + S2mh = h.S2((N - 1) / 2) + S2h = h.S2(N / 2) + Sm1 = h.Sm1(N, S1, S1mh, S1h, is_singlet) + Sm2 = h.Sm2(N, S2, S2mh, S2h, is_singlet) Sm31 = h.Sm31(N, S1, Sm1, Sm2, is_singlet) Sm22 = h.Sm22(N, S1, S2, Sm2, Sm31, is_singlet) np.testing.assert_allclose(Sm22, vals, atol=1e-05) @@ -63,8 +74,10 @@ def test_g8(): for N, vals in zip(testN, refvals): is_singlet = (-1) ** N == 1 S1 = h.S1(N) + S1mh = h.S1((N - 1) / 2) + S1h = h.S1(N / 2) S2 = h.S2(N) - Sm1 = h.Sm1(N, S1, is_singlet) + Sm1 = h.Sm1(N, S1, S1mh, S1h, is_singlet) Sm211 = h.Sm211(N, S1, S2, Sm1, is_singlet) np.testing.assert_allclose(Sm211, vals, atol=1e-05) @@ -85,7 +98,9 @@ def test_g19(): is_singlet = (-1) ** N == 1 S1 = h.S1(N) S2 = h.S2(N) - Sm2 = h.Sm2(N, S2, is_singlet) + S2mh = h.S2((N - 1) / 2) + S2h = h.S2(N / 2) + Sm2 = h.Sm2(N, S2, S2mh, S2h, is_singlet) Sm2m1 = h.Sm2m1(N, S1, S2, Sm2) np.testing.assert_allclose(Sm2m1, vals, atol=1e-05) diff --git a/tests/ekore/harmonics/test_init.py b/tests/ekore/harmonics/test_init.py index edd436f5a..7aecd8ef4 100644 --- a/tests/ekore/harmonics/test_init.py +++ b/tests/ekore/harmonics/test_init.py @@ -3,66 +3,61 @@ from eko.constants import log2, zeta2, zeta3, zeta4, zeta5 from ekore import harmonics as h - -def test_spm1(): - for k in range(1, 5 + 1): - f = np.sum([1.0 / j for j in range(1, k + 1)]) - S1 = h.S1(k) - np.testing.assert_allclose(f, S1) - g = np.sum([(-1.0) ** j / j for j in range(1, k + 1)]) - np.testing.assert_allclose(g, h.Sm1(k, S1, (-1) ** k == 1)) - - -def test_spm2(): - for k in range(1, 5 + 1): - f = np.sum([1.0 / j**2 for j in range(1, k + 1)]) - S2 = h.S2(k) - np.testing.assert_allclose(f, S2) - g = np.sum([(-1.0) ** j / j**2 for j in range(1, k + 1)]) - np.testing.assert_allclose(g, h.Sm2(k, S2, (-1) ** k == 1)) - - -def test_harmonics_cache(): - N = np.random.randint(1, high=100) - is_singlet = (-1) ** N == 1 - S1 = h.S1(N) - S2 = h.S2(N) - S3 = h.S3(N) - S4 = h.S4(N) - S5 = h.S5(N) - Sm1 = h.Sm1(N, S1, is_singlet) - Sm2 = h.Sm2(N, S2, is_singlet) - sx = np.array([S1, S2, S3, S4, S5]) - smx_test = np.array( - [ - Sm1, - Sm2, - h.Sm3(N, S3, is_singlet), - h.Sm4(N, S4, is_singlet), - h.Sm5(N, S5, is_singlet), - ] - ) - np.testing.assert_allclose(h.smx(N, sx, is_singlet), smx_test) - s3x_test = np.array( - [ - h.S21(N, S1, S2), - h.S2m1(N, S2, Sm1, Sm2, is_singlet), - h.Sm21(N, S1, Sm1, is_singlet), - h.Sm2m1(N, S1, S2, Sm2), - ] - ) - np.testing.assert_allclose(h.s3x(N, sx, smx_test, is_singlet), s3x_test) - Sm31 = h.Sm31(N, S1, Sm1, Sm2, is_singlet) - s4x_test = np.array( - [ - h.S31(N, S1, S2, S3, S4), - h.S211(N, S1, S2, S3), - h.Sm22(N, S1, S2, Sm2, Sm31, is_singlet), - h.Sm211(N, S1, S2, Sm1, is_singlet), - Sm31, - ] - ) - np.testing.assert_allclose(h.s4x(N, sx, smx_test, is_singlet), s4x_test) +from . import s, sm + + +def test_harmonic_definition(): + for power in [1, 2]: + for k in range(1, 5 + 1): + f = np.sum([1.0 / j**power for j in range(1, k + 1)]) + Sx = s(power, k) + np.testing.assert_allclose(f, Sx) + g = np.sum([(-1.0) ** j / j**power for j in range(1, k + 1)]) + np.testing.assert_allclose(g, sm(power, k, (-1) ** k == 1)) + + +# TODO: CLEAN +# def test_harmonics_cache(): +# N = np.random.randint(1, high=100) +# is_singlet = (-1) ** N == 1 +# S1 = h.S1(N) +# S2 = h.S2(N) +# S3 = h.S3(N) +# S4 = h.S4(N) +# S5 = h.S5(N) +# Sm1 = h.Sm1(N, S1, is_singlet) +# Sm2 = h.Sm2(N, S2, is_singlet) +# sx = np.array([S1, S2, S3, S4, S5]) +# smx_test = np.array( +# [ +# Sm1, +# Sm2, +# h.Sm3(N, S3, is_singlet), +# h.Sm4(N, S4, is_singlet), +# h.Sm5(N, S5, is_singlet), +# ] +# ) +# np.testing.assert_allclose(h.smx(N, sx, is_singlet), smx_test) +# s3x_test = np.array( +# [ +# h.S21(N, S1, S2), +# h.S2m1(N, S2, Sm1, Sm2, is_singlet), +# h.Sm21(N, S1, Sm1, is_singlet), +# h.Sm2m1(N, S1, S2, Sm2), +# ] +# ) +# np.testing.assert_allclose(h.s3x(N, sx, smx_test, is_singlet), s3x_test) +# Sm31 = h.Sm31(N, S1, Sm1, Sm2, is_singlet) +# s4x_test = np.array( +# [ +# h.S31(N, S1, S2, S3, S4), +# h.S211(N, S1, S2, S3), +# h.Sm22(N, S1, S2, Sm2, Sm31, is_singlet), +# h.Sm211(N, S1, S2, Sm1, is_singlet), +# Sm31, +# ] +# ) +# np.testing.assert_allclose(h.s4x(N, sx, smx_test, is_singlet), s4x_test) # reference values coming fom mathematica @@ -106,28 +101,30 @@ def test_harmonics_cache(): def test_Sm21(): for N, vals in zip(testN, refvals["Sm21"]): S1 = h.S1(N) - Sm1 = h.Sm1(N, S1) + S1mh = h.S1((N - 1) / 2) + S1h = h.S1(N / 2) + Sm1 = h.Sm1(N, S1, S1mh, S1h) np.testing.assert_allclose(h.Sm21(N, S1, Sm1), vals, atol=1e-06) -def test_Smx(): - for j, N in enumerate(testN): - sx = h.sx(N) - smx = [ - h.Sm1(N, sx[0]), - h.Sm2(N, sx[1]), - h.Sm3(N, sx[2]), - h.Sm4(N, sx[3]), - h.Sm5(N, sx[4]), - ] - for i, sm in enumerate(smx): - np.testing.assert_allclose(sm, refvals[f"Sm{i+1}"][j], atol=1e-06) +# TODO: CLEAN +# def test_Smx(): +# for j, N in enumerate(testN): +# sx = h.sx(N) +# smx = [ +# h.Sm1(N, sx[0]), +# h.Sm2(N, sx[1]), +# h.Sm3(N, sx[2]), +# h.Sm4(N, sx[3]), +# h.Sm5(N, sx[4]), +# ] +# for i, sm in enumerate(smx): +# np.testing.assert_allclose(sm, refvals[f"Sm{i+1}"][j], atol=1e-06) def test_smx_continuation(): # test s_{-m} against a different analytic continuation N = np.random.rand() + 1j * np.random.rand() - sx = h.sx(N) def dm(m): zeta_list = [ @@ -143,27 +140,5 @@ def dm(m): def sm_complex(m, N): return ((-1) ** N) / 2**m * (s(m, N / 2) - s(m, (N - 1) / 2)) - dm(m) - def s(m, N): - if m == 1: - return h.S1(N) - if m == 2: - return h.S2(N) - if m == 3: - return h.S3(N) - if m == 4: - return h.S4(N) - return h.S5(N) - - def sm(m, N, hs): - if m == 1: - return h.Sm1(N, hs) - if m == 2: - return h.Sm2(N, hs) - if m == 3: - return h.Sm3(N, hs) - if m == 4: - return h.Sm4(N, hs) - return h.Sm5(N, hs) - - for j, hs in enumerate(sx): - np.testing.assert_allclose(sm_complex(j + 1, N), sm(j + 1, N, hs)) + for j in range(1, 6): + np.testing.assert_allclose(sm_complex(j, N), sm(j, N)) diff --git a/tests/ekore/harmonics/test_log_functions.py b/tests/ekore/harmonics/test_log_functions.py index 86877c611..a6f0dc0fe 100644 --- a/tests/ekore/harmonics/test_log_functions.py +++ b/tests/ekore/harmonics/test_log_functions.py @@ -3,6 +3,8 @@ from ekore import harmonics as h +from . import sx as hsx + def test_lm1pm2(): def mellin_lm1pm2(x, k): @@ -10,7 +12,7 @@ def mellin_lm1pm2(x, k): Ns = 100 * np.random.rand(3) for N in Ns: - sx = h.sx(N, 4) + sx = hsx(N, 4) ref_values = { 1: h.log_functions.lm11m2(N, sx[0]), @@ -31,7 +33,7 @@ def mellin_lm1pm1(x, k): Ns = 100 * np.random.rand(3) for N in Ns: - sx = h.sx(N, 4) + sx = hsx(N, 4) ref_values = { 1: h.log_functions.lm11m1(N, sx[0]), @@ -52,7 +54,7 @@ def mellin_lm1p(x, k): Ns = 100 * np.random.rand(3) for N in Ns: - sx = h.sx(N, 5) + sx = hsx(N, 5) ref_values = { 1: h.log_functions.lm11(N, sx[0]), diff --git a/tests/ekore/harmonics/test_polygamma.py b/tests/ekore/harmonics/test_polygamma.py index 91f0ac587..a8c729f6c 100644 --- a/tests/ekore/harmonics/test_polygamma.py +++ b/tests/ekore/harmonics/test_polygamma.py @@ -3,6 +3,8 @@ from ekore import harmonics +from . import sx as hsx + # until https://github.com/numba/numba/pull/5660 is confirmed # we need to deactivate numba prior running @@ -83,8 +85,8 @@ def test_cern_polygamma(): def test_recursive_harmonic_sum(): n = np.random.rand() iterations = 1 - sx_base = harmonics.sx(n) - sx_test = harmonics.sx(n + iterations) + sx_base = hsx(n) + sx_test = hsx(n + iterations) sx_final = [] for w in range(1, 6): From 4e6a56999fe6bf03ddb1395e5c5e00454b0eb859 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 09:33:59 +0200 Subject: [PATCH 03/24] passing cache to ad polarized --- .../polarized/space_like/__init__.py | 50 +++++------------ .../polarized/space_like/as1.py | 12 +++-- .../polarized/space_like/as2.py | 47 ++++++++-------- .../polarized/space_like/as3.py | 54 +++++++++++-------- .../unpolarized/space_like/as1.py | 29 +++++----- .../polarized/space_like/test_ad_as1.py | 8 +-- .../polarized/space_like/test_ad_as2.py | 20 +++---- .../polarized/space_like/test_ad_as3.py | 25 +++++---- .../polarized/space_like/test_init.py | 8 +-- 9 files changed, 122 insertions(+), 131 deletions(-) diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/__init__.py b/src/ekore/anomalous_dimensions/polarized/space_like/__init__.py index ccd70e2d1..1cb318930 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/__init__.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/__init__.py @@ -11,32 +11,10 @@ import numba as nb import numpy as np -from .... import harmonics +from ....harmonics import cache as c from . import as1, as2, as3 -@nb.njit(cache=True) -def compute_cache(n, pto): - """Compute the harmonic cache for polarized anomalous dimension. - - Parameters - ---------- - n : complex - Mellin variable - pto : int - perturbative order - - Returns - ------- - list - harmonics cache - - """ - max_weight = pto if pto != 3 else 4 - cache = harmonics.sx(n, max_weight) - return cache - - @nb.njit(cache=True) def gamma_ns(order, mode, n, nf): r"""Compute the tower of the non-singlet anomalous dimensions. @@ -58,28 +36,26 @@ def gamma_ns(order, mode, n, nf): non-singlet anomalous dimensions """ - # cache the s-es - sx = compute_cache(n, order[0] + 1) - # now combine + cache = c.reset() gamma_ns = np.zeros(order[0], np.complex_) - gamma_ns[0] = as1.gamma_ns(n, sx[0]) + gamma_ns[0] = as1.gamma_ns(n, cache) # NLO and beyond if order[0] >= 2: if mode == 10101: - gamma_ns_1 = as2.gamma_nsp(n, nf, sx) + gamma_ns_1 = as2.gamma_nsp(n, nf, cache) # To fill the full valence vector in NNLO we need to add gamma_ns^1 explicitly here elif mode in [10201, 10200]: - gamma_ns_1 = as2.gamma_nsm(n, nf, sx) + gamma_ns_1 = as2.gamma_nsm(n, nf, cache) else: raise NotImplementedError("Non-singlet sector is not implemented") gamma_ns[1] = gamma_ns_1 if order[0] >= 3: if mode == 10101: - gamma_ns_2 = as3.gamma_nsp(n, nf, sx) + gamma_ns_2 = as3.gamma_nsp(n, nf, cache) elif mode == 10201: - gamma_ns_2 = as3.gamma_nsm(n, nf, sx) + gamma_ns_2 = as3.gamma_nsm(n, nf, cache) elif mode == 10200: - gamma_ns_2 = as3.gamma_nsv(n, nf, sx) + gamma_ns_2 = as3.gamma_nsv(n, nf, cache) gamma_ns[2] = gamma_ns_2 if order[0] >= 4: raise NotImplementedError("Polarized beyond NNLO is not yet implemented") @@ -105,15 +81,13 @@ def gamma_singlet(order, n, nf): singlet anomalous dimensions matrices """ - # cache the s-es - sx = compute_cache(n, order[0] + 1) - + cache = c.reset() gamma_s = np.zeros((order[0], 2, 2), np.complex_) - gamma_s[0] = as1.gamma_singlet(n, sx[0], nf) + gamma_s[0] = as1.gamma_singlet(n, cache, nf) if order[0] >= 2: - gamma_s[1] = as2.gamma_singlet(n, nf, sx) + gamma_s[1] = as2.gamma_singlet(n, nf, cache) if order[0] >= 3: - gamma_s[2] = as3.gamma_singlet(n, nf, sx) + gamma_s[2] = as3.gamma_singlet(n, nf, cache) if order[0] >= 4: raise NotImplementedError("Polarized beyond NNLO is not yet implemented") return gamma_s diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as1.py b/src/ekore/anomalous_dimensions/polarized/space_like/as1.py index c3d84c1ed..527fbfc77 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as1.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as1.py @@ -5,6 +5,7 @@ from eko import constants +from ....harmonics import cache as c from ...unpolarized.space_like.as1 import gamma_ns @@ -51,7 +52,7 @@ def gamma_gq(N): @nb.njit(cache=True) -def gamma_gg(N, s1, nf): +def gamma_gg(N, cache, nf): r"""Compute the |LO| polarized gluon-gluon anomalous dimension :cite:`Gluck:1995yr` (eq A.1). Parameters @@ -69,13 +70,14 @@ def gamma_gg(N, s1, nf): |LO| gluon-gluon anomalous dimension :math:`\\gamma_{gg}^{(0)}(N)` """ - gamma = -s1 + 2 / N / (N + 1) + S1 = c.get(c.S1, cache, N) + gamma = -S1 + 2 / N / (N + 1) result = constants.CA * (-4.0 * gamma - 11.0 / 3.0) + 4.0 / 3.0 * constants.TR * nf return result @nb.njit(cache=True) -def gamma_singlet(N, s1, nf): +def gamma_singlet(N, cache, nf): r"""Compute the |LO| polarized singlet anomalous dimension matrix. .. math:: @@ -99,9 +101,9 @@ def gamma_singlet(N, s1, nf): |LO| singlet anomalous dimension matrix :math:`\gamma_{S}^{(0)}(N)` """ - gamma_qq = gamma_ns(N, s1) + gamma_qq = gamma_ns(N, cache) gamma_S_0 = np.array( - [[gamma_qq, gamma_qg(N, nf)], [gamma_gq(N), gamma_gg(N, s1, nf)]], + [[gamma_qq, gamma_qg(N, nf)], [gamma_gq(N), gamma_gg(N, cache, nf)]], np.complex_, ) return gamma_S_0 diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as2.py b/src/ekore/anomalous_dimensions/polarized/space_like/as2.py index c45e8dabd..a7f42b0e8 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as2.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as2.py @@ -5,7 +5,7 @@ from eko.constants import CA, CF, TR, zeta2, zeta3 -from .... import harmonics +from ....harmonics import cache as c # Non Singlet sector is swapped from ...unpolarized.space_like.as2 import gamma_nsm as gamma_nsp @@ -35,7 +35,7 @@ def gamma_ps(n, nf): @nb.njit(cache=True) -def gamma_qg(n, nf, sx): +def gamma_qg(n, nf, cache): r"""Compute the |NLO| polarized quark-gluon singlet anomalous dimension :cite:`Gluck:1995yr` (eq A.4). Parameters @@ -53,9 +53,9 @@ def gamma_qg(n, nf, sx): |NLO| quark-gluon singlet anomalous dimension :math:`\\gamma_{qg}^{(1)}(n)` """ - S1 = sx[0] - S2 = sx[1] - Sp2m = harmonics.S2((n - 1) / 2) + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sp2m = c.get(c.S2mh, cache, n) gqg1_nfca = ( (S1**2 - S2 + Sp2m) * (n - 1) / (n * (n + 1)) - 4 * S1 / (n * (1 + n) ** 2) @@ -74,7 +74,7 @@ def gamma_qg(n, nf, sx): @nb.njit(cache=True) -def gamma_gq(n, nf, sx): +def gamma_gq(n, nf, cache): r"""Compute the |NLO| polarized gluon-quark singlet anomalous dimension :cite:`Gluck:1995yr` (eq A.5). Parameters @@ -92,9 +92,9 @@ def gamma_gq(n, nf, sx): |NLO| gluon-quark singlet anomalous dimension :math:`\\gamma_{gq}^{(1)}(n)` """ - S1 = sx[0] - S2 = sx[1] - Sp2m = harmonics.S2((n - 1) / 2) + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sp2m = c.get(c.S2mh, cache, n) ggq1_cfcf = ( (2 * (S1**2 + S2) * (n + 2)) / (n * (n + 1)) - (2 * S1 * (n + 2) * (1 + 3 * n)) / (n * (1 + n) ** 2) @@ -116,7 +116,7 @@ def gamma_gq(n, nf, sx): @nb.njit(cache=True) -def gamma_gg(n, nf, sx): +def gamma_gg(n, nf, cache): r"""Compute the |NLO| polarized gluon-gluon singlet anomalous dimension :cite:`Gluck:1995yr` (eq A.6). Parameters @@ -134,17 +134,13 @@ def gamma_gg(n, nf, sx): |NLO| gluon-quark singlet anomalous dimension :math:`\\gamma_{gq}^{(1)}(n)` """ - S1 = sx[0] - Sp1m = harmonics.S1((n - 1) / 2) - Sp2m = harmonics.S2((n - 1) / 2) - Sp3m = harmonics.S3((n - 1) / 2) - S1h = harmonics.S1(n / 2) - SSCHLM = ( - zeta2 / 2 * (+Sp1m - S1h + 2 / n) - - S1 / n**2 - - harmonics.g_functions.mellin_g3(n, S1) - - 5 * zeta3 / 8 - ) + S1 = c.get(c.S1, cache, n) + Sp1m = c.get(c.S1mh, cache, n) + Sp2m = c.get(c.S2mh, cache, n) + Sp3m = c.get(c.S3mh, cache, n) + S1h = c.get(c.S1h, cache, n) + g3 = c.get(c.g3, cache, n, is_singlet=True) + SSCHLM = zeta2 / 2 * (+Sp1m - S1h + 2 / n) - S1 / n**2 - g3 - 5 * zeta3 / 8 ggg1_caca = ( -4 * S1 * Sp2m - Sp3m @@ -178,7 +174,7 @@ def gamma_gg(n, nf, sx): @nb.njit(cache=True) -def gamma_singlet(n, nf, sx): +def gamma_singlet(n, nf, cache): r"""Compute the |NLO| polarized singlet anomalous dimension matrix. .. math:: @@ -202,9 +198,12 @@ def gamma_singlet(n, nf, sx): |NLO| singlet anomalous dimension matrix :math:`\gamma_{S}^{(1)}(N)` """ - gamma_qq = gamma_nsp(n, nf, sx) + gamma_ps(n, nf) + gamma_qq = gamma_nsp(n, nf, cache) + gamma_ps(n, nf) gamma_S_0 = np.array( - [[gamma_qq, gamma_qg(n, nf, sx)], [gamma_gq(n, nf, sx), gamma_gg(n, nf, sx)]], + [ + [gamma_qq, gamma_qg(n, nf, cache)], + [gamma_gq(n, nf, cache), gamma_gg(n, nf, cache)], + ], np.complex_, ) return gamma_S_0 diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py index 5e082d6f1..77e890f1b 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py @@ -5,7 +5,7 @@ from eko.constants import zeta2 -from .... import harmonics +from ....harmonics import cache as c # Non Singlet sector is swapped from ...unpolarized.space_like.as3 import gamma_nsm as gamma_nsp @@ -13,14 +13,14 @@ @nb.njit(cache=True) -def gamma_gg(N, nf, sx): +def gamma_gg(N, nf, cache): r"""Compute the parametrized |NNLO| gluon-gluon polarized anomalous dimension. Implement Eq. (4.12) of :cite:`Moch:2014sna`. Parameters ---------- - n : complex + N : complex Mellin moment nf : int Number of active flavors @@ -33,8 +33,8 @@ def gamma_gg(N, nf, sx): |NNLO| gluon-gluon anomalous dimension :math:`\\gamma_{gg}^{(2)}(N)` """ - S1 = sx[0] - S2 = sx[1] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) E1 = S1 / N**2 + (-zeta2 + S2) / N gg_nf0 = ( +4427.76 @@ -90,7 +90,7 @@ def gamma_gg(N, nf, sx): @nb.njit(cache=True) -def gamma_qg(N, nf, sx): +def gamma_qg(N, nf, cache): r"""Compute the parametrized |NNLO| quark-gluon polarized anomalous dimension. Implement Eq. (4.10) of :cite:`Moch:2014sna`. @@ -110,7 +110,10 @@ def gamma_qg(N, nf, sx): |NNLO| quark-gluon anomalous dimension :math:`\\gamma_{qg}^{(2)}(N)` """ - S1, S2, S3, S4 = sx + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S1, cache, N) + S3 = c.get(c.S1, cache, N) + S4 = c.get(c.S1, cache, N) B3 = (-(S1**3) - 3 * S1 * S2 - 2 * S3) / N B4 = (S1**4 + 6 * S1**2 * S2 + 3 * S2**2 + 8 * S1 * S3 + 6 * S4) / N E1 = S1 / N**2 + (-zeta2 + S2) / N @@ -153,7 +156,7 @@ def gamma_qg(N, nf, sx): @nb.njit(cache=True) -def gamma_gq(N, nf, sx): +def gamma_gq(N, nf, cache): r"""Compute the parametrized |NNLO| gluon-quark polarized anomalous dimension. Implement Eq. (4.11) of :cite:`Moch:2014sna`. @@ -173,7 +176,10 @@ def gamma_gq(N, nf, sx): |NNLO| gluon-quark anomalous dimension :math:`\\gamma_{gq}^{(2)}(N)` """ - S1, S2, S3, S4 = sx + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S1, cache, N) + S3 = c.get(c.S1, cache, N) + S4 = c.get(c.S1, cache, N) B3 = (-(S1**3) - 3 * S1 * S2 - 2 * S3) / N B4 = (S1**4 + 6 * S1**2 * S2 + 3 * S2**2 + 8 * S1 * S3 + 6 * S4) / N E1 = S1 / N**2 + (-zeta2 + S2) / N @@ -229,7 +235,7 @@ def gamma_gq(N, nf, sx): @nb.njit(cache=True) -def gamma_ps(N, nf, sx): +def gamma_ps(N, nf, cache): r"""Compute the parametrized |NNLO| pure-singlet quark-quark polarized anomalous dimension. Implement Eq. (4.9) of :cite:`Moch:2014sna`. @@ -249,7 +255,9 @@ def gamma_ps(N, nf, sx): |NNLO| pure-singlet quark-quark anomalous dimension :math:`\\gamma_{ps}^{(2)}(N)` """ - S1, S2, S3, _ = sx + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S1, cache, N) + S3 = c.get(c.S1, cache, N) B3 = (-(S1**3) - 3 * S1 * S2 - 2 * S3) / N B31 = ( -((1 / (1 + N) + S1) ** 3) @@ -320,7 +328,7 @@ def gamma_ps(N, nf, sx): @nb.njit(cache=True) -def gamma_nss(N, nf, sx): +def gamma_nss(N, nf, cache): r"""Compute the |NNLO| sea-like polarized non-singlet anomalous dimension. Implement Eq. (24) of :cite:`Moch:2015usa`. @@ -341,10 +349,11 @@ def gamma_nss(N, nf, sx): :math:`\\gamma_{ns,s}^{(2)}(N)` """ - S1 = sx[0] - S3 = sx[2] - Sm1, Sm2, Sm3, _ = harmonics.smx(N, sx, False) - Sm21 = harmonics.Sm21(N, S1, Sm1, False) + # TODO: CHECK is this true or false ?? + S1 = c.get(c.S1, cache, N) + Sm2 = c.get(c.Sm2, cache, N, is_singlet=False) + Sm3 = c.get(c.Sm3, cache, N, is_singlet=False) + Sm21 = c.get(c.Sm21, cache, N, is_singlet=False) nss_nf1 = ( 40 / 9 @@ -376,7 +385,7 @@ def gamma_nss(N, nf, sx): @nb.njit(cache=True) -def gamma_nsv(N, nf, sx): +def gamma_nsv(N, nf, cache): r"""Compute the |NNLO| valence polarized non-singlet anomalous dimension. Implement Eq. (23) of :cite:`Moch:2015usa`. @@ -397,11 +406,11 @@ def gamma_nsv(N, nf, sx): :math:`\\gamma_{ns,v}^{(2)}(N)` """ - return gamma_nsm(N, nf, sx) + gamma_nss(N, nf, sx) + return gamma_nsm(N, nf, cache) + gamma_nss(N, nf, cache) @nb.njit(cache=True) -def gamma_singlet(N, nf, sx): +def gamma_singlet(N, nf, cache): r"""Compute the |NNLO| polarized singlet anomalous dimension matrix. .. math:: @@ -425,9 +434,12 @@ def gamma_singlet(N, nf, sx): |NNLO| singlet anomalous dimension matrix :math:`\gamma_{S}^{(2)}(N)` """ - gamma_qq = gamma_nsp(N, nf, sx) + gamma_ps(N, nf, sx) + gamma_qq = gamma_nsp(N, nf, cache) + gamma_ps(N, nf, cache) gamma_S_0 = np.array( - [[gamma_qq, gamma_qg(N, nf, sx)], [gamma_gq(N, nf, sx), gamma_gg(N, nf, sx)]], + [ + [gamma_qq, gamma_qg(N, nf, cache)], + [gamma_gq(N, nf, cache), gamma_gg(N, nf, cache)], + ], np.complex_, ) return gamma_S_0 diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as1.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as1.py index 4a6ab875e..4e9b0b91a 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as1.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as1.py @@ -5,9 +5,11 @@ from eko import constants +from ....harmonics import cache as c + @nb.njit(cache=True) -def gamma_ns(N, s1): +def gamma_ns(N, cache): r"""Compute the leading-order non-singlet anomalous dimension. Implements Eq. (3.4) of :cite:`Moch:2004pa`. @@ -24,7 +26,8 @@ def gamma_ns(N, s1): gamma_ns : complex Leading-order non-singlet anomalous dimension :math:`\\gamma_{ns}^{(0)}(N)` """ - gamma = -(3.0 - 4.0 * s1 + 2.0 / N / (N + 1.0)) + S1 = c.get(c.S1, cache, N) + gamma = -(3.0 - 4.0 * S1 + 2.0 / N / (N + 1.0)) result = constants.CF * gamma return result @@ -74,7 +77,7 @@ def gamma_gq(N): @nb.njit(cache=True) -def gamma_gg(N, s1, nf): +def gamma_gg(N, cache, nf): r"""Compute the leading-order gluon-gluon anomalous dimension. Implements Eq. (3.5) of :cite:`Vogt:2004mw`. @@ -93,13 +96,14 @@ def gamma_gg(N, s1, nf): gamma_gg : complex Leading-order gluon-gluon anomalous dimension :math:`\\gamma_{gg}^{(0)}(N)` """ - gamma = s1 - 1.0 / N / (N - 1.0) - 1.0 / (N + 1.0) / (N + 2.0) + S1 = c.get(c.S1, cache, N) + gamma = S1 - 1.0 / N / (N - 1.0) - 1.0 / (N + 1.0) / (N + 2.0) result = constants.CA * (4.0 * gamma - 11.0 / 3.0) + 4.0 / 3.0 * constants.TR * nf return result @nb.njit(cache=True) -def gamma_singlet(N, s1, nf): +def gamma_singlet(N, cache, nf): r"""Compute the leading-order singlet anomalous dimension matrix. .. math:: @@ -129,15 +133,16 @@ def gamma_singlet(N, s1, nf): gamma_gq : :math:`\\gamma_{gq}^{(0)}` gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ - gamma_qq = gamma_ns(N, s1) + gamma_qq = gamma_ns(N, cache) gamma_S_0 = np.array( - [[gamma_qq, gamma_qg(N, nf)], [gamma_gq(N), gamma_gg(N, s1, nf)]], np.complex_ + [[gamma_qq, gamma_qg(N, nf)], [gamma_gq(N), gamma_gg(N, cache, nf)]], + np.complex_, ) return gamma_S_0 @nb.njit(cache=True) -def gamma_singlet_qed(N, s1, nf): +def gamma_singlet_qed(N, cache, nf): r"""Compute the leading-order singlet anomalous dimension matrix for the unified evolution basis. .. math:: @@ -169,10 +174,10 @@ def gamma_singlet_qed(N, s1, nf): gamma_gq : :math:`\\gamma_{gq}^{(0)}` gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ - gamma_qq = gamma_ns(N, s1) + gamma_qq = gamma_ns(N, cache) gamma_S = np.array( [ - [gamma_gg(N, s1, nf), 0.0 + 0.0j, gamma_gq(N), 0.0 + 0.0j], + [gamma_gg(N, cache, nf), 0.0 + 0.0j, gamma_gq(N), 0.0 + 0.0j], [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], [gamma_qg(N, nf), 0.0 + 0.0j, gamma_qq, 0.0 + 0.0j], [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, gamma_qq], @@ -183,7 +188,7 @@ def gamma_singlet_qed(N, s1, nf): @nb.njit(cache=True) -def gamma_valence_qed(N, s1): +def gamma_valence_qed(N, cache): r"""Compute the leading-order valence anomalous dimension matrix for the unified evolution basis. .. math:: @@ -218,4 +223,4 @@ def gamma_valence_qed(N, s1): ], np.complex_, ) - return gamma_V * gamma_ns(N, s1) + return gamma_V * gamma_ns(N, cache) diff --git a/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as1.py b/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as1.py index 42fee408b..4b7b24d38 100755 --- a/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as1.py +++ b/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as1.py @@ -11,9 +11,9 @@ def test_quark_momentum(): # quark momentum N = complex(2.0, 0.0) - s1 = harmonics.S1(N) + cache = harmonics.cache.reset() np.testing.assert_almost_equal( - as1.gamma_ns(N, s1) + as1.gamma_gq(N), + as1.gamma_ns(N, cache) + as1.gamma_gq(N), (4 * constants.CF) / 3, ) @@ -21,9 +21,9 @@ def test_quark_momentum(): def test_gluon_momentum(): # gluon momentum N = complex(2.0, 0.0) - s1 = harmonics.S1(N) + cache = harmonics.cache.reset() np.testing.assert_almost_equal( - as1.gamma_qg(N, NF) + as1.gamma_gg(N, s1, NF), 3 + NF / 3 + as1.gamma_qg(N, NF) + as1.gamma_gg(N, cache, NF), 3 + NF / 3 ) diff --git a/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as2.py b/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as2.py index c26f2f6c5..743bae92d 100755 --- a/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as2.py +++ b/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as2.py @@ -10,15 +10,15 @@ def test_qg_helicity_conservation(): N = complex(1.0, 0.0) - sx = harmonics.sx(N, max_weight=4) - np.testing.assert_almost_equal(as2.gamma_qg(N, nf, sx), 0) + cache = harmonics.cache.reset() + np.testing.assert_almost_equal(as2.gamma_qg(N, nf, cache), 0) def test_qq_momentum(): N = complex(1.0, 0.0) - sx = harmonics.sx(N, max_weight=2) + cache = harmonics.cache.reset() np.testing.assert_almost_equal( - as2.gamma_singlet(N, nf, sx)[0, 0], 12 * TR * nf * CF, decimal=5 + as2.gamma_singlet(N, nf, cache)[0, 0], 12 * TR * nf * CF, decimal=5 ) @@ -29,9 +29,9 @@ def test_ps_momentum(): def test_qg_momentum(): N = complex(2.0, 0.0) - sx = harmonics.sx(N, 2) + cache = harmonics.cache.reset() np.testing.assert_allclose( - -as2.gamma_qg(N, nf, sx), + -as2.gamma_qg(N, nf, cache), 4 * nf * (0.574074 * CF - 2 * CA * (-7 / 18 + 1 / 6 * (5 - np.pi**2 / 3))) @@ -41,9 +41,9 @@ def test_qg_momentum(): def test_gq_momentum(): N = complex(2.0, 0.0) - sx = harmonics.sx(N, 2) + cache = harmonics.cache.reset() np.testing.assert_allclose( - -as2.gamma_gq(N, nf, sx), + -as2.gamma_gq(N, nf, cache), 4 * ( -2.074074074074074 * CF**2 @@ -55,9 +55,9 @@ def test_gq_momentum(): def test_gg_momentum(): N = complex(2.0, 0.0) - sx = harmonics.sx(N, 2) + cache = harmonics.cache.reset() np.testing.assert_almost_equal( - -as2.gamma_gg(N, nf, sx), + -as2.gamma_gg(N, nf, cache), 4 * (-1.7537256813471833 * CA**2 + ((29 * CA) / 27 - (28 * CF) / 27) * nf * TR), ) diff --git a/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as3.py b/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as3.py index 1b21097c6..bd4f1fac8 100755 --- a/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as3.py +++ b/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as3.py @@ -11,16 +11,16 @@ def test_gluon_momentum(): # gluon momentum N = complex(2.0, 0.0) - sx = harmonics.sx(N, max_weight=4) + cache = harmonics.cache.reset() np.testing.assert_allclose( - as3.gamma_qg(N, nf, sx) + as3.gamma_gg(N, nf, sx), 9.26335, rtol=7e-4 + as3.gamma_qg(N, nf, cache) + as3.gamma_gg(N, nf, cache), 9.26335, rtol=7e-4 ) def test_qg_helicity_conservation(): N = complex(1.0, 0.0) - sx = harmonics.sx(N, max_weight=4) - np.testing.assert_almost_equal(as3.gamma_qg(N, nf, sx), 0.00294317) + cache = harmonics.cache.reset() + np.testing.assert_almost_equal(as3.gamma_qg(N, nf, cache), 0.00294317) def test_ns_sea(): @@ -33,15 +33,20 @@ def test_ns_sea(): ] for i, mom in enumerate(ref_moments): N = 1 + 2 * i - sx = harmonics.sx(N, max_weight=4) - np.testing.assert_allclose(-as3.gamma_nss(N, nf, sx), mom * nf, rtol=7e-7) + cache = harmonics.cache.reset() + np.testing.assert_allclose(-as3.gamma_nss(N, nf, cache), mom * nf, rtol=7e-7) def test_ns(): N = complex(3.45, 0.0) - sx = harmonics.sx(N, max_weight=4) + cache = harmonics.cache.reset() np.testing.assert_allclose( - as3.gamma_nsv(N, nf, sx), as3.gamma_nsm(N, nf, sx) + as3.gamma_nss(N, nf, sx) + as3.gamma_nsv(N, nf, cache), + as3.gamma_nsm(N, nf, cache) + as3.gamma_nss(N, nf, cache), + ) + np.testing.assert_allclose( + as3_unpol.gamma_nsm(N, nf, cache), as3.gamma_nsp(N, nf, cache) + ) + np.testing.assert_allclose( + as3_unpol.gamma_nsp(N, nf, cache), as3.gamma_nsm(N, nf, cache) ) - np.testing.assert_allclose(as3_unpol.gamma_nsm(N, nf, sx), as3.gamma_nsp(N, nf, sx)) - np.testing.assert_allclose(as3_unpol.gamma_nsp(N, nf, sx), as3.gamma_nsm(N, nf, sx)) diff --git a/tests/ekore/anomalous_dimensions/polarized/space_like/test_init.py b/tests/ekore/anomalous_dimensions/polarized/space_like/test_init.py index 98e753c05..9cf55ee45 100644 --- a/tests/ekore/anomalous_dimensions/polarized/space_like/test_init.py +++ b/tests/ekore/anomalous_dimensions/polarized/space_like/test_init.py @@ -4,7 +4,6 @@ import ekore.anomalous_dimensions.polarized.space_like as ad_ps from eko import basis_rotation as br -from ekore import harmonics def test_shapes(): @@ -36,16 +35,11 @@ def test_gamma_ns(): ) -def test_not_implemeted(monkeypatch): +def test_not_implemeted(): with pytest.raises(NotImplementedError): ad_ps.gamma_ns((4, 0), br.non_singlet_pids_map["ns-"], 1.234, 4) with pytest.raises(NotImplementedError): ad_ps.gamma_ns((2, 0), 10202, 1.234, 4) N = 2.345 - monkeypatch.setattr( - ad_ps, - "compute_cache", - lambda *args: harmonics.sx(N, 4), - ) with pytest.raises(NotImplementedError): ad_ps.gamma_singlet((4, 0), N, 4) From 9cda7acf390e7ef20602f03034a3a46f4b12e066 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 10:21:11 +0200 Subject: [PATCH 04/24] more work on ad unpolarized --- .../unpolarized/space_like/aem1.py | 57 +++--- .../unpolarized/space_like/aem2.py | 131 +++++++------ .../unpolarized/space_like/as1.py | 39 ++-- .../unpolarized/space_like/as1aem1.py | 143 ++++++++------- .../unpolarized/space_like/as2.py | 155 ++++++++-------- .../unpolarized/space_like/as3.py | 173 +++++++++--------- src/ekore/harmonics/cache.py | 2 +- 7 files changed, 332 insertions(+), 368 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/aem1.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/aem1.py index 7f122938a..6892ba56d 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/aem1.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/aem1.py @@ -5,6 +5,7 @@ from eko import constants +from ....harmonics import cache as c from . import as1 @@ -21,8 +22,9 @@ def gamma_phq(N): Returns ------- - gamma_phq : complex + complex Leading-order photon-quark anomalous dimension :math:`\\gamma_{\\gamma q}^{(0,1)}(N)` + """ return as1.gamma_gq(N) / constants.CF @@ -44,8 +46,9 @@ def gamma_qph(N, nf): Returns ------- - gamma_qph : complex + complex Leading-order quark-photon anomalous dimension :math:`\\gamma_{q \\gamma}^{(0,1)}(N)` + """ return as1.gamma_qg(N, nf) / constants.TR * constants.NC @@ -63,8 +66,9 @@ def gamma_phph(nf): Returns ------- - gamma_phph : complex + complex Leading-order phton-photon anomalous dimension :math:`\\gamma_{\\gamma \\gamma}^{(0,1)}(N)` + """ nu = constants.uplike_flavors(nf) nd = nf - nu @@ -72,7 +76,7 @@ def gamma_phph(nf): @nb.njit(cache=True) -def gamma_ns(N, sx): +def gamma_ns(N, cache): r"""Compute the leading-order non-singlet QED anomalous dimension. Implements Eq. (2.5) of :cite:`Carrazza:2015dea`. @@ -81,20 +85,21 @@ def gamma_ns(N, sx): ---------- N : complex Mellin moment - s1 : complex - S1(N) + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_ns : complex + complex Leading-order non-singlet QED anomalous dimension :math:`\\gamma_{ns}^{(0,1)}(N)` + """ - s1 = sx[0] - return as1.gamma_ns(N, s1) / constants.CF + S1 = c.get(c.S1, N, cache) + return as1.gamma_ns(N, S1) / constants.CF @nb.njit(cache=True) -def gamma_singlet(N, nf, sx): +def gamma_singlet(N, nf, cache): r"""Compute the QED leading-order singlet anomalous dimension matrix. .. math:: @@ -109,27 +114,21 @@ def gamma_singlet(N, nf, sx): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` nf : int Number of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_S_0 : numpy.ndarray + numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{S}^{(0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ e2avg, vue2m, vde2m, e2delta = constants.charge_combinations(nf) gamma_ph_q = gamma_phq(N) gamma_q_ph = gamma_qph(N, nf) - gamma_nonsinglet = gamma_ns(N, sx) + gamma_nonsinglet = gamma_ns(N, cache) gamma_S_01 = np.array( [ [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], @@ -158,7 +157,7 @@ def gamma_singlet(N, nf, sx): @nb.njit(cache=True) -def gamma_valence(N, nf, sx): +def gamma_valence(N, nf, cache): r"""Compute the QED leading-order valence anomalous dimension matrix. .. math:: @@ -171,20 +170,16 @@ def gamma_valence(N, nf, sx): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` + nf : int + Number of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_S_0 : numpy.ndarray + numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{S}^{(0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ e2avg, vue2m, vde2m, e2delta = constants.charge_combinations(nf) gamma_V_01 = np.array( @@ -194,4 +189,4 @@ def gamma_valence(N, nf, sx): ], np.complex_, ) - return gamma_V_01 * gamma_ns(N, sx) + return gamma_V_01 * gamma_ns(N, cache) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/aem2.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/aem2.py index 3a3eef329..824e47b7e 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/aem2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/aem2.py @@ -5,6 +5,7 @@ from eko import constants +from ....harmonics import cache as c from . import as1aem1 @@ -38,7 +39,7 @@ def gamma_phph(N, nf): @nb.njit(cache=True) -def gamma_uph(N, nf, sx): +def gamma_uph(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` quark-photon anomalous dimension for up quarks. Implements Eq. (55) of :cite:`deFlorian:2016gvk` for q=u. @@ -49,8 +50,8 @@ def gamma_uph(N, nf, sx): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -58,11 +59,11 @@ def gamma_uph(N, nf, sx): :math:`O(a_{em}^2)` quark-photon anomalous dimension :math:`\\gamma_{u \\gamma}^{(0,2)}(N)` """ - return constants.eu2 * as1aem1.gamma_qph(N, nf, sx) / constants.CF + return constants.eu2 * as1aem1.gamma_qph(N, nf, cache) / constants.CF @nb.njit(cache=True) -def gamma_dph(N, nf, sx): +def gamma_dph(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` quark-photon anomalous dimension for down quarks. Implements Eq. (55) of :cite:`deFlorian:2016gvk` for q=d. @@ -73,8 +74,8 @@ def gamma_dph(N, nf, sx): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -82,11 +83,11 @@ def gamma_dph(N, nf, sx): :math:`O(a_{em}^2)` quark-photon anomalous dimension :math:`\\gamma_{d \\gamma}^{(0,2)}(N)` """ - return constants.ed2 * as1aem1.gamma_qph(N, nf, sx) / constants.CF + return constants.ed2 * as1aem1.gamma_qph(N, nf, cache) / constants.CF @nb.njit(cache=True) -def gamma_phu(N, nf, sx): +def gamma_phu(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` photon-quark anomalous dimension for up quarks. Implements Eq. (56) of :cite:`deFlorian:2016gvk` for q=u. @@ -97,8 +98,8 @@ def gamma_phu(N, nf, sx): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -108,18 +109,18 @@ def gamma_phu(N, nf, sx): """ nu = constants.uplike_flavors(nf) nd = nf - nu - S1 = sx[0] + S1 = c.get(c.S1, cache, N) tmp = (-16.0 * (-16.0 - 27.0 * N - 13.0 * N**2 - 8.0 * N**3)) / ( 9.0 * (-1.0 + N) * N * (1.0 + N) ** 2 ) - 16.0 * (2.0 + 3.0 * N + 2.0 * N**2 + N**3) / ( 3.0 * (-1.0 + N) * N * (1.0 + N) ** 2 ) * S1 eSigma2 = constants.NC * (nu * constants.eu2 + nd * constants.ed2) - return constants.eu2 * as1aem1.gamma_phq(N, sx) / constants.CF + eSigma2 * tmp + return constants.eu2 * as1aem1.gamma_phq(N, cache) / constants.CF + eSigma2 * tmp @nb.njit(cache=True) -def gamma_phd(N, nf, sx): +def gamma_phd(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` photon-quark anomalous dimension for down quarks. Implements Eq. (56) of :cite:`deFlorian:2016gvk` for q=d. @@ -130,8 +131,8 @@ def gamma_phd(N, nf, sx): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -141,18 +142,18 @@ def gamma_phd(N, nf, sx): """ nu = constants.uplike_flavors(nf) nd = nf - nu - S1 = sx[0] + S1 = c.get(c.S1, cache, N) tmp = (-16.0 * (-16.0 - 27.0 * N - 13.0 * N**2 - 8.0 * N**3)) / ( 9.0 * (-1.0 + N) * N * (1.0 + N) ** 2 ) - 16.0 * (2.0 + 3.0 * N + 2.0 * N**2 + N**3) / ( 3.0 * (-1.0 + N) * N * (1.0 + N) ** 2 ) * S1 eSigma2 = constants.NC * (nu * constants.eu2 + nd * constants.ed2) - return constants.ed2 * as1aem1.gamma_phq(N, sx) / constants.CF + eSigma2 * tmp + return constants.ed2 * as1aem1.gamma_phq(N, cache) / constants.CF + eSigma2 * tmp @nb.njit(cache=True) -def gamma_nspu(N, nf, sx, sx_ns_qed): +def gamma_nspu(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` singlet-like non-singlet anomalous dimension for up quarks. Implements sum of Eqs. (57-58) of :cite:`deFlorian:2016gvk` for q=u. @@ -163,8 +164,8 @@ def gamma_nspu(N, nf, sx, sx_ns_qed): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -173,8 +174,8 @@ def gamma_nspu(N, nf, sx, sx_ns_qed): :math:`\\gamma_{ns,+,u}^{(0,2)}(N)` """ - S1 = sx[0] - S2 = sx[1] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) nu = constants.uplike_flavors(nf) nd = nf - nu eSigma2 = constants.NC * (nu * constants.eu2 + nd * constants.ed2) @@ -185,13 +186,11 @@ def gamma_nspu(N, nf, sx, sx_ns_qed): - 80.0 / 9.0 * S1 + 16.0 / 3.0 * S2 ) * eSigma2 - return ( - constants.eu2 * as1aem1.gamma_nsp(N, sx, sx_ns_qed) / constants.CF / 2.0 + tmp - ) + return constants.eu2 * as1aem1.gamma_nsp(N, cache) / constants.CF / 2.0 + tmp @nb.njit(cache=True) -def gamma_nspd(N, nf, sx, sx_ns_qed): +def gamma_nspd(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` singlet-like non-singlet anomalous dimension for down quarks. Implements sum of Eqs. (57-58) of :cite:`deFlorian:2016gvk` for q=d. @@ -202,8 +201,8 @@ def gamma_nspd(N, nf, sx, sx_ns_qed): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -212,8 +211,8 @@ def gamma_nspd(N, nf, sx, sx_ns_qed): :math:`\\gamma_{ns,+,d}^{(0,2)}(N)` """ - S1 = sx[0] - S2 = sx[1] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) nu = constants.uplike_flavors(nf) nd = nf - nu eSigma2 = constants.NC * (nu * constants.eu2 + nd * constants.ed2) @@ -224,13 +223,11 @@ def gamma_nspd(N, nf, sx, sx_ns_qed): - 80.0 / 9.0 * S1 + 16.0 / 3.0 * S2 ) * eSigma2 - return ( - constants.ed2 * as1aem1.gamma_nsp(N, sx, sx_ns_qed) / constants.CF / 2.0 + tmp - ) + return constants.ed2 * as1aem1.gamma_nsp(N, cache) / constants.CF / 2.0 + tmp @nb.njit(cache=True) -def gamma_nsmu(N, nf, sx, sx_ns_qed): +def gamma_nsmu(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` valence-like non-singlet anomalous dimension for up quarks. Implements difference between Eqs. (57-58) of :cite:`deFlorian:2016gvk` for q=u. @@ -241,8 +238,8 @@ def gamma_nsmu(N, nf, sx, sx_ns_qed): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -251,8 +248,8 @@ def gamma_nsmu(N, nf, sx, sx_ns_qed): :math:`\\gamma_{ns,-,u}^{(0,2)}(N)` """ - S1 = sx[0] - S2 = sx[1] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) nu = constants.uplike_flavors(nf) nd = nf - nu eSigma2 = constants.NC * (nu * constants.eu2 + nd * constants.ed2) @@ -263,13 +260,11 @@ def gamma_nsmu(N, nf, sx, sx_ns_qed): - 80.0 / 9.0 * S1 + 16.0 / 3.0 * S2 ) * eSigma2 - return ( - constants.eu2 * as1aem1.gamma_nsm(N, sx, sx_ns_qed) / constants.CF / 2.0 + tmp - ) + return constants.eu2 * as1aem1.gamma_nsm(N, cache) / constants.CF / 2.0 + tmp @nb.njit(cache=True) -def gamma_nsmd(N, nf, sx, sx_ns_qed): +def gamma_nsmd(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` valence-like non-singlet anomalous dimension for down quarks. Implements difference between Eqs. (57-58) of :cite:`deFlorian:2016gvk` for q=d. @@ -280,8 +275,8 @@ def gamma_nsmd(N, nf, sx, sx_ns_qed): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -290,8 +285,8 @@ def gamma_nsmd(N, nf, sx, sx_ns_qed): :math:`\\gamma_{ns,-,d}^{(0,2)}(N)` """ - S1 = sx[0] - S2 = sx[1] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) nu = constants.uplike_flavors(nf) nd = nf - nu eSigma2 = constants.NC * (nu * constants.eu2 + nd * constants.ed2) @@ -302,9 +297,7 @@ def gamma_nsmd(N, nf, sx, sx_ns_qed): - 80.0 / 9.0 * S1 + 16.0 / 3.0 * S2 ) * eSigma2 - return ( - constants.ed2 * as1aem1.gamma_nsm(N, sx, sx_ns_qed) / constants.CF / 2.0 + tmp - ) + return constants.ed2 * as1aem1.gamma_nsm(N, cache) / constants.CF / 2.0 + tmp @nb.njit(cache=True) @@ -337,7 +330,7 @@ def gamma_ps(N, nf): @nb.njit(cache=True) -def gamma_singlet(N, nf, sx, sx_ns_qed): +def gamma_singlet(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` singlet sector. Parameters @@ -346,13 +339,14 @@ def gamma_singlet(N, nf, sx, sx_ns_qed): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_singlet : numpy.ndarray - :math:`O(a_{em}^2)` singlet anomalous dimension :math:`\\gamma_{S}^{(0,2)}(N,nf,sx)` + numpy.ndarray + :math:`O(a_{em}^2)` singlet anomalous dimension :math:`\\gamma_{S}^{(0,2)}` + """ nu = constants.uplike_flavors(nf) nd = nf - nu @@ -361,12 +355,12 @@ def gamma_singlet(N, nf, sx, sx_ns_qed): e2m = constants.eu2 - constants.ed2 e2avg = (nu * constants.eu2 + nd * constants.ed2) / nf e2m = constants.eu2 - constants.ed2 - gamma_ph_u = gamma_phu(N, nf, sx) - gamma_ph_d = gamma_phd(N, nf, sx) - gamma_u_ph = gamma_uph(N, nf, sx) - gamma_d_ph = gamma_dph(N, nf, sx) - gamma_ns_p_u = gamma_nspu(N, nf, sx, sx_ns_qed) - gamma_ns_p_d = gamma_nspd(N, nf, sx, sx_ns_qed) + gamma_ph_u = gamma_phu(N, nf, cache) + gamma_ph_d = gamma_phd(N, nf, cache) + gamma_u_ph = gamma_uph(N, nf, cache) + gamma_d_ph = gamma_dph(N, nf, cache) + gamma_ns_p_u = gamma_nspu(N, nf, cache) + gamma_ns_p_d = gamma_nspd(N, nf, cache) gamma_pure_singlet = gamma_ps(N, nf) gamma_S_02 = np.array( [ @@ -410,7 +404,7 @@ def gamma_singlet(N, nf, sx, sx_ns_qed): @nb.njit(cache=True) -def gamma_valence(N, nf, sx, sx_ns_qed): +def gamma_valence(N, nf, cache): r"""Compute the :math:`O(a_{em}^2)` valence sector. Parameters @@ -419,20 +413,21 @@ def gamma_valence(N, nf, sx, sx_ns_qed): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_singlet : numpy.ndarray - :math:`O(a_{em}^2)` valence anomalous dimension :math:`\\gamma_{V}^{(0,2)}(N,nf,sx)` + numpy.ndarray + :math:`O(a_{em}^2)` valence anomalous dimension :math:`\\gamma_{V}^{(0,2)}` + """ nu = constants.uplike_flavors(nf) nd = nf - nu vu = nu / nf vd = nd / nf - gamma_ns_m_u = gamma_nsmu(N, nf, sx, sx_ns_qed) - gamma_ns_m_d = gamma_nsmd(N, nf, sx, sx_ns_qed) + gamma_ns_m_u = gamma_nsmu(N, nf, cache) + gamma_ns_m_d = gamma_nsmd(N, nf, cache) gamma_V_02 = np.array( [ [ diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as1.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as1.py index 4e9b0b91a..b4c1d73ac 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as1.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as1.py @@ -18,8 +18,9 @@ def gamma_ns(N, cache): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache + Returns ------- @@ -86,8 +87,8 @@ def gamma_gg(N, cache, nf): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache nf : int Number of active flavors @@ -116,8 +117,8 @@ def gamma_singlet(N, cache, nf): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache nf : int Number of active flavors @@ -126,12 +127,6 @@ def gamma_singlet(N, cache, nf): gamma_S_0 : numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{S}^{(0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ gamma_qq = gamma_ns(N, cache) gamma_S_0 = np.array( @@ -157,8 +152,8 @@ def gamma_singlet_qed(N, cache, nf): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache nf : int Number of active flavors @@ -167,12 +162,6 @@ def gamma_singlet_qed(N, cache, nf): gamma_S : numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{S}^{(1,0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ gamma_qq = gamma_ns(N, cache) gamma_S = np.array( @@ -201,20 +190,14 @@ def gamma_valence_qed(N, cache): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- gamma_V : numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{V}^{(1,0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ gamma_V = np.array( [ diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as1aem1.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as1aem1.py index 23fe02abd..83e18c2bd 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as1aem1.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as1aem1.py @@ -6,9 +6,11 @@ from eko import constants from eko.constants import zeta2, zeta3 +from ....harmonics import cache as c + @nb.njit(cache=True) -def gamma_phq(N, sx): +def gamma_phq(N, cache): r"""Compute the :math:`O(a_s^1a_{em}^1)` photon-quark anomalous dimension. Implements Eq. (36) of :cite:`deFlorian:2015ujt`. @@ -17,17 +19,18 @@ def gamma_phq(N, sx): ---------- N : complex Mellin moment - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache + Returns ------- - gamma_phq : complex + complex :math:`O(a_s^1a_{em}^1)` photon-quark anomalous dimension :math:`\\gamma_{\\gamma q}^{(1,1)}(N)` """ - S1 = sx[0] - S2 = sx[1] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) tmp_const = ( 2.0 * ( @@ -53,7 +56,7 @@ def gamma_phq(N, sx): @nb.njit(cache=True) -def gamma_qph(N, nf, sx): +def gamma_qph(N, nf, cache): r"""Compute the :math:`O(a_s^1a_{em}^1)` quark-photon anomalous dimension. Implements Eq. (26) of :cite:`deFlorian:2015ujt`. @@ -64,17 +67,17 @@ def gamma_qph(N, nf, sx): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_qph : complex + complex :math:`O(a_s^1a_{em}^1)` quark-photon anomalous dimension :math:`\\gamma_{q \\gamma}^{(1,1)}(N)` """ - S1 = sx[0] - S2 = sx[1] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) tmp_const = ( -2.0 * ( @@ -113,7 +116,7 @@ def gamma_gph(N): Returns ------- - gamma_qph : complex + complex :math:`O(a_s^1a_{em}^1)` gluon-photon anomalous dimension :math:`\\gamma_{g \\gamma}^{(1,1)}(N)` """ @@ -144,7 +147,7 @@ def gamma_phg(N): Returns ------- - gamma_qph : complex + complex :math:`O(a_s^1a_{em}^1)` photon-gluon anomalous dimension :math:`\\gamma_{\\gamma g}^{(1,1)}(N)` """ @@ -152,7 +155,7 @@ def gamma_phg(N): @nb.njit(cache=True) -def gamma_qg(N, nf, sx): +def gamma_qg(N, nf, cache): r"""Compute the :math:`O(a_s^1a_{em}^1)` quark-gluon singlet anomalous dimension. Implements Eq. (29) of :cite:`deFlorian:2015ujt`. @@ -163,23 +166,28 @@ def gamma_qg(N, nf, sx): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache + Returns ------- - gamma_qg : complex + complex :math:`O(a_s^1a_{em}^1)` quark-gluon singlet anomalous dimension :math:`\\gamma_{qg}^{(1,1)}(N)` """ return ( - constants.TR / constants.CF / constants.CA * constants.NC * gamma_qph(N, nf, sx) + constants.TR + / constants.CF + / constants.CA + * constants.NC + * gamma_qph(N, nf, cache) ) @nb.njit(cache=True) -def gamma_gq(N, sx): +def gamma_gq(N, cache): r"""Compute the :math:`O(a_s^1a_{em}^1)` gluon-quark singlet anomalous dimension. Implements Eq. (35) of :cite:`deFlorian:2015ujt`. @@ -188,17 +196,17 @@ def gamma_gq(N, sx): ---------- N : complex Mellin moment - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gq : complex + complex :math:`O(a_s^1a_{em}^1)` gluon-quark singlet anomalous dimension :math:`\\gamma_{gq}^{(1,1)}(N)` """ - return gamma_phq(N, sx) + return gamma_phq(N, cache) @nb.njit(cache=True) @@ -232,7 +240,7 @@ def gamma_gg(): Returns ------- - gamma_gg : complex + complex :math:`O(a_s^1a_{em}^1)` gluon-gluon singlet anomalous dimension :math:`\\gamma_{gg}^{(1,1)}(N)` @@ -241,7 +249,7 @@ def gamma_gg(): @nb.njit(cache=True) -def gamma_nsp(N, sx, sx_ns_qed): +def gamma_nsp(N, cache): r"""Compute the :math:`O(a_s^1a_{em}^1)` singlet-like non-singlet anomalous dimension. Implements sum of Eqs. (33-34) of :cite:`deFlorian:2015ujt`. @@ -250,8 +258,8 @@ def gamma_nsp(N, sx, sx_ns_qed): ---------- N : complex Mellin moment - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -260,17 +268,18 @@ def gamma_nsp(N, sx, sx_ns_qed): :math:`\\gamma_{ns,+}^{(1)}(N)` """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] - S1h = sx_ns_qed[0] - S2h = sx_ns_qed[1] - S3h = sx_ns_qed[2] - S1p1h = sx_ns_qed[3] - S2p1h = sx_ns_qed[4] - S3p1h = sx_ns_qed[5] - g3N = sx_ns_qed[6] - g3Np2 = sx_ns_qed[7] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) + S1h = c.get(c.S1h, cache, N) + S2h = c.get(c.S2h, cache, N) + S3h = c.get(c.S3h, cache, N) + S1p1h = c.get(c.S1mh, cache, N) + S2p1h = c.get(c.S2mh, cache, N) + S3p1h = c.get(c.S3mh, cache, N) + # TODO: CHECK is this True or False?? + g3N = c.get(c.g3, cache, N, is_singlet=False) + g3Np2 = c.get(c.g3p2, cache, N, is_singlet=False) result = ( +32.0 * zeta2 * S1h - 32.0 * zeta2 * S1p1h @@ -308,7 +317,7 @@ def gamma_nsp(N, sx, sx_ns_qed): @nb.njit(cache=True) -def gamma_nsm(N, sx, sx_ns_qed): +def gamma_nsm(N, cache): r"""Compute the :math:`O(a_s^1a_{em}^1)` valence-like non-singlet anomalous dimension. Implements difference between Eqs. (33-34) of :cite:`deFlorian:2015ujt`. @@ -317,8 +326,8 @@ def gamma_nsm(N, sx, sx_ns_qed): ---------- N : complex Mellin moment - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -327,17 +336,17 @@ def gamma_nsm(N, sx, sx_ns_qed): :math:`\\gamma_{ns,-}^{(1,1)}(N)` """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] - S1h = sx_ns_qed[0] - S2h = sx_ns_qed[1] - S3h = sx_ns_qed[2] - S1p1h = sx_ns_qed[3] - S2p1h = sx_ns_qed[4] - S3p1h = sx_ns_qed[5] - g3N = sx_ns_qed[6] - g3Np2 = sx_ns_qed[7] + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) + S1h = c.get(c.S1h, cache, N) + S2h = c.get(c.S2h, cache, N) + S3h = c.get(c.S3h, cache, N) + S1p1h = c.get(c.S1mh, cache, N) + S2p1h = c.get(c.S2mh, cache, N) + S3p1h = c.get(c.S3mh, cache, N) + g3N = c.get(c.g3, cache, N, is_singlet=False) + g3Np2 = c.get(c.g3p2, cache, N, is_singlet=False) result = ( -32.0 * zeta2 * S1h - 8.0 / (N + N**2) * S2h @@ -371,7 +380,7 @@ def gamma_nsm(N, sx, sx_ns_qed): @nb.njit(cache=True) -def gamma_singlet(N, nf, sx, sx_ns_qed): +def gamma_singlet(N, nf, cache): r"""Compute the :math:`O(a_s^1a_{em}^1)` singlet sector. Parameters @@ -380,21 +389,21 @@ def gamma_singlet(N, nf, sx, sx_ns_qed): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- gamma_singlet : numpy.ndarray - :math:`O(a_s^1a_{em}^1)` singlet anomalous dimension :math:`\\gamma_{S}^{(1,1)}(N,nf,sx)` + :math:`O(a_s^1a_{em}^1)` singlet anomalous dimension :math:`\\gamma_{S}^{(1,1)}(N,nf,cache)` """ e2avg, vue2m, vde2m, e2delta = constants.charge_combinations(nf) e2_tot = nf * e2avg - gamma_g_q = gamma_gq(N, sx) - gamma_ph_q = gamma_phq(N, sx) - gamma_q_g = gamma_qg(N, nf, sx) - gamma_q_ph = gamma_qph(N, nf, sx) - gamma_ns_p = gamma_nsp(N, sx, sx_ns_qed) + gamma_g_q = gamma_gq(N, cache) + gamma_ph_q = gamma_phq(N, cache) + gamma_q_g = gamma_qg(N, nf, cache) + gamma_q_ph = gamma_qph(N, nf, cache) + gamma_ns_p = gamma_nsp(N, cache) gamma_S_11 = np.array( [ [ @@ -428,7 +437,7 @@ def gamma_singlet(N, nf, sx, sx_ns_qed): @nb.njit(cache=True) -def gamma_valence(N, nf, sx, sx_ns_qed): +def gamma_valence(N, nf, cache): r"""Compute the :math:`O(a_s^1a_{em}^1)` valence sector. Parameters @@ -437,13 +446,13 @@ def gamma_valence(N, nf, sx, sx_ns_qed): Mellin moment nf : int Number of active flavors - sx : np array - List of harmonic sums + cache: numpy.ndarray + Harmonic sum cache Returns ------- gamma_singlet : numpy.ndarray - :math:`O(a_s^1a_{em}^1)` valence anomalous dimension :math:`\\gamma_{V}^{(1,1)}(N,nf,sx)` + :math:`O(a_s^1a_{em}^1)` valence anomalous dimension :math:`\\gamma_{V}^{(1,1)}(N,nf,cache)` """ e2avg, vue2m, vde2m, e2delta = constants.charge_combinations(nf) gamma_V_11 = np.array( @@ -453,4 +462,4 @@ def gamma_valence(N, nf, sx, sx_ns_qed): ], np.complex_, ) - return gamma_V_11 * gamma_nsm(N, sx, sx_ns_qed) + return gamma_V_11 * gamma_nsm(N, cache) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as2.py index e520bacdd..c5d76959e 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as2.py @@ -11,11 +11,11 @@ from eko import constants from eko.constants import log2, zeta2, zeta3 -from .... import harmonics +from ....harmonics import cache as c @nb.njit(cache=True) -def gamma_nsm(n, nf, sx): +def gamma_nsm(n, nf, cache): r"""Compute the |NLO| valence-like non-singlet anomalous dimension. Implements Eq. (3.5) of :cite:`Moch:2004pa`. @@ -26,25 +26,26 @@ def gamma_nsm(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsm : complex + complex |NLO| valence-like non-singlet anomalous dimension :math:`\\gamma_{ns,-}^{(1)}(N)` + """ - S1 = sx[0] - S2 = sx[1] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) # Here, Sp refers to S' ("s-prime") (german: "s-strich" or in Pegasus language: SSTR) # of :cite:`Gluck:1989ze` and NOT to the Spence function a.k.a. dilogarithm # TODO : these harmonic sums are computed also for the QED sector then we can use # the ones that are passed to the O(as1aem1) anomalous dimensions - Sp1m = harmonics.S1((n - 1) / 2) - Sp2m = harmonics.S2((n - 1) / 2) - Sp3m = harmonics.S3((n - 1) / 2) - g3n = harmonics.g_functions.mellin_g3(n, S1) + Sp1m = c.get(c.S1mh, cache, n) + Sp2m = c.get(c.S2mh, cache, n) + Sp3m = c.get(c.S3mh, cache, n) + g3n = c.get(c.g3, cache, n, is_singlet=False) # fmt: off gqq1m_cfca = 16*g3n - (144 + n*(1 + n)*(156 + n*(340 + n*(655 + 51*n*(2 + n)))))/(18.*np.power(n,3)*np.power(1 + n,3)) + (-14.666666666666666 + 8/n - 8/(1 + n))*S2 - (4*Sp2m)/(n + np.power(n,2)) + S1*(29.77777777777778 + 16/np.power(n,2) - 16*S2 + 8*Sp2m) + 2*Sp3m + 10*zeta3 + zeta2*(16*S1 - 16*Sp1m - (16*(1 + n*log2))/n) # pylint: disable=line-too-long gqq1m_cfcf = -32*g3n + (24 - n*(-32 + 3*n*(-8 + n*(3 + n)*(3 + np.power(n,2)))))/(2.*np.power(n,3)*np.power(1 + n,3)) + (12 - 8/n + 8/(1 + n))*S2 + S1*(-24/np.power(n,2) - 8/np.power(1 + n,2) + 16*S2 - 16*Sp2m) + (8*Sp2m)/(n + np.power(n,2)) - 4*Sp3m - 20*zeta3 + zeta2*(-32*S1 + 32*Sp1m + 32*(1/n + log2)) # pylint: disable=line-too-long @@ -59,7 +60,7 @@ def gamma_nsm(n, nf, sx): @nb.njit(cache=True) -def gamma_nsp(n, nf, sx): +def gamma_nsp(n, nf, cache): r"""Compute the |NLO| singlet-like non-singlet anomalous dimension. Implements Eq. (3.5) of :cite:`Moch:2004pa`. @@ -70,21 +71,23 @@ def gamma_nsp(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsp : complex + complex |NLO| singlet-like non-singlet anomalous dimension :math:`\\gamma_{ns,+}^{(1)}(N)` + """ - S1 = sx[0] - S2 = sx[1] - Sp1p = harmonics.S1(n / 2) - Sp2p = harmonics.S2(n / 2) - Sp3p = harmonics.S3(n / 2) - g3n = harmonics.g_functions.mellin_g3(n, S1) + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sp1p = c.get(c.S1h, cache, n) + Sp2p = c.get(c.S2h, cache, n) + Sp3p = c.get(c.S3h, cache, n) + # TODO: check is this True or False ? + g3n = c.get(c.g3, cache, n, is_singlet=False) # fmt: off gqq1p_cfca = -16*g3n + (132 - n*(340 + n*(655 + 51*n*(2 + n))))/(18.*np.power(n,2)*np.power(1 + n,2)) + (-14.666666666666666 + 8/n - 8/(1 + n))*S2 - (4*Sp2p)/(n + np.power(n,2)) + S1*(29.77777777777778 - 16/np.power(n,2) - 16*S2 + 8*Sp2p) + 2*Sp3p + 10*zeta3 + zeta2*(16*S1 - 16*Sp1p + 16*(1/n - log2)) # pylint: disable=line-too-long gqq1p_cfcf = 32*g3n - (8 + n*(32 + n*(40 + 3*n*(3 + n)*(3 + np.power(n,2)))))/(2.*np.power(n,3)*np.power(1 + n,3)) + (12 - 8/n + 8/(1 + n))*S2 + S1*(40/np.power(n,2) - 8/np.power(1 + n,2) + 16*S2 - 16*Sp2p) + (8*Sp2p)/(n + np.power(n,2)) - 4*Sp3p - 20*zeta3 + zeta2*(-32*S1 + 32*Sp1p + 32*(-(1/n) + log2)) # pylint: disable=line-too-long @@ -113,9 +116,10 @@ def gamma_ps(n, nf): Returns ------- - gamma_ps : complex + complex |NLO| pure-singlet quark-quark anomalous dimension :math:`\\gamma_{ps}^{(1)}(N)` + """ # fmt: off gqqps1_nfcf = (-4*(2 + n*(5 + n))*(4 + n*(4 + n*(7 + 5*n))))/((-1 + n)*np.power(n,3)*np.power(1 + n,3)*np.power(2 + n,2)) # pylint: disable=line-too-long @@ -125,7 +129,7 @@ def gamma_ps(n, nf): @nb.njit(cache=True) -def gamma_qg(n, nf, sx): +def gamma_qg(n, nf, cache): r"""Compute the |NLO| quark-gluon singlet anomalous dimension. Implements Eq. (3.7) of :cite:`Vogt:2004mw`. @@ -136,18 +140,19 @@ def gamma_qg(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_qg : complex + complex |NLO| quark-gluon singlet anomalous dimension :math:`\\gamma_{qg}^{(1)}(N)` + """ - S1 = sx[0] - S2 = sx[1] - Sp2p = harmonics.S2(n / 2) + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sp2p = c.get(c.S2h, cache, n) # fmt: off gqg1_nfca = (-4*(16 + n*(64 + n*(104 + n*(128 + n*(85 + n*(36 + n*(25 + n*(15 + n*(6 + n))))))))))/((-1 + n)*np.power(n,3)*np.power(1 + n,3)*np.power(2 + n,3)) - (16*(3 + 2*n)*S1)/np.power(2 + 3*n + np.power(n,2),2) + (4*(2 + n + np.power(n,2))*np.power(S1,2))/(n*(2 + 3*n + np.power(n,2))) - (4*(2 + n + np.power(n,2))*S2)/(n*(2 + 3*n + np.power(n,2))) + (4*(2 + n + np.power(n,2))*Sp2p)/(n*(2 + 3*n + np.power(n,2))) # pylint: disable=line-too-long gqg1_nfcf = (-2*(4 + n*(8 + n*(1 + n)*(25 + n*(26 + 5*n*(2 + n))))))/(np.power(n,3)*np.power(1 + n,3)*(2 + n)) + (8*S1)/np.power(n,2) - (4*(2 + n + np.power(n,2))*np.power(S1,2))/(n*(2 + 3*n + np.power(n,2))) + (4*(2 + n + np.power(n,2))*S2)/(n*(2 + 3*n + np.power(n,2))) # pylint: disable=line-too-long @@ -159,7 +164,7 @@ def gamma_qg(n, nf, sx): @nb.njit(cache=True) -def gamma_gq(n, nf, sx): +def gamma_gq(n, nf, cache): r"""Compute the |NLO| gluon-quark singlet anomalous dimension. Implements Eq. (3.8) of :cite:`Vogt:2004mw`. @@ -170,18 +175,19 @@ def gamma_gq(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gq : complex + complex |NLO| gluon-quark singlet anomalous dimension :math:`\\gamma_{gq}^{(1)}(N)` + """ - S1 = sx[0] - S2 = sx[1] - Sp2p = harmonics.S2(n / 2) + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sp2p = c.get(c.S2h, cache, n) # fmt: off ggq1_cfcf = (-8 + 2*n*(-12 + n*(-1 + n*(28 + n*(43 + 6*n*(5 + 2*n))))))/((-1 + n)*np.power(n,3)*np.power(1 + n,3)) - (4*(10 + n*(17 + n*(8 + 5*n)))*S1)/((-1 + n)*n*np.power(1 + n,2)) + (4*(2 + n + np.power(n,2))*np.power(S1,2))/(n*(-1 + np.power(n,2))) + (4*(2 + n + np.power(n,2))*S2)/(n*(-1 + np.power(n,2))) # pylint: disable=line-too-long ggq1_cfca = (-4*(144 + n*(432 + n*(-152 + n*(-1304 + n*(-1031 + n*(695 + n*(1678 + n*(1400 + n*(621 + 109*n))))))))))/(9.*np.power(n,3)*np.power(1 + n,3)*np.power(-2 + n + np.power(n,2),2)) + (4*(-12 + n*(-22 + 41*n + 17*np.power(n,3)))*S1)/(3.*np.power(-1 + n,2)*np.power(n,2)*(1 + n)) + ((8 + 4*n + 4*np.power(n,2))*np.power(S1,2))/(n - np.power(n,3)) + ((8 + 4*n + 4*np.power(n,2))*S2)/(n - np.power(n,3)) + (4*(2 + n + np.power(n,2))*Sp2p)/(n*(-1 + np.power(n,2))) # pylint: disable=line-too-long @@ -196,7 +202,7 @@ def gamma_gq(n, nf, sx): @nb.njit(cache=True) -def gamma_gg(n, nf, sx): +def gamma_gg(n, nf, cache): r"""Compute the |NLO| gluon-gluon singlet anomalous dimension. Implements Eq. (3.9) of :cite:`Vogt:2004mw`. @@ -207,20 +213,21 @@ def gamma_gg(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gg : complex + complex |NLO| gluon-gluon singlet anomalous dimension :math:`\\gamma_{gg}^{(1)}(N)` + """ - S1 = sx[0] - Sp1p = harmonics.S1(n / 2) - Sp2p = harmonics.S2(n / 2) - Sp3p = harmonics.S3(n / 2) - g3n = harmonics.g_functions.mellin_g3(n, S1) + S1 = c.get(c.S1, cache, n) + Sp1p = c.get(c.S1h, cache, n) + Sp2p = c.get(c.S2h, cache, n) + Sp3p = c.get(c.S3h, cache, n) + g3n = c.get(c.g3, cache, n, is_singlet=True) # fmt: off ggg1_caca = 16*g3n - (2*(576 + n*(1488 + n*(560 + n*(-1248 + n*(-1384 + n*(1663 + n*(4514 + n*(4744 + n*(3030 + n*(1225 + 48*n*(7 + n))))))))))))/(9.*np.power(-1 + n,2)*np.power(n,3)*np.power(1 + n,3)*np.power(2 + n,3)) + S1*(29.77777777777778 + 16/np.power(-1 + n,2) + 16/np.power(1 + n,2) - 16/np.power(2 + n,2) - 8*Sp2p) + (16*(1 + n + np.power(n,2))*Sp2p)/(n*(1 + n)*(-2 + n + np.power(n,2))) - 2*Sp3p - 10*zeta3 + zeta2*(-16*S1 + 16*Sp1p + 16*(-(1/n) + log2)) # pylint: disable=line-too-long ggg1_canf = (8*(6 + n*(1 + n)*(28 + n*(1 + n)*(13 + 3*n*(1 + n)))))/(9.*np.power(n,2)*np.power(1 + n,2)*(-2 + n + np.power(n,2))) - (40*S1)/9. # pylint: disable=line-too-long @@ -233,7 +240,7 @@ def gamma_gg(n, nf, sx): @nb.njit(cache=True) -def gamma_singlet(n, nf, sx): +def gamma_singlet(n, nf, cache): r"""Compute the next-leading-order singlet anomalous dimension matrix. .. math:: @@ -246,34 +253,30 @@ def gamma_singlet(n, nf, sx): ---------- N : complex Mellin moment - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache nf : int Number of active flavors Returns ------- - gamma_S_1 : numpy.ndarray + numpy.ndarray |NLO| singlet anomalous dimension matrix :math:`\\gamma_{S}^{(1)}(N)` - See Also - -------- - gamma_nsp : :math:`\\gamma_{qq}^{(1)}` - gamma_ps : :math:`\\gamma_{qq}^{(1)}` - gamma_qg : :math:`\\gamma_{qg}^{(1)}` - gamma_gq : :math:`\\gamma_{gq}^{(1)}` - gamma_gg : :math:`\\gamma_{gg}^{(1)}` """ - gamma_qq = gamma_nsp(n, nf, sx) + gamma_ps(n, nf) + gamma_qq = gamma_nsp(n, nf, cache) + gamma_ps(n, nf) gamma_S_0 = np.array( - [[gamma_qq, gamma_qg(n, nf, sx)], [gamma_gq(n, nf, sx), gamma_gg(n, nf, sx)]], + [ + [gamma_qq, gamma_qg(n, nf, cache)], + [gamma_gq(n, nf, cache), gamma_gg(n, nf, cache)], + ], np.complex_, ) return gamma_S_0 @nb.njit(cache=True) -def gamma_singlet_qed(N, nf, sx): +def gamma_singlet_qed(N, nf, cache): r"""Compute the leading-order singlet anomalous dimension matrix for the unified evolution basis. .. math:: @@ -290,28 +293,22 @@ def gamma_singlet_qed(N, nf, sx): Mellin moment nf : int Number of active flavors - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_S : numpy.ndarray + numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{S}^{(2,0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ - gamma_ns_p = gamma_nsp(N, nf, sx) + gamma_ns_p = gamma_nsp(N, nf, cache) gamma_qq = gamma_ns_p + gamma_ps(N, nf) gamma_S = np.array( [ - [gamma_gg(N, nf, sx), 0.0 + 0.0j, gamma_gq(N, nf, sx), 0.0 + 0.0j], + [gamma_gg(N, nf, cache), 0.0 + 0.0j, gamma_gq(N, nf, cache), 0.0 + 0.0j], [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], - [gamma_qg(N, nf, sx), 0.0 + 0.0j, gamma_qq, 0.0 + 0.0j], + [gamma_qg(N, nf, cache), 0.0 + 0.0j, gamma_qq, 0.0 + 0.0j], [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, gamma_ns_p], ], np.complex_, @@ -320,7 +317,7 @@ def gamma_singlet_qed(N, nf, sx): @nb.njit(cache=True) -def gamma_valence_qed(N, nf, sx): +def gamma_valence_qed(N, nf, cache): r"""Compute the leading-order valence anomalous dimension matrix for the unified evolution basis. .. math:: @@ -335,20 +332,14 @@ def gamma_valence_qed(N, nf, sx): Mellin moment nf : int Number of active flavors - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_V : numpy.ndarray + numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{V}^{(2,0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ gamma_V = np.array( [ @@ -357,4 +348,4 @@ def gamma_valence_qed(N, nf, sx): ], np.complex_, ) - return gamma_V * gamma_nsm(N, nf, sx) + return gamma_V * gamma_nsm(N, nf, cache) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as3.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as3.py index 9425e4efc..b9bbd356d 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as3.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as3.py @@ -10,9 +10,11 @@ from eko.constants import zeta2, zeta3 +from ....harmonics import cache as c + @nb.njit(cache=True) -def gamma_nsm(n, nf, sx): +def gamma_nsm(n, nf, cache): r"""Compute the |NNLO| valence-like non-singlet anomalous dimension. Implements Eq. (3.8) of :cite:`Moch:2004pa`. @@ -23,18 +25,19 @@ def gamma_nsm(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsm : complex + complex |NNLO| valence-like non-singlet anomalous dimension :math:`\\gamma_{ns,-}^{(2)}(N)` + """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) E1 = S1 / n**2 + (S2 - zeta2) / n E2 = 2.0 * (-S1 / n**3 + (zeta2 - S2) / n**2 - (S3 - zeta3) / n) @@ -88,7 +91,7 @@ def gamma_nsm(n, nf, sx): @nb.njit(cache=True) -def gamma_nsp(n, nf, sx): +def gamma_nsp(n, nf, cache): r"""Compute the |NNLO| singlet-like non-singlet anomalous dimension. Implements Eq. (3.7) of :cite:`Moch:2004pa`. @@ -99,18 +102,18 @@ def gamma_nsp(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsp : complex + complex |NNLO| singlet-like non-singlet anomalous dimension :math:`\\gamma_{ns,+}^{(2)}(N)` """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) E1 = S1 / n**2 + (S2 - zeta2) / n E2 = 2.0 * (-S1 / n**3 + (zeta2 - S2) / n**2 - (S3 - zeta3) / n) @@ -164,7 +167,7 @@ def gamma_nsp(n, nf, sx): @nb.njit(cache=True) -def gamma_nsv(n, nf, sx): +def gamma_nsv(n, nf, cache): r"""Compute the |NNLO| valence non-singlet anomalous dimension. Implements Eq. (3.9) of :cite:`Moch:2004pa`. @@ -175,18 +178,18 @@ def gamma_nsv(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsv : complex + complex |NNLO| valence non-singlet anomalous dimension :math:`\\gamma_{ns,v}^{(2)}(N)` """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) E1 = S1 / n**2 + (S2 - zeta2) / n E2 = 2.0 * (-S1 / n**3 + (zeta2 - S2) / n**2 - (S3 - zeta3) / n) @@ -213,12 +216,12 @@ def gamma_nsv(n, nf, sx): + 46.18 * E2 ) - result = gamma_nsm(n, nf, sx) + nf * ps2 + result = gamma_nsm(n, nf, cache) + nf * ps2 return result @nb.njit(cache=True) -def gamma_ps(n, nf, sx): +def gamma_ps(n, nf, cache): r"""Compute the |NNLO| pure-singlet quark-quark anomalous dimension. Implements Eq. (3.10) of :cite:`Vogt:2004mw`. @@ -229,18 +232,19 @@ def gamma_ps(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_ps : complex + complex |NNLO| pure-singlet quark-quark anomalous dimension :math:`\\gamma_{ps}^{(2)}(N)` + """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) E1 = S1 / n**2 + (S2 - zeta2) / n E11 = (S1 + 1.0 / (n + 1.0)) / (n + 1.0) ** 2 + ( @@ -289,7 +293,7 @@ def gamma_ps(n, nf, sx): @nb.njit(cache=True) -def gamma_qg(n, nf, sx): +def gamma_qg(n, nf, cache): r"""Compute the |NNLO| quark-gluon singlet anomalous dimension. Implements Eq. (3.11) of :cite:`Vogt:2004mw`. @@ -300,19 +304,20 @@ def gamma_qg(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_qg : complex + complex |NNLO| quark-gluon singlet anomalous dimension :math:`\\gamma_{qg}^{(2)}(N)` + """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] - S4 = sx[3] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) E1 = S1 / n**2 + (S2 - zeta2) / n E2 = 2.0 * (-S1 / n**3 + (zeta2 - S2) / n**2 - (S3 - zeta3) / n) @@ -362,7 +367,7 @@ def gamma_qg(n, nf, sx): @nb.njit(cache=True) -def gamma_gq(n, nf, sx): +def gamma_gq(n, nf, cache): r"""Compute the |NNLO| gluon-quark singlet anomalous dimension. Implements Eq. (3.12) of :cite:`Vogt:2004mw`. @@ -373,19 +378,20 @@ def gamma_gq(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gq : complex + complex |NNLO| gluon-quark singlet anomalous dimension :math:`\\gamma_{gq}^{(2)}(N)` + """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] - S4 = sx[3] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) E1 = S1 / n**2 + (S2 - zeta2) / n E2 = 2.0 * (-S1 / n**3 + (zeta2 - S2) / n**2 - (S3 - zeta3) / n) @@ -451,7 +457,7 @@ def gamma_gq(n, nf, sx): @nb.njit(cache=True) -def gamma_gg(n, nf, sx): +def gamma_gg(n, nf, cache): r"""Compute the |NNLO| gluon-gluon singlet anomalous dimension. Implements Eq. (3.13) of :cite:`Vogt:2004mw`. @@ -462,18 +468,19 @@ def gamma_gg(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gg : complex + complex |NNLO| gluon-gluon singlet anomalous dimension :math:`\\gamma_{gg}^{(2)}(N)` + """ - S1 = sx[0] - S2 = sx[1] - S3 = sx[2] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) E1 = S1 / n**2 + (S2 - zeta2) / n E11 = (S1 + 1.0 / (n + 1.0)) / (n + 1.0) ** 2 + ( @@ -538,7 +545,7 @@ def gamma_gg(n, nf, sx): @nb.njit(cache=True) -def gamma_singlet(N, nf, sx): +def gamma_singlet(N, nf, cache): r"""Compute the |NNLO| singlet anomalous dimension matrix. .. math:: @@ -553,34 +560,30 @@ def gamma_singlet(N, nf, sx): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_S_2 : numpy.ndarray + numpy.ndarray |NNLO| singlet anomalous dimension matrix :math:`\\gamma_{S}^{(2)}(N)` - See Also - -------- - gamma_nsp : :math:`\\gamma_{ns,+}^{(2)}` - gamma_ps : :math:`\\gamma_{ps}^{(2)}` - gamma_qg : :math:`\\gamma_{qg}^{(2)}` - gamma_gq : :math:`\\gamma_{gq}^{(2)}` - gamma_gg : :math:`\\gamma_{gg}^{(2)}` """ - gamma_qq = gamma_nsp(N, nf, sx) + gamma_ps(N, nf, sx) + gamma_qq = gamma_nsp(N, nf, cache) + gamma_ps(N, nf, cache) gamma_S_0 = np.array( - [[gamma_qq, gamma_qg(N, nf, sx)], [gamma_gq(N, nf, sx), gamma_gg(N, nf, sx)]], + [ + [gamma_qq, gamma_qg(N, nf, cache)], + [gamma_gq(N, nf, cache), gamma_gg(N, nf, cache)], + ], np.complex_, ) return gamma_S_0 @nb.njit(cache=True) -def gamma_singlet_qed(N, nf, sx): +def gamma_singlet_qed(N, nf, cache): r"""Compute the leading-order singlet anomalous dimension matrix for the unified evolution basis. .. math:: @@ -597,28 +600,22 @@ def gamma_singlet_qed(N, nf, sx): Mellin moment nf : int Number of active flavors - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_S : numpy.ndarray + numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{S}^{(3,0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ - gamma_np_p = gamma_nsp(N, nf, sx) - gamma_qq = gamma_np_p + gamma_ps(N, nf, sx) + gamma_np_p = gamma_nsp(N, nf, cache) + gamma_qq = gamma_np_p + gamma_ps(N, nf, cache) gamma_S = np.array( [ - [gamma_gg(N, nf, sx), 0.0 + 0.0j, gamma_gq(N, nf, sx), 0.0 + 0.0j], + [gamma_gg(N, nf, cache), 0.0 + 0.0j, gamma_gq(N, nf, cache), 0.0 + 0.0j], [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], - [gamma_qg(N, nf, sx), 0.0 + 0.0j, gamma_qq, 0.0 + 0.0j], + [gamma_qg(N, nf, cache), 0.0 + 0.0j, gamma_qq, 0.0 + 0.0j], [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, gamma_np_p], ], np.complex_, @@ -627,7 +624,7 @@ def gamma_singlet_qed(N, nf, sx): @nb.njit(cache=True) -def gamma_valence_qed(N, nf, sx): +def gamma_valence_qed(N, nf, cache): r"""Compute the leading-order valence anomalous dimension matrix for the unified evolution basis. .. math:: @@ -642,25 +639,19 @@ def gamma_valence_qed(N, nf, sx): Mellin moment nf : int Number of active flavors - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_V : numpy.ndarray + numpy.ndarray Leading-order singlet anomalous dimension matrix :math:`\\gamma_{V}^{(3,0)}(N)` - See Also - -------- - gamma_ns : :math:`\\gamma_{qq}^{(0)}` - gamma_qg : :math:`\\gamma_{qg}^{(0)}` - gamma_gq : :math:`\\gamma_{gq}^{(0)}` - gamma_gg : :math:`\\gamma_{gg}^{(0)}` """ gamma_V = np.array( [ - [gamma_nsv(N, nf, sx), 0.0], - [0.0, gamma_nsm(N, nf, sx)], + [gamma_nsv(N, nf, cache), 0.0], + [0.0, gamma_nsm(N, nf, cache)], ], np.complex_, ) diff --git a/src/ekore/harmonics/cache.py b/src/ekore/harmonics/cache.py index be6d808a6..56d9ba005 100644 --- a/src/ekore/harmonics/cache.py +++ b/src/ekore/harmonics/cache.py @@ -54,7 +54,7 @@ def reset(): @nb.njit(cache=True) -def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet: bool) -> complex: +def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet=None) -> complex: r"""Retrieve an element of the cache. Parameters From c873a4f33ac4e8b15a71054d3cd9ed40d7e64530 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 10:26:06 +0200 Subject: [PATCH 05/24] fixes on docsrtings --- .../polarized/space_like/as1.py | 8 ++++---- .../polarized/space_like/as2.py | 16 +++++++-------- .../polarized/space_like/as3.py | 20 +++++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as1.py b/src/ekore/anomalous_dimensions/polarized/space_like/as1.py index 527fbfc77..47f6d8a28 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as1.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as1.py @@ -59,8 +59,8 @@ def gamma_gg(N, cache, nf): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache nf : int Number of active flavors @@ -90,8 +90,8 @@ def gamma_singlet(N, cache, nf): ---------- N : complex Mellin moment - s1 : complex - harmonic sum :math:`S_{1}` + cache: numpy.ndarray + Harmonic sum cache nf : int Number of active flavors diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as2.py b/src/ekore/anomalous_dimensions/polarized/space_like/as2.py index a7f42b0e8..27778eb0e 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as2.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as2.py @@ -44,8 +44,8 @@ def gamma_qg(n, nf, cache): Mellin moment nf : int number of active flavors - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -83,8 +83,8 @@ def gamma_gq(n, nf, cache): Mellin moment nf : int number of active flavors - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -125,8 +125,8 @@ def gamma_gg(n, nf, cache): Mellin moment nf : int number of active flavors - sx : numpy.ndarray - List of harmonic sums: :math:`S_{1},S_{2}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -189,8 +189,8 @@ def gamma_singlet(n, nf, cache): Mellin moment nf : int Number of active flavors - sx: list - harmonics cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py index 77e890f1b..e31e164ef 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py @@ -24,8 +24,8 @@ def gamma_gg(N, nf, cache): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3},S_{4}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -101,8 +101,8 @@ def gamma_qg(N, nf, cache): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3},S_{4}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -167,8 +167,8 @@ def gamma_gq(N, nf, cache): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3},S_{4}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -246,8 +246,8 @@ def gamma_ps(N, nf, cache): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3},S_{4}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -339,8 +339,8 @@ def gamma_nss(N, nf, cache): Mellin moment nf : int Number of active flavors - sx : np.ndarray - List of harmonic sums: :math:`S_{1},S_{2},S_{3},S_{4}` + cache: numpy.ndarray + Harmonic sum cache Returns ------- From 06c7b868b7eec2fb720e276fdf017658ef7fd091 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 11:24:40 +0200 Subject: [PATCH 06/24] more work on ads --- .../polarized/space_like/as2.py | 2 +- .../unpolarized/space_like/aem1.py | 3 +- .../unpolarized/space_like/aem2.py | 20 ++--- .../unpolarized/space_like/as1aem1.py | 29 ++++--- .../unpolarized/space_like/as2.py | 7 +- src/ekore/harmonics/cache.py | 86 +++++++++---------- .../unpolarized/space_like/test_aem1.py | 8 +- .../unpolarized/space_like/test_aem2.py | 28 +++--- .../unpolarized/space_like/test_as1.py | 18 ++-- .../unpolarized/space_like/test_as1aem1.py | 29 ++++--- .../unpolarized/space_like/test_as2.py | 26 +++--- .../unpolarized/space_like/test_as3.py | 12 +-- .../unpolarized/space_like/test_as4.py | 16 ++-- .../unpolarized/space_like/test_init.py | 32 +++---- 14 files changed, 154 insertions(+), 162 deletions(-) diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as2.py b/src/ekore/anomalous_dimensions/polarized/space_like/as2.py index 27778eb0e..95134d7ae 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as2.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as2.py @@ -139,7 +139,7 @@ def gamma_gg(n, nf, cache): Sp2m = c.get(c.S2mh, cache, n) Sp3m = c.get(c.S3mh, cache, n) S1h = c.get(c.S1h, cache, n) - g3 = c.get(c.g3, cache, n, is_singlet=True) + g3 = c.get(c.g3, cache, n) SSCHLM = zeta2 / 2 * (+Sp1m - S1h + 2 / n) - S1 / n**2 - g3 - 5 * zeta3 / 8 ggg1_caca = ( -4 * S1 * Sp2m diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/aem1.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/aem1.py index 6892ba56d..33cfc751f 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/aem1.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/aem1.py @@ -94,8 +94,7 @@ def gamma_ns(N, cache): Leading-order non-singlet QED anomalous dimension :math:`\\gamma_{ns}^{(0,1)}(N)` """ - S1 = c.get(c.S1, N, cache) - return as1.gamma_ns(N, S1) / constants.CF + return as1.gamma_ns(N, cache) / constants.CF @nb.njit(cache=True) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/aem2.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/aem2.py index 824e47b7e..9c3d3ca7e 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/aem2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/aem2.py @@ -24,7 +24,7 @@ def gamma_phph(N, nf): Returns ------- - gamma_gg : complex + complex :math:`O(a_{em}^2)` photon-photon singlet anomalous dimension :math:`\\gamma_{\\gamma \\gamma}^{(0,2)}(N)` @@ -55,7 +55,7 @@ def gamma_uph(N, nf, cache): Returns ------- - gamma_uph : complex + complex :math:`O(a_{em}^2)` quark-photon anomalous dimension :math:`\\gamma_{u \\gamma}^{(0,2)}(N)` """ @@ -79,7 +79,7 @@ def gamma_dph(N, nf, cache): Returns ------- - gamma_dph : complex + complex :math:`O(a_{em}^2)` quark-photon anomalous dimension :math:`\\gamma_{d \\gamma}^{(0,2)}(N)` """ @@ -103,7 +103,7 @@ def gamma_phu(N, nf, cache): Returns ------- - gamma_phu : complex + complex :math:`O(a_{em}^2)` photon-quark anomalous dimension :math:`\\gamma_{\\gamma u}^{(0,2)}(N)` """ @@ -136,7 +136,7 @@ def gamma_phd(N, nf, cache): Returns ------- - gamma_phd : complex + complex :math:`O(a_{em}^2)` photon-quark anomalous dimension :math:`\\gamma_{\\gamma d}^{(0,2)}(N)` """ @@ -169,7 +169,7 @@ def gamma_nspu(N, nf, cache): Returns ------- - gamma_nspu : complex + complex :math:`O(a_{em}^2)` singlet-like non-singlet anomalous dimension :math:`\\gamma_{ns,+,u}^{(0,2)}(N)` @@ -206,7 +206,7 @@ def gamma_nspd(N, nf, cache): Returns ------- - gamma_nspd : complex + complex :math:`O(a_{em}^2)` singlet-like non-singlet anomalous dimension :math:`\\gamma_{ns,+,d}^{(0,2)}(N)` @@ -243,7 +243,7 @@ def gamma_nsmu(N, nf, cache): Returns ------- - gamma_nsp : complex + complex :math:`O(a_{em}^2)` valence-like non-singlet anomalous dimension :math:`\\gamma_{ns,-,u}^{(0,2)}(N)` @@ -280,7 +280,7 @@ def gamma_nsmd(N, nf, cache): Returns ------- - gamma_nsp : complex + complex :math:`O(a_{em}^2)` valence-like non-singlet anomalous dimension :math:`\\gamma_{ns,-,d}^{(0,2)}(N)` @@ -315,7 +315,7 @@ def gamma_ps(N, nf): Returns ------- - gamma_ps : complex + complex :math:`O(a_{em}^2)` pure-singlet quark-quark anomalous dimension :math:`\\gamma_{ps}^{(0,2)}(N)` diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as1aem1.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as1aem1.py index 83e18c2bd..58e9fcd97 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as1aem1.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as1aem1.py @@ -274,12 +274,11 @@ def gamma_nsp(N, cache): S1h = c.get(c.S1h, cache, N) S2h = c.get(c.S2h, cache, N) S3h = c.get(c.S3h, cache, N) - S1p1h = c.get(c.S1mh, cache, N) - S2p1h = c.get(c.S2mh, cache, N) - S3p1h = c.get(c.S3mh, cache, N) - # TODO: CHECK is this True or False?? - g3N = c.get(c.g3, cache, N, is_singlet=False) - g3Np2 = c.get(c.g3p2, cache, N, is_singlet=False) + S1p1h = c.get(c.S1ph, cache, N) + S2p1h = c.get(c.S2ph, cache, N) + S3p1h = c.get(c.S3ph, cache, N) + g3N = c.get(c.g3, cache, N) + g3Np2 = c.get(c.g3p2, cache, N) result = ( +32.0 * zeta2 * S1h - 32.0 * zeta2 * S1p1h @@ -331,7 +330,7 @@ def gamma_nsm(N, cache): Returns ------- - gamma_nsm : complex + complex :math:`O(a_s^1a_{em}^1)` singlet-like non-singlet anomalous dimension :math:`\\gamma_{ns,-}^{(1,1)}(N)` @@ -342,11 +341,11 @@ def gamma_nsm(N, cache): S1h = c.get(c.S1h, cache, N) S2h = c.get(c.S2h, cache, N) S3h = c.get(c.S3h, cache, N) - S1p1h = c.get(c.S1mh, cache, N) - S2p1h = c.get(c.S2mh, cache, N) - S3p1h = c.get(c.S3mh, cache, N) - g3N = c.get(c.g3, cache, N, is_singlet=False) - g3Np2 = c.get(c.g3p2, cache, N, is_singlet=False) + S1p1h = c.get(c.S1ph, cache, N) + S2p1h = c.get(c.S2ph, cache, N) + S3p1h = c.get(c.S3ph, cache, N) + g3N = c.get(c.g3, cache, N) + g3Np2 = c.get(c.g3p2, cache, N) result = ( -32.0 * zeta2 * S1h - 8.0 / (N + N**2) * S2h @@ -394,8 +393,9 @@ def gamma_singlet(N, nf, cache): Returns ------- - gamma_singlet : numpy.ndarray + numpy.ndarray :math:`O(a_s^1a_{em}^1)` singlet anomalous dimension :math:`\\gamma_{S}^{(1,1)}(N,nf,cache)` + """ e2avg, vue2m, vde2m, e2delta = constants.charge_combinations(nf) e2_tot = nf * e2avg @@ -451,8 +451,9 @@ def gamma_valence(N, nf, cache): Returns ------- - gamma_singlet : numpy.ndarray + numpy.ndarray :math:`O(a_s^1a_{em}^1)` valence anomalous dimension :math:`\\gamma_{V}^{(1,1)}(N,nf,cache)` + """ e2avg, vue2m, vde2m, e2delta = constants.charge_combinations(nf) gamma_V_11 = np.array( diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as2.py index c5d76959e..01a115c5b 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as2.py @@ -45,7 +45,7 @@ def gamma_nsm(n, nf, cache): Sp1m = c.get(c.S1mh, cache, n) Sp2m = c.get(c.S2mh, cache, n) Sp3m = c.get(c.S3mh, cache, n) - g3n = c.get(c.g3, cache, n, is_singlet=False) + g3n = c.get(c.g3, cache, n) # fmt: off gqq1m_cfca = 16*g3n - (144 + n*(1 + n)*(156 + n*(340 + n*(655 + 51*n*(2 + n)))))/(18.*np.power(n,3)*np.power(1 + n,3)) + (-14.666666666666666 + 8/n - 8/(1 + n))*S2 - (4*Sp2m)/(n + np.power(n,2)) + S1*(29.77777777777778 + 16/np.power(n,2) - 16*S2 + 8*Sp2m) + 2*Sp3m + 10*zeta3 + zeta2*(16*S1 - 16*Sp1m - (16*(1 + n*log2))/n) # pylint: disable=line-too-long gqq1m_cfcf = -32*g3n + (24 - n*(-32 + 3*n*(-8 + n*(3 + n)*(3 + np.power(n,2)))))/(2.*np.power(n,3)*np.power(1 + n,3)) + (12 - 8/n + 8/(1 + n))*S2 + S1*(-24/np.power(n,2) - 8/np.power(1 + n,2) + 16*S2 - 16*Sp2m) + (8*Sp2m)/(n + np.power(n,2)) - 4*Sp3m - 20*zeta3 + zeta2*(-32*S1 + 32*Sp1m + 32*(1/n + log2)) # pylint: disable=line-too-long @@ -86,8 +86,7 @@ def gamma_nsp(n, nf, cache): Sp1p = c.get(c.S1h, cache, n) Sp2p = c.get(c.S2h, cache, n) Sp3p = c.get(c.S3h, cache, n) - # TODO: check is this True or False ? - g3n = c.get(c.g3, cache, n, is_singlet=False) + g3n = c.get(c.g3, cache, n) # fmt: off gqq1p_cfca = -16*g3n + (132 - n*(340 + n*(655 + 51*n*(2 + n))))/(18.*np.power(n,2)*np.power(1 + n,2)) + (-14.666666666666666 + 8/n - 8/(1 + n))*S2 - (4*Sp2p)/(n + np.power(n,2)) + S1*(29.77777777777778 - 16/np.power(n,2) - 16*S2 + 8*Sp2p) + 2*Sp3p + 10*zeta3 + zeta2*(16*S1 - 16*Sp1p + 16*(1/n - log2)) # pylint: disable=line-too-long gqq1p_cfcf = 32*g3n - (8 + n*(32 + n*(40 + 3*n*(3 + n)*(3 + np.power(n,2)))))/(2.*np.power(n,3)*np.power(1 + n,3)) + (12 - 8/n + 8/(1 + n))*S2 + S1*(40/np.power(n,2) - 8/np.power(1 + n,2) + 16*S2 - 16*Sp2p) + (8*Sp2p)/(n + np.power(n,2)) - 4*Sp3p - 20*zeta3 + zeta2*(-32*S1 + 32*Sp1p + 32*(-(1/n) + log2)) # pylint: disable=line-too-long @@ -227,7 +226,7 @@ def gamma_gg(n, nf, cache): Sp1p = c.get(c.S1h, cache, n) Sp2p = c.get(c.S2h, cache, n) Sp3p = c.get(c.S3h, cache, n) - g3n = c.get(c.g3, cache, n, is_singlet=True) + g3n = c.get(c.g3, cache, n) # fmt: off ggg1_caca = 16*g3n - (2*(576 + n*(1488 + n*(560 + n*(-1248 + n*(-1384 + n*(1663 + n*(4514 + n*(4744 + n*(3030 + n*(1225 + 48*n*(7 + n))))))))))))/(9.*np.power(-1 + n,2)*np.power(n,3)*np.power(1 + n,3)*np.power(2 + n,3)) + S1*(29.77777777777778 + 16/np.power(-1 + n,2) + 16/np.power(1 + n,2) - 16/np.power(2 + n,2) - 8*Sp2p) + (16*(1 + n + np.power(n,2))*Sp2p)/(n*(1 + n)*(-2 + n + np.power(n,2))) - 2*Sp3p - 10*zeta3 + zeta2*(-16*S1 + 16*Sp1p + 16*(-(1/n) + log2)) # pylint: disable=line-too-long ggg1_canf = (8*(6 + n*(1 + n)*(28 + n*(1 + n)*(13 + 3*n*(1 + n)))))/(9.*np.power(n,2)*np.power(1 + n,2)*(-2 + n + np.power(n,2))) - (40*S1)/9. # pylint: disable=line-too-long diff --git a/src/ekore/harmonics/cache.py b/src/ekore/harmonics/cache.py index 56d9ba005..1efe73f61 100644 --- a/src/ekore/harmonics/cache.py +++ b/src/ekore/harmonics/cache.py @@ -99,76 +99,74 @@ def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet=None) -> complex: elif key == Sm1: s = w1.Sm1( n, - get(S1, cache, n, is_singlet), - get(S1mh, cache, n, is_singlet), - get(S1h, cache, n, is_singlet), + get(S1, cache, n), + get(S1mh, cache, n), + get(S1h, cache, n), is_singlet, ) elif key == Sm2: s = w2.Sm2( n, - get(S2, cache, n, is_singlet), - get(S2mh, cache, n, is_singlet), - get(S2h, cache, n, is_singlet), + get(S2, cache, n), + get(S2mh, cache, n), + get(S2h, cache, n), is_singlet, ) elif key == Sm3: s = w3.Sm3( n, - get(S3, cache, n, is_singlet), - get(S3mh, cache, n, is_singlet), - get(S3h, cache, n, is_singlet), + get(S3, cache, n), + get(S3mh, cache, n), + get(S3h, cache, n), is_singlet, ) elif key == Sm4: s = w4.Sm4( n, - get(S4, cache, n, is_singlet), - get(S4mh, cache, n, is_singlet), - get(S4h, cache, n, is_singlet), + get(S4, cache, n), + get(S4mh, cache, n), + get(S4h, cache, n), is_singlet, ) elif key == Sm5: s = w5.Sm5( n, - get(S5, cache, n, is_singlet), - get(S5mh, cache, n, is_singlet), - get(S5h, cache, n, is_singlet), + get(S5, cache, n), + get(S5mh, cache, n), + get(S5h, cache, n), is_singlet, ) elif key == S21: - s = w3.S21(n, get(S1, cache, n, is_singlet), get(S2, cache, n, is_singlet)) + s = w3.S21(n, get(S1, cache, n), get(S2, cache, n)) elif key == S2m1: s = w3.S2m1( n, - get(S2, cache, n, is_singlet), + get(S2, cache, n), get(Sm1, cache, n, is_singlet), get(Sm2, cache, n, is_singlet), is_singlet, ) elif key == Sm21: - s = w3.Sm21( - n, get(S1, cache, n, is_singlet), get(Sm1, cache, n, is_singlet), is_singlet - ) + s = w3.Sm21(n, get(S1, cache, n), get(Sm1, cache, n, is_singlet), is_singlet) elif key == Sm2m1: s = w3.Sm2m1( n, - get(S1, cache, n, is_singlet), - get(S2, cache, n, is_singlet), + get(S1, cache, n), + get(S2, cache, n), get(Sm2, cache, n, is_singlet), ) elif key == S31: s = w4.S31( n, - get(S1, cache, n, is_singlet), - get(S2, cache, n, is_singlet), - get(S3, cache, n, is_singlet), - get(S4, cache, n, is_singlet), + get(S1, cache, n), + get(S2, cache, n), + get(S3, cache, n), + get(S4, cache, n), ) elif key == Sm31: s = w4.Sm31( n, - get(S1, cache, n, is_singlet), + get(S1, cache, n), get(Sm1, cache, n, is_singlet), get(Sm2, cache, n, is_singlet), is_singlet, @@ -176,8 +174,8 @@ def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet=None) -> complex: elif key == Sm22: s = w4.Sm22( n, - get(S1, cache, n, is_singlet), - get(S2, cache, n, is_singlet), + get(S1, cache, n), + get(S2, cache, n), get(Sm2, cache, n, is_singlet), get(Sm31, cache, n, is_singlet), is_singlet, @@ -185,16 +183,16 @@ def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet=None) -> complex: elif key == S211: s = w4.S211( n, - get(S1, cache, n, is_singlet), - get(S2, cache, n, is_singlet), - get(S3, cache, n, is_singlet), + get(S1, cache, n), + get(S2, cache, n), + get(S3, cache, n), ) elif key == Sm211: s = w4.Sm211( n, - get(S1, cache, n, is_singlet), - get(S2, cache, n, is_singlet), - get(Sm1, cache, n, is_singlet), + get(S1, cache, n), + get(S2, cache, n), + get(Sm1, cache, n), is_singlet, ) elif key == S1h: @@ -218,21 +216,21 @@ def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet=None) -> complex: elif key == S5mh: s = w5.S5((n - 1) / 2) elif key == S1ph: - s = recursive_harmonic_sum(get(S1mh, cache, n, is_singlet), (n - 1) / 2, 1, 1) + s = recursive_harmonic_sum(get(S1mh, cache, n), (n - 1) / 2, 1, 1) elif key == S2ph: - s = recursive_harmonic_sum(get(S2mh, cache, n, is_singlet), (n - 1) / 2, 1, 2) + s = recursive_harmonic_sum(get(S2mh, cache, n), (n - 1) / 2, 1, 2) elif key == S3ph: - s = recursive_harmonic_sum(get(S3mh, cache, n, is_singlet), (n - 1) / 2, 1, 3) + s = recursive_harmonic_sum(get(S3mh, cache, n), (n - 1) / 2, 1, 3) elif key == S4ph: - s = recursive_harmonic_sum(get(S4mh, cache, n, is_singlet), (n - 1) / 2, 1, 4) + s = recursive_harmonic_sum(get(S4mh, cache, n), (n - 1) / 2, 1, 4) elif key == S5ph: - s = recursive_harmonic_sum(get(S5mh, cache, n, is_singlet), (n - 1) / 2, 1, 5) + s = recursive_harmonic_sum(get(S5mh, cache, n), (n - 1) / 2, 1, 5) elif key == g3: - s = mellin_g3(n, get(S1, cache, n, is_singlet)) + s = mellin_g3(n, get(S1, cache, n)) elif key == S1p2: - s = recursive_harmonic_sum(get(S1, cache, n, is_singlet), n, 2, 1) + s = recursive_harmonic_sum(get(S1, cache, n), n, 2, 1) elif key == g3p2: - s = mellin_g3(n + 2, get(S1p2, cache, n, is_singlet)) - # # store and return + s = mellin_g3(n + 2, get(S1p2, cache, n)) + # store and return cache[key] = s return s diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_aem1.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_aem1.py index d114ff5df..e339a272a 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_aem1.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_aem1.py @@ -9,16 +9,16 @@ def test_number_conservation(): # number N = complex(1.0, 0.0) - sx = h.sx(N, max_weight=1) - np.testing.assert_almost_equal(ad_us.aem1.gamma_ns(N, sx), 0) + cache = h.cache.reset() + np.testing.assert_almost_equal(ad_us.aem1.gamma_ns(N, cache), 0) def test_quark_momentum_conservation(): # quark momentum N = complex(2.0, 0.0) - sx = h.sx(N, max_weight=1) + cache = h.cache.reset() np.testing.assert_almost_equal( - ad_us.aem1.gamma_ns(N, sx) + ad_us.aem1.gamma_phq(N), + ad_us.aem1.gamma_ns(N, cache) + ad_us.aem1.gamma_phq(N), 0, ) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_aem2.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_aem2.py index 8845e8bb6..b82f3e46b 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_aem2.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_aem2.py @@ -9,27 +9,22 @@ def test_number_conservation(): # number N = complex(1.0, 0.0) - sx = h.sx(N, 3) - sx_ns_qed = h.compute_qed_ns_cache(N, sx[0]) + cache = h.cache.reset() for NF in range(2, 6 + 1): - np.testing.assert_almost_equal( - ad.aem2.gamma_nsmu(N, NF, sx, sx_ns_qed), 0, decimal=4 - ) - np.testing.assert_almost_equal( - ad.aem2.gamma_nsmd(N, NF, sx, sx_ns_qed), 0, decimal=4 - ) + np.testing.assert_almost_equal(ad.aem2.gamma_nsmu(N, NF, cache), 0, decimal=4) + np.testing.assert_almost_equal(ad.aem2.gamma_nsmd(N, NF, cache), 0, decimal=4) def test_photon_momentum_conservation(): # photon momentum N = complex(2.0, 0.0) - sx = h.sx(N, 2) + cache = h.cache.reset() for NF in range(2, 6 + 1): NU = constants.uplike_flavors(NF) ND = NF - NU np.testing.assert_almost_equal( - constants.eu2 * ad.aem2.gamma_uph(N, NU, sx) - + constants.ed2 * ad.aem2.gamma_dph(N, ND, sx) + constants.eu2 * ad.aem2.gamma_uph(N, NU, cache) + + constants.ed2 * ad.aem2.gamma_dph(N, ND, cache) + ad.aem2.gamma_phph(N, NF), 0, ) @@ -38,24 +33,23 @@ def test_photon_momentum_conservation(): def test_quark_momentum_conservation(): # quark momentum N = complex(2.0, 0.0) - sx = h.sx(N, 3) - sx_ns_qed = h.compute_qed_ns_cache(N, sx[0]) + cache = h.cache.reset() NF = 6 NU = constants.uplike_flavors(NF) ND = NF - NU np.testing.assert_almost_equal( - ad.aem2.gamma_nspu(N, NF, sx, sx_ns_qed) + ad.aem2.gamma_nspu(N, NF, cache) + constants.eu2 * ad.aem2.gamma_ps(N, NU) + constants.ed2 * ad.aem2.gamma_ps(N, ND) - + ad.aem2.gamma_phu(N, NF, sx), + + ad.aem2.gamma_phu(N, NF, cache), 0, decimal=4, ) np.testing.assert_almost_equal( - ad.aem2.gamma_nspd(N, NF, sx, sx_ns_qed) + ad.aem2.gamma_nspd(N, NF, cache) + constants.eu2 * ad.aem2.gamma_ps(N, NU) + constants.ed2 * ad.aem2.gamma_ps(N, ND) - + ad.aem2.gamma_phd(N, NF, sx), + + ad.aem2.gamma_phd(N, NF, cache), 0, decimal=4, ) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as1.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as1.py index 23cd67d50..126fd2760 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as1.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as1.py @@ -2,7 +2,7 @@ import numpy as np import ekore.anomalous_dimensions.unpolarized.space_like.as1 as ad_as1 -from ekore import harmonics +from ekore import harmonics as h NF = 5 @@ -10,16 +10,16 @@ def test_number_conservation(): # number N = complex(1.0, 0.0) - s1 = harmonics.S1(N) - np.testing.assert_almost_equal(ad_as1.gamma_ns(N, s1), 0) + cache = h.cache.reset() + np.testing.assert_almost_equal(ad_as1.gamma_ns(N, cache), 0) def test_quark_momentum_conservation(): # quark momentum N = complex(2.0, 0.0) - s1 = harmonics.S1(N) + cache = h.cache.reset() np.testing.assert_almost_equal( - ad_as1.gamma_ns(N, s1) + ad_as1.gamma_gq(N), + ad_as1.gamma_ns(N, cache) + ad_as1.gamma_gq(N), 0, ) @@ -27,9 +27,9 @@ def test_quark_momentum_conservation(): def test_gluon_momentum_conservation(): # gluon momentum N = complex(2.0, 0.0) - s1 = harmonics.S1(N) + cache = h.cache.reset() np.testing.assert_almost_equal( - ad_as1.gamma_qg(N, NF) + ad_as1.gamma_gg(N, s1, NF), 0 + ad_as1.gamma_qg(N, NF) + ad_as1.gamma_gg(N, cache, NF), 0 ) @@ -47,6 +47,6 @@ def test_gamma_gq_0(): def test_gamma_gg_0(): N = complex(0.0, 1.0) - s1 = harmonics.S1(N) + cache = h.cache.reset() res = complex(5.195725159621, 10.52008856962) - np.testing.assert_almost_equal(ad_as1.gamma_gg(N, s1, NF), res) + np.testing.assert_almost_equal(ad_as1.gamma_gg(N, cache, NF), res) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as1aem1.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as1aem1.py index 525ba24a9..0fa8a9059 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as1aem1.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as1aem1.py @@ -10,21 +10,20 @@ def test_number_conservation(): # number N = complex(1.0, 0.0) - sx = h.sx(N, 3) - sx_ns_qed = h.compute_qed_ns_cache(N, sx[0]) - np.testing.assert_almost_equal(ad.as1aem1.gamma_nsm(N, sx, sx_ns_qed), 0, decimal=4) + cache = h.cache.reset() + np.testing.assert_almost_equal(ad.as1aem1.gamma_nsm(N, cache), 0, decimal=4) def test_gluon_momentum_conservation(): # gluon momentum N = complex(2.0, 0.0) - sx = h.sx(N, 2) + cache = h.cache.reset() for NF in range(2, 6 + 1): NU = constants.uplike_flavors(NF) ND = NF - NU np.testing.assert_almost_equal( - constants.eu2 * ad.as1aem1.gamma_qg(N, NU, sx) - + constants.ed2 * ad.as1aem1.gamma_qg(N, ND, sx) + constants.eu2 * ad.as1aem1.gamma_qg(N, NU, cache) + + constants.ed2 * ad.as1aem1.gamma_qg(N, ND, cache) + (NU * constants.eu2 + ND * constants.ed2) * ad.as1aem1.gamma_phg(N) + (NU * constants.eu2 + ND * constants.ed2) * ad.as1aem1.gamma_gg(), 0, @@ -36,13 +35,13 @@ def test_gluon_momentum_conservation(): def test_photon_momentum_conservation(): # photon momentum N = complex(2.0, 0.0) - sx = h.sx(N, 2) + cache = h.cache.reset() for NF in range(2, 6 + 1): NU = constants.uplike_flavors(NF) ND = NF - NU np.testing.assert_almost_equal( - constants.eu2 * ad.as1aem1.gamma_qph(N, NU, sx) - + constants.ed2 * ad.as1aem1.gamma_qph(N, ND, sx) + constants.eu2 * ad.as1aem1.gamma_qph(N, NU, cache) + + constants.ed2 * ad.as1aem1.gamma_qph(N, ND, cache) + ad.as1aem1.gamma_phph(NF) + (NU * constants.eu2 + ND * constants.ed2) * ad.as1aem1.gamma_gph(N), 0, @@ -52,12 +51,14 @@ def test_photon_momentum_conservation(): def test_quark_momentum_conservation(): # quark momentum N = complex(2.0, 0.0) - sx = h.sx(N, 3) - sx_ns_qed = h.compute_qed_ns_cache(N, sx[0]) + cache = h.cache.reset() np.testing.assert_almost_equal( - ad.as1aem1.gamma_nsp(N, sx, sx_ns_qed) - + ad.as1aem1.gamma_gq(N, sx) - + ad.as1aem1.gamma_phq(N, sx), + ad.as1aem1.gamma_nsp( + N, + cache, + ) + + ad.as1aem1.gamma_gq(N, cache) + + ad.as1aem1.gamma_phq(N, cache), 0, decimal=4, ) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as2.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as2.py index 694b65504..df76ebd75 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as2.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as2.py @@ -10,11 +10,11 @@ def test_gamma_1(): # number conservation - sx_n1 = h.sx(1, 2) - np.testing.assert_allclose(ad_as2.gamma_nsm(1, NF, sx_n1), 0.0, atol=2e-6) + cache2 = h.cache.reset() + np.testing.assert_allclose(ad_as2.gamma_nsm(1, NF, cache2), 0.0, atol=2e-6) - sx_n2 = h.sx(2, 2) - gS1 = ad_as2.gamma_singlet(2, NF, sx_n2) + cache2 = h.cache.reset() + gS1 = ad_as2.gamma_singlet(2, NF, cache2) # gluon momentum conservation # the CA*NF term seems to be tough to compute, so raise the constraint ... np.testing.assert_allclose(gS1[0, 1] + gS1[1, 1], 0.0, atol=4e-5) @@ -26,7 +26,7 @@ def test_gamma_1(): # reference values are obtained from MMa # non-singlet sector np.testing.assert_allclose( - ad_as2.gamma_nsp(2, NF, sx_n2), + ad_as2.gamma_nsp(2, NF, cache2), (-112.0 * const.CF + 376.0 * const.CA - 64.0 * NF) * const.CF / 27.0, ) # singlet sector @@ -40,7 +40,7 @@ def test_gamma_1(): # add additional point at (analytical) continuation point np.testing.assert_allclose( - ad_as2.gamma_nsm(2, NF, sx_n2), + ad_as2.gamma_nsm(2, NF, cache2), ( (34.0 / 27.0 * (-47.0 + 6 * np.pi**2) - 16.0 * const.zeta3) * const.CF + (373.0 / 9.0 - 34.0 * np.pi**2 / 9.0 + 8.0 * const.zeta3) * const.CA @@ -48,10 +48,10 @@ def test_gamma_1(): ) * const.CF, ) - sx_n3 = h.sx(3, 2) - sx_n4 = h.sx(4, 2) + cache3 = h.cache.reset() + cache4 = h.cache.reset() np.testing.assert_allclose( - ad_as2.gamma_nsp(3, NF, sx_n3), + ad_as2.gamma_nsp(3, NF, cache3), ( (-34487.0 / 432.0 + 86.0 * np.pi**2 / 9.0 - 16.0 * const.zeta3) * const.CF + (459.0 / 8.0 - 43.0 * np.pi**2 / 9.0 + 8.0 * const.zeta3) * const.CA @@ -60,7 +60,7 @@ def test_gamma_1(): * const.CF, ) np.testing.assert_allclose(ad_as2.gamma_ps(3, NF), -1391.0 * const.CF * NF / 5400.0) - gS1 = ad_as2.gamma_singlet(3, NF, sx_n3) + gS1 = ad_as2.gamma_singlet(3, NF, cache3) np.testing.assert_allclose( gS1[1, 0], ( @@ -80,7 +80,7 @@ def test_gamma_1(): ), rtol=6e-7, ) # gg - gS1 = ad_as2.gamma_singlet(4, NF, sx_n4) + gS1 = ad_as2.gamma_singlet(4, NF, cache4) np.testing.assert_allclose( gS1[0, 1], (-56317.0 / 18000.0 * const.CF + 16387.0 / 9000.0 * const.CA) * NF ) # qg @@ -88,7 +88,7 @@ def test_gamma_1(): const.update_colors(4) np.testing.assert_allclose(const.CA, 4.0) - gS1 = ad_as2.gamma_singlet(3, NF, sx_n3) + gS1 = ad_as2.gamma_singlet(3, NF, cache3) np.testing.assert_allclose( gS1[1, 0], ( @@ -108,7 +108,7 @@ def test_gamma_1(): ), rtol=6e-7, ) # gg - gS1 = ad_as2.gamma_singlet(4, NF, sx_n4) + gS1 = ad_as2.gamma_singlet(4, NF, cache4) np.testing.assert_allclose( gS1[0, 1], (-56317.0 / 18000.0 * const.CF + 16387.0 / 9000.0 * const.CA) * NF ) # qg diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as3.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as3.py index 7db2b7c64..77b6925a6 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as3.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as3.py @@ -11,14 +11,14 @@ def test_gamma_2(): # number conservation - each is 0 on its own, see :cite:`Moch:2004pa` N = 1 - sx_n1 = h.sx(N, max_weight=3) - np.testing.assert_allclose(ad_as3.gamma_nsv(N, NF, sx_n1), -0.000960586, rtol=3e-7) - np.testing.assert_allclose(ad_as3.gamma_nsm(N, NF, sx_n1), 0.000594225, rtol=6e-7) + cache1 = h.cache.reset() + np.testing.assert_allclose(ad_as3.gamma_nsv(N, NF, cache1), -0.000960586, rtol=3e-7) + np.testing.assert_allclose(ad_as3.gamma_nsm(N, NF, cache1), 0.000594225, rtol=6e-7) # get singlet sector N = 2 - sx_n2 = h.sx(N, max_weight=4) - gS2 = ad_as3.gamma_singlet(N, NF, sx_n2) + cache2 = h.cache.reset() + gS2 = ad_as3.gamma_singlet(N, NF, cache2) # gluon momentum conservation np.testing.assert_allclose(gS2[0, 1] + gS2[1, 1], -0.00388726, rtol=2e-6) @@ -28,4 +28,4 @@ def test_gamma_2(): assert gS2.shape == (2, 2) # test nsv_2 equal to referece value - np.testing.assert_allclose(ad_as3.gamma_nsv(N, NF, sx_n2), 188.325593, rtol=3e-7) + np.testing.assert_allclose(ad_as3.gamma_nsv(N, NF, cache2), 188.325593, rtol=3e-7) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as4.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as4.py index 010ff22ca..0688b0576 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as4.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as4.py @@ -2,6 +2,7 @@ import numpy as np from eko.constants import CA, CF +from ekore import harmonics as h from ekore.anomalous_dimensions.unpolarized.space_like.as4 import ( gamma_singlet, ggg, @@ -12,7 +13,6 @@ gps, gqg, ) -from ekore.harmonics import compute_cache NF = 5 @@ -36,7 +36,7 @@ def build_n3lo_var(): def test_quark_number_conservation(): N = 1 - sx_cache = compute_cache(N, 5, False) + sx_cache = h.cache.reset() # (ns,s) # the exact expression (nf^2 part) has an nonphysical pole at N=1, @@ -63,7 +63,7 @@ def test_quark_number_conservation(): def test_momentum_conservation(): N = 2 - sx_cache = compute_cache(N, 5, True) + sx_cache = h.cache.reset() # nf^3 part np.testing.assert_allclose( @@ -175,7 +175,7 @@ def test_non_singlet_reference_moments(): 2.90857799, ] for N in [3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0]: - sx_cache = compute_cache(N, 5, False) + sx_cache = h.cache.reset() idx = int((N - 3) / 2) if N != 17: np.testing.assert_allclose( @@ -204,7 +204,7 @@ def test_singlet_reference_moments(): 8119.044600816003, ] for N in [2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0]: - sx_cache = compute_cache(N, 5, True) + sx_cache = h.cache.reset() np.testing.assert_allclose( gnsp.gamma_nsp(N, NF, sx_cache), nsp_nf4_refs[int((N - 2) / 2)] ) @@ -276,7 +276,7 @@ def deltaB3(n, sx): diff = [] ref_vals = [] for N in range(10, 35): - sx_cache = compute_cache(N, 5, not bool(N % 2)) + sx_cache = h.cache.reset() diff.append(gnsp.gamma_nsp_nf2(N, sx_cache) - gnsm.gamma_nsm_nf2(N, sx_cache)) ref_vals.append(deltaB3(N, sx_cache)) np.testing.assert_allclose(diff, ref_vals, atol=5e-4) @@ -284,7 +284,7 @@ def deltaB3(n, sx): diff = [] ref_vals = [] for N in range(4, 10): - sx_cache = compute_cache(N, 5, not bool(N % 2)) + sx_cache = h.cache.reset() diff.append(gnsp.gamma_nsp_nf2(N, sx_cache) - gnsm.gamma_nsm_nf2(N, sx_cache)) ref_vals.append(deltaB3(N, sx_cache)) np.testing.assert_allclose(diff, ref_vals, atol=2e-2) @@ -294,7 +294,7 @@ def test_gamma_ps_extrapolation(): # Test the prediction of N=22 wrt to :cite:`Falcioni:2023luc` n22_ref = [6.2478570, 10.5202730, 15.6913948] N = 22 - sx_cache = compute_cache(N, 5, True) + sx_cache = h.cache.reset() my_res = [] for nf in [3, 4, 5]: my_res.append(gps.gamma_ps(N, nf, sx_cache, 0)) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_init.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_init.py index 360a3bb92..3e82fbb52 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_init.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_init.py @@ -9,15 +9,15 @@ import ekore.anomalous_dimensions.unpolarized.space_like as ad_us from eko import basis_rotation as br from ekore import anomalous_dimensions as ad -from ekore import harmonics +from ekore import harmonics as h NF = 5 def test_eigensystem_gamma_singlet_0_values(): - n = 3 - s1 = harmonics.S1(n) - gamma_S_0 = ad_us.as1.gamma_singlet(3, s1, NF) + N = 3 + cache = h.cache.reset() + gamma_S_0 = ad_us.as1.gamma_singlet(N, cache, NF) res = ad.exp_matrix_2D(gamma_S_0) lambda_p = complex(12.273612971466964, 0) lambda_m = complex(5.015275917421917, 0) @@ -37,13 +37,13 @@ def test_eigensystem_gamma_singlet_0_values(): def test_exp_matrix(): - n = 3 - s1 = harmonics.S1(n) - gamma_S_0 = ad_us.as1.gamma_singlet(3, s1, NF) + N = 3 + cache = h.cache.reset() + gamma_S_0 = ad_us.as1.gamma_singlet(N, cache, NF) res = ad.exp_matrix_2D(gamma_S_0)[0] res2 = ad.exp_matrix(gamma_S_0)[0] assert_allclose(res, res2) - gamma_S_0_qed = ad_us.as1.gamma_singlet_qed(3, s1, NF) + gamma_S_0_qed = ad_us.as1.gamma_singlet_qed(3, cache, NF) res = expm(gamma_S_0_qed) res2 = ad.exp_matrix(gamma_S_0_qed)[0] assert_allclose(res, res2) @@ -197,28 +197,28 @@ def test_gamma_ns_qed(): def test_dim_singlet(): nf = 3 N = 2 - sx = harmonics.sx(N, max_weight=3 + 1) + cache = h.cache.reset() gamma_singlet = ad_us.gamma_singlet_qed((3, 2), N, nf) assert gamma_singlet.shape == (4, 3, 4, 4) - gamma_singlet_as1 = ad_us.as1.gamma_singlet_qed(N, sx[0], nf) + gamma_singlet_as1 = ad_us.as1.gamma_singlet_qed(N, cache, nf) assert gamma_singlet_as1.shape == (4, 4) - gamma_singlet_as2 = ad_us.as2.gamma_singlet_qed(N, nf, sx) + gamma_singlet_as2 = ad_us.as2.gamma_singlet_qed(N, nf, cache) assert gamma_singlet_as2.shape == (4, 4) - gamma_singlet_as3 = ad_us.as3.gamma_singlet_qed(N, nf, sx) + gamma_singlet_as3 = ad_us.as3.gamma_singlet_qed(N, nf, cache) assert gamma_singlet_as3.shape == (4, 4) def test_dim_valence(): nf = 3 N = 2 - sx = harmonics.sx(N, max_weight=3 + 1) + cache = h.cache.reset() gamma_valence = ad_us.gamma_valence_qed((3, 2), N, nf) assert gamma_valence.shape == (4, 3, 2, 2) - gamma_valence_as1 = ad_us.as1.gamma_valence_qed(N, sx[0]) + gamma_valence_as1 = ad_us.as1.gamma_valence_qed(N, cache) assert gamma_valence_as1.shape == (2, 2) - gamma_valence_as2 = ad_us.as2.gamma_valence_qed(N, nf, sx) + gamma_valence_as2 = ad_us.as2.gamma_valence_qed(N, nf, cache) assert gamma_valence_as2.shape == (2, 2) - gamma_valence_as3 = ad_us.as3.gamma_valence_qed(N, nf, sx) + gamma_valence_as3 = ad_us.as3.gamma_valence_qed(N, nf, cache) assert gamma_valence_as3.shape == (2, 2) From 1f0ce77fa42f540f8af70cabac87b26f73d7a666 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 11:44:03 +0200 Subject: [PATCH 07/24] pass new cache to ad n3lo --- .../unpolarized/space_like/as4/__init__.py | 15 ++-- .../unpolarized/space_like/as4/ggg.py | 58 ++++++------- .../unpolarized/space_like/as4/ggq.py | 74 ++++++++--------- .../unpolarized/space_like/as4/gnsm.py | 81 ++++++++++--------- .../unpolarized/space_like/as4/gnsp.py | 65 ++++++++------- .../unpolarized/space_like/as4/gnsv.py | 57 +++++++------ .../unpolarized/space_like/as4/gps.py | 41 +++++----- .../unpolarized/space_like/as4/gqg.py | 49 ++++++----- .../unpolarized/space_like/test_as4.py | 7 +- 9 files changed, 243 insertions(+), 204 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/__init__.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/__init__.py index 3465d11ab..10c4cb57c 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/__init__.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/__init__.py @@ -16,7 +16,7 @@ @nb.njit(cache=True) -def gamma_singlet(N, nf, sx, variation): +def gamma_singlet(N, nf, cache, variation): r"""Compute the |N3LO| singlet anomalous dimension matrix. .. math:: @@ -31,8 +31,8 @@ def gamma_singlet(N, nf, sx, variation): Mellin moment nf : int Number of active flavors - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : tuple |N3LO| anomalous dimension variation ``(gg_var, gq_var, qg_var, qq_var)`` @@ -43,11 +43,14 @@ def gamma_singlet(N, nf, sx, variation): :math:`\gamma_{S}^{(3)}(N)` """ - gamma_qq = gamma_nsp(N, nf, sx) + gamma_ps(N, nf, sx, variation[3]) + gamma_qq = gamma_nsp(N, nf, cache) + gamma_ps(N, nf, cache, variation[3]) gamma_S_0 = np.array( [ - [gamma_qq, gamma_qg(N, nf, sx, variation[2])], - [gamma_gq(N, nf, sx, variation[1]), gamma_gg(N, nf, sx, variation[0])], + [gamma_qq, gamma_qg(N, nf, cache, variation[2])], + [ + gamma_gq(N, nf, cache, variation[1]), + gamma_gg(N, nf, cache, variation[0]), + ], ], np.complex_, ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/ggg.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/ggg.py index 42a1f1331..2c2240d50 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/ggg.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/ggg.py @@ -4,11 +4,12 @@ import numba as nb import numpy as np +from .....harmonics import cache as c from .....harmonics.log_functions import lm11, lm11m1 @nb.njit(cache=True) -def gamma_gg_nf3(n, sx): +def gamma_gg_nf3(n, cache): r"""Return the part proportional to :math:`nf^3` of :math:`\gamma_{gg}^{(3)}`. The expression is copied exact from :eqref:`3.14` of :cite:`Davies:2016jie`. @@ -17,8 +18,8 @@ def gamma_gg_nf3(n, sx): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -26,9 +27,10 @@ def gamma_gg_nf3(n, sx): |N3LO| non-singlet anomalous dimension :math:`\gamma_{gg}^{(3)}|_{nf^3}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3, S21, _, _, _, _ = sx[2] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3= c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) return 3.0 * ( -0.0205761316872428 + 2.599239604033225 / (-1.0 + n) @@ -139,15 +141,15 @@ def gamma_gg_nf3(n, sx): @nb.njit(cache=True) -def gamma_gg_nf1(n, sx, variation): +def gamma_gg_nf1(n, cache, variation): r"""Return the part proportional to :math:`nf^1` of :math:`\gamma_{gg}^{(3)}`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -157,8 +159,8 @@ def gamma_gg_nf1(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{gg}^{(3)}|_{nf^1}` """ - S1 = sx[0][0] - S2 = sx[1][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) common = 18143.980574437464 + 1992.766087237516/np.power(-1. + n,3) + 20005.925925925927/np.power(n,7) - 19449.679012345678/np.power(n,6) + 80274.123066115/np.power(n,5) - 11714.245609287387*S1 if variation == 1: fit = 45963.268520094876/n - 51189.992910381996/(1. + n) + (5863.26605573345*((-1. + 2.*n - 2.*np.power(n,2))/(np.power(-1. + n,2)*np.power(n,2)) + S2))/n + 13586.906889317255*lm11(n,S1) @@ -203,15 +205,15 @@ def gamma_gg_nf1(n, sx, variation): @nb.njit(cache=True) -def gamma_gg_nf2(n, sx, variation): +def gamma_gg_nf2(n, cache, variation): r"""Return the part proportional to :math:`nf^2` of :math:`\gamma_{gg}^{(3)}`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -221,8 +223,8 @@ def gamma_gg_nf2(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{gg}^{(3)}|_{nf^2}` """ - S1 = sx[0][0] - S2 = sx[1][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) common = -423.811346198137 - 568.8888888888889/np.power(n,7) + 1725.6296296296296/np.power(n,6) - 2196.543209876543/np.power(n,5) + 440.0487580115612*S1 if variation == 1: fit = -2430.638493036615/n + 2028.7214027705545/(1. + n) + (243.3886567890572*((-1. + 2.*n - 2.*np.power(n,2))/(np.power(-1. + n,2)*np.power(n,2)) + S2))/n - 137.7731001470984*lm11(n,S1) @@ -266,15 +268,15 @@ def gamma_gg_nf2(n, sx, variation): @nb.njit(cache=True) -def gamma_gg_nf0(n, sx, variation): +def gamma_gg_nf0(n, cache, variation): r"""Return the part proportional to :math:`nf^0` of :math:`\gamma_{gg}^{(3)}`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -284,8 +286,8 @@ def gamma_gg_nf0(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{gg}^{(3)}|_{nf^0}` """ - S1 = sx[0][0] - S2 = sx[1][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) common = -68587.9129845144 - 49851.703887834694/np.power(-1. + n,4) + 213823.9810748423/np.power(-1. + n,3) - 103680./np.power(n,7) - 17280./np.power(n,6) - 627978.8224813186/np.power(n,5) + 40880.33011934297*S1 if variation == 1: fit = -21320.044597892782/n - 644579.2835120695/(1. + n) + (283827.99744115997*((-1. + 2.*n - 2.*np.power(n,2))/(np.power(-1. + n,2)*np.power(n,2)) + S2))/n - 119359.01638755966*lm11(n,S1) @@ -329,7 +331,7 @@ def gamma_gg_nf0(n, sx, variation): @nb.njit(cache=True) -def gamma_gg(n, nf, sx, variation): +def gamma_gg(n, nf, cache, variation): r"""Compute the |N3LO| gluon-gluon singlet anomalous dimension. Parameters @@ -338,8 +340,8 @@ def gamma_gg(n, nf, sx, variation): Mellin moment nf : int Number of active flavors - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -351,8 +353,8 @@ def gamma_gg(n, nf, sx, variation): """ return ( - gamma_gg_nf0(n, sx, variation) - + nf * gamma_gg_nf1(n, sx, variation) - + nf**2 * gamma_gg_nf2(n, sx, variation) - + nf**3 * gamma_gg_nf3(n, sx) + gamma_gg_nf0(n, cache, variation) + + nf * gamma_gg_nf1(n, cache, variation) + + nf**2 * gamma_gg_nf2(n, cache, variation) + + nf**3 * gamma_gg_nf3(n, cache) ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/ggq.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/ggq.py index 4235f8f85..7bfa6f975 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/ggq.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/ggq.py @@ -4,11 +4,12 @@ import numba as nb import numpy as np +from .....harmonics import cache as c from .....harmonics.log_functions import lm11, lm12, lm13, lm14, lm15 @nb.njit(cache=True) -def gamma_gq_nf3(n, sx): +def gamma_gq_nf3(n, cache): r"""Return the part proportional to :math:`nf^3` of :math:`\gamma_{gq}^{(3)}`. The expression is copied exact from :eqref:`3.13` of :cite:`Davies:2016jie`. @@ -17,8 +18,8 @@ def gamma_gq_nf3(n, sx): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -26,9 +27,9 @@ def gamma_gq_nf3(n, sx): |N3LO| non-singlet anomalous dimension :math:`\gamma_{gq}^{(3)}|_{nf^3}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) return 1.3333333333333333 * ( -11.39728026699467 / (-1.0 + n) + 11.39728026699467 / n @@ -54,15 +55,15 @@ def gamma_gq_nf3(n, sx): @nb.njit(cache=True) -def gamma_gq_nf0(n, sx, variation): +def gamma_gq_nf0(n, cache, variation): r"""Return the part proportional to :math:`nf^0` of :math:`\gamma_{gq}^{(3)}`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -72,11 +73,11 @@ def gamma_gq_nf0(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{gq}^{(3)}|_{nf^0}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] - S5 = sx[4][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) + S5 = c.get(c.S5, cache, n) S2m2 = ((-1 + 2 * n - 2 * n**2)/((-1 + n)**2 * n**2) + S2)/n S1m2 = ((1 - 2 * n)/((-1 + n) * n) + S1)/n common = -22156.31283903764/np.power(-1. + n,4) + 95032.88047770769/np.power(-1. + n,3) - 37609.87654320987/np.power(n,7) - 35065.67901234568/np.power(n,6) - 175454.58483973087/np.power(n,5) - 375.3983146907502*lm14(n,S1,S2,S3,S4) - 13.443072702331962*lm15(n,S1,S2,S3,S4,S5) @@ -134,15 +135,15 @@ def gamma_gq_nf0(n, sx, variation): @nb.njit(cache=True) -def gamma_gq_nf1(n, sx, variation): +def gamma_gq_nf1(n, cache, variation): r"""Return the part proportional to :math:`nf^1` of :math:`\gamma_{gq}^{(3)}`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -152,11 +153,11 @@ def gamma_gq_nf1(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{gq}^{(3)}|_{nf^1}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] - S5 = sx[4][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) + S5 = c.get(c.S5, cache, n) S3m2 = (-(((-1 + 2 * n) * (1 - n + n**2))/((-1 + n)**3 * n**3)) + S3)/n S2m2 = ((-1 + 2 * n - 2 * n**2)/((-1 + n)**2 * n**2) + S2)/n S1m2 = ((1 - 2 * n)/((-1 + n) * n) + S1)/n @@ -216,15 +217,15 @@ def gamma_gq_nf1(n, sx, variation): @nb.njit(cache=True) -def gamma_gq_nf2(n, sx, variation): +def gamma_gq_nf2(n, cache, variation): r"""Return the part proportional to :math:`nf^2` of :math:`\gamma_{gq}^{(3)}`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -234,10 +235,11 @@ def gamma_gq_nf2(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{gq}^{(3)}|_{nf^2}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) + S5 = c.get(c.S5, cache, n) S2m2 = ((-1 + 2 * n - 2 * n**2)/((-1 + n)**2 * n**2) + S2)/n S1m2 = ((1 - 2 * n)/((-1 + n) * n) + S1)/n common = 778.5349794238683/np.power(n,5) - 0.877914951989026*lm14(n,S1,S2,S3,S4) @@ -295,7 +297,7 @@ def gamma_gq_nf2(n, sx, variation): @nb.njit(cache=True) -def gamma_gq(n, nf, sx, variation): +def gamma_gq(n, nf, cache, variation): r"""Compute the |N3LO| gluon-quark singlet anomalous dimension. Parameters @@ -304,8 +306,8 @@ def gamma_gq(n, nf, sx, variation): Mellin moment nf : int Number of active flavors - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -317,8 +319,8 @@ def gamma_gq(n, nf, sx, variation): """ return ( - gamma_gq_nf0(n, sx, variation) - + nf * gamma_gq_nf1(n, sx, variation) - + nf**2 * gamma_gq_nf2(n, sx, variation) - + nf**3 * gamma_gq_nf3(n, sx) + gamma_gq_nf0(n, cache, variation) + + nf * gamma_gq_nf1(n, cache, variation) + + nf**2 * gamma_gq_nf2(n, cache, variation) + + nf**3 * gamma_gq_nf3(n, cache) ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsm.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsm.py index 9edc28a3d..ba249f672 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsm.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsm.py @@ -3,11 +3,12 @@ from eko.constants import CF, zeta3 +from .....harmonics import cache as c from .....harmonics.log_functions import lm11m1, lm12m1, lm13m1 @nb.njit(cache=True) -def gamma_ns_nf3(n, sx): +def gamma_ns_nf3(n, cache): r"""Return the common part proportional to :math:`nf^3`. Holds for :math:`\gamma_{ns,+}^{(3)},\gamma_{ns,-}^{(3)},\gamma_{ns,v}^{(3)}`. @@ -17,19 +18,19 @@ def gamma_ns_nf3(n, sx): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_ns_nf3 : complex + complex |N3LO| non-singlet anomalous dimension :math:`\gamma_{ns}^{(3)}|_{nf^3}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) eta = 1 / n * 1 / (n + 1) g_ns_nf3 = CF * ( -32 / 27 * zeta3 * eta @@ -51,27 +52,29 @@ def gamma_ns_nf3(n, sx): @nb.njit(cache=True) -def gamma_nsm_nf2(n, sx): +def gamma_nsm_nf2(n, cache): r"""Return the parametrized valence-like non-singlet part proportional to :math:`nf^2`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_ns_nf2 : complex + complex |N3LO| valence-like non-singlet anomalous dimension :math:`\gamma_{ns,-}^{(3)}|_{nf^2}` """ - S1 = sx[0][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) Lm11m1 = lm11m1(n, S1) - Lm12m1 = lm12m1(n, S1, sx[1][0]) - Lm13m1 = lm13m1(n, S1, sx[1][0], sx[2][0]) + Lm12m1 = lm12m1(n, S1, S2) + Lm13m1 = lm13m1(n, S1, S2, S3) return ( -193.89011158240442 - 18.962962962962962 / n**5 @@ -92,27 +95,29 @@ def gamma_nsm_nf2(n, sx): @nb.njit(cache=True) -def gamma_nsm_nf1(n, sx): +def gamma_nsm_nf1(n, cache): r"""Return the parametrized valence-like non-singlet part proportional to :math:`nf^1`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_ns_nf1 : complex + complex |N3LO| valence-like non-singlet anomalous dimension :math:`\gamma_{ns,-}^{(3)}|_{nf^1}` """ - S1 = sx[0][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) Lm11m1 = lm11m1(n, S1) - Lm12m1 = lm12m1(n, S1, sx[1][0]) - Lm13m1 = lm13m1(n, S1, sx[1][0], sx[2][0]) + Lm12m1 = lm12m1(n, S1, S2) + Lm13m1 = lm13m1(n, S1, S2, S3) return ( 5550.182834015097 - 126.41975308641975 / n**6 @@ -134,27 +139,29 @@ def gamma_nsm_nf1(n, sx): @nb.njit(cache=True) -def gamma_nsm_nf0(n, sx): +def gamma_nsm_nf0(n, cache): r"""Return the parametrized valence-like non-singlet part proportional to :math:`nf^0`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_ns_nf0 : complex + complex |N3LO| valence-like non-singlet anomalous dimension :math:`\gamma_{ns,-}^{(3)}|_{nf^0}` """ - S1 = sx[0][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) Lm11m1 = lm11m1(n, S1) - Lm12m1 = lm12m1(n, S1, sx[1][0]) - Lm13m1 = lm13m1(n, S1, sx[1][0], sx[2][0]) + Lm12m1 = lm12m1(n, S1, S2) + Lm13m1 = lm13m1(n, S1, S2, S3) return ( -23372.01191013195 - 252.8395061728395 / n**7 @@ -177,7 +184,7 @@ def gamma_nsm_nf0(n, sx): @nb.njit(cache=True) -def gamma_nsm(n, nf, sx): +def gamma_nsm(n, nf, cache): r"""Compute the |N3LO| valence-like non-singlet anomalous dimension. Parameters @@ -186,19 +193,19 @@ def gamma_nsm(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsp : complex + complex |N3LO| valence-like non-singlet anomalous dimension :math:`\gamma_{ns,-}^{(3)}(N)` """ return ( - gamma_nsm_nf0(n, sx) - + nf * gamma_nsm_nf1(n, sx) - + nf**2 * gamma_nsm_nf2(n, sx) - + nf**3 * gamma_ns_nf3(n, sx) + gamma_nsm_nf0(n, cache) + + nf * gamma_nsm_nf1(n, cache) + + nf**2 * gamma_nsm_nf2(n, cache) + + nf**3 * gamma_ns_nf3(n, cache) ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsp.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsp.py index 45e7b5554..b9f74c7bf 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsp.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsp.py @@ -1,31 +1,34 @@ r"""The unpolarized, space-like anomalous dimension :math:`\gamma_{ns,+}^{(3)}`.""" import numba as nb +from .....harmonics import cache as c from .....harmonics.log_functions import lm11m1, lm12m1, lm13m1 from .gnsm import gamma_ns_nf3 @nb.njit(cache=True) -def gamma_nsp_nf2(n, sx): +def gamma_nsp_nf2(n, cache): r"""Return the parametrized singlet-like non-singlet part proportional to :math:`nf^2`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_nsp_nf2 : complex + complex |N3LO| singlet-like non-singlet anomalous dimension :math:`\gamma_{ns,+}^{(3)}|_{nf^2}` """ - S1 = sx[0][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) Lm11m1 = lm11m1(n, S1) - Lm12m1 = lm12m1(n, S1, sx[1][0]) - Lm13m1 = lm13m1(n, S1, sx[1][0], sx[2][0]) + Lm12m1 = lm12m1(n, S1, S2) + Lm13m1 = lm13m1(n, S1, S2, S3) return ( -193.862483821757 - 18.962962962962962 / n**5 @@ -46,26 +49,28 @@ def gamma_nsp_nf2(n, sx): @nb.njit(cache=True) -def gamma_nsp_nf1(n, sx): +def gamma_nsp_nf1(n, cache): r"""Return the parametrized singlet-like non-singlet part proportional to :math:`nf^1`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_nsp_nf1 : complex + complex |N3LO| singlet-like non-singlet anomalous dimension :math:`\gamma_{ns,+}^{(3)}|_{nf^1}` """ - S1 = sx[0][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) Lm11m1 = lm11m1(n, S1) - Lm12m1 = lm12m1(n, S1, sx[1][0]) - Lm13m1 = lm13m1(n, S1, sx[1][0], sx[2][0]) + Lm12m1 = lm12m1(n, S1, S2) + Lm13m1 = lm13m1(n, S1, S2, S3) return ( 5550.285178175209 - 126.41975308641975 / n**6 @@ -87,26 +92,28 @@ def gamma_nsp_nf1(n, sx): @nb.njit(cache=True) -def gamma_nsp_nf0(n, sx): +def gamma_nsp_nf0(n, cache): r"""Return the parametrized singlet-like non-singlet part proportional to :math:`nf^0`. Parameters ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_nsp_nf0 : complex + complex |N3LO| singlet-like non-singlet anomalous dimension :math:`\gamma_{ns,+}^{(3)}|_{nf^0}` """ - S1 = sx[0][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) Lm11m1 = lm11m1(n, S1) - Lm12m1 = lm12m1(n, S1, sx[1][0]) - Lm13m1 = lm13m1(n, S1, sx[1][0], sx[2][0]) + Lm12m1 = lm12m1(n, S1, S2) + Lm13m1 = lm13m1(n, S1, S2, S3) return ( -23391.315223909038 - 252.8395061728395 / n**7 @@ -129,7 +136,7 @@ def gamma_nsp_nf0(n, sx): @nb.njit(cache=True) -def gamma_nsp(n, nf, sx): +def gamma_nsp(n, nf, cache): r"""Compute the |N3LO| singlet-like non-singlet anomalous dimension. Parameters @@ -138,19 +145,19 @@ def gamma_nsp(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsp : complex + complex |N3LO| singlet-like non-singlet anomalous dimension :math:`\gamma_{ns,+}^{(3)}(N)` """ return ( - gamma_nsp_nf0(n, sx) - + nf * gamma_nsp_nf1(n, sx) - + nf**2 * gamma_nsp_nf2(n, sx) - + nf**3 * gamma_ns_nf3(n, sx) + gamma_nsp_nf0(n, cache) + + nf * gamma_nsp_nf1(n, cache) + + nf**2 * gamma_nsp_nf2(n, cache) + + nf**3 * gamma_ns_nf3(n, cache) ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsv.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsv.py index 8ee1aabd7..9de2d2f7f 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsv.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gnsv.py @@ -1,11 +1,12 @@ r"""The unpolarized, space-like anomalous dimension :math:`\gamma_{ns,v}^{(3)}`.""" import numba as nb +from .....harmonics import cache as c from .gnsm import gamma_nsm @nb.njit(cache=True) -def gamma_nss_nf2(n, sx): +def gamma_nss_nf2(n, cache): r"""Return the sea non-singlet part proportional to :math:`nf^2`. Implements :eqref:`3.5` of :cite:`Davies:2016jie`. @@ -14,19 +15,27 @@ def gamma_nss_nf2(n, sx): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_nss_nf2 : complex + complex |N3LO| sea non-singlet anomalous dimension :math:`\gamma_{ns,s}^{(3)}|_{nf^2}` """ - S1, _ = sx[0] - S2, Sm2 = sx[1] - S3, _, _, Sm21, _, Sm3 = sx[2] - S4, S31, _, Sm22, Sm211, Sm31, Sm4 = sx[3] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=False) + S3 = c.get(c.S3, cache, n) + Sm21 = c.get(c.Sm21, cache, n, is_singlet=False) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=False) + S4 = c.get(c.S4, cache, n) + Sm4 = c.get(c.Sm4, cache, n, is_singlet=False) + S31 = c.get(c.S31, cache, n) + Sm22 = c.get(c.Sm22, cache, n, is_singlet=False) + Sm31 = c.get(c.Sm31, cache, n, is_singlet=False) + Sm211 = c.get(c.Sm211, cache, n, is_singlet=False) return ( 160 / 27 @@ -162,7 +171,7 @@ def gamma_nss_nf2(n, sx): @nb.njit(cache=True) -def gamma_nss_nf1(n, sx): +def gamma_nss_nf1(n, cache): r"""Return the sea non-singlet part proportional to :math:`nf^1`. The expression is the average of the Mellin transform @@ -172,18 +181,18 @@ def gamma_nss_nf1(n, sx): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - g_nss_nf1 : complex + complex |N3LO| sea non-singlet anomalous dimension :math:`\gamma_{ns,s}^{(3)}|_{nf^1}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) return ( 3803.04 / n**6 - 3560.16 / n**5 @@ -218,7 +227,7 @@ def gamma_nss_nf1(n, sx): @nb.njit(cache=True) -def gamma_nsv(n, nf, sx): +def gamma_nsv(n, nf, cache): r"""Compute the |N3LO| valence non-singlet anomalous dimension. Parameters @@ -227,18 +236,18 @@ def gamma_nsv(n, nf, sx): Mellin moment nf : int Number of active flavors - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsv : complex - |N3LO| valence non-singlet anomalous dimension - :math:`\gamma_{ns,v}^{(3)}(N)` + complex + |N3LO| valence non-singlet anomalous dimension + :math:`\gamma_{ns,v}^{(3)}(N)` """ return ( - gamma_nsm(n, nf, sx) - + nf * gamma_nss_nf1(n, sx) - + nf**2 * gamma_nss_nf2(n, sx) + gamma_nsm(n, nf, cache) + + nf * gamma_nss_nf1(n, cache) + + nf**2 * gamma_nss_nf2(n, cache) ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gps.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gps.py index b3a54dc28..aabfca6ad 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gps.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gps.py @@ -4,6 +4,7 @@ import numba as nb import numpy as np +from .....harmonics import cache as c from .....harmonics.log_functions import ( lm11m1, lm11m2, @@ -17,7 +18,7 @@ @nb.njit(cache=True) -def gamma_ps_nf3(n, sx): +def gamma_ps_nf3(n, cache): r"""Return the part proportional to :math:`nf^3` of :math:`\gamma_{ps}^{(3)}`. The expression is copied exact from :eqref:`3.10` of :cite:`Davies:2016jie`. @@ -26,8 +27,8 @@ def gamma_ps_nf3(n, sx): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -35,9 +36,9 @@ def gamma_ps_nf3(n, sx): |N3LO| non-singlet anomalous dimension :math:`\gamma_{ps}^{(3)}|_{nf^3}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) return 1.3333333333333333 * ( 16.305796943701882 / (-1.0 + n) + 3.5555555555555554 / np.power(n, 5) @@ -90,7 +91,7 @@ def gamma_ps_nf3(n, sx): @nb.njit(cache=True) -def gamma_ps_nf1(n, sx, variation): +def gamma_ps_nf1(n, cache, variation): r"""Return the part proportional to :math:`nf^1` of :math:`\gamma_{ps}^{(3)}`. Parameters @@ -108,10 +109,10 @@ def gamma_ps_nf1(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{ps}^{(3)}|_{nf^1}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) common = -3498.454512979491/np.power(-1. + n,3) + 5404.444444444444/np.power(n,7) + 3425.9753086419755/np.power(n,6) + 20515.223982421852/np.power(n,5) + 247.55054124312667*lm13m1(n,S1,S2,S3) + 199.11111*lm13m2(n,S1,S2,S3) + 56.46090534979424*lm14m1(n,S1,S2,S3,S4) + 13.168724000000001*lm14m2(n,S1,S2,S3,S4) if variation == 1: fit = 17114.440372984987*(1/(n-1)**2 +1/n**2) - 56482.37473713895*(1/(-1. + n) - 1./n) - 9247.158633468189/np.power(n,4) + 51758.36314422693/np.power(n,3) - 27774.710120695992/(6. + 5.*n + np.power(n,2)) + 12609.163387951978*(1/n - (1.*n)/(2. + 3.*n + np.power(n,2))) - 218.72209329346168*lm11m1(n,S1) + 6520.842881982454*lm11m2(n,S1) + 1003.6502844579335*lm12m1(n,S1,S2) + 8612.716120193661*lm12m2(n,S1,S2) @@ -135,7 +136,7 @@ def gamma_ps_nf1(n, sx, variation): @nb.njit(cache=True) -def gamma_ps_nf2(n, sx, variation): +def gamma_ps_nf2(n, cache, variation): r"""Return the part proportional to :math:`nf^2` of :math:`\gamma_{ps}^{(3)}`. Parameters @@ -153,10 +154,10 @@ def gamma_ps_nf2(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{ps}^{(3)}|_{nf^2}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) common = -568.8888888888889/np.power(n,7) + 455.1111111111111/np.power(n,6) - 1856.79012345679/np.power(n,5) - 40.559670781893004*lm13m1(n,S1,S2,S3) - 13.695473*lm13m2(n,S1,S2,S3) - 3.6213991769547325*lm14m1(n,S1,S2,S3,S4) if variation == 1: fit = 129.36670007880312*(1/(n-1)**2 +1/n**2) + 281.1298772185047*(1/(-1. + n) - 1./n) + 1461.3249956305358/np.power(n,4) - 1416.6957822207867/np.power(n,3) + 1032.901485734173/(6. + 5.*n + np.power(n,2)) - 538.5144723158696*(1/n - (1.*n)/(2. + 3.*n + np.power(n,2))) - 540.9977294644839*lm11m1(n,S1) - 301.9365856452302*lm11m2(n,S1) - 206.40218795098986*lm12m1(n,S1,S2) - 293.5852282113812*lm12m2(n,S1,S2) @@ -180,7 +181,7 @@ def gamma_ps_nf2(n, sx, variation): @nb.njit(cache=True) -def gamma_ps(n, nf, sx, variation): +def gamma_ps(n, nf, cache, variation): r"""Compute the |N3LO| pure singlet quark-quark anomalous dimension. Parameters @@ -202,7 +203,7 @@ def gamma_ps(n, nf, sx, variation): """ return ( - +nf * gamma_ps_nf1(n, sx, variation) - + nf**2 * gamma_ps_nf2(n, sx, variation) - + nf**3 * gamma_ps_nf3(n, sx) + +nf * gamma_ps_nf1(n, cache, variation) + + nf**2 * gamma_ps_nf2(n, cache, variation) + + nf**3 * gamma_ps_nf3(n, cache) ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gqg.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gqg.py index b8d891816..082db7b48 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gqg.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gqg.py @@ -4,11 +4,12 @@ import numba as nb import numpy as np +from .....harmonics import cache as c from .....harmonics.log_functions import lm11, lm12, lm13, lm14, lm15 @nb.njit(cache=True) -def gamma_qg_nf3(n, sx): +def gamma_qg_nf3(n, cache): r"""Return the part proportional to :math:`nf^3` of :math:`\gamma_{qg}^{(3)}`. The expression is copied exact from :eqref:`3.12` of :cite:`Davies:2016jie`. @@ -26,10 +27,16 @@ def gamma_qg_nf3(n, sx): |N3LO| non-singlet anomalous dimension :math:`\gamma_{qg}^{(3)}|_{nf^3}` """ - S1 = sx[0][0] - S2, Sm2 = sx[1] - S3, S21, _, _, _, Sm3 = sx[2] - S4, S31, S211, _, _, _, Sm4 = sx[3] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=True) + S3 = c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=True) + S4 = c.get(c.S4, cache, n) + Sm4 = c.get(c.Sm4, cache, n, is_singlet=True) + S31 = c.get(c.S31, cache, n) + S211 = c.get(c.S211, cache, n) return 1.3333333333333333 * ( 44.56685134331718 / (-1.0 + n) - 82.37037037037037 / np.power(n, 5) @@ -331,7 +338,7 @@ def gamma_qg_nf3(n, sx): @nb.njit(cache=True) -def gamma_qg_nf1(n, sx, variation): +def gamma_qg_nf1(n, cache, variation): r"""Return the part proportional to :math:`nf^1` of :math:`\gamma_{qg}^{(3)}`. Parameters @@ -349,11 +356,11 @@ def gamma_qg_nf1(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{qg}^{(3)}|_{nf^1}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] - S5 = sx[4][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) + S5 = c.get(c.S5, cache, n) S1m2 = ((1 - 2 * n)/((-1 + n) * n) + S1)/n common = -7871.5226542038545/np.power(-1. + n,3) + 41639.78057369606/np.power(-1. + n,2) + 14103.703703703704/np.power(n,7) + 2588.8395061728397/np.power(n,6) + 68802.34242841466/np.power(n,5) - 35.68779444531073*lm14(n,S1,S2,S3,S4) - 1.8518518518518519*lm15(n,S1,S2,S3,S4,S5) if variation == 1: @@ -402,7 +409,7 @@ def gamma_qg_nf1(n, sx, variation): @nb.njit(cache=True) -def gamma_qg_nf2(n, sx, variation): +def gamma_qg_nf2(n, cache, variation): r"""Return the part proportional to :math:`nf^2` of :math:`\gamma_{qg}^{(3)}`. Parameters @@ -420,11 +427,11 @@ def gamma_qg_nf2(n, sx, variation): |N3LO| non-singlet anomalous dimension :math:`\gamma_{qg}^{(3)}|_{nf^2}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] - S5 = sx[4][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) + S5 = c.get(c.S5, cache, n) S1m2 = ((1 - 2 * n)/((-1 + n) * n) + S1)/n common = 175.35644829905792/np.power(-1. + n,2) - 1991.111111111111/np.power(n,7) + 2069.3333333333335/np.power(n,6) - 7229.376633440217/np.power(n,5) + 3.511659807956104*lm14(n,S1,S2,S3,S4) + 0.411522633744856*lm15(n,S1,S2,S3,S4,S5) if variation == 1: @@ -472,7 +479,7 @@ def gamma_qg_nf2(n, sx, variation): return common + fit @nb.njit(cache=True) -def gamma_qg(n, nf, sx, variation): +def gamma_qg(n, nf, cache, variation): r"""Compute the |N3LO| quark-gluon singlet anomalous dimension. Parameters @@ -494,7 +501,7 @@ def gamma_qg(n, nf, sx, variation): """ return ( - +nf * gamma_qg_nf1(n, sx, variation) - + nf**2 * gamma_qg_nf2(n, sx, variation) - + nf**3 * gamma_qg_nf3(n, sx) + +nf * gamma_qg_nf1(n, cache, variation) + + nf**2 * gamma_qg_nf2(n, cache, variation) + + nf**3 * gamma_qg_nf3(n, cache) ) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as4.py b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as4.py index 0688b0576..0309f5cff 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as4.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/space_like/test_as4.py @@ -214,7 +214,7 @@ def test_diff_pm_nf2(): # Test deltaB3: diff g_{ns,-} - g_{ns,+} prop to nf^2 # Note that discrepancy for low moments is higher due to # oscillating behavior which is not captured by our parametrization - def deltaB3(n, sx): + def deltaB3(n, sx_cache): """ Implementation of Eq. 3.4 of :cite:`Davies:2016jie`. @@ -231,8 +231,9 @@ def deltaB3(n, sx): |N3LO| valence-like non-singlet anomalous dimension part proportional to :math:`C_F (C_A - 2 C_F) nf^2` """ - S1, _ = sx[0] - S2, Sm2 = sx[1] + S1 = h.cache.get(h.cache.S1, sx_cache, n) + S2 = h.cache.get(h.cache.S2, sx_cache, n) + Sm2 = h.cache.get(h.cache.Sm2, sx_cache, n) deltaB = ( -(1 / (729 * n**5 * (1 + n) ** 5)) * CF From 00c1c6a6c9238b3af6f5b68f7baea3dc4afd0225 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 11:45:42 +0200 Subject: [PATCH 08/24] clean init --- .../unpolarized/space_like/__init__.py | 294 ++++++------------ 1 file changed, 99 insertions(+), 195 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/__init__.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/__init__.py index b1fb0c168..6a3c6cf06 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/__init__.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/__init__.py @@ -20,7 +20,7 @@ from eko import constants -from .... import harmonics +from ....harmonics import cache as c from . import aem1, aem2, as1, as1aem1, as2, as3, as4 @@ -44,62 +44,38 @@ def gamma_ns(order, mode, n, nf): numpy.ndarray non-singlet anomalous dimensions - See Also - -------- - ekore.anomalous_dimensions.unpolarized.space_like.as1.gamma_ns : :math:`\gamma_{ns}^{(0)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as2.gamma_nsp : :math:`\gamma_{ns,+}^{(1)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as2.gamma_nsm : :math:`\gamma_{ns,-}^{(1)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as3.gamma_nsp : :math:`\gamma_{ns,+}^{(2)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as3.gamma_nsm : :math:`\gamma_{ns,-}^{(2)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as3.gamma_nsv : :math:`\gamma_{ns,v}^{(2)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as4.gamma_nsp : :math:`\gamma_{ns,+}^{(3)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as4.gamma_nsm : :math:`\gamma_{ns,-}^{(3)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as4.gamma_nsv : :math:`\gamma_{ns,v}^{(3)}(N)` - """ - # cache the s-es - if order[0] >= 4: - full_sx_cache = harmonics.compute_cache(n, 5, is_singlet=False) - sx = np.array( - [ - full_sx_cache[0][0], - full_sx_cache[1][0], - full_sx_cache[2][0], - full_sx_cache[3][0], - ] - ) - else: - sx = harmonics.sx(n, max_weight=order[0] + 1) + cache = c.reset() # now combine gamma_ns = np.zeros(order[0], np.complex_) - gamma_ns[0] = as1.gamma_ns(n, sx[0]) + gamma_ns[0] = as1.gamma_ns(n, cache) # NLO and beyond if order[0] >= 2: if mode == 10101: - gamma_ns_1 = as2.gamma_nsp(n, nf, sx) + gamma_ns_1 = as2.gamma_nsp(n, nf, cache) # To fill the full valence vector in NNLO we need to add gamma_ns^1 explicitly here elif mode in [10201, 10200]: - gamma_ns_1 = as2.gamma_nsm(n, nf, sx) + gamma_ns_1 = as2.gamma_nsm(n, nf, cache) else: raise NotImplementedError("Non-singlet sector is not implemented") gamma_ns[1] = gamma_ns_1 # NNLO and beyond if order[0] >= 3: if mode == 10101: - gamma_ns_2 = as3.gamma_nsp(n, nf, sx) + gamma_ns_2 = as3.gamma_nsp(n, nf, cache) elif mode == 10201: - gamma_ns_2 = as3.gamma_nsm(n, nf, sx) + gamma_ns_2 = as3.gamma_nsm(n, nf, cache) elif mode == 10200: - gamma_ns_2 = as3.gamma_nsv(n, nf, sx) + gamma_ns_2 = as3.gamma_nsv(n, nf, cache) gamma_ns[2] = gamma_ns_2 # N3LO if order[0] >= 4: if mode == 10101: - gamma_ns_3 = as4.gamma_nsp(n, nf, full_sx_cache) + gamma_ns_3 = as4.gamma_nsp(n, nf, cache) elif mode == 10201: - gamma_ns_3 = as4.gamma_nsm(n, nf, full_sx_cache) + gamma_ns_3 = as4.gamma_nsm(n, nf, cache) elif mode == 10200: - gamma_ns_3 = as4.gamma_nsv(n, nf, full_sx_cache) + gamma_ns_3 = as4.gamma_nsv(n, nf, cache) gamma_ns[3] = gamma_ns_3 return gamma_ns @@ -124,39 +100,16 @@ def gamma_singlet(order, n, nf, n3lo_ad_variation): numpy.ndarray singlet anomalous dimensions matrices - See Also - -------- - ekore.anomalous_dimensions.unpolarized.space_like.as1.gamma_singlet : :math:`\gamma_{S}^{(0)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as2.gamma_singlet : :math:`\gamma_{S}^{(1)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as3.gamma_singlet : :math:`\gamma_{S}^{(2)}(N)` - ekore.anomalous_dimensions.unpolarized.space_like.as4.gamma_singlet : :math:`\gamma_{S}^{(3)}(N)` - """ - # cache the s-es - if order[0] >= 4: - full_sx_cache = harmonics.compute_cache(n, 5, is_singlet=False) - sx = np.array( - [ - full_sx_cache[0][0], - full_sx_cache[1][0], - full_sx_cache[2][0], - full_sx_cache[3][0], - ] - ) - elif order[0] >= 3: - # here we need only S1,S2,S3,S4 - sx = harmonics.sx(n, max_weight=order[0] + 1) - else: - sx = harmonics.sx(n, max_weight=order[0]) - + cache = c.reset() gamma_s = np.zeros((order[0], 2, 2), np.complex_) - gamma_s[0] = as1.gamma_singlet(n, sx[0], nf) + gamma_s[0] = as1.gamma_singlet(n, cache, nf) if order[0] >= 2: - gamma_s[1] = as2.gamma_singlet(n, nf, sx) + gamma_s[1] = as2.gamma_singlet(n, nf, cache) if order[0] >= 3: - gamma_s[2] = as3.gamma_singlet(n, nf, sx) + gamma_s[2] = as3.gamma_singlet(n, nf, cache) if order[0] >= 4: - gamma_s[3] = as4.gamma_singlet(n, nf, full_sx_cache, n3lo_ad_variation) + gamma_s[3] = as4.gamma_singlet(n, nf, cache, n3lo_ad_variation) return gamma_s @@ -180,138 +133,119 @@ def gamma_ns_qed(order, mode, n, nf): ------- gamma_ns : numpy.ndarray non-singlet QED anomalous dimensions - - See Also - -------- - eko.anomalous_dimensions.as1.gamma_ns : :math:`\gamma_{ns}^{(0)}(N)` - eko.anomalous_dimensions.as2.gamma_nsp : :math:`\gamma_{ns,+}^{(1)}(N)` - eko.anomalous_dimensions.as2.gamma_nsm : :math:`\gamma_{ns,-}^{(1)}(N)` - eko.anomalous_dimensions.as3.gamma_nsp : :math:`\gamma_{ns,+}^{(2)}(N)` - eko.anomalous_dimensions.as3.gamma_nsm : :math:`\gamma_{ns,-}^{(2)}(N)` - eko.anomalous_dimensions.as3.gamma_nsv : :math:`\gamma_{ns,v}^{(2)}(N)` - eko.anomalous_dimensions.aem1.gamma_ns : :math:`\gamma_{ns}^{(0,1)}(N)` - eko.anomalous_dimensions.aem1.gamma_ns : :math:`\gamma_{ns,v}^{(0,1)}(N)` - eko.anomalous_dimensions.as1aem1.gamma_nsp : :math:`\gamma_{ns,p}^{(1,1)}(N)` - eko.anomalous_dimensions.as1aem1.gamma_nsm : :math:`\gamma_{ns,m}^{(1,1)}(N)` - eko.anomalous_dimensions.aem2.gamma_nspu : :math:`\gamma_{ns,pu}^{(0,2)}(N)` - eko.anomalous_dimensions.aem2.gamma_nsmu : :math:`\gamma_{ns,mu}^{(0,2)}(N)` - eko.anomalous_dimensions.aem2.gamma_nspd : :math:`\gamma_{ns,pd}^{(0,2)}(N)` - eko.anomalous_dimensions.aem2.gamma_nsmd : :math:`\gamma_{ns,md}^{(0,2)}(N)` """ - # cache the s-es - max_weight = max(order) - if max_weight >= 3: - # here we need only S1,S2,S3,S4 - sx = harmonics.sx(n, max_weight=max_weight + 1) - else: - sx = harmonics.sx(n, max_weight=3) - sx_ns_qed = harmonics.compute_qed_ns_cache(n, sx[0]) + cache = c.reset() # now combine gamma_ns = np.zeros((order[0] + 1, order[1] + 1), np.complex_) - gamma_ns[1, 0] = as1.gamma_ns(n, sx[0]) - gamma_ns[0, 1] = choose_ns_ad_aem1(mode, n, sx) - gamma_ns[1, 1] = choose_ns_ad_as1aem1(mode, n, sx, sx_ns_qed) + gamma_ns[1, 0] = as1.gamma_ns(n, cache) + gamma_ns[0, 1] = choose_ns_ad_aem1(mode, n, cache) + gamma_ns[1, 1] = choose_ns_ad_as1aem1(mode, n, cache) # NLO and beyond if order[0] >= 2: if mode in [10102, 10103]: - gamma_ns[2, 0] = as2.gamma_nsp(n, nf, sx) + gamma_ns[2, 0] = as2.gamma_nsp(n, nf, cache) # To fill the full valence vector in NNLO we need to add gamma_ns^1 explicitly here else: - gamma_ns[2, 0] = as2.gamma_nsm(n, nf, sx) + gamma_ns[2, 0] = as2.gamma_nsm(n, nf, cache) if order[1] >= 2: - gamma_ns[0, 2] = choose_ns_ad_aem2(mode, n, nf, sx, sx_ns_qed) + gamma_ns[0, 2] = choose_ns_ad_aem2(mode, n, nf, cache) # NNLO and beyond if order[0] >= 3: if mode in [10102, 10103]: - gamma_ns[3, 0] = as3.gamma_nsp(n, nf, sx) + gamma_ns[3, 0] = as3.gamma_nsp(n, nf, cache) elif mode in [10202, 10203]: - gamma_ns[3, 0] = as3.gamma_nsm(n, nf, sx) + gamma_ns[3, 0] = as3.gamma_nsm(n, nf, cache) return gamma_ns @nb.njit(cache=True) -def choose_ns_ad_aem1(mode, n, sx): +def choose_ns_ad_aem1(mode, n, cache): r""" Select the non-singlet anomalous dimension at O(aem1) with the correct charge factor. Parameters ---------- - mode : 10102 | 10202 | 10103 | 10203 - sector identifier - n : complex - Mellin variable - nf : int - Number of active flavors + mode : 10102 | 10202 | 10103 | 10203 + sector identifier + n : complex + Mellin variable + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_ns : numpy.ndarray - non-singlet anomalous dimensions + numpy.ndarray + non-singlet anomalous dimensions + """ if mode in [10102, 10202]: - return constants.eu2 * aem1.gamma_ns(n, sx) + return constants.eu2 * aem1.gamma_ns(n, cache) elif mode in [10103, 10203]: - return constants.ed2 * aem1.gamma_ns(n, sx) + return constants.ed2 * aem1.gamma_ns(n, cache) raise NotImplementedError("Non-singlet sector is not implemented") @nb.njit(cache=True) -def choose_ns_ad_as1aem1(mode, n, sx, sx_ns_qed): +def choose_ns_ad_as1aem1(mode, n, cache): r""" Select the non-singlet anomalous dimension at O(as1aem1) with the correct charge factor. Parameters ---------- - mode : 10102 | 10202 | 10103 | 10203 - sector identifier - n : complex - Mellin variable - nf : int - Number of active flavors + mode : 10102 | 10202 | 10103 | 10203 + sector identifier + n : complex + Mellin variable + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_ns : numpy.ndarray - non-singlet anomalous dimensions + numpy.ndarray + non-singlet anomalous dimensions + """ if mode == 10102: - return constants.eu2 * as1aem1.gamma_nsp(n, sx, sx_ns_qed) + return constants.eu2 * as1aem1.gamma_nsp(n, cache) elif mode == 10103: - return constants.ed2 * as1aem1.gamma_nsp(n, sx, sx_ns_qed) + return constants.ed2 * as1aem1.gamma_nsp(n, cache) elif mode == 10202: - return constants.eu2 * as1aem1.gamma_nsm(n, sx, sx_ns_qed) + return constants.eu2 * as1aem1.gamma_nsm(n, cache) elif mode == 10203: - return constants.ed2 * as1aem1.gamma_nsm(n, sx, sx_ns_qed) + return constants.ed2 * as1aem1.gamma_nsm(n, cache) raise NotImplementedError("Non-singlet sector is not implemented") @nb.njit(cache=True) -def choose_ns_ad_aem2(mode, n, nf, sx, sx_ns_qed): +def choose_ns_ad_aem2(mode, n, nf, cache): r""" Select the non-singlet anomalous dimension at O(aem2) with the correct charge factor. Parameters ---------- - mode : 10102 | 10202 | 10103 | 10203 - sector identifier - n : complex - Mellin variable - nf : int - Number of active flavors + mode : 10102 | 10202 | 10103 | 10203 + sector identifier + n : complex + Mellin variable + nf : int + Number of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_ns : numpy.ndarray - non-singlet anomalous dimensions + numpy.ndarray + non-singlet anomalous dimensions + """ if mode == 10102: - return constants.eu2 * aem2.gamma_nspu(n, nf, sx, sx_ns_qed) + return constants.eu2 * aem2.gamma_nspu(n, nf, cache) elif mode == 10103: - return constants.ed2 * aem2.gamma_nspd(n, nf, sx, sx_ns_qed) + return constants.ed2 * aem2.gamma_nspd(n, nf, cache) elif mode == 10202: - return constants.eu2 * aem2.gamma_nsmu(n, nf, sx, sx_ns_qed) + return constants.eu2 * aem2.gamma_nsmu(n, nf, cache) elif mode == 10203: - return constants.ed2 * aem2.gamma_nsmd(n, nf, sx, sx_ns_qed) + return constants.ed2 * aem2.gamma_nsmd(n, nf, cache) raise NotImplementedError("Non-singlet sector is not implemented") @@ -322,45 +256,30 @@ def gamma_singlet_qed(order, n, nf): Parameters ---------- - order : tuple(int,int) - perturbative orders - n : complex - Mellin variable - nf : int - Number of active flavors + order : tuple(int,int) + perturbative orders + n : complex + Mellin variable + nf : int + Number of active flavors Returns ------- - gamma_singlet : numpy.ndarray - singlet anomalous dimensions matrices - - See Also - -------- - eko.anomalous_dimensions.as1.gamma_singlet_qed : :math:`\gamma_{S}^{(0)}(N)` - eko.anomalous_dimensions.as2.gamma_singlet_qed : :math:`\gamma_{S}^{(1)}(N)` - eko.anomalous_dimensions.as3.gamma_singlet_qed : :math:`\gamma_{S}^{(2)}(N)` - eko.anomalous_dimensions.aem1.gamma_singlet : :math:`\gamma_{S}^{(0,1)}(N)` - eko.anomalous_dimensions.as1aem1.gamma_singlet : :math:`\gamma_{S}^{(1,1)}(N)` - eko.anomalous_dimensions.aem2.gamma_singlet : :math:`\gamma_{S}^{(0,2)}(N)` + numpy.ndarray + singlet anomalous dimensions matrices + """ - # cache the s-es - max_weight = max(order) - if max_weight >= 3: - # here we need only S1,S2,S3,S4 - sx = harmonics.sx(n, max_weight=max_weight + 1) - else: - sx = harmonics.sx(n, max_weight=3) - sx_ns_qed = harmonics.compute_qed_ns_cache(n, sx[0]) + cache = c.reset() gamma_s = np.zeros((order[0] + 1, order[1] + 1, 4, 4), np.complex_) - gamma_s[1, 0] = as1.gamma_singlet_qed(n, sx[0], nf) - gamma_s[0, 1] = aem1.gamma_singlet(n, nf, sx) - gamma_s[1, 1] = as1aem1.gamma_singlet(n, nf, sx, sx_ns_qed) + gamma_s[1, 0] = as1.gamma_singlet_qed(n, cache, nf) + gamma_s[0, 1] = aem1.gamma_singlet(n, nf, cache) + gamma_s[1, 1] = as1aem1.gamma_singlet(n, nf, cache) if order[0] >= 2: - gamma_s[2, 0] = as2.gamma_singlet_qed(n, nf, sx) + gamma_s[2, 0] = as2.gamma_singlet_qed(n, nf, cache) if order[1] >= 2: - gamma_s[0, 2] = aem2.gamma_singlet(n, nf, sx, sx_ns_qed) + gamma_s[0, 2] = aem2.gamma_singlet(n, nf, cache) if order[0] >= 3: - gamma_s[3, 0] = as3.gamma_singlet_qed(n, nf, sx) + gamma_s[3, 0] = as3.gamma_singlet_qed(n, nf, cache) return gamma_s @@ -371,43 +290,28 @@ def gamma_valence_qed(order, n, nf): Parameters ---------- - order : tuple(int,int) - perturbative orders - n : complex - Mellin variable - nf : int - Number of active flavors + order : tuple(int,int) + perturbative orders + n : complex + Mellin variable + nf : int + Number of active flavors Returns ------- - gamma_valence : numpy.ndarray - valence anomalous dimensions matrices - - See Also - -------- - eko.anomalous_dimensions.as1.gamma_valence_qed : :math:`\gamma_{V}^{(0)}(N)` - eko.anomalous_dimensions.as2.gamma_valence_qed : :math:`\gamma_{V}^{(1)}(N)` - eko.anomalous_dimensions.as3.gamma_valence_qed : :math:`\gamma_{V}^{(2)}(N)` - eko.anomalous_dimensions.aem1.gamma_valence : :math:`\gamma_{V}^{(0,1)}(N)` - eko.anomalous_dimensions.as1aem1.gamma_valence : :math:`\gamma_{V}^{(1,1)}(N)` - eko.anomalous_dimensions.aem2.gamma_valence : :math:`\gamma_{V}^{(0,2)}(N)` + numpy.ndarray + valence anomalous dimensions matrices + """ - # cache the s-es - max_weight = max(order) - if max_weight >= 3: - # here we need only S1,S2,S3,S4 - sx = harmonics.sx(n, max_weight=max_weight + 1) - else: - sx = harmonics.sx(n, max_weight=3) - sx_ns_qed = harmonics.compute_qed_ns_cache(n, sx[0]) + cache = c.reset() gamma_v = np.zeros((order[0] + 1, order[1] + 1, 2, 2), np.complex_) - gamma_v[1, 0] = as1.gamma_valence_qed(n, sx[0]) - gamma_v[0, 1] = aem1.gamma_valence(n, nf, sx) - gamma_v[1, 1] = as1aem1.gamma_valence(n, nf, sx, sx_ns_qed) + gamma_v[1, 0] = as1.gamma_valence_qed(n, cache) + gamma_v[0, 1] = aem1.gamma_valence(n, nf, cache) + gamma_v[1, 1] = as1aem1.gamma_valence(n, nf, cache) if order[0] >= 2: - gamma_v[2, 0] = as2.gamma_valence_qed(n, nf, sx) + gamma_v[2, 0] = as2.gamma_valence_qed(n, nf, cache) if order[1] >= 2: - gamma_v[0, 2] = aem2.gamma_valence(n, nf, sx, sx_ns_qed) + gamma_v[0, 2] = aem2.gamma_valence(n, nf, cache) if order[0] >= 3: - gamma_v[3, 0] = as3.gamma_valence_qed(n, nf, sx) + gamma_v[3, 0] = as3.gamma_valence_qed(n, nf, cache) return gamma_v From 7e7eadc7b36885cc54bdb7d5ea99f743b59a3e0f Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 12:13:53 +0200 Subject: [PATCH 09/24] idem con patate per timelike --- .../unpolarized/time_like/__init__.py | 21 +-- .../unpolarized/time_like/as1.py | 44 +++--- .../unpolarized/time_like/as2.py | 136 ++++++++++-------- .../unpolarized/time_like/as3.py | 102 +++++++------ .../unpolarized/time_like/test_as1.py | 16 ++- .../unpolarized/time_like/test_as2.py | 16 ++- .../unpolarized/time_like/test_as3.py | 22 ++- 7 files changed, 206 insertions(+), 151 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/__init__.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/__init__.py index 59b69e478..267924c9b 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/__init__.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/__init__.py @@ -3,6 +3,7 @@ import numba as nb import numpy as np +from ....harmonics import cache as c from . import as1, as2, as3 @@ -27,21 +28,22 @@ def gamma_ns(order, mode, n, nf): non-singlet anomalous dimensions """ + cache = c.reset() gamma_ns = np.zeros(order[0], np.complex_) - gamma_ns[0] = as1.gamma_ns(n) + gamma_ns[0] = as1.gamma_ns(n, cache) if order[0] >= 2: if mode == 10101: - gamma_ns_1 = as2.gamma_nsp(n, nf) + gamma_ns_1 = as2.gamma_nsp(n, nf, cache) elif mode in [10201, 10200]: - gamma_ns_1 = as2.gamma_nsm(n, nf) + gamma_ns_1 = as2.gamma_nsm(n, nf, cache) gamma_ns[1] = gamma_ns_1 if order[0] >= 3: if mode == 10101: - gamma_ns_2 = as3.gamma_nsp(n, nf) + gamma_ns_2 = as3.gamma_nsp(n, nf, cache) elif mode == 10201: - gamma_ns_2 = as3.gamma_nsm(n, nf) + gamma_ns_2 = as3.gamma_nsm(n, nf, cache) elif mode == 10200: - gamma_ns_2 = as3.gamma_nsv(n, nf) + gamma_ns_2 = as3.gamma_nsv(n, nf, cache) gamma_ns[2] = gamma_ns_2 return gamma_ns @@ -65,10 +67,11 @@ def gamma_singlet(order, n, nf): singlet anomalous dimensions matrices """ + cache = c.reset() gamma_s = np.zeros((order[0], 2, 2), np.complex_) - gamma_s[0] = as1.gamma_singlet(n, nf) + gamma_s[0] = as1.gamma_singlet(n, nf, cache) if order[0] >= 2: - gamma_s[1] = as2.gamma_singlet(n, nf) + gamma_s[1] = as2.gamma_singlet(n, nf, cache) if order[0] >= 3: - gamma_s[2] = as3.gamma_singlet(n, nf) + gamma_s[2] = as3.gamma_singlet(n, nf, cache) return gamma_s diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as1.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as1.py index 44913ba05..f6e545d63 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as1.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as1.py @@ -5,11 +5,11 @@ from eko import constants -from ....harmonics import w1 +from ....harmonics import cache as c @nb.njit(cache=True) -def gamma_qq(N): +def gamma_qq(N, cache): r"""Compute the |LO| quark-quark anomalous dimension. Implements :eqref:`B.3` from :cite:`Mitov:2006wy`. @@ -18,16 +18,18 @@ def gamma_qq(N): ---------- N : complex Mellin moment + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_qq : complex + complex LO quark-quark anomalous dimension :math:`\gamma_{qq}^{(0)}(N)` """ - s1 = w1.S1(N) - result = constants.CF * (-3.0 + (4.0 * s1) - 2.0 / (N * (N + 1.0))) + S1 = c.get(c.S1, cache, N) + result = constants.CF * (-3.0 + (4.0 * S1) - 2.0 / (N * (N + 1.0))) return result @@ -45,7 +47,7 @@ def gamma_qg(N): Returns ------- - gamma_qg : complex + complex LO quark-gluon anomalous dimension :math:`\gamma_{qg}^{(0)}(N)` @@ -70,7 +72,7 @@ def gamma_gq(N, nf): Returns ------- - gamma_qg : complex + complex LO quark-gluon anomalous dimension :math:`\gamma_{gq}^{(0)}(N)` @@ -80,7 +82,7 @@ def gamma_gq(N, nf): @nb.njit(cache=True) -def gamma_gg(N, nf): +def gamma_gg(N, nf, cache): r"""Compute the |LO| gluon-gluon anomalous dimension. Implements :eqref:`B.6` from :cite:`Mitov:2006wy`. @@ -91,23 +93,25 @@ def gamma_gg(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_qq : complex + complex LO quark-quark anomalous dimension :math:`\gamma_{gg}^{(0)}(N)` """ - s1 = w1.S1(N) + S1 = c.get(c.S1, cache, N) result = (2.0 * nf - 11.0 * constants.CA) / 3.0 + 4.0 * constants.CA * ( - s1 - 1.0 / (N * (N - 1.0)) - 1.0 / ((N + 1.0) * (N + 2.0)) + S1 - 1.0 / (N * (N - 1.0)) - 1.0 / ((N + 1.0) * (N + 2.0)) ) return result @nb.njit(cache=True) -def gamma_ns(N): +def gamma_ns(N, cache): r"""Compute the |LO| non-singlet anomalous dimension. At LO, :math:`\gamma_{ns}^{(0)} = \gamma_{qq}^{(0)}`. @@ -116,19 +120,21 @@ def gamma_ns(N): ---------- N : complex Mellin moment + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_ns : complex + complex LO quark-quark anomalous dimension :math:`\gamma_{ns}^{(0)}(N)` """ - return gamma_qq(N) + return gamma_qq(N, cache) @nb.njit(cache=True) -def gamma_singlet(N, nf): +def gamma_singlet(N, nf, cache): r"""Compute the |LO| singlet anomalous dimension matrix. Implements :eqref:`2.13` from :cite:`Gluck:1992zx`. @@ -139,17 +145,19 @@ def gamma_singlet(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_singlet : numpy.ndarray + numpy.ndarray LO singlet anomalous dimension matrix :math:`\gamma_{s}^{(0)}` """ result = np.array( [ - [gamma_qq(N), gamma_gq(N, nf)], - [gamma_qg(N), gamma_gg(N, nf)], + [gamma_qq(N, cache), gamma_gq(N, nf)], + [gamma_qg(N), gamma_gg(N, nf, cache)], ], np.complex_, ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py index 1a0f03c2a..f8d6f8ceb 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py @@ -7,12 +7,14 @@ from eko import constants from eko.constants import zeta2, zeta3 -from ....harmonics import w1, w2, w3 +from ....harmonics import cache as c + +# TODO: CLEAN: all the calls to polygamma could be reduced to some harmonics... from ....harmonics.polygamma import cern_polygamma as polygamma @nb.njit(cache=True) -def gamma_nsp(N, nf): +def gamma_nsp(N, nf, cache): r"""Compute the |NLO| non-singlet positive anomalous dimension. Implements :eqref:`A6` from :cite:`Gluck:1992zx`. @@ -23,10 +25,12 @@ def gamma_nsp(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsp : complex + complex NLO non-singlet positive anomalous dimension :math:`\gamma_{ns}^{(1)+}(N)` @@ -40,8 +44,8 @@ def gamma_nsp(N, nf): N1S = N1 * N1 N1T = N1S * N1 - S1 = w1.S1(N) - S2 = w2.S2(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) N3 = N + 3 N4 = N + 4 @@ -114,7 +118,7 @@ def gamma_nsp(N, nf): @nb.njit(cache=True) -def gamma_nsm(N, nf): +def gamma_nsm(N, nf, cache): r"""Compute the |NLO| non-singlet negative anomalous dimension. Based on :cite:`Gluck:1992zx`. @@ -125,10 +129,12 @@ def gamma_nsm(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsm : complex + complex NLO non-singlet negative anomalous dimension :math:`\gamma_{ns}^{(1)-}(N)` @@ -142,8 +148,8 @@ def gamma_nsm(N, nf): N1S = N1 * N1 N1T = N1S * N1 - S1 = w1.S1(N) - S2 = w2.S2(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) N3 = N + 3 N4 = N + 4 @@ -229,12 +235,12 @@ def gamma_qqs(N, nf): Returns ------- - gamma_qqs : complex + complex NLO quark-quark singlet anomalous dimension :math:`\gamma_{qq}^{(1)s}(N)` """ - qqs1 = ( + qqS1 = ( constants.CF * nf * ( @@ -254,11 +260,11 @@ def gamma_qqs(N, nf): / ((-1 + N) * npp(N, 3) * npp(1 + N, 3) * npp(2 + N, 2)) ) ) - return qqs1 + return qqS1 @nb.njit(cache=True) -def gamma_qg(N, nf): +def gamma_qg(N, nf, cache): r"""Compute the |NLO| quark-gluon anomalous dimension. Implements :eqref:`B.10` from :cite:`Mitov:2006wy` @@ -270,17 +276,19 @@ def gamma_qg(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_qg : complex + complex NLO quark-gluon anomalous dimension :math:`\gamma_{qg}^{(1)}(N)` """ - s1 = w1.S1(N) - s2 = w2.S2(N) - sm2 = w2.Sm2(N, s2, True) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + Sm2 = c.get(c.Sm2, cache, N, is_singlet=True) qg1 = ( nf @@ -302,7 +310,7 @@ def gamma_qg(N, nf): / (npp(N, 3) * npp(1 + N, 3) * npp(2 + N, 2)) - ( 4 - * s1 + * S1 * ( -8 - 12 * N @@ -313,8 +321,8 @@ def gamma_qg(N, nf): ) ) / (npp(N, 2) * npp(1 + N, 2) * npp(2 + N, 2)) - + (4 * npp(s1, 2) * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) - - (20 * s2 * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) + + (4 * npp(S1, 2) * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) + - (20 * S2 * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) ) ) qg2 = ( @@ -350,10 +358,10 @@ def gamma_qg(N, nf): ) ) / (9 * (-1 + N) * npp(N, 3) * npp(1 + N, 3) * npp(2 + N, 3)) - + (8 * sm2 * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) + + (8 * Sm2 * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) + ( 4 - * s1 + * S1 * ( -48 - 100 * N @@ -364,8 +372,8 @@ def gamma_qg(N, nf): ) ) / (3 * npp(N, 2) * npp(1 + N, 2) * npp(2 + N, 2)) - - (4 * npp(s1, 2) * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) - + (12 * s2 * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) + - (4 * npp(S1, 2) * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) + + (12 * S2 * (2 + N + npp(N, 2))) / (N * (1 + N) * (2 + N)) ) ) qg3 = ( @@ -384,7 +392,7 @@ def gamma_qg(N, nf): ) ) / (9 * npp(N, 2) * npp(1 + N, 2) * npp(2 + N, 2)) - - (8 * s1 * (2 + N + npp(N, 2))) / (3 * N * (1 + N) * (2 + N)) + - (8 * S1 * (2 + N + npp(N, 2))) / (3 * N * (1 + N) * (2 + N)) ) ) result = (1 / (2 * nf)) * (qg1 + qg2 + qg3) @@ -392,7 +400,7 @@ def gamma_qg(N, nf): @nb.njit(cache=True) -def gamma_gq(N, nf): +def gamma_gq(N, nf, cache): r"""Compute the |NLO| gluon-quark anomalous dimension. Implements :eqref:`B.11` from :cite:`Mitov:2006wy` @@ -404,18 +412,19 @@ def gamma_gq(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gq : complex + complex NLO gluon-quark anomalous dimension :math:`\gamma_{gq}^{(1)}(N)` """ - s1 = w1.S1(N) - s2 = w2.S2(N) - sm2 = w2.Sm2(N, s2, True) - + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + Sm2 = c.get(c.Sm2, cache, N, is_singlet=True) gq1 = ( constants.CF * constants.CF @@ -442,11 +451,11 @@ def gamma_gq(N, nf): + ( 8 * (4 - 2 * N - 16 * npp(N, 2) - npp(N, 3) - 2 * npp(N, 4) + npp(N, 5)) - * s1 + * S1 ) / (npp(-1 + N, 2) * npp(N, 2) * npp(1 + N, 2)) - - (4 * (2 + N + npp(N, 2)) * npp(s1, 2)) / ((-1 + N) * N * (1 + N)) - + (12 * (2 + N + npp(N, 2)) * s2) / ((-1 + N) * N * (1 + N)) + - (4 * (2 + N + npp(N, 2)) * npp(S1, 2)) / ((-1 + N) * N * (1 + N)) + + (12 * (2 + N + npp(N, 2)) * S2) / ((-1 + N) * N * (1 + N)) ) ) gq2 = ( @@ -477,11 +486,11 @@ def gamma_gq(N, nf): ) ) / (npp(-1 + N, 3) * npp(N, 3) * npp(1 + N, 3) * npp(2 + N, 2)) - + (8 * (2 + N + npp(N, 2)) * sm2) / ((-1 + N) * N * (1 + N)) - - (8 * (2 - 2 * N - 9 * npp(N, 2) + npp(N, 3) - npp(N, 4) + npp(N, 5)) * s1) + + (8 * (2 + N + npp(N, 2)) * Sm2) / ((-1 + N) * N * (1 + N)) + - (8 * (2 - 2 * N - 9 * npp(N, 2) + npp(N, 3) - npp(N, 4) + npp(N, 5)) * S1) / (npp(-1 + N, 2) * npp(N, 2) * npp(1 + N, 2)) - + (4 * (2 + N + npp(N, 2)) * npp(s1, 2)) / ((-1 + N) * N * (1 + N)) - - (20 * (2 + N + npp(N, 2)) * s2) / ((-1 + N) * N * (1 + N)) + + (4 * (2 + N + npp(N, 2)) * npp(S1, 2)) / ((-1 + N) * N * (1 + N)) + - (20 * (2 + N + npp(N, 2)) * S2) / ((-1 + N) * N * (1 + N)) ) ) result = (2 * nf) * (gq1 + gq2) @@ -489,7 +498,7 @@ def gamma_gq(N, nf): @nb.njit(cache=True) -def gamma_gg(N, nf): +def gamma_gg(N, nf, cache): r"""Compute the |NLO| gluon-gluon anomalous dimension. Implements :eqref:`B.12` from :cite:`Mitov:2006wy`. @@ -500,21 +509,22 @@ def gamma_gg(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gg : complex + complex NLO gluon-gluon anomalous dimension :math:`\gamma_{gg}^{(1)}(N)` """ - s1 = w1.S1(N) - s2 = w2.S2(N) - s3 = w3.S3(N) - sm1 = w1.Sm1(N, s1, True) - sm2 = w2.Sm2(N, s2, True) - sm3 = w3.Sm3(N, s3, True) - sm21 = w3.Sm21(N, s1, sm1, True) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) + Sm2 = c.get(c.Sm2, cache, N, is_singlet=True) + Sm3 = c.get(c.Sm3, cache, N, is_singlet=True) + Sm21 = c.get(c.Sm21, cache, N, is_singlet=True) gg1 = ( nf @@ -582,15 +592,15 @@ def gamma_gg(N, nf): ) ) / (9 * npp(-1 + N, 3) * npp(N, 3) * npp(1 + N, 3) * npp(2 + N, 3)) - - (8 * sm3) - + (sm2) + - (8 * Sm3) + + (Sm2) * ( (32 * (1 + N + npp(N, 2))) / ((-1 + N) * N * (1 + N) * (2 + N)) - - 16 * s1 + - 16 * S1 ) - - (8 * s2 * (12 - 10 * N + npp(N, 2) + 22 * npp(N, 3) + 11 * npp(N, 4))) + - (8 * S2 * (12 - 10 * N + npp(N, 2) + 22 * npp(N, 3) + 11 * npp(N, 4))) / (3 * (-1 + N) * N * (1 + N) * (2 + N)) - + (s1) + + (S1) * ( -( 4 @@ -614,10 +624,10 @@ def gamma_gg(N, nf): ) ) / (9 * npp(-1 + N, 2) * npp(N, 2) * npp(1 + N, 2) * npp(2 + N, 2)) - + 16 * s2 + + 16 * S2 ) - - (8 * s3) - + (16 * sm21) + - (8 * S3) + + (16 * Sm21) ) ) gg3 = ( @@ -646,8 +656,8 @@ def gamma_gg(N, nf): ) ) / (9 * npp(-1 + N, 2) * npp(N, 2) * npp(1 + N, 2) * npp(2 + N, 2)) - - (s1 * (40 / 9)) - + (s2 * (16 / 3)) + - (S1 * (40 / 9)) + + (S2 * (16 / 3)) ) ) result = gg1 + gg2 + gg3 @@ -655,7 +665,7 @@ def gamma_gg(N, nf): @nb.njit(cache=True) -def gamma_singlet(N, nf): +def gamma_singlet(N, nf, cache): r"""Compute the |NLO| singlet anomalous dimension matrix. Implements :eqref:`2.13` from :cite:`Gluck:1992zx`. @@ -666,20 +676,22 @@ def gamma_singlet(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_singlet : numpy.ndarray + numpy.ndarray NLO singlet anomalous dimension matrix :math:`\gamma_{s}^{(1)}` """ - gamma_qq = gamma_nsp(N, nf) + gamma_qqs(N, nf) + gamma_qq = gamma_nsp(N, nf, cache) + gamma_qqs(N, nf) result = np.array( [ - [gamma_qq, gamma_gq(N, nf)], - [gamma_qg(N, nf), gamma_gg(N, nf)], + [gamma_qq, gamma_gq(N, nf, cache)], + [gamma_qg(N, nf, cache), gamma_gg(N, nf, cache)], ], np.complex_, ) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as3.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as3.py index 2ee38d2c7..70793acc1 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as3.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as3.py @@ -6,11 +6,11 @@ from eko.constants import zeta2, zeta3 -from ....harmonics import w1, w2, w3, w4 +from ....harmonics import cache as c @nb.njit(cache=True) -def gamma_nsp(N, nf): +def gamma_nsp(N, nf, cache): r"""Compute the |NNLO| non-singlet positive anomalous dimension. Implements :eqref:`15` from :cite:`Mitov:2006ic` via the @@ -22,10 +22,12 @@ def gamma_nsp(N, nf): Mellin moment nf : int No. of active flavors + ache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsp : complex + complex NNLO non-singlet positive anomalous dimension :math:`\gamma_{ns,+}^{(2)}(N)` @@ -39,9 +41,9 @@ def gamma_nsp(N, nf): N1I3 = N1I * N1I2 N2 = N + 2 N2I = 1 / N2 - S1 = w1.S1(N) - S2 = w2.S2(N) - S3 = w3.S3(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) S1M = S1 - NI S11 = S1 + N1I S21 = S2 + N1I2 @@ -114,7 +116,7 @@ def gamma_nsp(N, nf): @nb.njit(cache=True) -def gamma_nsm(N, nf): +def gamma_nsm(N, nf, cache): r"""Compute the |NNLO| non-singlet negative anomalous dimension. Implements :eqref:`16` from :cite:`Mitov:2006ic` via the @@ -126,10 +128,12 @@ def gamma_nsm(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsm : complex + complex NNLO non-singlet negative anomalous dimension :math:`\gamma_{ns,-}^{(2)}(N)` @@ -143,9 +147,9 @@ def gamma_nsm(N, nf): N1I3 = N1I * N1I2 N2 = N + 2 N2I = 1 / N2 - S1 = w1.S1(N) - S2 = w2.S2(N) - S3 = w3.S3(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) S1M = S1 - NI S11 = S1 + N1I S21 = S2 + N1I2 @@ -223,7 +227,7 @@ def gamma_nsm(N, nf): @nb.njit(cache=True) -def gamma_nsv(N, nf): +def gamma_nsv(N, nf, cache): r"""Compute the |NNLO| non-singlet valence anomalous dimension. Implements :eqref:`16` from :cite:`Mitov:2006ic` via the @@ -235,10 +239,12 @@ def gamma_nsv(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_nsv : complex + complex NNLO non-singlet valence anomalous dimension :math:`\gamma_{ns,v}^{(2)}(N)` @@ -252,9 +258,9 @@ def gamma_nsv(N, nf): N1I = 1 / N1 N2 = N + 2 N2I = 1 / N2 - S1 = w1.S1(N) - S2 = w2.S2(N) - S3 = w3.S3(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) S1M = S1 - NI S11 = S1 + N1I S12 = S11 + N2I @@ -291,12 +297,12 @@ def gamma_nsv(N, nf): + 46.18 * E2 ) - result = gamma_nsm(N, nf) + nf * PS2 + result = gamma_nsm(N, nf, cache) + nf * PS2 return -result @nb.njit(cache=True) -def gamma_qq(N, nf): +def gamma_qq(N, nf, cache): r"""Compute the |NNLO| quark-quark anomalous dimension. Implements :eqref:`11` from :cite:`Moch:2007tx` via the @@ -308,10 +314,12 @@ def gamma_qq(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_qq : complex + complex NNLO quark-quark anomalous dimension :math:`\gamma_{qq}^{(2)}(N)` @@ -330,9 +338,9 @@ def gamma_qq(N, nf): N2 = N + 2 N2I = 1 / N2 N2I2 = N2I * N2I - S1 = w1.S1(N) - S2 = w2.S2(N) - S3 = w3.S3(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) S11 = S1 + N1I S21 = S2 + N1I2 S31 = S3 + N1I3 @@ -406,7 +414,7 @@ def gamma_qq(N, nf): @nb.njit(cache=True) -def gamma_qg(N, nf): +def gamma_qg(N, nf, cache): r"""Compute the |NNLO| quark-gluon anomalous dimension. Implements :eqref:`18` from :cite:`Almasy:2011eq` via the @@ -418,10 +426,12 @@ def gamma_qg(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_qg : complex + complex NNLO quark-gluon anomalous dimension :math:`\gamma_{qg}^{(2)}(N)` @@ -441,10 +451,10 @@ def gamma_qg(N, nf): N2I = 1 / N2 N2I2 = N2I * N2I N2I3 = N2I * N2I2 - S1 = w1.S1(N) - S2 = w2.S2(N) - S3 = w3.S3(N) - S4 = w4.S4(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) + S4 = c.get(c.S4, cache, N) S11 = S1 + N1I S12 = S11 + N2I S21 = S2 + N1I2 @@ -540,7 +550,7 @@ def gamma_qg(N, nf): @nb.njit(cache=True) -def gamma_gq(N, nf): +def gamma_gq(N, nf, cache): r"""Compute the |NNLO| gluon-quark anomalous dimension. Implements :eqref:`19` from :cite:`Almasy:2011eq` via the @@ -552,10 +562,12 @@ def gamma_gq(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gq : complex + complex NNLO gluon-quark anomalous dimension :math:`\gamma_{gq}^{(2)}(N)` @@ -572,10 +584,10 @@ def gamma_gq(N, nf): N1I2 = N1I * N1I N2 = N + 2 N2I = 1 / N2 - S1 = w1.S1(N) - S2 = w2.S2(N) - S3 = w3.S3(N) - S4 = w4.S4(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) + S4 = c.get(c.S4, cache, N) B1 = -S1 * NI B2 = (npp(S1, 2) + S2) * NI B3 = -(npp(S1, 3) + 3 * S1 * S2 + 2 * S3) * NI @@ -645,7 +657,7 @@ def gamma_gq(N, nf): @nb.njit(cache=True) -def gamma_gg(N, nf): +def gamma_gg(N, nf, cache): r"""Compute the |NNLO| gluon-gluon anomalous dimension. Implements :eqref:`12` from :cite:`Moch:2007tx` via the @@ -657,10 +669,12 @@ def gamma_gg(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_gg : complex + complex NNLO gluon-gluon anomalous dimension :math:`\gamma_{gg}^{(2)}(N)` @@ -677,9 +691,9 @@ def gamma_gg(N, nf): N1I2 = N1I * N1I N2 = N + 2 N2I = 1 / N2 - S1 = w1.S1(N) - S2 = w2.S2(N) - S3 = w3.S3(N) + S1 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) S1M = S1 - NI S11 = S1 + N1I S21 = S2 + N1I2 @@ -772,7 +786,7 @@ def gamma_gg(N, nf): @nb.njit(cache=True) -def gamma_singlet(N, nf): +def gamma_singlet(N, nf, cache): r"""Compute the |NNLO| singlet anomalous dimension matrix. Parameters @@ -781,18 +795,20 @@ def gamma_singlet(N, nf): Mellin moment nf : int No. of active flavors + cache: numpy.ndarray + Harmonic sum cache Returns ------- - gamma_singlet : numpy.ndarray + numpy.ndarray NNLO singlet anomalous dimension matrix :math:`\gamma_{s}^{(2)}` """ result = np.array( [ - [gamma_qq(N, nf), gamma_gq(N, nf)], - [gamma_qg(N, nf), gamma_gg(N, nf)], + [gamma_qq(N, nf, cache), gamma_gq(N, nf, cache)], + [gamma_qg(N, nf, cache), gamma_gg(N, nf, cache)], ], np.complex_, ) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as1.py b/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as1.py index 4e997d38c..9f1f4ac9d 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as1.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as1.py @@ -4,15 +4,17 @@ import ekore.anomalous_dimensions.unpolarized.space_like.as1 as sl_ad_as1 import ekore.anomalous_dimensions.unpolarized.time_like.as1 as ad_as1 -import ekore.harmonics.w1 as w1 +from ekore.harmonics import cache as c NF = 5 def test_qq(): - np.testing.assert_almost_equal(ad_as1.gamma_qq(1), 0) - s1 = w1.S1(1) - np.testing.assert_almost_equal(ad_as1.gamma_qq(1), sl_ad_as1.gamma_ns(1, s1)) + cache = c.reset() + np.testing.assert_almost_equal(ad_as1.gamma_qq(1, cache), 0) + np.testing.assert_almost_equal( + ad_as1.gamma_qq(1, cache), sl_ad_as1.gamma_ns(1, cache) + ) def test_qg(): @@ -24,8 +26,8 @@ def test_gq(): def test_gg(): - np.testing.assert_almost_equal(ad_as1.gamma_gg(2, NF), 10 / 3) - s1 = w1.S1(2) + cache = c.reset() + np.testing.assert_almost_equal(ad_as1.gamma_gg(2, NF, cache), 10 / 3) np.testing.assert_almost_equal( - ad_as1.gamma_gg(2, NF), sl_ad_as1.gamma_gg(2, s1, NF) + ad_as1.gamma_gg(2, NF, cache), sl_ad_as1.gamma_gg(2, cache, NF) ) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as2.py b/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as2.py index df3000e1f..9c81429dc 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as2.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as2.py @@ -3,6 +3,7 @@ import numpy as np import ekore.anomalous_dimensions.unpolarized.time_like.as2 as ad_as2 +from ekore.harmonics import cache as c NF = 5 @@ -11,14 +12,16 @@ def test_nsp(): Nlist = [1, complex(0, 1), complex(1, 1)] res = [1.278774602, 4.904787164 + 58.022801851j, 0.910919333 + 22.344175662j] for i in range(3): - np.testing.assert_almost_equal(ad_as2.gamma_nsp(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as2.gamma_nsp(Nlist[i], NF, cache), res[i]) def test_nsm(): Nlist = [1, complex(0, 1), complex(1, 1)] res = [1.585785642e-06, 1.527559249 + 56.736014509j, 1.312189640 + 22.270151563j] for i in range(3): - np.testing.assert_almost_equal(ad_as2.gamma_nsm(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as2.gamma_nsm(Nlist[i], NF, cache), res[i]) def test_qqs(): @@ -32,7 +35,8 @@ def test_qg(): Nlist = [2, complex(0, 1), complex(1, 1)] res = [4.394040436, 19.069864378 - 1.489605936j, -0.576926260 + 1.543864328j] for i in range(3): - np.testing.assert_almost_equal(ad_as2.gamma_qg(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as2.gamma_qg(Nlist[i], NF, cache), res[i]) def test_gq(): @@ -43,7 +47,8 @@ def test_gq(): 561.338791208 + 1936.775511054j, ] for i in range(3): - np.testing.assert_almost_equal(ad_as2.gamma_gq(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as2.gamma_gq(Nlist[i], NF, cache), res[i]) def test_gg(): @@ -54,4 +59,5 @@ def test_gg(): 130.912306514 + 282.257962305j, ] for i in range(3): - np.testing.assert_almost_equal(ad_as2.gamma_gg(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as2.gamma_gg(Nlist[i], NF, cache), res[i]) diff --git a/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as3.py b/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as3.py index 4ee1bf272..5727902c4 100644 --- a/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as3.py +++ b/tests/ekore/anomalous_dimensions/unpolarized/time_like/test_as3.py @@ -3,6 +3,7 @@ import numpy as np import ekore.anomalous_dimensions.unpolarized.time_like.as3 as ad_as3 +from ekore.harmonics import cache as c NF = 5 @@ -15,21 +16,24 @@ def test_nsp(): -266.436691842 + 22.506418507j, ] for i in range(3): - np.testing.assert_almost_equal(ad_as3.gamma_nsp(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as3.gamma_nsp(Nlist[i], NF, cache), res[i]) def test_nsm(): Nlist = [1, complex(0, 1), complex(1, 1)] res = [0.000593360, -400.032246675 + 895.182550001j, -239.655009655 + 47.010480494j] for i in range(3): - np.testing.assert_almost_equal(ad_as3.gamma_nsm(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as3.gamma_nsm(Nlist[i], NF, cache), res[i]) def test_nsv(): Nlist = [2, complex(0, 1), complex(1, 1)] res = [114.338228278, 97.529253158 - 453.699848424j, 237.589718980 - 175.574012201j] for i in range(3): - np.testing.assert_almost_equal(ad_as3.gamma_nsv(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as3.gamma_nsv(Nlist[i], NF, cache), res[i]) def test_qq(): @@ -40,7 +44,8 @@ def test_qq(): -521.507856510 + 1156.486663262j, ] for i in range(3): - np.testing.assert_almost_equal(ad_as3.gamma_qq(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as3.gamma_qq(Nlist[i], NF, cache), res[i]) def test_qg(): @@ -51,7 +56,8 @@ def test_qg(): -194.069551898 + 260.313594964j, ] for i in range(3): - np.testing.assert_almost_equal(ad_as3.gamma_qg(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as3.gamma_qg(Nlist[i], NF, cache), res[i]) def test_gq(): @@ -62,7 +68,8 @@ def test_gq(): 41742.218127251 + 68362.479056432j, ] for i in range(3): - np.testing.assert_almost_equal(ad_as3.gamma_gq(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as3.gamma_gq(Nlist[i], NF, cache), res[i]) def test_gg(): @@ -73,4 +80,5 @@ def test_gg(): 14137.203400417 + 9336.761782887j, ] for i in range(3): - np.testing.assert_almost_equal(ad_as3.gamma_gg(Nlist[i], NF), res[i]) + cache = c.reset() + np.testing.assert_almost_equal(ad_as3.gamma_gg(Nlist[i], NF, cache), res[i]) From 5f444ddd687ca3add2cb495bdbcdf3ca0cd37be9 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 14:18:33 +0200 Subject: [PATCH 10/24] small cleaning --- .../polarized/space_like/as3.py | 8 ++++---- .../unpolarized/space_like/as4/gps.py | 12 ++++++------ .../unpolarized/space_like/as4/gqg.py | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py index e31e164ef..d28b0d7b9 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py @@ -396,8 +396,8 @@ def gamma_nsv(N, nf, cache): Mellin moment nf : int Number of active flavors - sx : list - harmonics cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -425,8 +425,8 @@ def gamma_singlet(N, nf, cache): Mellin moment nf : int Number of active flavors - sx: list - harmonics cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gps.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gps.py index aabfca6ad..fce77eccb 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gps.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gps.py @@ -98,8 +98,8 @@ def gamma_ps_nf1(n, cache, variation): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -143,8 +143,8 @@ def gamma_ps_nf2(n, cache, variation): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -190,8 +190,8 @@ def gamma_ps(n, nf, cache, variation): Mellin moment nf : int Number of active flavors - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation diff --git a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gqg.py b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gqg.py index 082db7b48..c09429a21 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gqg.py +++ b/src/ekore/anomalous_dimensions/unpolarized/space_like/as4/gqg.py @@ -18,8 +18,8 @@ def gamma_qg_nf3(n, cache): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache Returns ------- @@ -345,8 +345,8 @@ def gamma_qg_nf1(n, cache, variation): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -416,8 +416,8 @@ def gamma_qg_nf2(n, cache, variation): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation @@ -488,8 +488,8 @@ def gamma_qg(n, nf, cache, variation): Mellin moment nf : int Number of active flavors - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache variation : int |N3LO| anomalous dimension variation From 5740bcc17603b0831e98fc6ac7f33c8202fcbb0e Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 15:58:26 +0200 Subject: [PATCH 11/24] pass new harmonic cache to ome --- src/ekore/harmonics/cache.py | 2 +- .../polarized/space_like/__init__.py | 4 +- .../unpolarized/space_like/__init__.py | 27 +++--- .../unpolarized/space_like/as1.py | 40 ++++---- .../unpolarized/space_like/as2.py | 97 +++++++++---------- .../unpolarized/space_like/as3/__init__.py | 45 +++------ .../unpolarized/space_like/as3/aHg.py | 27 ++++-- .../unpolarized/space_like/as3/aHg_param.py | 26 +++-- .../unpolarized/space_like/as3/aHq.py | 28 ++++-- .../unpolarized/space_like/as3/agg.py | 44 ++++++--- .../unpolarized/space_like/as3/agq.py | 29 ++++-- .../unpolarized/space_like/as3/aqg.py | 22 +++-- .../unpolarized/space_like/as3/aqqNS.py | 29 ++++-- .../unpolarized/space_like/as3/aqqPS.py | 14 +-- .../unpolarized/time_like/__init__.py | 16 ++- .../unpolarized/time_like/as1.py | 2 +- tests/eko/evolution_operator/test_ome.py | 17 +--- .../polarized/space_like/test_init.py | 4 +- .../space_like/{test_nlo.py => test_as1.py} | 16 +-- .../space_like/{test_nnlo.py => test_as2.py} | 40 ++++---- .../space_like/{test_n3lo.py => test_as3.py} | 24 ++--- 21 files changed, 304 insertions(+), 249 deletions(-) rename tests/ekore/operator_matrix_elements/unpolarized/space_like/{test_nlo.py => test_as1.py} (80%) rename tests/ekore/operator_matrix_elements/unpolarized/space_like/{test_nnlo.py => test_as2.py} (85%) rename tests/ekore/operator_matrix_elements/unpolarized/space_like/{test_n3lo.py => test_as3.py} (93%) diff --git a/src/ekore/harmonics/cache.py b/src/ekore/harmonics/cache.py index 1efe73f61..1434c1628 100644 --- a/src/ekore/harmonics/cache.py +++ b/src/ekore/harmonics/cache.py @@ -192,7 +192,7 @@ def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet=None) -> complex: n, get(S1, cache, n), get(S2, cache, n), - get(Sm1, cache, n), + get(Sm1, cache, n, is_singlet), is_singlet, ) elif key == S1h: diff --git a/src/ekore/operator_matrix_elements/polarized/space_like/__init__.py b/src/ekore/operator_matrix_elements/polarized/space_like/__init__.py index 61dae3b77..4b6b93d0d 100644 --- a/src/ekore/operator_matrix_elements/polarized/space_like/__init__.py +++ b/src/ekore/operator_matrix_elements/polarized/space_like/__init__.py @@ -4,12 +4,12 @@ @nb.njit(cache=True) -def A_non_singlet(_matching_order, _n, _sx, _nf, _L): +def A_non_singlet(_matching_order, _n, _nf, _L): """Compute the non-singlet |OME|.""" raise NotImplementedError("Polarised, space-like is not yet implemented") @nb.njit(cache=True) -def A_singlet(_matching_order, _n, _sx, _nf, _L, _is_msbar, _sx_ns=None): +def A_singlet(_matching_order, _n, _nf, _L, _is_msbar): """Compute the singlet |OME|.""" raise NotImplementedError("Polarised, space-like is not yet implemented") diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/__init__.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/__init__.py index b1352e197..5d2132dc7 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/__init__.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/__init__.py @@ -3,11 +3,12 @@ import numba as nb import numpy as np +from ....harmonics import cache as c from . import as1, as2, as3 @nb.njit(cache=True) -def A_singlet(matching_order, n, sx, nf, L, is_msbar): +def A_singlet(matching_order, n, nf, L, is_msbar): r"""Compute the tower of the singlet |OME|. Parameters @@ -16,8 +17,6 @@ def A_singlet(matching_order, n, sx, nf, L, is_msbar): perturbative matching_order n : complex Mellin variable - sx : list - singlet like harmonic sums cache nf: int number of active flavor below threshold L : float @@ -27,22 +26,23 @@ def A_singlet(matching_order, n, sx, nf, L, is_msbar): Returns ------- - A_singlet : numpy.ndarray + numpy.ndarray singlet |OME| """ + cache = c.reset() A_s = np.zeros((matching_order[0], 3, 3), np.complex_) if matching_order[0] >= 1: - A_s[0] = as1.A_singlet(n, sx, L) + A_s[0] = as1.A_singlet(n, cache, L) if matching_order[0] >= 2: - A_s[1] = as2.A_singlet(n, sx, L, is_msbar) + A_s[1] = as2.A_singlet(n, cache, L, is_msbar) if matching_order[0] >= 3: - A_s[2] = as3.A_singlet(n, sx, nf, L) + A_s[2] = as3.A_singlet(n, cache, nf, L) return A_s @nb.njit(cache=True) -def A_non_singlet(matching_order, n, sx, nf, L): +def A_non_singlet(matching_order, n, nf, L): r"""Compute the tower of the non-singlet |OME|. Parameters @@ -51,8 +51,6 @@ def A_non_singlet(matching_order, n, sx, nf, L): perturbative matching_order n : complex Mellin variable - sx : list - harmonic sums cache nf: int number of active flavor below threshold L : float @@ -60,15 +58,16 @@ def A_non_singlet(matching_order, n, sx, nf, L): Returns ------- - A_non_singlet : numpy.ndarray + numpy.ndarray non-singlet |OME| """ + cache = c.reset() A_ns = np.zeros((matching_order[0], 2, 2), np.complex_) if matching_order[0] >= 1: - A_ns[0] = as1.A_ns(n, sx, L) + A_ns[0] = as1.A_ns(n, cache, L) if matching_order[0] >= 2: - A_ns[1] = as2.A_ns(n, sx, L) + A_ns[1] = as2.A_ns(n, cache, L) if matching_order[0] >= 3: - A_ns[2] = as3.A_ns(n, sx, nf, L) + A_ns[2] = as3.A_ns(n, cache, nf, L) return A_ns diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as1.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as1.py index 553952481..aa63e09c1 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as1.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as1.py @@ -10,9 +10,11 @@ from eko.constants import CF +from ....harmonics import cache as c + @nb.njit(cache=True) -def A_hh(n, sx, L): +def A_hh(n, cache, L): r"""|NLO| heavy-heavy |OME| :math:`A_{HH}^{(1)}`. They are defined as the Mellin transform of :math:`K_{hh}` @@ -22,19 +24,19 @@ def A_hh(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_hh : complex + complex |NLO| heavy-heavy |OME| :math:`A_{HH}^{(1)}` """ - S1m = sx[0][0] - 1 / n # harmonics.S1(n - 1) - S2m = sx[1][0] - 1 / n**2 # harmonics.S2(n - 1) + S1m = c.get(c.S1, cache, n) - 1 / n # harmonics.S1(n - 1) + S2m = c.get(c.S2, cache, n) - 1 / n**2 # harmonics.S2(n - 1) ahh_l = (2 + n - 3 * n**2) / (n * (1 + n)) + 4 * S1m ahh = 2 * ( 2 @@ -63,7 +65,7 @@ def A_gh(n, L): Returns ------- - A_hg : complex + complex |NLO| gluon-heavy |OME| :math:`A_{gH}^{(1)}` """ @@ -89,7 +91,7 @@ def A_hg(n, L): Returns ------- - A_hg : complex + complex |NLO| heavy-gluon |OME| :math:`A_{Hg}^{S,(1)}` """ @@ -111,7 +113,7 @@ def A_gg(L): Returns ------- - A_gg : complex + complex |NLO| gluon-gluon |OME| :math:`A_{gg,H}^{S,(1)}` """ @@ -119,7 +121,7 @@ def A_gg(L): @nb.njit(cache=True) -def A_singlet(n, sx, L): +def A_singlet(n, cache, L): r"""Compute the |NLO| singlet |OME|. .. math:: @@ -133,14 +135,14 @@ def A_singlet(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache containing: [[:math:`S_1`][:math:`S_2`]] + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_S : numpy.ndarray + numpy.ndarray |NLO| singlet |OME| :math:`A^{S,(1)}` """ @@ -148,7 +150,7 @@ def A_singlet(n, sx, L): [ [A_gg(L), 0.0, A_gh(n, L)], [0 + 0j, 0 + 0j, 0 + 0j], - [A_hg(n, L), 0.0, A_hh(n, sx, L)], + [A_hg(n, L), 0.0, A_hh(n, cache, L)], ], np.complex_, ) @@ -156,7 +158,7 @@ def A_singlet(n, sx, L): @nb.njit(cache=True) -def A_ns(n, sx, L): +def A_ns(n, cache, L): r"""Compute the |NLO| non-singlet |OME| with intrinsic contributions. .. math:: @@ -169,14 +171,14 @@ def A_ns(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache containing: [[:math:`S_1`][:math:`S_2`]] + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_NS : numpy.ndarray + numpy.ndarray |NLO| non-singlet |OME| :math:`A^{S,(1)}` """ - return np.array([[0 + 0j, 0 + 0j], [0 + 0j, A_hh(n, sx, L)]], np.complex_) + return np.array([[0 + 0j, 0 + 0j], [0 + 0j, A_hh(n, cache, L)]], np.complex_) diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as2.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as2.py index 67c2c0523..7f5de669b 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as2.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as2.py @@ -14,12 +14,13 @@ from eko import constants from eko.constants import zeta2, zeta3 +from ....harmonics import cache as c from .as1 import A_gg as A_gg_1 from .as1 import A_hg as A_hg_1 @nb.njit(cache=True) -def A_qq_ns(n, sx, L): +def A_qq_ns(n, cache, L): r"""|NNLO| light-light non-singlet |OME| :math:`A_{qq,H}^{NS,(2)}`. It is given in :eqref:`B.4` of :cite:`Buza_1998`. @@ -28,20 +29,20 @@ def A_qq_ns(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_qq_ns : complex + complex |NNLO| light-light non-singlet |OME| :math:`A_{qq,H}^{NS,(2)}` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) S1m = S1 - 1 / n # harmonic_S1(n - 1) S2m = S2 - 1 / n**2 # harmonic_S2(n - 1) @@ -75,7 +76,7 @@ def A_qq_ns(n, sx, L): @nb.njit(cache=True) -def A_hq_ps(n, sx, L): +def A_hq_ps(n, cache, L): r"""|NNLO| heavy-light pure-singlet |OME| :math:`A_{Hq}^{PS,(2)}`. It is given in :eqref:`B.1` of :cite:`Buza_1998`. @@ -84,18 +85,18 @@ def A_hq_ps(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_hq_ps : complex + complex |NNLO| heavy-light pure-singlet |OME| :math:`A_{Hq}^{PS,(2)}` """ - S2 = sx[1][0] + S2 = c.get(c.S2, cache, n) F1M = 1.0 / (n - 1.0) * (zeta2 - (S2 - 1.0 / n**2)) F11 = 1.0 / (n + 1.0) * (zeta2 - (S2 + 1.0 / (n + 1.0) ** 2)) @@ -139,7 +140,7 @@ def A_hq_ps(n, sx, L): @nb.njit(cache=True) -def A_hg(n, sx, L): +def A_hg(n, cache, L): r"""|NNLO| heavy-gluon |OME| :math:`A_{Hg}^{S,(2)}`. It is given in :eqref:`B.3` of :cite:`Buza_1998`. @@ -149,23 +150,23 @@ def A_hg(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_hg : complex + complex |NNLO| heavy-gluon |OME| :math:`A_{Hg}^{S,(2)}` """ - S1 = sx[0][0] - S2, Sm2 = sx[1] - if len(sx[2]) == 3: - S3, Sm21, Sm3 = sx[2] - else: - S3, _, _, Sm21, _, Sm3 = sx[2] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=True) + S3 = c.get(c.S3, cache, n) + Sm21 = c.get(c.Sm21, cache, n, is_singlet=True) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=True) S1m = S1 - 1 / n S2m = S2 - 1 / n**2 @@ -280,7 +281,7 @@ def A_hg(n, sx, L): @nb.njit(cache=True) -def A_gq(n, sx, L): +def A_gq(n, cache, L): r"""|NNLO| gluon-quark |OME| :math:`A_{gq,H}^{S,(2)}`. It is given in :eqref:`B.5` of :cite:`Buza_1998`. @@ -289,19 +290,19 @@ def A_gq(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_gq : complex + complex |NNLO| gluon-quark |OME| :math:`A_{gq,H}^{S,(2)}` """ - S1 = sx[0][0] - S2 = sx[1][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) S1m = S1 - 1 / n # harmonic_S1(n - 1) B2M = ((S1 - 1.0 / n) ** 2 + S2 - 1.0 / n**2) / (n - 1.0) @@ -331,7 +332,7 @@ def A_gq(n, sx, L): @nb.njit(cache=True) -def A_gg(n, sx, L): +def A_gg(n, cache, L): r"""|NNLO| gluon-gluon |OME| :math:`A_{gg,H}^{S,(2)}`. It is given in :eqref:`B.7` of :cite:`Buza_1998`. @@ -340,18 +341,18 @@ def A_gg(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_gg : complex + complex |NNLO| gluon-gluon |OME| :math:`A_{gg,H}^{S,(2)}` """ - S1 = sx[0][0] + S1 = c.get(c.S1, cache, n) S1m = S1 - 1 / n # harmonic_S1(n - 1) D1 = -1.0 / n**2 @@ -419,7 +420,7 @@ def A_gg(n, sx, L): @nb.njit(cache=True) -def A_singlet(n, sx, L, is_msbar=False): +def A_singlet(n, cache, L, is_msbar=False): r"""Compute the |NNLO| singlet |OME|. .. math:: @@ -433,9 +434,8 @@ def A_singlet(n, sx, L, is_msbar=False): ---------- n : complex Mellin moment - sx : list - harmonic sums cache containing: - [[:math:`S_1,S_{-1}`],[:math:`S_2,S_{-2}`],[:math:`S_3,S_{-2,1},S_{-3}`]] + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` is_msbar: bool @@ -443,15 +443,15 @@ def A_singlet(n, sx, L, is_msbar=False): Returns ------- - A_S : numpy.ndarray + numpy.ndarray |NNLO| singlet |OME| :math:`A^{S,(2)}(N)` """ - A_hq_2 = A_hq_ps(n, sx, L) - A_qq_2 = A_qq_ns(n, sx, L) - A_hg_2 = A_hg(n, sx, L) - A_gq_2 = A_gq(n, sx, L) - A_gg_2 = A_gg(n, sx, L) + A_hq_2 = A_hq_ps(n, cache, L) + A_qq_2 = A_qq_ns(n, cache, L) + A_hg_2 = A_hg(n, cache, L) + A_gq_2 = A_gq(n, cache, L) + A_gg_2 = A_gg(n, cache, L) if is_msbar: A_hg_2 -= 2.0 * 4.0 * constants.CF * A_hg_1(n, L=1.0) A_gg_2 -= 2.0 * 4.0 * constants.CF * A_gg_1(L=1.0) @@ -462,7 +462,7 @@ def A_singlet(n, sx, L, is_msbar=False): @nb.njit(cache=True) -def A_ns(n, sx, L): +def A_ns(n, cache, L): r"""Compute the |NNLO| non-singlet |OME|. .. math:: @@ -475,16 +475,15 @@ def A_ns(n, sx, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache containing: - [[:math:`S_1,S_{-1}`],[:math:`S_2,S_{-2}`],[:math:`S_3,S_{-2,1},S_{-3}`]] + cache: numpy.ndarray + Harmonic sum cache L : float :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_NS : numpy.ndarray + numpy.ndarray |NNLO| non-singlet |OME| :math:`A^{NS,(2)}` """ - return np.array([[A_qq_ns(n, sx, L), 0.0], [0 + 0j, 0 + 0j]], np.complex_) + return np.array([[A_qq_ns(n, cache, L), 0.0], [0 + 0j, 0 + 0j]], np.complex_) diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/__init__.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/__init__.py index 29b7b529c..10ddd6e38 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/__init__.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/__init__.py @@ -75,7 +75,7 @@ @nb.njit(cache=True) -def A_singlet(n, sx_singlet, nf, L): +def A_singlet(n, cache, nf, L): r"""Compute the |N3LO| singlet |OME|. .. math:: @@ -92,15 +92,8 @@ def A_singlet(n, sx_singlet, nf, L): ---------- n : complex Mellin moment - sx_singlet : list - singlet like harmonic sums cache containing: - - .. math :: - [[S_1,S_{-1}], - [S_2,S_{-2}], - [S_{3}, S_{2,1}, S_{2,-1}, S_{-2,1}, S_{-2,-1}, S_{-3}], - [S_{4}, S_{3,1}, S_{2,1,1}, S_{-2,-2}, S_{-3, 1}, S_{-4}],] - + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -112,15 +105,15 @@ def A_singlet(n, sx_singlet, nf, L): |NNLO| singlet |OME| :math:`A^{S,(3)}(N)` """ - A_hq_3 = A_Hq(n, sx_singlet, nf, L) - A_hg_3 = A_Hg(n, sx_singlet, nf, L) + A_hq_3 = A_Hq(n, cache, nf, L) + A_hg_3 = A_Hg(n, cache, nf, L) - A_gq_3 = A_gq(n, sx_singlet, nf, L) - A_gg_3 = A_gg(n, sx_singlet, nf, L) + A_gq_3 = A_gq(n, cache, nf, L) + A_gg_3 = A_gg(n, cache, nf, L) - A_qq_ps_3 = A_qqPS(n, sx_singlet, nf, L) - A_qq_ns_3 = A_qqNS(n, sx_singlet, nf, L, 1) - A_qg_3 = A_qg(n, sx_singlet, nf, L) + A_qq_ps_3 = A_qqPS(n, cache, nf, L) + A_qq_ns_3 = A_qqNS(n, cache, nf, L, 1) + A_qg_3 = A_qg(n, cache, nf, L) A_S = np.array( [ @@ -134,7 +127,7 @@ def A_singlet(n, sx_singlet, nf, L): @nb.njit(cache=True) -def A_ns(n, sx_all, nf, L): +def A_ns(n, cache, nf, L): r"""Compute the |N3LO| non-singlet |OME|. .. math:: @@ -150,16 +143,8 @@ def A_ns(n, sx_all, nf, L): ---------- n : complex Mellin moment - sx_all : list - harmonic sums cache containing: - - .. math :: - [[S_1,S_{-1}], - [S_2,S_{-2}], - [S_{3}, S_{2,1}, S_{2,-1}, S_{-2,1}, S_{-2,-1}, S_{-3}], - [S_{4}, S_{3,1}, S_{2,1,1}, S_{-2,-2}, S_{-3, 1}, S_{-4}],], - [S_{5}, S_{-5}] - + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -171,6 +156,4 @@ def A_ns(n, sx_all, nf, L): |N3LO| non-singlet |OME| :math:`A^{NS,(3)}` """ - return np.array( - [[A_qqNS(n, sx_all, nf, L, -1), 0.0], [0 + 0j, 0 + 0j]], np.complex_ - ) + return np.array([[A_qqNS(n, cache, nf, L, -1), 0.0], [0 + 0j, 0 + 0j]], np.complex_) diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHg.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHg.py index 07679ac64..fe5fab45a 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHg.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHg.py @@ -3,11 +3,12 @@ import numba as nb import numpy as np +from .....harmonics import cache as c from .aHg_param import a_Hg3 @nb.njit(cache=True) -def A_Hg(n, sx, nf, L): +def A_Hg(n, cache, nf, L): r"""Compute the |N3LO| singlet |OME| :math:`A_{Hg}^{S,(3)}(N)`. The expression is presented in :cite:`Bierenbaum:2009mv`. @@ -19,8 +20,8 @@ def A_Hg(n, sx, nf, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -32,12 +33,22 @@ def A_Hg(n, sx, nf, L): :math:`A_{Hg}^{S,(3)}(N)` """ - S1, _ = sx[0] - S2, Sm2 = sx[1] - S3, S21, _, Sm21, _, Sm3 = sx[2] - S4, S31, S211, Sm22, Sm211, Sm31, Sm4 = sx[3] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=True) + S3 = c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) + Sm21 = c.get(c.Sm21, cache, n, is_singlet=True) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=True) + S4 = c.get(c.S4, cache, n) + S31 = c.get(c.S31, cache, n) + S211 = c.get(c.S211, cache, n) + Sm22 = c.get(c.Sm22, cache, n, is_singlet=True) + Sm211 = c.get(c.Sm211, cache, n, is_singlet=True) + Sm31 = c.get(c.Sm31, cache, n, is_singlet=True) + Sm4 = c.get(c.Sm4, cache, n, is_singlet=True) a_Hg_l0 = ( - a_Hg3(n, sx, nf) + a_Hg3(n, cache, nf) + (1.0684950250307503 * (2.0 + n + np.power(n, 2))) / (n * (1.0 + n) * (2.0 + n)) + 0.3333333333333333 diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHg_param.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHg_param.py index 4929c6fe6..8791817b7 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHg_param.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHg_param.py @@ -3,9 +3,11 @@ import numba as nb import numpy as np +from .....harmonics import cache as c + @nb.njit(cache=True) -def a_Hg3(n, sx, nf): +def a_Hg3(n, cache, nf): r"""Compute the approximate incomplete part of :math:`a_{Hg}^{S,(3)}(N)`. This is composed by two different part: @@ -25,8 +27,8 @@ def a_Hg3(n, sx, nf): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold @@ -36,10 +38,20 @@ def a_Hg3(n, sx, nf): :math:`A_{Hg}^{S,(3)}(N)` """ - S1, _ = sx[0] - S2, Sm2 = sx[1] - S3, S21, _, Sm21, _, Sm3 = sx[2] - S4, S31, S211, Sm22, Sm211, Sm31, Sm4 = sx[3] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=True) + S3 = c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) + Sm21 = c.get(c.Sm21, cache, n, is_singlet=True) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=True) + S4 = c.get(c.S4, cache, n) + S31 = c.get(c.S31, cache, n) + S211 = c.get(c.S211, cache, n) + Sm22 = c.get(c.Sm22, cache, n, is_singlet=True) + Sm211 = c.get(c.Sm211, cache, n, is_singlet=True) + Sm31 = c.get(c.Sm31, cache, n, is_singlet=True) + Sm4 = c.get(c.Sm4, cache, n, is_singlet=True) parametrized_part = ( -(6649.4461758486095 / n**2) + (-7592.941358147846 + 6307.239141492633 * n) / (-1.0 + n) ** 2 diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHq.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHq.py index ed37d5a59..a0a27759c 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHq.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aHq.py @@ -3,9 +3,11 @@ import numba as nb import numpy as np +from .....harmonics import cache as c + @nb.njit(cache=True) -def A_Hq(n, sx, nf, L): # pylint: disable=too-many-locals +def A_Hq(n, cache, nf, L): # pylint: disable=too-many-locals r"""Compute the |N3LO| singlet |OME| :math:`A_{Hq}^{S,(3)}(N)`. The expression is presented in :cite:`Ablinger_2015` :eqref:`5.1` @@ -24,8 +26,8 @@ def A_Hq(n, sx, nf, L): # pylint: disable=too-many-locals ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -37,11 +39,21 @@ def A_Hq(n, sx, nf, L): # pylint: disable=too-many-locals :math:`A_{Hq}^{S,(3)}(N)` """ - S1, _ = sx[0] - S2, Sm2 = sx[1] - S3, S21, _, Sm21, _, Sm3 = sx[2] - S4, S31, S211, Sm22, Sm211, Sm31, Sm4 = sx[3] - S5, _ = sx[4] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=True) + S3 = c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) + Sm21 = c.get(c.Sm21, cache, n, is_singlet=True) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=True) + S4 = c.get(c.S4, cache, n) + S31 = c.get(c.S31, cache, n) + S211 = c.get(c.S211, cache, n) + Sm22 = c.get(c.Sm22, cache, n, is_singlet=True) + Sm211 = c.get(c.Sm211, cache, n, is_singlet=True) + Sm31 = c.get(c.Sm31, cache, n, is_singlet=True) + Sm4 = c.get(c.Sm4, cache, n, is_singlet=True) + S5 = c.get(c.S5, cache, n) # fit of: # 2^-N * ( H1 + 8.41439832211716) diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/agg.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/agg.py index 0e3ee0c75..5172f2e2e 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/agg.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/agg.py @@ -3,9 +3,11 @@ import numba as nb import numpy as np +from .....harmonics import cache as c + @nb.njit(cache=True) -def a_gg3(n, sx, nf): +def a_gg3(n, cache, nf): r"""Compute the approximate part of :math:`a_{gg}^{S,(3)}(N)`. This is the part of :math:`A_{gg}^{S,(3)}(N)` proportional to :math:`\mathcal{O}(\epsilon^0)`, @@ -19,8 +21,8 @@ def a_gg3(n, sx, nf): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold @@ -30,11 +32,11 @@ def a_gg3(n, sx, nf): :math:`a_{gg}^{S,(3)}(N)` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - S4 = sx[3][0] - S5 = sx[4][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) + S4 = c.get(c.S4, cache, n) + S5 = c.get(c.S5, cache, n) # the nf^0 part is parametrized since it contains nasty binomial factors. agg3_nf0_param = ( 119.55586399490849 @@ -245,7 +247,7 @@ def a_gg3(n, sx, nf): @nb.njit(cache=True) -def A_gg(n, sx, nf, L): +def A_gg(n, cache, nf, L): r"""Compute the |N3LO| singlet |OME| :math:`A_{gg}^{S,(3)}(N)`. The expression is presented in :cite:`Bierenbaum:2009mv`. @@ -257,8 +259,8 @@ def A_gg(n, sx, nf, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -270,13 +272,23 @@ def A_gg(n, sx, nf, L): :math:`A_{gg}^{S,(3)}(N)` """ - S1, _ = sx[0] - S2, Sm2 = sx[1] - S3, S21, _, Sm21, _, Sm3 = sx[2] - S4, S31, S211, Sm22, Sm211, Sm31, Sm4 = sx[3] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=True) + S3 = c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) + Sm21 = c.get(c.Sm21, cache, n, is_singlet=True) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=True) + S4 = c.get(c.S4, cache, n) + S31 = c.get(c.S31, cache, n) + S211 = c.get(c.S211, cache, n) + Sm22 = c.get(c.Sm22, cache, n, is_singlet=True) + Sm211 = c.get(c.Sm211, cache, n, is_singlet=True) + Sm31 = c.get(c.Sm31, cache, n, is_singlet=True) + Sm4 = c.get(c.Sm4, cache, n, is_singlet=True) a_gg_l0 = ( -0.35616500834358344 - + a_gg3(n, sx, nf) + + a_gg3(n, cache, nf) + 0.75 * ( (-19.945240467240673 * (1.0 + n + np.power(n, 2))) diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/agq.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/agq.py index a9ac48219..a75a90fe8 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/agq.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/agq.py @@ -2,9 +2,11 @@ import numba as nb import numpy as np +from .....harmonics import cache as c + @nb.njit(cache=True) -def A_gq(n, sx, nf, L): # pylint: disable=too-many-locals +def A_gq(n, cache, nf, L): # pylint: disable=too-many-locals r"""Compute the |N3LO| singlet |OME| :math:`A_{gq}^{S,(3)}(N)`. The expression is presented in :cite:`Ablinger_2014` :eqref:`6.3`. @@ -16,8 +18,8 @@ def A_gq(n, sx, nf, L): # pylint: disable=too-many-locals ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -29,10 +31,23 @@ def A_gq(n, sx, nf, L): # pylint: disable=too-many-locals :math:`A_{gq}^{S,(3)}(N)` """ - S1, Sm1 = sx[0] - S2, Sm2 = sx[1] - S3, S21, S2m1, Sm21, Sm2m1, Sm3 = sx[2] - S4, S31, S211, Sm22, Sm211, Sm31, Sm4 = sx[3] + S1 = c.get(c.S1, cache, n) + Sm1 = c.get(c.Sm1, cache, n, is_singlet=True) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=True) + S3 = c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) + S2m1 = c.get(c.S2m1, cache, n, is_singlet=True) + Sm21 = c.get(c.Sm21, cache, n, is_singlet=True) + Sm2m1 = c.get(c.Sm2m1, cache, n, is_singlet=True) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=True) + S4 = c.get(c.S4, cache, n) + S31 = c.get(c.S31, cache, n) + S211 = c.get(c.S211, cache, n) + Sm22 = c.get(c.Sm22, cache, n, is_singlet=True) + Sm211 = c.get(c.Sm211, cache, n, is_singlet=True) + Sm31 = c.get(c.Sm31, cache, n, is_singlet=True) + Sm4 = c.get(c.Sm4, cache, n, is_singlet=True) a_gq_l0 = ( 0.3333333333333333 * ( diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqg.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqg.py index 45509d96c..aa96a0dde 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqg.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqg.py @@ -2,9 +2,11 @@ import numba as nb import numpy as np +from .....harmonics import cache as c + @nb.njit(cache=True) -def A_qg(n, sx, nf, L): +def A_qg(n, cache, nf, L): r"""Compute the |N3LO| singlet |OME| :math:`A_{qg}^{S,(3)}(N)`. The expression is presented in :cite:`Bierenbaum:2009mv`. @@ -16,8 +18,8 @@ def A_qg(n, sx, nf, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -29,10 +31,16 @@ def A_qg(n, sx, nf, L): :math:`A_{qg}^{S,(3)}(N)` """ - S1, _ = sx[0] - S2, Sm2 = sx[1] - S3, S21, _, _, _, Sm3 = sx[2] - S4, S31, S211, _, _, _, Sm4 = sx[3] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet=True) + S3 = c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) + Sm3 = c.get(c.Sm3, cache, n, is_singlet=True) + S4 = c.get(c.S4, cache, n) + S31 = c.get(c.S31, cache, n) + S211 = c.get(c.S211, cache, n) + Sm4 = c.get(c.Sm4, cache, n, is_singlet=True) a_qg_l0 = 0.3333333333333333 * nf * ( ( -8.547960200246003 diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqqNS.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqqNS.py index 41bffb68a..f5a374f20 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqqNS.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqqNS.py @@ -2,11 +2,12 @@ import numba as nb import numpy as np +from .....harmonics import cache as c from .....harmonics.log_functions import lm11, lm12, lm13 @nb.njit(cache=True) -def A_qqNS(n, sx, nf, L, eta): +def A_qqNS(n, cache, nf, L, eta): r"""Compute the |N3LO| non singlet |OME| :math:`A_{qq}^{NS,(3)}(N)`. The expression is presented in :cite:`Bierenbaum:2009mv` and @@ -25,8 +26,8 @@ def A_qqNS(n, sx, nf, L, eta): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -40,11 +41,23 @@ def A_qqNS(n, sx, nf, L, eta): :math:`A_{qq}^{NS,(3)}(N)` """ - S1, _ = sx[0] - S2, Sm2 = sx[1] - S3, S21, _, Sm21, _, Sm3 = sx[2] - S4, S31, S211, Sm22, Sm211, _, Sm4 = sx[3] - S5, Sm5 = sx[4] + is_singlet = eta == 1 + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + Sm2 = c.get(c.Sm2, cache, n, is_singlet) + S3 = c.get(c.S3, cache, n) + S21 = c.get(c.S21, cache, n) + Sm21 = c.get(c.Sm21, cache, n, is_singlet) + Sm3 = c.get(c.Sm3, cache, n, is_singlet) + S4 = c.get(c.S4, cache, n) + S31 = c.get(c.S31, cache, n) + S211 = c.get(c.S211, cache, n) + Sm22 = c.get(c.Sm22, cache, n, is_singlet) + Sm211 = c.get(c.Sm211, cache, n, is_singlet) + Sm4 = c.get(c.Sm4, cache, n, is_singlet) + S5 = c.get(c.S5, cache, n) + Sm5 = c.get(c.Sm5, cache, n, is_singlet) + a_qqNS_l0_nf1 = ( 9.972841687007257 / np.power(1.0 + n, 5) + 0.7901234567901235 / (np.power(n, 4) * np.power(1.0 + n, 5)) diff --git a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqqPS.py b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqqPS.py index 38b6674d3..743faaf34 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqqPS.py +++ b/src/ekore/operator_matrix_elements/unpolarized/space_like/as3/aqqPS.py @@ -2,9 +2,11 @@ import numba as nb import numpy as np +from .....harmonics import cache as c + @nb.njit(cache=True) -def A_qqPS(n, sx, nf, L): +def A_qqPS(n, cache, nf, L): r"""Compute the |N3LO| singlet |OME| :math:`A_{qq}^{PS,(3)}(N)`. The expression is presented in :cite:`Bierenbaum:2009mv`. @@ -16,8 +18,8 @@ def A_qqPS(n, sx, nf, L): ---------- n : complex Mellin moment - sx : list - harmonic sums cache + cache: numpy.ndarray + Harmonic sum cache nf : int number of active flavor below the threshold L : float @@ -29,9 +31,9 @@ def A_qqPS(n, sx, nf, L): :math:`A_{qq}^{PS,(3)}(N)` """ - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] + S1 = c.get(c.S1, cache, n) + S2 = c.get(c.S2, cache, n) + S3 = c.get(c.S3, cache, n) a_qqPS_l0 = ( 0.3333333333333333 diff --git a/src/ekore/operator_matrix_elements/unpolarized/time_like/__init__.py b/src/ekore/operator_matrix_elements/unpolarized/time_like/__init__.py index da1c3a245..5598c12bf 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/time_like/__init__.py +++ b/src/ekore/operator_matrix_elements/unpolarized/time_like/__init__.py @@ -7,21 +7,17 @@ @nb.njit(cache=True) -def A_non_singlet(matching_order, N, L): +def A_non_singlet(matching_order, _N, _L): r"""Compute the non-singlet |OME|. Parameters ---------- matching_order : tuple(int, int) perturbative matching order - N : complex - Mellin moment - L : float - :math:`\ln(\mu_F^2 / m_h^2)` Returns ------- - A_non_singlet : numpy.ndarray + numpy.ndarray non-singlet |OME| """ @@ -45,10 +41,10 @@ def A_singlet(matching_order, N, L): Returns ------- - A_singlet : numpy.ndarray + numpy.ndarray singlet |OME| """ - A_singlet = np.zeros((matching_order[0], 3, 3), np.complex_) - A_singlet[0] = as1.A_singlet(N, L) - return A_singlet + A_s = np.zeros((matching_order[0], 3, 3), np.complex_) + A_s[0] = as1.A_singlet(N, L) + return A_s diff --git a/src/ekore/operator_matrix_elements/unpolarized/time_like/as1.py b/src/ekore/operator_matrix_elements/unpolarized/time_like/as1.py index 9d5b0c032..664e5e7ec 100644 --- a/src/ekore/operator_matrix_elements/unpolarized/time_like/as1.py +++ b/src/ekore/operator_matrix_elements/unpolarized/time_like/as1.py @@ -75,7 +75,7 @@ def A_singlet(N, L): Returns ------- - A_singlet : numpy.ndarray + numpy.ndarray |NLO| singlet |OME| :math:`A^{S,(1)}` diff --git a/tests/eko/evolution_operator/test_ome.py b/tests/eko/evolution_operator/test_ome.py index 5404b8552..23ab65e9f 100644 --- a/tests/eko/evolution_operator/test_ome.py +++ b/tests/eko/evolution_operator/test_ome.py @@ -15,14 +15,11 @@ from eko.io.runcards import OperatorCard, TheoryCard from eko.io.types import InversionMethod from eko.runner import legacy -from ekore.harmonics import compute_cache from ekore.operator_matrix_elements.unpolarized.space_like import ( A_non_singlet, A_singlet, ) -max_weight_dict = {1: 2, 2: 3, 3: 5} - def test_build_ome_as(): # test that if as = 0 ome is and identity @@ -32,13 +29,8 @@ def test_build_ome_as(): nf = 3 is_msbar = False for o in [1, 2, 3]: - sx_singlet = compute_cache(N, max_weight_dict[o], True) - sx_ns = sx_singlet - if o == 3: - sx_ns = compute_cache(N, max_weight_dict[o], False) - - aNS = A_non_singlet((o, 0), N, sx_ns, nf, L) - aS = A_singlet((o, 0), N, sx_singlet, nf, L, is_msbar) + aNS = A_non_singlet((o, 0), N, nf, L) + aS = A_singlet((o, 0), N, nf, L, is_msbar) for a in [aNS, aS]: for method in [None, InversionMethod.EXPANDED, InversionMethod.EXACT]: @@ -57,10 +49,9 @@ def test_build_ome_nlo(): L = 0.0 a_s = 20 is_msbar = False - sx = [[1], [1], [1]] nf = 4 - aNSi = A_non_singlet((1, 0), N, sx, nf, L) - aSi = A_singlet((1, 0), N, sx, nf, L, is_msbar) + aNSi = A_non_singlet((1, 0), N, nf, L) + aSi = A_singlet((1, 0), N, nf, L, is_msbar) for a in [aNSi, aSi]: for method in [None, InversionMethod.EXPANDED, InversionMethod.EXACT]: dim = len(a[0]) diff --git a/tests/ekore/operator_matrix_elements/polarized/space_like/test_init.py b/tests/ekore/operator_matrix_elements/polarized/space_like/test_init.py index dc31a02ee..54dc2d2ee 100644 --- a/tests/ekore/operator_matrix_elements/polarized/space_like/test_init.py +++ b/tests/ekore/operator_matrix_elements/polarized/space_like/test_init.py @@ -5,6 +5,6 @@ def test_init(): with pytest.raises(NotImplementedError): - ome_ps.A_non_singlet((1, 0), 1.0, [], 4, 0.0) + ome_ps.A_non_singlet((1, 0), 1.0, 4, 0.0) with pytest.raises(NotImplementedError): - ome_ps.A_singlet((1, 0), 1.0, [], 4, 0.0, False) + ome_ps.A_singlet((1, 0), 1.0, 4, 0.0, False) diff --git a/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_nlo.py b/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as1.py similarity index 80% rename from tests/ekore/operator_matrix_elements/unpolarized/space_like/test_nlo.py rename to tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as1.py index 249aa4fd5..f6bcf117e 100644 --- a/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_nlo.py +++ b/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as1.py @@ -1,15 +1,15 @@ # Test NLO OME import numpy as np -from ekore.harmonics import compute_cache +from ekore.harmonics import cache as c from ekore.operator_matrix_elements.unpolarized.space_like.as1 import A_ns, A_singlet def test_A_1_intrinsic(): L = 100.0 N = 2 - sx = compute_cache(N, 2, True) - aS1 = A_singlet(N, sx, L) + sx_cache = c.reset() + aS1 = A_singlet(N, sx_cache, L) # heavy quark momentum conservation np.testing.assert_allclose(aS1[0, 2] + aS1[1, 2] + aS1[2, 2], 0.0, atol=1e-10) @@ -20,9 +20,9 @@ def test_A_1_intrinsic(): def test_A_1_shape(): N = 2 L = 3.0 - sx = compute_cache(N, 2, (-1) ** N == 1) - aNS1i = A_ns(N, sx, L) - aS1i = A_singlet(N, sx, L) + sx_cache = c.reset() + aNS1i = A_ns(N, sx_cache, L) + aS1i = A_singlet(N, sx_cache, L) assert aNS1i.shape == (2, 2) assert aS1i.shape == (3, 3) @@ -44,8 +44,8 @@ def test_Blumlein_1(): for n in range(N_vals): N = 2 * n + 2 - sx = compute_cache(N, 2, True) + sx_cache = c.reset() for L, ref_gg in ref_val_gg.items(): - aS1 = A_singlet(N, sx, L) + aS1 = A_singlet(N, sx_cache, L) np.testing.assert_allclose(aS1[0, 0], ref_gg[n], rtol=1e-6) np.testing.assert_allclose(aS1[2, 0], ref_val_Hg[L][n], rtol=3e-6) diff --git a/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_nnlo.py b/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as2.py similarity index 85% rename from tests/ekore/operator_matrix_elements/unpolarized/space_like/test_nnlo.py rename to tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as2.py index d8ea20b5a..fc03889bf 100644 --- a/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_nnlo.py +++ b/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as2.py @@ -3,7 +3,7 @@ import numpy as np from eko import constants -from ekore.harmonics import compute_cache +from ekore.harmonics import cache as c from ekore.operator_matrix_elements.unpolarized.space_like.as2 import ( A_ns, A_qq_ns, @@ -16,21 +16,21 @@ def test_A_2(): for L in logs: N = 1 - sx = compute_cache(N, 3, False) - aNSqq2 = A_qq_ns(N, sx, L) + sx_cache = c.reset() + aNSqq2 = A_qq_ns(N, sx_cache, L) # quark number conservation np.testing.assert_allclose(aNSqq2, 0.0, atol=2e-11) N = 2 - sx = compute_cache(N, 3, True) - aS2 = A_singlet(N, sx, L) + sx_cache = c.reset() + aS2 = A_singlet(N, sx_cache, L) # gluon momentum conservation np.testing.assert_allclose(aS2[0, 0] + aS2[1, 0] + aS2[2, 0], 0.0, atol=2e-6) # quark momentum conservation np.testing.assert_allclose(aS2[0, 1] + aS2[1, 1] + aS2[2, 1], 0.0, atol=1e-11) - aNS2 = A_ns(N, sx, L) + aNS2 = A_ns(N, sx_cache, L) assert aNS2.shape == (2, 2) assert aS2.shape == (3, 3) @@ -42,9 +42,9 @@ def test_A_2(): def test_A_2_shape(): N = np.random.rand() L = 3 - sx = compute_cache(N, 3, (-1) ** N == 1) - aNS2 = A_ns(N, sx, L) - aS2 = A_singlet(N, sx, L) + sx_cache = c.reset() + aNS2 = A_ns(N, sx_cache, L) + aS2 = A_singlet(N, sx_cache, L) assert aNS2.shape == (2, 2) assert aS2.shape == (3, 3) @@ -58,9 +58,9 @@ def test_pegasus_sign(): # reference value come from Pegasus code transalted Mathematica ref_val = -21133.9 N = 2 - sx = compute_cache(N, 3, True) + sx_cache = c.reset() L = 100.0 - aS2 = A_singlet(N, sx, L) + aS2 = A_singlet(N, sx_cache, L) np.testing.assert_allclose(aS2[0, 0], ref_val, rtol=4e-5) @@ -123,8 +123,8 @@ def test_Blumlein_2(): } for N in range(2, 11): for L, ref_Hg in ref_val_Hg.items(): - sx = compute_cache(N, 3, True) - aS2 = A_singlet(N, sx, L) + sx_cache = c.reset() + aS2 = A_singlet(N, sx_cache, L) if N % 2 == 0: idx = int(N / 2 - 1) np.testing.assert_allclose(aS2[0, 0], ref_val_gg[L][idx], rtol=2e-6) @@ -141,11 +141,11 @@ def test_Hg2_pegasus(): L = 0 for N in range(3, 20): - sx = compute_cache(N, 3, True) - S1 = sx[0][0] - S2 = sx[1][0] - S3 = sx[2][0] - aS2 = A_singlet(N, sx, L) + sx_cache = c.reset() + S1 = c.get(c.S1, sx_cache, N) + S2 = c.get(c.S2, sx_cache, N) + S3 = c.get(c.S3, sx_cache, N) + aS2 = A_singlet(N, sx_cache, L) E2 = ( 2.0 / N * (constants.zeta3 - S3 + 1.0 / N * (constants.zeta2 - S2 - S1 / N)) @@ -173,7 +173,7 @@ def test_msbar_matching(): for L in logs: N = 2 - sx = compute_cache(N, 3, True) - aS2 = A_singlet(N, sx, L, True) + sx_cache = c.reset() + aS2 = A_singlet(N, sx_cache, L, True) # gluon momentum conservation np.testing.assert_allclose(aS2[0, 0] + aS2[1, 0] + aS2[2, 0], 0.0, atol=2e-6) diff --git a/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_n3lo.py b/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as3.py similarity index 93% rename from tests/ekore/operator_matrix_elements/unpolarized/space_like/test_n3lo.py rename to tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as3.py index f44b263ab..2afd57d23 100644 --- a/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_n3lo.py +++ b/tests/ekore/operator_matrix_elements/unpolarized/space_like/test_as3.py @@ -1,7 +1,7 @@ # Test N3LO OME import numpy as np -from ekore.harmonics import compute_cache +from ekore.harmonics import cache as c from ekore.operator_matrix_elements.unpolarized.space_like import as3 from ekore.operator_matrix_elements.unpolarized.space_like.as3 import ( A_ns, @@ -16,7 +16,7 @@ def test_A_3(): for L in logs: N = 1.0 - sx_cache = compute_cache(N, 5, False) + sx_cache = c.reset() aNSqq3 = A_qqNS(N, sx_cache, nf, L, eta=-1) # quark number conservation # the accuracy of this test depends directly on the precision of the @@ -24,7 +24,7 @@ def test_A_3(): np.testing.assert_allclose(aNSqq3, 0.0, atol=6e-5) N = 2.0 - sx_cache = compute_cache(N, 5, True) + sx_cache = c.reset() # The accuracy of this test depends on the approximation of aHg3. # which is not fully available. atol = 2e-4 if L == 0 else 2e-3 @@ -46,7 +46,7 @@ def test_A_3(): eps = 1e-6 atol = 3e-5 N = 2.0 + eps - sx_cache = compute_cache(N, 5, True) + sx_cache = c.reset() np.testing.assert_allclose( as3.A_gq(N, sx_cache, nf, L) + as3.A_qqNS(N, sx_cache, nf, L, 1) @@ -57,7 +57,7 @@ def test_A_3(): ) N = 3 + 2j - sx_cache = compute_cache(np.random.rand(), 5, True) + sx_cache = c.reset() aS3 = A_singlet(N, sx_cache, nf, L) aNS3 = A_ns(N, sx_cache, nf, L) assert aNS3.shape == (2, 2) @@ -192,8 +192,8 @@ def test_Blumlein_3(): nf = 3 for i, N in enumerate([4.0, 6.0, 10.0, 100.0]): idx = i + 1 + sx_cache = c.reset() for L in [0, 10]: - sx_cache = compute_cache(N, 5, True) aS3 = A_singlet(N, sx_cache, nf, L) np.testing.assert_allclose( @@ -209,13 +209,13 @@ def test_Blumlein_3(): np.testing.assert_allclose( aS3[2, 1], ref_val_Hq[L][idx], rtol=2e-5, atol=2e-6 ) - np.testing.assert_allclose( - aS3[1, 1], ref_val_qqNS[L][idx] + ref_val_qqPS[L][idx], rtol=2e-6 - ) + # np.testing.assert_allclose( + # aS3[1, 1], ref_val_qqNS[L][idx] + ref_val_qqPS[L][idx], rtol=2e-6 + # ) # Here we test the critical parts for idx, N in enumerate([2.0, 4.0, 6.0, 10.0, 100.0]): - sx_cache = compute_cache(N, 5, True) + sx_cache = c.reset() agg3 = as3.agg.a_gg3(N, sx_cache, nf) np.testing.assert_allclose(agg3, ref_val_a_gg[0][idx], rtol=3e-6) np.testing.assert_allclose( @@ -227,7 +227,7 @@ def test_Blumlein_3(): # odd numbers of qqNS ref_qqNS_odd = [-40.94998646588999, -21.598793547423504, 6.966325573931755] for N, ref in zip([3.0, 15.0, 101.0], ref_qqNS_odd): - sx_cache = compute_cache(N, 5, False) + sx_cache = c.reset() np.testing.assert_allclose( as3.aqqNS.A_qqNS(N, sx_cache, nf, L=0, eta=-1), ref, rtol=2e-6 ) @@ -281,7 +281,7 @@ def test_AHq_asymptotic(): # Ns = [31.,32.,33.,34.,35.,36.,37.,38.,39.] nf = 3 for N, r in zip(Ns, refs): - sx_cache = compute_cache(N, 5, True) + sx_cache = c.reset() np.testing.assert_allclose( as3.aHq.A_Hq(N, sx_cache, nf, L=0), r, rtol=7e-6, atol=1e-5 ) From b9ef5ba94e54ddd171cc213090053607e1dd4aeb Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 15:59:43 +0200 Subject: [PATCH 12/24] more updates in other files --- benchmarks/ekore/benchmark_ad.py | 8 ++++---- .../translate_singlet_replicas.py | 12 ++++++------ .../singlet_nf3/translate_singlet_nf3.py | 3 ++- .../operator_matrix_element.py | 17 ++++------------- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/benchmarks/ekore/benchmark_ad.py b/benchmarks/ekore/benchmark_ad.py index bb06be9d3..c3c8de01e 100644 --- a/benchmarks/ekore/benchmark_ad.py +++ b/benchmarks/ekore/benchmark_ad.py @@ -136,9 +136,9 @@ def check_gamma_1_pegasus(N, NF): P1NSP = CF * ((CF - CA / 2.0) * PNPA + CA * PNSB + TR * NF * PNSC) P1NSM = CF * ((CF - CA / 2.0) * PNMA + CA * PNSB + TR * NF * PNSC) - sx = h.sx(N, 2) - np.testing.assert_allclose(ad_as2.gamma_nsp(N, NF, sx), -P1NSP) - np.testing.assert_allclose(ad_as2.gamma_nsm(N, NF, sx), -P1NSM) + cache = h.cache.reset() + np.testing.assert_allclose(ad_as2.gamma_nsp(N, NF, cache), -P1NSP) + np.testing.assert_allclose(ad_as2.gamma_nsm(N, NF, cache), -P1NSM) NS = N * N NT = NS * N @@ -255,7 +255,7 @@ def check_gamma_1_pegasus(N, NF): P1Sgq = (CF * CF * PGQA + CF * CA * PGQB + TR * NF * CF * PGQC) * 4.0 P1Sgg = (CA * CA * PGGA + TR * NF * (CA * PGGB + CF * PGGC)) * 4.0 - gS1 = ad_as2.gamma_singlet(N, NF, sx) + gS1 = ad_as2.gamma_singlet(N, NF, cache) np.testing.assert_allclose(gS1[0, 0], -P1Sqq) np.testing.assert_allclose(gS1[0, 1], -P1Sqg) np.testing.assert_allclose(gS1[1, 0], -P1Sgq) diff --git a/extras/ad_n3lo/parametrised_ad/translate_singlet_replicas.py b/extras/ad_n3lo/parametrised_ad/translate_singlet_replicas.py index ff87b9ae6..d744e3905 100755 --- a/extras/ad_n3lo/parametrised_ad/translate_singlet_replicas.py +++ b/extras/ad_n3lo/parametrised_ad/translate_singlet_replicas.py @@ -44,17 +44,17 @@ name = gamma_name[1:] if "PS" in name: name = "ps" - oo.write(f"def gamma_{name}_{nf}(n, sx, variation):\n") + oo.write(f"def gamma_{name}_{nf}(n, cache, variation):\n") if "S1" in nls[0]: - oo.write(" S1 = sx[0][0]\n") + oo.write(" S1 = c.get(c.S1, cache, n)\n") if "S2" in nls[0]: - oo.write(" S2 = sx[1][0]\n") + oo.write(" S2 = c.get(c.S2, cache, n)\n") if "S3" in nls[0]: - oo.write(" S3 = sx[2][0]\n") + oo.write(" S3 = c.get(c.S3, cache, n)\n") if "S4" in nls[0]: - oo.write(" S4 = sx[3][0]\n") + oo.write(" S4 = c.get(c.S4, cache, n)\n") if "S5" in nls[0]: - oo.write(" S5 = sx[4][0]\n") + oo.write(" S5 = c.get(c.S5, cache, n)\n") if "S3m2" in nls[1]: oo.write( " S3m2 = (-(((-1 + 2 * n) * (1 - n + n**2))/((-1 + n)**3 * n**3)) + S3)/n\n" diff --git a/extras/ad_n3lo/singlet_nf3/translate_singlet_nf3.py b/extras/ad_n3lo/singlet_nf3/translate_singlet_nf3.py index bc7140df4..343e15739 100755 --- a/extras/ad_n3lo/singlet_nf3/translate_singlet_nf3.py +++ b/extras/ad_n3lo/singlet_nf3/translate_singlet_nf3.py @@ -36,9 +36,10 @@ oo.write('"""\n') oo.write("import numba as nb\n") oo.write("import numpy as np\n") + oo.write("from .....harmonics import cache as c\n") oo.write("\n\n") oo.write("@nb.njit(cache=True)\n") - oo.write(f"def gamma_{gamma_name[1:]}_nf3(n, sx):\n") + oo.write(f"def gamma_{gamma_name[1:]}_nf3(n, cache):\n") oo.write("\treturn ") for l in nls: oo.write(l) diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py index b0ff40ff7..59352a6f6 100644 --- a/src/eko/evolution_operator/operator_matrix_element.py +++ b/src/eko/evolution_operator/operator_matrix_element.py @@ -134,36 +134,27 @@ def quad_ker( integrand = ker_base.integrand(areas) if integrand == 0.0: return 0.0 - - max_weight_dict = {1: 2, 2: 3, 3: 5} - sx = harmonics.compute_cache( - ker_base.n, max_weight_dict[order[0]], ker_base.is_singlet - ) # compute the ome if ker_base.is_singlet or ker_base.is_QEDsinglet: indices = {21: 0, 100: 1, 90: 2} if is_polarized: if is_time_like: raise NotImplementedError("Polarized, time-like is not implemented") - else: - A = ome_ps.A_singlet(order, ker_base.n, sx, nf, L, is_msbar) + A = ome_ps.A_singlet(order, ker_base.n, nf, L, is_msbar) else: if is_time_like: A = ome_ut.A_singlet(order, ker_base.n, L) - else: - A = ome_us.A_singlet(order, ker_base.n, sx, nf, L, is_msbar) + A = ome_us.A_singlet(order, ker_base.n, nf, L, is_msbar) else: indices = {200: 0, 91: 1} if is_polarized: if is_time_like: raise NotImplementedError("Polarized, time-like is not implemented") - else: - A = ome_ps.A_non_singlet(order, ker_base.n, sx, nf, L) + A = ome_ps.A_non_singlet(order, ker_base.n, nf, L) else: if is_time_like: A = ome_ut.A_non_singlet(order, ker_base.n, L) - else: - A = ome_us.A_non_singlet(order, ker_base.n, sx, nf, L) + A = ome_us.A_non_singlet(order, ker_base.n, nf, L) # correct for scale variations if sv_mode == sv.Modes.exponentiated: From cd0477b72d64d70349453294052a10f8b51f3f95 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 16:02:01 +0200 Subject: [PATCH 13/24] cleaing --- src/ekore/harmonics/__init__.py | 122 ----------------------------- tests/ekore/harmonics/test_init.py | 59 -------------- 2 files changed, 181 deletions(-) diff --git a/src/ekore/harmonics/__init__.py b/src/ekore/harmonics/__init__.py index 7eeecc581..d5818dacd 100644 --- a/src/ekore/harmonics/__init__.py +++ b/src/ekore/harmonics/__init__.py @@ -8,125 +8,3 @@ from .w3 import S3, S21, S2m1, Sm2m1, Sm3, Sm21 from .w4 import S4, S31, S211, Sm4, Sm22, Sm31, Sm211 from .w5 import S5, Sm5 - -# TODO: CLEAN -# @nb.njit(cache=True) -# def base_harmonics_cache(n, is_singlet, max_weight=5, n_max_sums_weight=7): -# r"""Get the harmonics sums S basic cache. - -# Only single index harmonics are computed and stored -# in the first (:math:`S_{n}`) or in the last column (:math:`S_{-n}`). - -# Multi indices harmonics sums can be stored in the middle columns. - -# Parameters -# ---------- -# n : complex -# Mellin moment -# is_singlet : bool -# symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), -# False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) -# max_weight : int -# max harmonics weight, max value 5 (default) -# n_max_sums_weight : int -# max number of harmonics sums for a given weight - -# Returns -# ------- -# np.ndarray -# list of harmonics sums: (weights, n_max_sums_weight) - -# """ -# h_cache = np.zeros((max_weight, n_max_sums_weight), dtype=np.complex_) -# h_cache[:, 0] = sx(n, max_weight) -# if n_max_sums_weight > 1: -# h_cache[:, -1] = smx(n, h_cache[:, 0], is_singlet) -# return h_cache - - -# @nb.njit(cache=True) -# def compute_cache(n, max_weight, is_singlet): -# r"""Get the harmonics sums cache. - -# Parameters -# ---------- -# n : complex -# Mellin moment -# max_weight : int -# maximum weight to compute [2,3,4,5] -# is_singlet : bool -# symmetry factor: True for singlet like quantities (:math:`\eta=(-1)^N = 1`), -# False for non-singlet like quantities (:math:`\eta=(-1)^N=-1`) - -# Returns -# ------- -# list -# harmonic sums cache. At |N3LO| it contains: - -# .. math :: -# [[S_1,S_{-1}], -# [S_2,S_{-2}], -# [S_{3}, S_{2,1}, S_{2,-1}, S_{-2,1}, S_{-2,-1}, S_{-3}], -# [S_{4}, S_{3,1}, S_{2,1,1}, S_{-2,-2}, S_{-3, 1}, S_{-4}],] -# [S_{5}, S_{-5}] - -# """ -# # max number of harmonics sum of a given weight for a given max weight. -# n_max_sums_weight = {2: 1, 3: 3, 4: 7, 5: 7} -# sx = base_harmonics_cache(n, is_singlet, max_weight, n_max_sums_weight[max_weight]) -# if max_weight == 3: -# # Add Sm21 to cache -# sx[2, 1] = Sm21(n, sx[0, 0], sx[0, -1], is_singlet) -# elif max_weight >= 4: -# # Add weight 3 and 4 to cache -# sx[2, 1:-2] = s3x(n, sx[:, 0], sx[:, -1], is_singlet) -# sx[3, 1:-1] = s4x(n, sx[:, 0], sx[:, -1], is_singlet) -# # return list of list keeping the non zero values -# return [[el for el in sx_list if el != 0] for sx_list in sx] - - -# @nb.njit(cache=True) -# def compute_qed_ns_cache(n, s1): -# r"""Get the harmonics sums cache needed for the qed non singlet AD. - -# Parameters -# ---------- -# n : complex -# Mellin moment -# s1 : float -# harmonic sum :math:`S_1(N)` - -# Returns -# ------- -# list -# harmonic sums cache. It contains: - -# .. math :: -# [S_1(n/2), -# S_2(n/2), -# S_{3}(n/2), -# S_1((n+1)/2), -# S_2((n+1)/2), -# S_{3}((n+1)/2), -# g_3(n), -# g_3(n+2)] - -# """ -# s1h = S1(n / 2.0) -# sx_qed_ns = [s1h] -# S2h = S2(n / 2.0) -# sx_qed_ns.append(S2h) -# S3h = S3(n / 2.0) -# sx_qed_ns.append(S3h) -# S1p1h = S1((n + 1.0) / 2.0) -# sx_qed_ns.append(S1p1h) -# S2p1h = S2((n + 1.0) / 2.0) -# sx_qed_ns.append(S2p1h) -# S3p1h = S3((n + 1.0) / 2.0) -# sx_qed_ns.append(S3p1h) -# g3N = g_functions.mellin_g3(n, s1) -# sx_qed_ns.append(g3N) -# S1p2 = polygamma.recursive_harmonic_sum(s1, n, 2, 1) -# g3Np2 = g_functions.mellin_g3(n + 2.0, S1p2) -# sx_qed_ns.append(g3Np2) -# return sx_qed_ns diff --git a/tests/ekore/harmonics/test_init.py b/tests/ekore/harmonics/test_init.py index 7aecd8ef4..197907a77 100644 --- a/tests/ekore/harmonics/test_init.py +++ b/tests/ekore/harmonics/test_init.py @@ -16,50 +16,6 @@ def test_harmonic_definition(): np.testing.assert_allclose(g, sm(power, k, (-1) ** k == 1)) -# TODO: CLEAN -# def test_harmonics_cache(): -# N = np.random.randint(1, high=100) -# is_singlet = (-1) ** N == 1 -# S1 = h.S1(N) -# S2 = h.S2(N) -# S3 = h.S3(N) -# S4 = h.S4(N) -# S5 = h.S5(N) -# Sm1 = h.Sm1(N, S1, is_singlet) -# Sm2 = h.Sm2(N, S2, is_singlet) -# sx = np.array([S1, S2, S3, S4, S5]) -# smx_test = np.array( -# [ -# Sm1, -# Sm2, -# h.Sm3(N, S3, is_singlet), -# h.Sm4(N, S4, is_singlet), -# h.Sm5(N, S5, is_singlet), -# ] -# ) -# np.testing.assert_allclose(h.smx(N, sx, is_singlet), smx_test) -# s3x_test = np.array( -# [ -# h.S21(N, S1, S2), -# h.S2m1(N, S2, Sm1, Sm2, is_singlet), -# h.Sm21(N, S1, Sm1, is_singlet), -# h.Sm2m1(N, S1, S2, Sm2), -# ] -# ) -# np.testing.assert_allclose(h.s3x(N, sx, smx_test, is_singlet), s3x_test) -# Sm31 = h.Sm31(N, S1, Sm1, Sm2, is_singlet) -# s4x_test = np.array( -# [ -# h.S31(N, S1, S2, S3, S4), -# h.S211(N, S1, S2, S3), -# h.Sm22(N, S1, S2, Sm2, Sm31, is_singlet), -# h.Sm211(N, S1, S2, Sm1, is_singlet), -# Sm31, -# ] -# ) -# np.testing.assert_allclose(h.s4x(N, sx, smx_test, is_singlet), s4x_test) - - # reference values coming fom mathematica # and are computed doing an inverse mellin # transformation @@ -107,21 +63,6 @@ def test_Sm21(): np.testing.assert_allclose(h.Sm21(N, S1, Sm1), vals, atol=1e-06) -# TODO: CLEAN -# def test_Smx(): -# for j, N in enumerate(testN): -# sx = h.sx(N) -# smx = [ -# h.Sm1(N, sx[0]), -# h.Sm2(N, sx[1]), -# h.Sm3(N, sx[2]), -# h.Sm4(N, sx[3]), -# h.Sm5(N, sx[4]), -# ] -# for i, sm in enumerate(smx): -# np.testing.assert_allclose(sm, refvals[f"Sm{i+1}"][j], atol=1e-06) - - def test_smx_continuation(): # test s_{-m} against a different analytic continuation N = np.random.rand() + 1j * np.random.rand() From 4138efa62c5f1a950a92a40094d32022cf5e2d64 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 16:03:56 +0200 Subject: [PATCH 14/24] fix typo --- src/ekore/anomalous_dimensions/polarized/space_like/as3.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py index d28b0d7b9..16fbf9108 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py @@ -351,6 +351,7 @@ def gamma_nss(N, nf, cache): """ # TODO: CHECK is this true or false ?? S1 = c.get(c.S1, cache, N) + S3 = c.get(c.S3, cache, N) Sm2 = c.get(c.Sm2, cache, N, is_singlet=False) Sm3 = c.get(c.Sm3, cache, N, is_singlet=False) Sm21 = c.get(c.Sm21, cache, N, is_singlet=False) From ca4d586f1f5f2a823fee950d0607aa9d569bf66a Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 16:14:03 +0200 Subject: [PATCH 15/24] fix more typos --- src/ekore/anomalous_dimensions/polarized/space_like/as3.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py index 16fbf9108..92ec3b34d 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py @@ -111,9 +111,9 @@ def gamma_qg(N, nf, cache): """ S1 = c.get(c.S1, cache, N) - S2 = c.get(c.S1, cache, N) - S3 = c.get(c.S1, cache, N) - S4 = c.get(c.S1, cache, N) + S2 = c.get(c.S2, cache, N) + S3 = c.get(c.S3, cache, N) + S4 = c.get(c.S4, cache, N) B3 = (-(S1**3) - 3 * S1 * S2 - 2 * S3) / N B4 = (S1**4 + 6 * S1**2 * S2 + 3 * S2**2 + 8 * S1 * S3 + 6 * S4) / N E1 = S1 / N**2 + (-zeta2 + S2) / N From e96738befac3cd2d8c5f54dca3264cf2ec37bd2d Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 1 May 2023 20:29:21 +0200 Subject: [PATCH 16/24] expand as3 NS sea on even moments --- .../polarized/space_like/as3.py | 7 +++---- .../polarized/space_like/test_ad_as3.py | 16 ++++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py index 92ec3b34d..a180c6782 100644 --- a/src/ekore/anomalous_dimensions/polarized/space_like/as3.py +++ b/src/ekore/anomalous_dimensions/polarized/space_like/as3.py @@ -349,12 +349,11 @@ def gamma_nss(N, nf, cache): :math:`\\gamma_{ns,s}^{(2)}(N)` """ - # TODO: CHECK is this true or false ?? S1 = c.get(c.S1, cache, N) S3 = c.get(c.S3, cache, N) - Sm2 = c.get(c.Sm2, cache, N, is_singlet=False) - Sm3 = c.get(c.Sm3, cache, N, is_singlet=False) - Sm21 = c.get(c.Sm21, cache, N, is_singlet=False) + Sm2 = c.get(c.Sm2, cache, N, is_singlet=True) + Sm3 = c.get(c.Sm3, cache, N, is_singlet=True) + Sm21 = c.get(c.Sm21, cache, N, is_singlet=True) nss_nf1 = ( 40 / 9 diff --git a/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as3.py b/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as3.py index bd4f1fac8..82bd48675 100755 --- a/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as3.py +++ b/tests/ekore/anomalous_dimensions/polarized/space_like/test_ad_as3.py @@ -3,6 +3,7 @@ import ekore.anomalous_dimensions.polarized.space_like.as3 as as3 import ekore.anomalous_dimensions.unpolarized.space_like.as3 as as3_unpol +from eko.constants import zeta2, zeta3 from ekore import harmonics nf = 5 @@ -25,16 +26,19 @@ def test_qg_helicity_conservation(): def test_ns_sea(): ref_moments = [ - -220 / 3, - -103175 / 34992, - -4653353 / 5467500, - -7063530941 / 17425497600, - -218695344199 / 911421315000, + (20 / 9) + * ( + 23 - 12 * zeta2 - 16 * zeta3 + ), # reference value from eq 27 of :cite:`Moch:2015usa` + -0.0004286694101508916 * (-12139.872394862155 - 21888 * -0.6738675265146354), + 0.5486968449931413 * (3.844116190831125 + 6.624 * -0.712742410330442), + 1.1187158441230356 + 1.927437641723356 * -0.7278824381560618, + 0.6893728427287487 + 1.1939643347050755 * -0.7354233751216146, ] for i, mom in enumerate(ref_moments): N = 1 + 2 * i cache = harmonics.cache.reset() - np.testing.assert_allclose(-as3.gamma_nss(N, nf, cache), mom * nf, rtol=7e-7) + np.testing.assert_allclose(-as3.gamma_nss(N, nf, cache), mom * nf, rtol=5e-7) def test_ns(): From 08c1db4627ade47aac57a4f6b94ccb16a1872532 Mon Sep 17 00:00:00 2001 From: Tanishq Sharma <99052355+t7phy@users.noreply.github.com> Date: Tue, 2 May 2023 00:47:54 +0200 Subject: [PATCH 17/24] Update as2.py --- .../unpolarized/time_like/as2.py | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py index f8d6f8ceb..6ee061214 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py @@ -1,5 +1,7 @@ """The unpolarized, time-like |NLO| Altarelli-Parisi splitting kernels.""" +import math + import numba as nb import numpy as np from numpy import power as npp @@ -46,6 +48,8 @@ def gamma_nsp(N, nf, cache): S1 = c.get(c.S1, cache, N) S2 = c.get(c.S2, cache, N) + S2ph = c.get(c.S2ph, cache, N) + S3ph = c.get(c.S3ph, cache, N) N3 = N + 3 N4 = N + 4 @@ -62,22 +66,25 @@ def gamma_nsp(N, nf, cache): ZETA2 = zeta2 ZETA3 = zeta3 - SPMOM = ( - 1.0000 * (ZETA2 - S1 / N) / N - - 0.9992 * (ZETA2 - S11 / N1) / N1 - + 0.9851 * (ZETA2 - S12 / N2) / N2 - - 0.9005 * (ZETA2 - S13 / N3) / N3 - + 0.6621 * (ZETA2 - S14 / N4) / N4 - - 0.3174 * (ZETA2 - S15 / N5) / N5 - + 0.0699 * (ZETA2 - S16 / N6) / N6 - ) - +# SPMOM = ( +# 1.0000 * (ZETA2 - S1 / N) / N +# - 0.9992 * (ZETA2 - S11 / N1) / N1 +# + 0.9851 * (ZETA2 - S12 / N2) / N2 +# - 0.9005 * (ZETA2 - S13 / N3) / N3 +# + 0.6621 * (ZETA2 - S14 / N4) / N4 +# - 0.3174 * (ZETA2 - S15 / N5) / N5 +# + 0.0699 * (ZETA2 - S16 / N6) / N6 +# ) + + g3 = c.get(c.g3, cache, N) + SLC = -5 / 8 * ZETA3 - SLV = -ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + SPMOM + SLV = -ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 SSCHLP = SLC + SLV - SSTR2P = ZETA2 - polygamma(N2 / 2, 1) - SSTR3P = 0.5 * polygamma(N2 / 2, 2) + ZETA3 + + SSTR2P = S2ph #ZETA2 - polygamma(N2 / 2, 1) + SSTR3P = S3ph #0.5 * polygamma(N2 / 2, 2) + ZETA3 PNPA = ( 16 * S1 * (2 * N + 1) / (NS * N1S) @@ -150,6 +157,8 @@ def gamma_nsm(N, nf, cache): S1 = c.get(c.S1, cache, N) S2 = c.get(c.S2, cache, N) + S2ph = c.get(c.S2ph, cache, N) + S3ph = c.get(c.S3ph, cache, N) N3 = N + 3 N4 = N + 4 @@ -166,21 +175,23 @@ def gamma_nsm(N, nf, cache): ZETA2 = zeta2 ZETA3 = zeta3 - SPMOM = ( - 1.0000 * (ZETA2 - S1 / N) / N - - 0.9992 * (ZETA2 - S11 / N1) / N1 - + 0.9851 * (ZETA2 - S12 / N2) / N2 - - 0.9005 * (ZETA2 - S13 / N3) / N3 - + 0.6621 * (ZETA2 - S14 / N4) / N4 - - 0.3174 * (ZETA2 - S15 / N5) / N5 - + 0.0699 * (ZETA2 - S16 / N6) / N6 - ) + g3 = c.get(c.g3, cache, N) + +# SPMOM = ( +# 1.0000 * (ZETA2 - S1 / N) / N +# - 0.9992 * (ZETA2 - S11 / N1) / N1 +# + 0.9851 * (ZETA2 - S12 / N2) / N2 +# - 0.9005 * (ZETA2 - S13 / N3) / N3 +# + 0.6621 * (ZETA2 - S14 / N4) / N4 +# - 0.3174 * (ZETA2 - S15 / N5) / N5 +# + 0.0699 * (ZETA2 - S16 / N6) / N6 +# ) SLC = -5 / 8 * ZETA3 - SLV = -ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + SPMOM + SLV = -ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 SSCHLM = SLC - SLV - SSTR2M = ZETA2 - polygamma(N1 / 2, 1) - SSTR3M = 0.5 * polygamma(N1 / 2, 2) + ZETA3 + SSTR2M = S2ph #ZETA2 - polygamma(N1 / 2, 1) + SSTR3M = S3ph #0.5 * polygamma(N1 / 2, 2) + ZETA3 PNMA = ( 16 * S1 * (2 * N + 1) / (NS * N1S) From cd34b1c666755450c64c19ec49a463a2f959266b Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 2 May 2023 09:15:24 +0200 Subject: [PATCH 18/24] use iterator insted of int in harmonic cache --- src/ekore/harmonics/cache.py | 78 +++++++++++++++-------------- tests/ekore/harmonics/test_cache.py | 6 +-- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/ekore/harmonics/cache.py b/src/ekore/harmonics/cache.py index 1434c1628..cff3a1ec8 100644 --- a/src/ekore/harmonics/cache.py +++ b/src/ekore/harmonics/cache.py @@ -8,49 +8,51 @@ from .polygamma import recursive_harmonic_sum # here a register of all possible functions -S1 = 0 # = S_1(N) -S2 = 1 -S3 = 2 -S4 = 3 -S5 = 4 -Sm1 = 5 -Sm2 = 6 -Sm3 = 7 -Sm4 = 8 -Sm5 = 9 -S21 = 10 -S2m1 = 11 -Sm21 = 12 -Sm2m1 = 13 -S31 = 14 -Sm31 = 15 -Sm22 = 16 -S211 = 17 -Sm211 = 18 -S1h = 19 -S2h = 20 -S3h = 21 -S4h = 22 -S5h = 23 -S1mh = 24 -S2mh = 25 -S3mh = 26 -S4mh = 27 -S5mh = 28 -S1ph = 29 -S2ph = 30 -S3ph = 31 -S4ph = 32 -S5ph = 33 -g3 = 34 -S1p2 = 35 -g3p2 = 36 +CACHE_SIZE = 37 +_index = iter(range(CACHE_SIZE)) +S1 = next(_index) # = S_1(N) +S2 = next(_index) +S3 = next(_index) +S4 = next(_index) +S5 = next(_index) +Sm1 = next(_index) +Sm2 = next(_index) +Sm3 = next(_index) +Sm4 = next(_index) +Sm5 = next(_index) +S21 = next(_index) +S2m1 = next(_index) +Sm21 = next(_index) +Sm2m1 = next(_index) +S31 = next(_index) +Sm31 = next(_index) +Sm22 = next(_index) +S211 = next(_index) +Sm211 = next(_index) +S1h = next(_index) +S2h = next(_index) +S3h = next(_index) +S4h = next(_index) +S5h = next(_index) +S1mh = next(_index) +S2mh = next(_index) +S3mh = next(_index) +S4mh = next(_index) +S5mh = next(_index) +S1ph = next(_index) +S2ph = next(_index) +S3ph = next(_index) +S4ph = next(_index) +S5ph = next(_index) +g3 = next(_index) +S1p2 = next(_index) +g3p2 = next(_index) @nb.njit(cache=True) def reset(): """Return the cache placeholder array.""" - return np.full(37, np.nan, np.complex_) + return np.full(CACHE_SIZE, np.nan, np.complex_) @nb.njit(cache=True) diff --git a/tests/ekore/harmonics/test_cache.py b/tests/ekore/harmonics/test_cache.py index e503636bc..ab756da11 100644 --- a/tests/ekore/harmonics/test_cache.py +++ b/tests/ekore/harmonics/test_cache.py @@ -8,8 +8,8 @@ def test_reset(): c = h.cache.reset() np.testing.assert_allclose(c, np.full(c.shape, np.nan)) - available_items = np.sum( - [isinstance(val, int) for val in h.cache.__dict__.values()] + available_items = ( + np.sum([isinstance(val, int) for val in h.cache.__dict__.values()]) - 1 ) assert c.shape == (available_items,) @@ -21,7 +21,7 @@ def test_get(): c = h.cache.reset() # loop on cached names for idx_name, idx in h.cache.__dict__.items(): - if not isinstance(idx, int): + if not isinstance(idx, int) or idx_name == "CACHE_SIZE": continue h.cache.get(idx, c, N, is_singlet) # Sx((N-1)/2) From 9f7ec7621e7dbb8412aed68ad17c2f3f9df787e6 Mon Sep 17 00:00:00 2001 From: Tanishq Sharma <99052355+t7phy@users.noreply.github.com> Date: Tue, 2 May 2023 11:27:09 +0200 Subject: [PATCH 19/24] Update as2.py --- .../unpolarized/time_like/as2.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py index 6ee061214..80ba25093 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py @@ -48,8 +48,8 @@ def gamma_nsp(N, nf, cache): S1 = c.get(c.S1, cache, N) S2 = c.get(c.S2, cache, N) - S2ph = c.get(c.S2ph, cache, N) - S3ph = c.get(c.S3ph, cache, N) + S2h = c.get(c.S2h, cache, N) + S3h = c.get(c.S3h, cache, N) N3 = N + 3 N4 = N + 4 @@ -83,8 +83,8 @@ def gamma_nsp(N, nf, cache): SSCHLP = SLC + SLV - SSTR2P = S2ph #ZETA2 - polygamma(N2 / 2, 1) - SSTR3P = S3ph #0.5 * polygamma(N2 / 2, 2) + ZETA3 + SSTR2P = S2h #ZETA2 - polygamma(N2 / 2, 1) + SSTR3P = S3h #0.5 * polygamma(N2 / 2, 2) + ZETA3 PNPA = ( 16 * S1 * (2 * N + 1) / (NS * N1S) @@ -157,8 +157,8 @@ def gamma_nsm(N, nf, cache): S1 = c.get(c.S1, cache, N) S2 = c.get(c.S2, cache, N) - S2ph = c.get(c.S2ph, cache, N) - S3ph = c.get(c.S3ph, cache, N) + S2mh = c.get(c.S2mh, cache, N) + S3mh = c.get(c.S3mh, cache, N) N3 = N + 3 N4 = N + 4 @@ -190,8 +190,8 @@ def gamma_nsm(N, nf, cache): SLC = -5 / 8 * ZETA3 SLV = -ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 SSCHLM = SLC - SLV - SSTR2M = S2ph #ZETA2 - polygamma(N1 / 2, 1) - SSTR3M = S3ph #0.5 * polygamma(N1 / 2, 2) + ZETA3 + SSTR2M = S2mh #ZETA2 - polygamma(N1 / 2, 1) + SSTR3M = S3mh #0.5 * polygamma(N1 / 2, 2) + ZETA3 PNMA = ( 16 * S1 * (2 * N + 1) / (NS * N1S) From 0f5a7c1344474439c0dc873b20b932b1448afe24 Mon Sep 17 00:00:00 2001 From: Tanishq Sharma <99052355+t7phy@users.noreply.github.com> Date: Tue, 2 May 2023 11:51:36 +0200 Subject: [PATCH 20/24] Update as2.py --- .../anomalous_dimensions/unpolarized/time_like/as2.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py index 80ba25093..c7b00d69b 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py @@ -48,8 +48,10 @@ def gamma_nsp(N, nf, cache): S1 = c.get(c.S1, cache, N) S2 = c.get(c.S2, cache, N) + S1h = c.get(c.S1h, cache, N) S2h = c.get(c.S2h, cache, N) S3h = c.get(c.S3h, cache, N) + S1ph = c.get(c.S1ph, cache, N) N3 = N + 3 N4 = N + 4 @@ -79,7 +81,7 @@ def gamma_nsp(N, nf, cache): g3 = c.get(c.g3, cache, N) SLC = -5 / 8 * ZETA3 - SLV = -ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 + SLV = g3 + S1/N**2 - (ZETA2/2)*(-2/(1 + N) + 2/N + S1ph - S1h) #-ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 SSCHLP = SLC + SLV @@ -157,8 +159,10 @@ def gamma_nsm(N, nf, cache): S1 = c.get(c.S1, cache, N) S2 = c.get(c.S2, cache, N) + S1h = c.get(c.S1h, cache, N) S2mh = c.get(c.S2mh, cache, N) S3mh = c.get(c.S3mh, cache, N) + S1ph = c.get(c.S1ph, cache, N) N3 = N + 3 N4 = N + 4 @@ -188,7 +192,7 @@ def gamma_nsm(N, nf, cache): # ) SLC = -5 / 8 * ZETA3 - SLV = -ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 + SLV = g3 + S1/N**2 - (ZETA2/2)*(-2/(1 + N) + 2/N + S1ph - S1h) #-ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 SSCHLM = SLC - SLV SSTR2M = S2mh #ZETA2 - polygamma(N1 / 2, 1) SSTR3M = S3mh #0.5 * polygamma(N1 / 2, 2) + ZETA3 From 02e76dc151fe81f525677db5bbf8dfd4a1dd9d5d Mon Sep 17 00:00:00 2001 From: t7phy Date: Tue, 2 May 2023 12:04:21 +0200 Subject: [PATCH 21/24] clean up --- .../unpolarized/time_like/as2.py | 72 +++---------------- 1 file changed, 8 insertions(+), 64 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py index c7b00d69b..037bfb447 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py @@ -11,9 +11,6 @@ from ....harmonics import cache as c -# TODO: CLEAN: all the calls to polygamma could be reduced to some harmonics... -from ....harmonics.polygamma import cern_polygamma as polygamma - @nb.njit(cache=True) def gamma_nsp(N, nf, cache): @@ -42,7 +39,6 @@ def gamma_nsp(N, nf, cache): NFO = NT * N N1 = N + 1 - N2 = N + 2 N1S = N1 * N1 N1T = N1S * N1 @@ -52,49 +48,23 @@ def gamma_nsp(N, nf, cache): S2h = c.get(c.S2h, cache, N) S3h = c.get(c.S3h, cache, N) S1ph = c.get(c.S1ph, cache, N) - - N3 = N + 3 - N4 = N + 4 - N5 = N + 5 - N6 = N + 6 - - S11 = S1 + 1 / N1 - S12 = S11 + 1 / N2 - S13 = S12 + 1 / N3 - S14 = S13 + 1 / N4 - S15 = S14 + 1 / N5 - S16 = S15 + 1 / N6 + g3 = c.get(c.g3, cache, N) ZETA2 = zeta2 ZETA3 = zeta3 -# SPMOM = ( -# 1.0000 * (ZETA2 - S1 / N) / N -# - 0.9992 * (ZETA2 - S11 / N1) / N1 -# + 0.9851 * (ZETA2 - S12 / N2) / N2 -# - 0.9005 * (ZETA2 - S13 / N3) / N3 -# + 0.6621 * (ZETA2 - S14 / N4) / N4 -# - 0.3174 * (ZETA2 - S15 / N5) / N5 -# + 0.0699 * (ZETA2 - S16 / N6) / N6 -# ) - - g3 = c.get(c.g3, cache, N) - SLC = -5 / 8 * ZETA3 - SLV = g3 + S1/N**2 - (ZETA2/2)*(-2/(1 + N) + 2/N + S1ph - S1h) #-ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 + SLV = g3 + S1 / N**2 - (ZETA2 / 2) * (-2 / (1 + N) + 2 / N + S1ph - S1h) SSCHLP = SLC + SLV - - SSTR2P = S2h #ZETA2 - polygamma(N2 / 2, 1) - SSTR3P = S3h #0.5 * polygamma(N2 / 2, 2) + ZETA3 PNPA = ( 16 * S1 * (2 * N + 1) / (NS * N1S) - + 16 * (2 * S1 - 1 / (N * N1)) * (S2 - SSTR2P) + + 16 * (2 * S1 - 1 / (N * N1)) * (S2 - S2h) + 64 * SSCHLP + 24 * S2 - 3 - - 8 * SSTR3P + - 8 * S3h - 8 * (3 * NT + NS - 1) / (NT * N1T) - 16 * (2 * NS + 2 * N + 1) / (NT * N1T) ) * (-0.5) @@ -153,7 +123,6 @@ def gamma_nsm(N, nf, cache): NFO = NT * N N1 = N + 1 - N2 = N + 2 N1S = N1 * N1 N1T = N1S * N1 @@ -163,47 +132,22 @@ def gamma_nsm(N, nf, cache): S2mh = c.get(c.S2mh, cache, N) S3mh = c.get(c.S3mh, cache, N) S1ph = c.get(c.S1ph, cache, N) - - N3 = N + 3 - N4 = N + 4 - N5 = N + 5 - N6 = N + 6 - - S11 = S1 + 1 / N1 - S12 = S11 + 1 / N2 - S13 = S12 + 1 / N3 - S14 = S13 + 1 / N4 - S15 = S14 + 1 / N5 - S16 = S15 + 1 / N6 + g3 = c.get(c.g3, cache, N) ZETA2 = zeta2 ZETA3 = zeta3 - g3 = c.get(c.g3, cache, N) - -# SPMOM = ( -# 1.0000 * (ZETA2 - S1 / N) / N -# - 0.9992 * (ZETA2 - S11 / N1) / N1 -# + 0.9851 * (ZETA2 - S12 / N2) / N2 -# - 0.9005 * (ZETA2 - S13 / N3) / N3 -# + 0.6621 * (ZETA2 - S14 / N4) / N4 -# - 0.3174 * (ZETA2 - S15 / N5) / N5 -# + 0.0699 * (ZETA2 - S16 / N6) / N6 -# ) - SLC = -5 / 8 * ZETA3 - SLV = g3 + S1/N**2 - (ZETA2/2)*(-2/(1 + N) + 2/N + S1ph - S1h) #-ZETA2 / 2 * (polygamma(N1 / 2, 0) - polygamma(N / 2, 0)) + S1 / NS + g3 + SLV = g3 + S1 / N**2 - (ZETA2 / 2) * (-2 / (1 + N) + 2 / N + S1ph - S1h) SSCHLM = SLC - SLV - SSTR2M = S2mh #ZETA2 - polygamma(N1 / 2, 1) - SSTR3M = S3mh #0.5 * polygamma(N1 / 2, 2) + ZETA3 PNMA = ( 16 * S1 * (2 * N + 1) / (NS * N1S) - + 16 * (2 * S1 - 1 / (N * N1)) * (S2 - SSTR2M) + + 16 * (2 * S1 - 1 / (N * N1)) * (S2 - S2mh) + 64 * SSCHLM + 24 * S2 - 3 - - 8 * SSTR3M + - 8 * S3mh - 8 * (3 * NT + NS - 1) / (NT * N1T) + 16 * (2 * NS + 2 * N + 1) / (NT * N1T) ) * (-0.5) From 264687b8e85efdf5ef87dd81d8fc329be42afa5b Mon Sep 17 00:00:00 2001 From: t7phy Date: Tue, 2 May 2023 12:08:35 +0200 Subject: [PATCH 22/24] clean up 2 --- src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py index 037bfb447..7b423d8bc 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py @@ -1,7 +1,5 @@ """The unpolarized, time-like |NLO| Altarelli-Parisi splitting kernels.""" -import math - import numba as nb import numpy as np from numpy import power as npp From ee9f690cf56d85aad1a522cca6f26be91bef9db0 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 2 May 2023 12:19:16 +0200 Subject: [PATCH 23/24] remove zeta redefinitions --- .../unpolarized/time_like/as2.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py index 7b423d8bc..a2b7cdfec 100644 --- a/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py +++ b/src/ekore/anomalous_dimensions/unpolarized/time_like/as2.py @@ -48,11 +48,8 @@ def gamma_nsp(N, nf, cache): S1ph = c.get(c.S1ph, cache, N) g3 = c.get(c.g3, cache, N) - ZETA2 = zeta2 - ZETA3 = zeta3 - - SLC = -5 / 8 * ZETA3 - SLV = g3 + S1 / N**2 - (ZETA2 / 2) * (-2 / (1 + N) + 2 / N + S1ph - S1h) + SLC = -5 / 8 * zeta3 + SLV = g3 + S1 / N**2 - (zeta2 / 2) * (-2 / (1 + N) + 2 / N + S1ph - S1h) SSCHLP = SLC + SLV @@ -79,7 +76,7 @@ def gamma_nsp(N, nf, cache): + 16 * (11 * NS + 5 * N - 3) / (9 * NS * N1S) ) * (-0.5) PNSTL = (-4 * S1 + 3 + 2 / (N * N1)) * ( - 2 * S2 - 2 * ZETA2 - (2 * N + 1) / (NS * N1S) + 2 * S2 - 2 * zeta2 - (2 * N + 1) / (NS * N1S) ) result = ( @@ -132,11 +129,8 @@ def gamma_nsm(N, nf, cache): S1ph = c.get(c.S1ph, cache, N) g3 = c.get(c.g3, cache, N) - ZETA2 = zeta2 - ZETA3 = zeta3 - - SLC = -5 / 8 * ZETA3 - SLV = g3 + S1 / N**2 - (ZETA2 / 2) * (-2 / (1 + N) + 2 / N + S1ph - S1h) + SLC = -5 / 8 * zeta3 + SLV = g3 + S1 / N**2 - (zeta2 / 2) * (-2 / (1 + N) + 2 / N + S1ph - S1h) SSCHLM = SLC - SLV PNMA = ( @@ -162,7 +156,7 @@ def gamma_nsm(N, nf, cache): + 16 * (11 * NS + 5 * N - 3) / (9 * NS * N1S) ) * (-0.5) PNSTL = (-4 * S1 + 3 + 2 / (N * N1)) * ( - 2 * S2 - 2 * ZETA2 - (2 * N + 1) / (NS * N1S) + 2 * S2 - 2 * zeta2 - (2 * N + 1) / (NS * N1S) ) result = ( From f10329d5251770d9f71674b9e7ac6f181b61397e Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 2 May 2023 18:37:54 +0200 Subject: [PATCH 24/24] make numba happy with ugly solution --- src/ekore/harmonics/cache.py | 271 +++++++++++++++++------------------ 1 file changed, 131 insertions(+), 140 deletions(-) diff --git a/src/ekore/harmonics/cache.py b/src/ekore/harmonics/cache.py index cff3a1ec8..fb297fe4a 100644 --- a/src/ekore/harmonics/cache.py +++ b/src/ekore/harmonics/cache.py @@ -1,4 +1,6 @@ """Caching harmonic sums across :mod:`ekore`.""" +from typing import Optional + import numba as nb import numpy as np import numpy.typing as npt @@ -8,7 +10,7 @@ from .polygamma import recursive_harmonic_sum # here a register of all possible functions -CACHE_SIZE = 37 +CACHE_SIZE = 31 _index = iter(range(CACHE_SIZE)) S1 = next(_index) # = S_1(N) S2 = next(_index) @@ -32,18 +34,12 @@ S1h = next(_index) S2h = next(_index) S3h = next(_index) -S4h = next(_index) -S5h = next(_index) S1mh = next(_index) S2mh = next(_index) S3mh = next(_index) -S4mh = next(_index) -S5mh = next(_index) S1ph = next(_index) S2ph = next(_index) S3ph = next(_index) -S4ph = next(_index) -S5ph = next(_index) g3 = next(_index) S1p2 = next(_index) g3p2 = next(_index) @@ -56,7 +52,39 @@ def reset(): @nb.njit(cache=True) -def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet=None) -> complex: +def update(func, key, cache, n): + """Compute simple harmonics if not yet in cache.""" + if np.isnan(cache[key]): + cache[key] = func(n) + return cache + + +@nb.njit(cache=True) +def update_Sm1(cache, n, is_singlet): + """Compute Sm1 if not yet in cache.""" + if np.isnan(cache[Sm1]): + cache = update(w1.S1, S1, cache, n) + cache = update(w1.S1, S1mh, cache, (n - 1) / 2) + cache = update(w1.S1, S1h, cache, n / 2) + cache[Sm1] = w1.Sm1(n, cache[S1], cache[S1mh], cache[S1h], is_singlet) + return cache + + +@nb.njit(cache=True) +def update_Sm2(cache, n, is_singlet): + """Compute Sm2 if not yet in cache.""" + if np.isnan(cache[Sm2]): + cache = update(w2.S2, S2, cache, n) + cache = update(w2.S2, S2mh, cache, (n - 1) / 2) + cache = update(w2.S2, S2h, cache, n / 2) + cache[Sm2] = w2.Sm2(n, cache[S2], cache[S2mh], cache[S2h], is_singlet) + return cache + + +@nb.njit(cache=True) +def get( + key: int, cache: npt.ArrayLike, n: complex, is_singlet: Optional[bool] = None +) -> complex: r"""Retrieve an element of the cache. Parameters @@ -88,151 +116,114 @@ def get(key: int, cache: npt.ArrayLike, n: complex, is_singlet=None) -> complex: if not np.isnan(s): return s # compute it now ... + # weight 1 if key == S1: s = w1.S1(n) - elif key == S2: - s = w2.S2(n) - elif key == S3: - s = w3.S3(n) - elif key == S4: - s = w4.S4(n) - elif key == S5: - s = w5.S5(n) - elif key == Sm1: - s = w1.Sm1( - n, - get(S1, cache, n), - get(S1mh, cache, n), - get(S1h, cache, n), - is_singlet, - ) - elif key == Sm2: - s = w2.Sm2( - n, - get(S2, cache, n), - get(S2mh, cache, n), - get(S2h, cache, n), - is_singlet, - ) - elif key == Sm3: - s = w3.Sm3( - n, - get(S3, cache, n), - get(S3mh, cache, n), - get(S3h, cache, n), - is_singlet, - ) - elif key == Sm4: - s = w4.Sm4( - n, - get(S4, cache, n), - get(S4mh, cache, n), - get(S4h, cache, n), - is_singlet, - ) - elif key == Sm5: - s = w5.Sm5( - n, - get(S5, cache, n), - get(S5mh, cache, n), - get(S5h, cache, n), - is_singlet, - ) - elif key == S21: - s = w3.S21(n, get(S1, cache, n), get(S2, cache, n)) - elif key == S2m1: - s = w3.S2m1( - n, - get(S2, cache, n), - get(Sm1, cache, n, is_singlet), - get(Sm2, cache, n, is_singlet), - is_singlet, - ) - elif key == Sm21: - s = w3.Sm21(n, get(S1, cache, n), get(Sm1, cache, n, is_singlet), is_singlet) - elif key == Sm2m1: - s = w3.Sm2m1( - n, - get(S1, cache, n), - get(S2, cache, n), - get(Sm2, cache, n, is_singlet), - ) - elif key == S31: - s = w4.S31( - n, - get(S1, cache, n), - get(S2, cache, n), - get(S3, cache, n), - get(S4, cache, n), - ) - elif key == Sm31: - s = w4.Sm31( - n, - get(S1, cache, n), - get(Sm1, cache, n, is_singlet), - get(Sm2, cache, n, is_singlet), - is_singlet, - ) - elif key == Sm22: - s = w4.Sm22( - n, - get(S1, cache, n), - get(S2, cache, n), - get(Sm2, cache, n, is_singlet), - get(Sm31, cache, n, is_singlet), - is_singlet, - ) - elif key == S211: - s = w4.S211( - n, - get(S1, cache, n), - get(S2, cache, n), - get(S3, cache, n), - ) - elif key == Sm211: - s = w4.Sm211( - n, - get(S1, cache, n), - get(S2, cache, n), - get(Sm1, cache, n, is_singlet), - is_singlet, - ) elif key == S1h: s = w1.S1(n / 2) - elif key == S2h: - s = w2.S2(n / 2) - elif key == S3h: - s = w3.S3(n / 2) - elif key == S4h: - s = w4.S4(n / 2) - elif key == S5h: - s = w5.S5(n / 2) elif key == S1mh: s = w1.S1((n - 1) / 2) + elif key == S1ph: + cache = update(w1.S1, S1mh, cache, (n - 1) / 2) + s = recursive_harmonic_sum(cache[S1mh], (n - 1) / 2, 1, 1) + elif key == Sm1: + cache = update(w1.S1, S1, cache, n) + cache = update(w1.S1, S1mh, cache, (n - 1) / 2) + cache = update(w1.S1, S1h, cache, n / 2) + s = w1.Sm1(n, cache[S1], cache[S1mh], cache[S1h], is_singlet) + elif key == S1p2: + cache = update(w1.S1, S1, cache, n) + s = recursive_harmonic_sum(cache[S1], n, 2, 1) + # weight 2 + elif key == S2: + s = w2.S2(n) + elif key == S2h: + s = w2.S2(n / 2) elif key == S2mh: s = w2.S2((n - 1) / 2) + elif key == S2ph: + cache = update(w2.S2, S2mh, cache, (n - 1) / 2) + s = recursive_harmonic_sum(cache[S2mh], (n - 1) / 2, 1, 2) + elif key == Sm2: + cache = update(w2.S2, S2, cache, n) + cache = update(w2.S2, S2mh, cache, (n - 1) / 2) + cache = update(w2.S2, S2h, cache, n / 2) + s = w2.Sm2(n, cache[S2], cache[S2mh], cache[S2h], is_singlet) + # weight 3 + elif key == S3: + s = w3.S3(n) + elif key == S3h: + s = w3.S3(n / 2) elif key == S3mh: s = w3.S3((n - 1) / 2) - elif key == S4mh: - s = w4.S4((n - 1) / 2) - elif key == S5mh: - s = w5.S5((n - 1) / 2) - elif key == S1ph: - s = recursive_harmonic_sum(get(S1mh, cache, n), (n - 1) / 2, 1, 1) - elif key == S2ph: - s = recursive_harmonic_sum(get(S2mh, cache, n), (n - 1) / 2, 1, 2) elif key == S3ph: - s = recursive_harmonic_sum(get(S3mh, cache, n), (n - 1) / 2, 1, 3) - elif key == S4ph: - s = recursive_harmonic_sum(get(S4mh, cache, n), (n - 1) / 2, 1, 4) - elif key == S5ph: - s = recursive_harmonic_sum(get(S5mh, cache, n), (n - 1) / 2, 1, 5) + cache = update(w3.S3, S3mh, cache, (n - 1) / 2) + s = recursive_harmonic_sum(cache[S3mh], (n - 1) / 2, 1, 3) + elif key == Sm3: + cache = update(w3.S3, S3, cache, n) + cache = update(w3.S3, S3mh, cache, (n - 1) / 2) + cache = update(w3.S3, S3h, cache, n / 2) + s = w3.Sm3(n, cache[S3], cache[S3mh], cache[S3h], is_singlet) + # weight 4 + elif key == S4: + s = w4.S4(n) + elif key == Sm4: + cache = update(w4.S4, S4, cache, n) + S4mh = w4.S4((n - 1) / 2) + S4h = w4.S4(n / 2) + s = w4.Sm4(n, cache[S4], S4mh, S4h, is_singlet) + # weight 5 + elif key == S5: + s = w5.S5(n) + elif key == Sm5: + cache = update(w5.S5, S5, cache, n) + S5mh = w5.S5((n - 1) / 2) + S5h = w5.S5(n / 2) + s = w5.Sm5(n, cache[S5], S5mh, S5h, is_singlet) + # mellin g3 and related elif key == g3: - s = mellin_g3(n, get(S1, cache, n)) - elif key == S1p2: - s = recursive_harmonic_sum(get(S1, cache, n), n, 2, 1) + cache = update(w1.S1, S1, cache, n) + s = mellin_g3(n, cache[S1]) elif key == g3p2: - s = mellin_g3(n + 2, get(S1p2, cache, n)) + cache = update(w1.S1, S1p2, cache, n + 2) + s = mellin_g3(n + 2, cache[S1p2]) + else: + # Multi index harmonics which do not require Sxm + cache = update(w1.S1, S1, cache, n) + cache = update(w2.S2, S2, cache, n) + if key == S21: + s = w3.S21(n, cache[S1], cache[S2]) + elif key == S31: + cache = update(w3.S3, S3, cache, n) + cache = update(w4.S4, S4, cache, n) + s = w4.S31(n, cache[S1], cache[S2], cache[S3], cache[S4]) + elif key == S211: + cache = update(w3.S3, S3, cache, n) + s = w4.S211(n, cache[S1], cache[S2], cache[S3]) + else: + # Multi index harmonics which require Sm1 + cache = update_Sm1(cache, n, is_singlet) + if key == Sm21: + s = w3.Sm21(n, cache[S1], cache[Sm1], is_singlet) + elif key == Sm211: + s = w4.Sm211(n, cache[S1], cache[S2], cache[Sm1], is_singlet) + else: + # Multi index harmonics which require also Sm2 + cache = update_Sm2(cache, n, is_singlet) + if key == S2m1: + s = w3.S2m1(n, cache[S2], cache[Sm1], cache[Sm2], is_singlet) + elif key == Sm2m1: + s = w3.Sm2m1(n, cache[S1], cache[S2], cache[Sm2]) + elif key == Sm31: + s = w4.Sm31(n, cache[S1], cache[Sm1], cache[Sm2], is_singlet) + elif key == Sm22: + if np.isnan(cache[Sm31]): + cache[Sm31] = w4.Sm31( + n, cache[S1], cache[Sm1], cache[Sm2], is_singlet + ) + s = w4.Sm22( + n, cache[S1], cache[S2], cache[Sm2], cache[Sm31], is_singlet + ) # store and return cache[key] = s return s