diff --git a/n3fit/src/n3fit/layers/msr_normalization.py b/n3fit/src/n3fit/layers/msr_normalization.py index d5af933e5e..c31bf8fb41 100644 --- a/n3fit/src/n3fit/layers/msr_normalization.py +++ b/n3fit/src/n3fit/layers/msr_normalization.py @@ -2,9 +2,10 @@ from n3fit.backends import operations as op GLUON_IDX = [[2]] -V_IDX = [[3], [6], [7], [8]] +V_IDX = [[3], [7], [8]] V3_IDX = [[4]] V8_IDX = [[5]] +V15_IDX = [[6]] class MSR_Normalization(MetaLayer): @@ -30,7 +31,7 @@ def __init__(self, output_dim=14, mode="ALL", **kwargs): if self._msr_enabled: idx += GLUON_IDX if self._vsr_enabled: - idx += V_IDX + V3_IDX + V8_IDX + idx += V_IDX + V3_IDX + V8_IDX + V15_IDX self._out_scatter = op.as_layer( op.scatter_to_one, op_kwargs={"indices": idx, "output_dim": output_dim} @@ -41,9 +42,10 @@ def __init__(self, output_dim=14, mode="ALL", **kwargs): def call(self, pdf_integrated): """Imposes the valence and momentum sum rules: A_g = (1-sigma)/g - A_v = A_v15 = A_v24 = A_v35 = 3/V + A_v = A_v24 = A_v35 = 3/V A_v3 = 1/V_3 A_v8 = 3/V_8 + A_v15 = 3/V_15 Note that both the input and the output are in the 14-flavours fk-basis """ @@ -58,6 +60,7 @@ def call(self, pdf_integrated): n_av = [3.0 / y[V_IDX[0][0]]] * len(V_IDX) n_av3 = [1.0 / y[V3_IDX[0][0]]] * len(V3_IDX) n_av8 = [3.0 / y[V8_IDX[0][0]]] * len(V8_IDX) - norm_constants += n_av + n_av3 + n_av8 + n_av15 = [3.0 / y[V15_IDX[0][0]]] * len(V15_IDX) + norm_constants += n_av + n_av3 + n_av8 + n_av15 return self._out_scatter(norm_constants) diff --git a/n3fit/src/n3fit/layers/rotations.py b/n3fit/src/n3fit/layers/rotations.py index 88fa8d722b..347571094d 100644 --- a/n3fit/src/n3fit/layers/rotations.py +++ b/n3fit/src/n3fit/layers/rotations.py @@ -78,7 +78,7 @@ def call(self, pdf_raw): x[2], # v x[3], # v3 x[4], # v8 - x[2], # v15 + x[8], # v15 x[2], # v24 x[2], # v35 x[5], # t3 diff --git a/n3fit/src/n3fit/layers/x_operations.py b/n3fit/src/n3fit/layers/x_operations.py index a61460edfc..f3cc9c32e9 100644 --- a/n3fit/src/n3fit/layers/x_operations.py +++ b/n3fit/src/n3fit/layers/x_operations.py @@ -33,7 +33,7 @@ class xDivide(MetaLayer): def __init__(self, output_dim=BASIS_SIZE, div_list=None, **kwargs): if div_list is None: - div_list = [3, 4, 5] + div_list = [3, 4, 5, 6] self.output_dim = output_dim self.div_list = div_list super().__init__(**kwargs) diff --git a/n3fit/src/n3fit/msr.py b/n3fit/src/n3fit/msr.py index 0bf85c52d3..e99006de47 100644 --- a/n3fit/src/n3fit/msr.py +++ b/n3fit/src/n3fit/msr.py @@ -36,7 +36,7 @@ def gen_integration_input(nx): return xgrid, weights_array -def msr_impose(nx=int(2e3), basis_size=8, mode='All', scaler=None): +def msr_impose(nx=int(2e3), mode='All', scaler=None): """ This function receives: Generates a function that applies a normalization layer to the fit. @@ -51,8 +51,6 @@ def msr_impose(nx=int(2e3), basis_size=8, mode='All', scaler=None): ---------- nx: int number of points for the integration grid, default: 2000 - basis_size: int - number of flavours output of the NN, default: 8 mode: str what sum rules to compute (MSR, VSR or All), default: All scaler: scaler @@ -69,16 +67,14 @@ def msr_impose(nx=int(2e3), basis_size=8, mode='All', scaler=None): # 2. Prepare the pdf for integration # for that we need to multiply several flavours with 1/x division_by_x = xDivide() - # 3. Now create the integration layer (the layer that will simply integrate, given some weight integrator = xIntegrator(weights_array, input_shape=(nx,)) # 4. Now create the normalization by selecting the right integrations - normalizer = MSR_Normalization(input_shape=(basis_size,), mode=mode) + normalizer = MSR_Normalization(mode=mode) # 5. Make the xgrid array into a backend input layer so it can be given to the normalization xgrid_input = op.numpy_to_input(xgrid, name="integration_grid") - # Finally prepare a function which will take as input the output of the PDF model # and will return it appropiately normalized. def apply_normalization(layer_pdf): diff --git a/n3fit/src/n3fit/tests/test_vpinterface.py b/n3fit/src/n3fit/tests/test_vpinterface.py index 6b9edf0d15..3575308cc1 100644 --- a/n3fit/src/n3fit/tests/test_vpinterface.py +++ b/n3fit/src/n3fit/tests/test_vpinterface.py @@ -14,7 +14,7 @@ def generate_n3pdf(layers=1, members=1, name="n3fit"): """Generate a N3PDF model""" fake_fl = [ {"fl": i, "largex": [0, 1], "smallx": [1, 2]} - for i in ["u", "ubar", "d", "dbar", "c", "cbar", "s", "sbar"] + for i in ["u", "ubar", "d", "dbar", "c", "g", "s", "sbar"] ] nodes = list(np.random.randint(1, 10, size=layers)) + [8] activations = ["tanh"] * layers + ["linear"] @@ -24,6 +24,7 @@ def generate_n3pdf(layers=1, members=1, name="n3fit"): seed=np.random.randint(100), flav_info=fake_fl, parallel_models=members, + fitbasis="FLAVOUR" ) return N3PDF(pdf_model, name=name) diff --git a/validphys2/src/validphys/pdfbases.py b/validphys2/src/validphys/pdfbases.py index 6154b59325..0970a385ba 100644 --- a/validphys2/src/validphys/pdfbases.py +++ b/validphys2/src/validphys/pdfbases.py @@ -502,12 +502,14 @@ def f_(transform_func): 'photon' : {'photon':1}, }, aliases = {'gluon':'g', 'singlet': r'\Sigma', 'sng': r'\Sigma', 'sigma': r'\Sigma', - 'v': 'V', 'v3': 'V3', 'v8': 'V8', 't3': 'T3', 't8': 'T8', 't15': 'T15'}, + 'v': 'V', 'v3': 'V3', 'v8': 'V8', 't3': 'T3', 't8': 'T8', 't15': 'T15', 'v15': 'V15',}, default_elements=(r'\Sigma', 'V', 'T3', 'V3', 'T8', 'V8', 'T15', 'gluon', ) ) EVOL = evolution +CCBAR_ASYMM = evolution + PDF4LHC20 = LinearBasis.from_mapping({ r'\Sigma': { 'u': 1, 'ubar': 1, 'd': 1, 'dbar': 1, 's': 1, 'sbar': 1, @@ -684,7 +686,15 @@ def fitbasis_to_NN31IC(flav_info, fitbasis): """ if fitbasis == 'NN31IC': - return np.identity(8) + sng = {'sng': 1, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 'cp': 0, 'g': 0 } + v = {'sng': 0, 'v': 1, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 'cp': 0, 'g': 0 } + v3 = {'sng': 0, 'v': 0, 'v3': 1, 'v8': 0, 't3': 0, 't8': 0, 'cp': 0, 'g': 0 } + v8 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 1, 't3': 0, 't8': 0, 'cp': 0, 'g': 0 } + t3 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 1, 't8': 0, 'cp': 0, 'g': 0 } + t8 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 1, 'cp': 0, 'g': 0 } + cp = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 'cp': 1, 'g': 0 } + g = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 'cp': 0, 'g': 1 } + v15 = {'sng': 0, 'v': 1, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 'cp': 0, 'g': 0 } elif fitbasis == 'NN31PC': sng = {'sng': 1, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 'g': 0 } @@ -695,6 +705,7 @@ def fitbasis_to_NN31IC(flav_info, fitbasis): t8 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 1, 'g': 0 } cp = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 'g': 0 } g = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 'g': 1 } + v15 = {'sng': 0, 'v': 1, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0} elif fitbasis == 'FLAVOUR': sng = {'u': 1, 'ubar': 1, 'd': 1, 'dbar': 1, 's': 1, 'sbar': 1, 'c': 2, 'g': 0 } @@ -705,6 +716,7 @@ def fitbasis_to_NN31IC(flav_info, fitbasis): t8 = {'u': 1, 'ubar': 1, 'd': 1, 'dbar': 1, 's': -2, 'sbar': -2, 'c': 0, 'g': 0 } cp = {'u': 0, 'ubar': 0, 'd': 0, 'dbar': 0, 's': 0, 'sbar': 0, 'c': 2, 'g': 0 } g = {'u': 0, 'ubar': 0, 'd': 0, 'dbar': 0, 's': 0, 'sbar': 0, 'c': 0, 'g': 1 } + v15 = {'u': 1, 'ubar': -1, 'd': 1, 'dbar': -1, 's': 1, 'sbar': -1, 'c': 0, 'g': 0 } elif fitbasis == 'EVOL' or fitbasis == 'evolution': sng = {'sng': 1, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0 } @@ -715,6 +727,7 @@ def fitbasis_to_NN31IC(flav_info, fitbasis): t8 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 1, 't15': 0, 'g': 0 } cp = {'sng': 0.25, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': -0.25, 'g': 0 } g = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 1 } + v15 = {'sng': 0, 'v': 1, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0 } elif fitbasis == 'PDF4LHC20': sng = {'sng': 1, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0 } @@ -725,10 +738,21 @@ def fitbasis_to_NN31IC(flav_info, fitbasis): t8 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 1, 't15': 0, 'g': 0 } cp = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0 } g = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 1 } + v15 = {'sng': 0, 'v': 1, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0 } + + elif fitbasis == "CCBAR_ASYMM": + sng = {'sng': 1, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0, 'v15': 0 } + v = {'sng': 0, 'v': 1, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0, 'v15': 0 } + v3 = {'sng': 0, 'v': 0, 'v3': 1, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0, 'v15': 0 } + v8 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 1, 't3': 0, 't8': 0, 't15': 0, 'g': 0, 'v15': 0 } + t3 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 1, 't8': 0, 't15': 0, 'g': 0, 'v15': 0 } + t8 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 1, 't15': 0, 'g': 0, 'v15': 0 } + cp = {'sng': 0.25, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': -0.25, 'g': 0, 'v15': 0 } + g = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 1, 'v15': 0 } + v15 = {'sng': 0, 'v': 0, 'v3': 0, 'v8': 0, 't3': 0, 't8': 0, 't15': 0, 'g': 0, 'v15': 1 } + + flist = [sng, g, v, v3, v8, t3, t8, cp, v15] - flist = [sng, g, v, v3, v8, t3, t8, cp] - - evol_basis = False mat = [] for f in flist: for flav_dict in flav_info: @@ -736,6 +760,5 @@ def fitbasis_to_NN31IC(flav_info, fitbasis): mat.append(f[flav_name]) nflavs = len(flav_info) - mat = np.asarray(mat).reshape(8, nflavs) # Return the transpose of the matrix, to have the first index referring to flavour - return mat.transpose() + return np.asarray(mat).reshape(9, nflavs).T diff --git a/validphys2/src/validphys/sumrules.py b/validphys2/src/validphys/sumrules.py index 5196feea16..4e5ee3ee5e 100644 --- a/validphys2/src/validphys/sumrules.py +++ b/validphys2/src/validphys/sumrules.py @@ -96,6 +96,7 @@ def f(x, lpdf, Q): "uvalence": _make_pdf_integrand({"u": 1, "ubar": -1}), "dvalence": _make_pdf_integrand({"d": 1, "dbar": -1}), "svalence": _make_pdf_integrand({"s": 1, "sbar": -1}), + "cvalence": _make_pdf_integrand({"c": 1, "cbar": -1}), } UNKNOWN_SUM_RULES = { @@ -106,6 +107,7 @@ def f(x, lpdf, Q): "s momentum fraction": _make_momentum_fraction_integrand({"s": 1}), "sbar momentum fraction": _make_momentum_fraction_integrand({"sbar": 1}), "cp momentum fraction": _make_momentum_fraction_integrand({"c": 1, "cbar": 1}), + "cm momentum fraction": _make_momentum_fraction_integrand({"c": 1, "cbar": -1}), "g momentum fraction": _make_momentum_fraction_integrand({"g": 1}), "T3": _make_pdf_integrand({"u": 1, "ubar": 1, "d": -1, "dbar": -1}), "T8": _make_pdf_integrand( @@ -118,6 +120,7 @@ def f(x, lpdf, Q): 'uvalence': 2, 'dvalence': 1, 'svalence': 0, + 'cvalence': 0, } @@ -141,7 +144,7 @@ def _sum_rules(rules_dict, lpdf, Q): @check_positive('Q') def sum_rules(pdf:PDF, Q:numbers.Real): - """Compute the momentum, uvalence, dvalence and svalence sum rules for + """Compute the momentum, uvalence, dvalence, svalence and cvalence sum rules for each member (as defined by libnnpdf), at the energy scale ``Q``. Return a SumRulesGrid object with the list of values for each sum rule. The integration is performed with absolute and relative tolerance of 1e-4.""" @@ -166,6 +169,7 @@ def unknown_sum_rules(pdf: PDF, Q: numbers.Real): - s momentum fraction - sbar momentum fraction - cp momentum fraction + - cm momentum fraction - g momentum fraction - T3 - T8 diff --git a/validphys2/src/validphys/tests/regressions/test_sum_rules_MC.csv b/validphys2/src/validphys/tests/regressions/test_sum_rules_MC.csv index e90c460b2e..f23678562d 100644 --- a/validphys2/src/validphys/tests/regressions/test_sum_rules_MC.csv +++ b/validphys2/src/validphys/tests/regressions/test_sum_rules_MC.csv @@ -1,8 +1,9 @@ mean std min max Central value -momentum 1.0000359402582584 5.358395010408105e-07 1.0000346238340416 1.0000372086565177 1.0000359458599606 -uvalence 1.9997926747574069 0.0002809483175437137 1.998765120611357 2.0001202779127008 1.9997937994497308 -dvalence 0.9997164295681845 0.00028118151759189136 0.9986902415578234 1.000046111974624 0.9997173113369415 -svalence 0.00025025303862949585 0.0003303956500365186 -0.00042417491773433236 0.0014490597353980783 0.0002507254062854847 +momentum 1.0000359402582584 5.358395010688445e-07 1.0000346238340414 1.0000372086565177 1.000035945859961 +uvalence 1.9997926747574089 0.0002809483175438455 1.9987651206113481 2.000120277912697 1.9997937994497326 +dvalence 0.9997164295682045 0.00028118151761139914 0.9986902415578238 1.0000461119746196 0.9997173113369362 +svalence 0.0002502530386336261 0.0003303956500400418 -0.0004241749177333505 0.00144905973539311 0.00025072540628739287 +cvalence -1.3250980807101706e-05 1.1497112653961402e-05 -5.583234972306736e-05 1.9950740107887218e-05 -1.3025352765570286e-05 u momentum fraction 0.2555 0.0021 -1.0 -1.0 -1.0 ubar momentum fraction 0.03387 0.00074 -1.0 -1.0 -1.0 d momentum fraction 0.1278 0.0021 -1.0 -1.0 -1.0 @@ -10,6 +11,7 @@ dbar momentum fraction 0.0422 0.0012 -1.0 -1.0 -1.0 s momentum fraction 0.0316 0.002 -1.0 -1.0 -1.0 sbar momentum fraction 0.0253 0.0012 -1.0 -1.0 -1.0 cp momentum fraction 0.0286 0.0017 -1.0 -1.0 -1.0 +cm momentum fraction -7.024e-05 8.7e-07 -1.0 -1.0 -1.0 g momentum fraction 0.4466 0.0017 -1.0 -1.0 -1.0 T3 0.79 0.23 -1.0 -1.0 -1.0 T8 4.73 0.7 -1.0 -1.0 -1.0 diff --git a/validphys2/src/validphys/tests/regressions/test_sum_rules_hessian.csv b/validphys2/src/validphys/tests/regressions/test_sum_rules_hessian.csv index 04168d5838..bd29ecee9e 100644 --- a/validphys2/src/validphys/tests/regressions/test_sum_rules_hessian.csv +++ b/validphys2/src/validphys/tests/regressions/test_sum_rules_hessian.csv @@ -1,8 +1,9 @@ mean std min max Central value -momentum 1.0000359346945835 3.249002390618474e-08 1.0000357949386856 1.000036007099919 1.000035943610909 -uvalence 1.9997947975241677 3.774745222364767e-05 1.9996255039155293 1.9998795897064394 1.9998052948252174 -dvalence 0.9997193904389039 3.913237872100671e-05 0.9995455646219639 0.9998033688013618 0.9997281952294002 -svalence 0.00021668009787772745 4.881864767300481e-05 2.8212616664191614e-05 0.00037062725233145966 0.00021200815810076823 +momentum 1.0000359346945835 3.249002389936152e-08 1.000035794938686 1.0000360070999192 1.000035943610909 +uvalence 1.999794797524114 3.7747452172582034e-05 1.9996255039155355 1.9998795897064396 1.9998052948252143 +dvalence 0.9997193904388911 3.913237869423472e-05 0.9995455646219693 0.9998033688013626 0.9997281952294024 +svalence 0.00021668009787584756 4.8818647675234034e-05 2.8212616642056543e-05 0.00037062725233308336 0.00021200815810049067 +cvalence -1.4051604747740869e-05 1.6214339259070918e-06 -2.1935653748207965e-05 -1.107482404248553e-05 -1.3850510260915482e-05 u momentum fraction 0.2554 0.00025 -1.0 -1.0 -1.0 ubar momentum fraction 0.03386 0.0001 -1.0 -1.0 -1.0 d momentum fraction 0.1277 0.00029 -1.0 -1.0 -1.0 @@ -10,6 +11,7 @@ dbar momentum fraction 0.04224 0.00016 -1.0 -1.0 -1.0 s momentum fraction 0.03172 0.00027 -1.0 -1.0 -1.0 sbar momentum fraction 0.0253 0.00016 -1.0 -1.0 -1.0 cp momentum fraction 0.02882 0.00023 -1.0 -1.0 -1.0 +cm momentum fraction -7.022e-05 1.1e-07 -1.0 -1.0 -1.0 g momentum fraction 0.44649 0.00025 -1.0 -1.0 -1.0 T3 0.807 0.033 -1.0 -1.0 -1.0 T8 4.65 0.1 -1.0 -1.0 -1.0