From 58e11324628d937eae9c059b7b446958b896717d Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 10:15:46 +0200 Subject: [PATCH 01/73] Add first candidate for `Grid::evolve` --- pineappl/Cargo.toml | 2 + pineappl/src/grid.rs | 398 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 399 insertions(+), 1 deletion(-) diff --git a/pineappl/Cargo.toml b/pineappl/Cargo.toml index 23c56ffb..2ee8981c 100644 --- a/pineappl/Cargo.toml +++ b/pineappl/Cargo.toml @@ -30,3 +30,5 @@ anyhow = "1.0.48" lhapdf = "0.2.0" rand = { default-features = false, version = "0.8.4" } rand_pcg = { default-features = false, version = "0.3.1" } +serde_yaml = "0.9.13" +ndarray-npy = "0.8.1" diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index c0b7b77f..c6af2641 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -16,7 +16,7 @@ use git_version::git_version; use indicatif::{ProgressBar, ProgressStyle}; use itertools::Itertools; use lz4_flex::frame::{FrameDecoder, FrameEncoder}; -use ndarray::{s, Array3, Array5, Axis, Dimension}; +use ndarray::{s, Array, Array2, Array3, Array5, Axis, Dimension}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::cmp::Ordering; @@ -263,6 +263,9 @@ pub enum GridError { /// Maximum supported file format version for this library. supported_version: u64, }, + /// Returned from [`Grid::evolve`] if the evolution failed. + #[error("TODO")] + EvolutionFailure, } #[derive(Clone, Deserialize, Serialize)] @@ -385,6 +388,46 @@ pub struct EkoInfo { pub lumi_id_types: String, } +/// Information about the evolution kernel operator (EKO) passed to [`Grid::evolve`] as `operator`, +/// which is used to convert a [`Grid`] into an [`FkTable`]. The dimensions of the EKO must +/// correspond to the values given in [`fac1`], [`pids0`], [`x0`], [`pids1`] and [`x1`], exactly in +/// this order. Members with a `1` are defined at the squared factorization scales given in +/// [`fac1`] (often called process scales) and are found in the [`Grid`] that [`Grid::evolve`] is +/// called with and members with a `0` are defined at the squared factorization scale [`fac0`] +/// (often called fitting scale or starting scale) that defines the resulting [`FkTable`]. +/// +/// The EKO may convert a `Grid` from a basis given by the particle identifiers [`pids1`] to a +/// possibly different basis given by [`pids0`]. This basis must also be identified using +/// [`lumi_id_types`], which tells [`FkTable::convolute`] how to perform a convolution. The +/// members [`ren1`] and [`alphas`] must be the strong couplings given at the respective +/// renormalization scales. Finally, [`xir`] and [`xif`] must +pub struct OperatorInfo { + /// Squared factorization scales of the `Grid`. + pub fac1: Vec, + /// Particle identifiers of the `FkTable`. + pub pids0: Vec, + /// `x`-grid coordinates of the `FkTable` + pub x0: Vec, + /// Particle identifiers of the `Grid`. If the `Grid` contains more particle identifiers than + /// given here, the contributions of them are silently ignored. + pub pids1: Vec, + /// `x`-grid coordinates of the `Grid`. + pub x1: Vec, + + /// Squared factorization scale of the `FkTable`. + pub fac0: f64, + /// Renormalization scales of the `Grid`. + pub ren1: Vec, + /// Strong couplings corresponding to the order given in [`ren1`]. + pub alphas: Vec, + /// Multiplicative factor for the central renormalization scale. + pub xir: f64, + /// Multiplicative factor for the central factorization scale. + pub xif: f64, + /// Identifier of the particle basis for the `FkTable`. + pub lumi_id_types: String, +} + /// Main data structure of `PineAPPL`. This structure contains a `Subgrid` for each `LumiEntry`, /// bin, and coupling order it was created with. #[derive(Clone, Deserialize, Serialize)] @@ -1815,6 +1858,260 @@ impl Grid { FkTable::try_from(result).ok() } + /// Converts this `Grid` into an [`FkTable`] using an evolution kernel operator (EKO) given as + /// `operator`. The dimensions and properties of this operator must be described using `info`. + /// The parameter `order_mask` can be used to include or exclude orders from this operation, + /// and must correspond to the ordering given by [`Grid::orders`]. Orders that are not given + /// are enabled, and in particular if `order_mask` is empty all orders are activated. + #[must_use] + pub fn evolve( + &self, + operator: &Array5, + info: &OperatorInfo, + order_mask: &[bool], + ) -> Result { + // naming convention: whenever an index has `0` in its name, it's meant to index something + // at fitting scale (at Q0), and when instead it has `1` it denotes something at a process + // scale + + // TODO: here we assume that we convolute with two PDFs + + // TODO: convert these to errors + if operator.dim().1 != info.pids1.len() { + todo!(); + } + + if operator.dim().3 != info.pids0.len() { + todo!() + } + + // TODO: for the time being we assume that all x-grids are the same - lift this restriction + assert!(self + .subgrids + .iter() + .filter_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x1_grid())) + .chain( + self.subgrids + .iter() + .filter_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x2_grid())) + ) + .all_equal()); + + // list of all non-zero PID indices + let pid_indices: Vec<_> = (0..operator.dim().3) + .cartesian_product(0..operator.dim().1) + .filter(|&(pid0_idx, pid1_idx)| { + // 1) at least one element of the operator must be non-zero, and 2) the pid must be + // contained in the lumi somewhere + operator + .slice(s![.., pid1_idx, .., pid0_idx, ..]) + .iter() + .any(|&value| value != 0.0) + && self + .lumi + .iter() + .flat_map(|lumi| lumi.entry()) + .any(|&(a, b, _)| a == info.pids1[pid1_idx] || b == info.pids1[pid1_idx]) + }) + .collect(); + + // list of all non-zero PIDs + let pids: Vec<_> = pid_indices + .iter() + .map(|&(pid0_idx, pid1_idx)| (info.pids0[pid0_idx], info.pids1[pid1_idx])) + .collect(); + + // create the corresponding operators accessible in the form [muf2, x0, x1] + let operators: Vec<_> = pid_indices + .iter() + .map(|&(pid0_idx, pid1_idx)| { + operator + .slice(s![.., pid1_idx, .., pid0_idx, ..]) + .permuted_axes([0, 2, 1]) + .as_standard_layout() + .into_owned() + }) + .collect(); + + mem::drop(pid_indices); + + let mut pids0_filtered: Vec<_> = pids.iter().map(|&(pid0, _)| pid0).collect(); + pids0_filtered.sort(); + pids0_filtered.dedup(); + let pids0_filtered = pids0_filtered; + + let lumi0: Vec<_> = pids0_filtered + .iter() + .copied() + .cartesian_product(pids0_filtered.iter().copied()) + .collect(); + + mem::drop(pids0_filtered); + + //println!("{:#?}", lumi0); + + let mut sub_fk_tables = + Array2::from_shape_simple_fn((self.bin_info().bins(), lumi0.len()), || { + Array2::zeros((info.x0.len(), info.x0.len())) + }); + + for (_bin, (subgrids_ol, mut tables)) in self + .subgrids + .axis_iter(Axis(1)) + .zip(sub_fk_tables.axis_iter_mut(Axis(0))) + .enumerate() + { + for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { + let mut fac: Vec<_> = subgrids_o + .iter() + .flat_map(|subgrid| { + subgrid + .mu2_grid() + .iter() + .map(|mu2| mu2.fac) + .collect::>() + }) + .collect(); + fac.sort_by(|a, b| a.partial_cmp(b).unwrap()); + fac.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 4)); + let fac = fac; + + let mut array = if let Some((nx1, nx2)) = subgrids_o.iter().find_map(|subgrid| { + (!subgrid.is_empty()) + .then(|| (subgrid.x1_grid().len(), subgrid.x2_grid().len())) + }) { + Array3::::zeros((fac.len(), nx1, nx2)) + } else { + // `find_map` may fail if all grids are empty + break; + }; + + // add subgrids for different orders, but the same bin and lumi, using the right + // couplings + for (subgrid, order) in subgrids_o + .iter() + .zip(self.orders.iter()) + .zip(order_mask.iter().chain(iter::repeat(&true))) + .filter_map(|((subgrid, order), &enabled)| { + (enabled && !subgrid.is_empty()).then(|| (subgrid, order)) + }) + { + let mut logs = 1.0; + + if order.logxir > 0 { + if approx_eq!(f64, info.xir, 1.0, ulps = 4) { + continue; + } else { + logs *= (info.xir * info.xir).ln(); + } + } + + if order.logxif > 0 { + if approx_eq!(f64, info.xif, 1.0, ulps = 4) { + continue; + } else { + logs *= (info.xif * info.xif).ln(); + } + } + + for ((imu2, ix1, ix2), value) in subgrid.iter() { + let Mu2 { + ren: mur2, + fac: muf2, + } = subgrid.mu2_grid()[imu2]; + + let als = if let Some(alphas) = info + .ren1 + .iter() + .zip(info.alphas.iter()) + .find_map(|(&ren1, &alphas)| { + approx_eq!(f64, ren1, mur2, ulps = 4).then(|| alphas) + }) { + alphas.powi(order.alphas.try_into().unwrap()) + } else { + // TODO: return an error that no alphas was found + todo!(); + }; + + let mu2_index = fac + .iter() + .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 4)) + .unwrap(); + + array[[mu2_index, ix1, ix2]] += als * logs * value; + } + } + + //println!("bin = {}, lumi = {}", bin, lumi1); + + for &(pida1, pidb1, factor) in self.lumi[lumi1].entry() { + //println!("-- pida1 = {}, pidb1 = {}", pida1, pidb1); + + for (/*pida0, pidb0,*/ fk_table, opa, opb) in lumi0 + .iter() + .zip(tables.iter_mut()) + .filter_map(|(&(pida0, pidb0), fk_table)| { + pids.iter() + .zip(operators.iter()) + .cartesian_product(pids.iter().zip(operators.iter())) + .find_map(|((&(pa0, pa1), opa), (&(pb0, pb1), opb))| { + (pa0 == pida0 && pa1 == pida1 && pb0 == pidb0 && pb1 == pidb1) + .then(|| (opa, opb)) + }) + .map(|(opa, opb)| (/*pida0, pidb0,*/ fk_table, opa, opb)) + }) + { + //println!("evolve {} -> {}, {} -> {}", pida1, pida0, pidb1, pidb0); + + let mut result = Array2::zeros((array.dim().1, array.dim().2)); + + for imu2 in 0..array.dim().0 { + let opa = opa.index_axis(Axis(0), imu2); + let opb = opb.index_axis(Axis(0), imu2); + let arr = array.index_axis(Axis(0), imu2); + + result += &opa.dot(&arr.dot(&opb.t())); + } + + fk_table.scaled_add(factor, &result); + } + } + } + + // TODO: to reduce memory footprint convert the ndarrays here + } + + let mut grid = Grid { + subgrids: Array::from_iter(sub_fk_tables.into_iter().map(|table| { + ImportOnlySubgridV2::new( + SparseArray3::from_ndarray(&table.insert_axis(Axis(0)), 0, 1), + vec![Mu2 { + // TODO: FK tables don't depend on the renormalization scale + //ren: -1.0, + ren: info.fac0, + fac: info.fac0, + }], + info.x0.clone(), + info.x0.clone(), + ) + .into() + })) + .into_shape((1, self.bin_info().bins(), lumi0.len())) + .unwrap(), + lumi: lumi0.iter().map(|&(a, b)| lumi_entry![a, b, 1.0]).collect(), + bin_limits: self.bin_limits.clone(), + orders: vec![Order::new(0, 0, 0, 0)], + subgrid_params: SubgridParams::default(), + more_members: self.more_members.clone(), + }; + + // write additional metadata + grid.set_key_value("lumi_id_types", &info.lumi_id_types); + + // TODO: convert unwrap to error + Ok(FkTable::try_from(grid).unwrap()) + } + /// Deletes bins with the corresponding `bin_indices`. Repeated indices and indices larger or /// equal the bin length are ignored. pub fn delete_bins(&mut self, bin_indices: &[usize]) { @@ -2453,4 +2750,103 @@ mod tests { assert_eq!(fk.bins(), 1); } + + #[test] + #[ignore] + fn grid_convolute_eko_for_lhcbwp8tev() { + use lhapdf::Pdf; + use ndarray::{Array1, Array5}; + use std::fs::File; + + let grid = "../LHCB_WP_8TEV.pineappl.lz4"; + let metadata = "../LHCB_WP_8TEV/metadata.yaml"; + let alphas = "../LHCB_WP_8TEV/alphas.npy"; + let operator = "../LHCB_WP_8TEV/operators.npy"; + + #[derive(Deserialize)] + struct Metadata { + #[serde(rename = "Q2grid")] + q2_grid: Vec, + #[allow(dead_code)] + eko_version: String, + inputgrid: Vec, + inputpids: Vec, + #[allow(dead_code)] + interpolation_is_log: bool, + #[allow(dead_code)] + interpolation_polynomial_degree: usize, + #[allow(dead_code)] + interpolation_xgrid: Vec, + q2_ref: f64, + targetgrid: Vec, + targetpids: Vec, + } + + let grid = Grid::read(File::open(grid).unwrap()).unwrap(); + + let lhapdf = Pdf::with_setname_and_nmem("NNPDF40_nnlo_as_01180").unwrap(); + let mut pdf = |id, x, q2| lhapdf.xfx_q2(id, x, q2); + let mut als = |q2| lhapdf.alphas_q2(q2); + let mut cache = LumiCache::with_one(2212, &mut pdf, &mut als); + let results = grid.convolute(&mut cache, &[], &[], &[], &[(1.0, 1.0)]); + + assert_eq!( + results, + [ + 890.2387443571963, + 835.660120450909, + 746.6184824761646, + 625.2924916248973, + 485.015536246328, + 344.90077665184435, + 175.56380647931934, + 48.34350718500204 + ] + ); + + let metadata: Metadata = serde_yaml::from_reader(File::open(metadata).unwrap()).unwrap(); + let alphas: Array1 = ndarray_npy::read_npy(alphas).unwrap(); + let alphas: Vec = alphas.to_vec(); + + let info = OperatorInfo { + fac1: metadata.q2_grid.clone(), + pids0: metadata.inputpids, + x0: metadata.inputgrid, + pids1: metadata.targetpids, + x1: metadata.targetgrid, + fac0: metadata.q2_ref, + ren1: metadata.q2_grid, // TODO: check whether this is true in the general case + alphas, + xir: 1.0, + xif: 1.0, + lumi_id_types: String::from("pdg_mc_ids"), + }; + let operator: Array5 = ndarray_npy::read_npy(operator).unwrap(); + + assert_eq!(operator.dim(), (1, 14, 50, 14, 50)); + + let fk_table = grid.evolve(&operator, &info, &[]).unwrap(); + + let evolved_results = fk_table + .grid() + .convolute(&mut cache, &[], &[], &[], &[(1.0, 1.0)]); + + fk_table + .write(File::create("fk_table.pineappl").unwrap()) + .unwrap(); + + assert_eq!( + evolved_results, + [ + 1487.9078765387771, + 1345.6851727580326, + 1153.200724621109, + 924.9096054295742, + 686.8280502253064, + 467.0606813737761, + 222.82409765430953, + 55.01443172570564 + ] + ); + } } From 1e824cf29beeb19bc4a446a46497e5411ab8d86f Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 14:45:28 +0200 Subject: [PATCH 02/73] Finish documentation of `Grid::evolve` --- pineappl/src/grid.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index c6af2641..371bcb21 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -393,14 +393,16 @@ pub struct EkoInfo { /// correspond to the values given in [`fac1`], [`pids0`], [`x0`], [`pids1`] and [`x1`], exactly in /// this order. Members with a `1` are defined at the squared factorization scales given in /// [`fac1`] (often called process scales) and are found in the [`Grid`] that [`Grid::evolve`] is -/// called with and members with a `0` are defined at the squared factorization scale [`fac0`] -/// (often called fitting scale or starting scale) that defines the resulting [`FkTable`]. +/// called with. Members with a `0` are defined at the squared factorization scale [`fac0`] (often +/// called fitting scale or starting scale) and are found in the [`FkTable`] resulting from +/// [`Grid::evolve`]. /// /// The EKO may convert a `Grid` from a basis given by the particle identifiers [`pids1`] to a /// possibly different basis given by [`pids0`]. This basis must also be identified using -/// [`lumi_id_types`], which tells [`FkTable::convolute`] how to perform a convolution. The -/// members [`ren1`] and [`alphas`] must be the strong couplings given at the respective -/// renormalization scales. Finally, [`xir`] and [`xif`] must +/// [`lumi_id_types`], which tells [`FkTable::convolute`] how to perform a convolution. The members +/// [`ren1`] and [`alphas`] must be the strong couplings given at the respective renormalization +/// scales. Finally, [`xir`] and [`xif`] can be used to vary the renormalization and factorization +/// scales, respectively, around their central values. pub struct OperatorInfo { /// Squared factorization scales of the `Grid`. pub fac1: Vec, @@ -1870,10 +1872,6 @@ impl Grid { info: &OperatorInfo, order_mask: &[bool], ) -> Result { - // naming convention: whenever an index has `0` in its name, it's meant to index something - // at fitting scale (at Q0), and when instead it has `1` it denotes something at a process - // scale - // TODO: here we assume that we convolute with two PDFs // TODO: convert these to errors From 66d103a9cad51902af6ef7e3d33611787a94f695 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 14:46:44 +0200 Subject: [PATCH 03/73] Add more checks of `Grid::evolve`'s arguments --- pineappl/src/grid.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 371bcb21..b76754ef 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1872,28 +1872,37 @@ impl Grid { info: &OperatorInfo, order_mask: &[bool], ) -> Result { - // TODO: here we assume that we convolute with two PDFs - // TODO: convert these to errors + if operator.dim().0 != info.fac1.len() { + todo!(); + } + if operator.dim().1 != info.pids1.len() { todo!(); } if operator.dim().3 != info.pids0.len() { - todo!() + todo!(); + } + + let x1 = self + .subgrids + .iter() + .find_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x1_grid())) + .unwrap_or_default(); + + // TODO: if all subgrids are empty return an empty FkTable + if x1.is_empty() { + todo!(); } + // TODO: here we assume that we convolute with two PDFs // TODO: for the time being we assume that all x-grids are the same - lift this restriction assert!(self .subgrids .iter() - .filter_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x1_grid())) - .chain( - self.subgrids - .iter() - .filter_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x2_grid())) - ) - .all_equal()); + .any(|subgrid| subgrid.is_empty() + || (subgrid.x1_grid() == x1 && subgrid.x2_grid() == x1))); // list of all non-zero PID indices let pid_indices: Vec<_> = (0..operator.dim().3) From 58e8321538a75303f658ac2084783a7ae7260939 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 14:48:11 +0200 Subject: [PATCH 04/73] Add temporary fix of x-grid ordering --- pineappl/src/grid.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index b76754ef..94df658f 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1932,11 +1932,13 @@ impl Grid { let operators: Vec<_> = pid_indices .iter() .map(|&(pid0_idx, pid1_idx)| { - operator + let mut op = operator .slice(s![.., pid1_idx, .., pid0_idx, ..]) - .permuted_axes([0, 2, 1]) - .as_standard_layout() - .into_owned() + .permuted_axes([0, 2, 1]); + // TODO: implement the general case in which the process-scale x-grid points are + // correctly chosen + op.invert_axis(Axis(2)); + op.as_standard_layout().into_owned() }) .collect(); From bc48d9086f1fa1a89e0a3d1d6b4d954eb641665b Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 14:48:50 +0200 Subject: [PATCH 05/73] Update unit test of `Grid::evolve` --- pineappl/src/grid.rs | 66 +++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 94df658f..2a8c6d76 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2793,7 +2793,7 @@ mod tests { let grid = Grid::read(File::open(grid).unwrap()).unwrap(); - let lhapdf = Pdf::with_setname_and_nmem("NNPDF40_nnlo_as_01180").unwrap(); + let lhapdf = Pdf::with_setname_and_nmem("NNPDF40_nlo_as_01180").unwrap(); let mut pdf = |id, x, q2| lhapdf.xfx_q2(id, x, q2); let mut als = |q2| lhapdf.alphas_q2(q2); let mut cache = LumiCache::with_one(2212, &mut pdf, &mut als); @@ -2802,20 +2802,23 @@ mod tests { assert_eq!( results, [ - 890.2387443571963, - 835.660120450909, - 746.6184824761646, - 625.2924916248973, - 485.015536246328, - 344.90077665184435, - 175.56380647931934, - 48.34350718500204 + 877.9498750860583, + 823.5123400865052, + 735.605093586326, + 616.3465722662226, + 478.63703336207277, + 341.06729874517384, + 174.3688634669724, + 48.27440593682665 ] ); let metadata: Metadata = serde_yaml::from_reader(File::open(metadata).unwrap()).unwrap(); let alphas: Array1 = ndarray_npy::read_npy(alphas).unwrap(); - let alphas: Vec = alphas.to_vec(); + let alphas = alphas.to_vec(); + let operator: Array5 = ndarray_npy::read_npy(operator).unwrap(); + + assert_eq!(operator.dim(), (1, 14, 50, 14, 50)); let info = OperatorInfo { fac1: metadata.q2_grid.clone(), @@ -2825,36 +2828,47 @@ mod tests { x1: metadata.targetgrid, fac0: metadata.q2_ref, ren1: metadata.q2_grid, // TODO: check whether this is true in the general case - alphas, + alphas: alphas, xir: 1.0, xif: 1.0, - lumi_id_types: String::from("pdg_mc_ids"), + lumi_id_types: "pdg_mc_ids".to_string(), }; - let operator: Array5 = ndarray_npy::read_npy(operator).unwrap(); - - assert_eq!(operator.dim(), (1, 14, 50, 14, 50)); + //let mut grid_axes = grid.axes().unwrap(); + //grid_axes.pids = metadata.targetpids.clone(); // TODO: which one them? + //let eko_info = EkoInfo { + // muf2_0: metadata.q2_ref, + // alphas, + // xir: 1.0, + // xif: 1.0, + // target_x_grid: metadata.inputgrid, + // target_pids: metadata.targetpids, + // grid_axes, + // lumi_id_types: "pdg_mc_ids".to_string(), + //}; + + //let fk_table = grid.convolute_eko(operator, eko_info, &[]).unwrap(); let fk_table = grid.evolve(&operator, &info, &[]).unwrap(); let evolved_results = fk_table .grid() .convolute(&mut cache, &[], &[], &[], &[(1.0, 1.0)]); - fk_table - .write(File::create("fk_table.pineappl").unwrap()) - .unwrap(); + //fk_table + // .write(File::create("fk_table.pineappl").unwrap()) + // .unwrap(); assert_eq!( evolved_results, [ - 1487.9078765387771, - 1345.6851727580326, - 1153.200724621109, - 924.9096054295742, - 686.8280502253064, - 467.0606813737761, - 222.82409765430953, - 55.01443172570564 + 1526.1321420502966, + 1380.605564314246, + 1182.565055380693, + 947.3266541818663, + 702.6776451873732, + 477.8683182368509, + 229.2748278368886, + 58.35460083148634 ] ); } From 75899fe9d655fa3ed95a16d4c318848193f1bccb Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 15:13:54 +0200 Subject: [PATCH 06/73] Replace `todo` macros with errors --- pineappl/src/grid.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 2a8c6d76..5aeb52f1 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1872,17 +1872,17 @@ impl Grid { info: &OperatorInfo, order_mask: &[bool], ) -> Result { - // TODO: convert these to errors + // TODO: improve the error message information if operator.dim().0 != info.fac1.len() { - todo!(); + return Err(GridError::EvolutionFailure); } if operator.dim().1 != info.pids1.len() { - todo!(); + return Err(GridError::EvolutionFailure); } if operator.dim().3 != info.pids0.len() { - todo!(); + return Err(GridError::EvolutionFailure); } let x1 = self @@ -2038,8 +2038,8 @@ impl Grid { }) { alphas.powi(order.alphas.try_into().unwrap()) } else { - // TODO: return an error that no alphas was found - todo!(); + // TODO: improve this error message + return Err(GridError::EvolutionFailure); }; let mu2_index = fac From 435a49e197d2437e74bac869a334c3157a3c9f17 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 15:14:35 +0200 Subject: [PATCH 07/73] Fix warnings reported by clippy --- pineappl/src/grid.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 5aeb52f1..4e3c8834 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1865,7 +1865,10 @@ impl Grid { /// The parameter `order_mask` can be used to include or exclude orders from this operation, /// and must correspond to the ordering given by [`Grid::orders`]. Orders that are not given /// are enabled, and in particular if `order_mask` is empty all orders are activated. - #[must_use] + /// + /// # Errors + /// + /// TODO pub fn evolve( &self, operator: &Array5, @@ -1917,7 +1920,7 @@ impl Grid { && self .lumi .iter() - .flat_map(|lumi| lumi.entry()) + .flat_map(LumiEntry::entry) .any(|&(a, b, _)| a == info.pids1[pid1_idx] || b == info.pids1[pid1_idx]) }) .collect(); @@ -1945,7 +1948,7 @@ impl Grid { mem::drop(pid_indices); let mut pids0_filtered: Vec<_> = pids.iter().map(|&(pid0, _)| pid0).collect(); - pids0_filtered.sort(); + pids0_filtered.sort_unstable(); pids0_filtered.dedup(); let pids0_filtered = pids0_filtered; @@ -2010,17 +2013,17 @@ impl Grid { if order.logxir > 0 { if approx_eq!(f64, info.xir, 1.0, ulps = 4) { continue; - } else { - logs *= (info.xir * info.xir).ln(); } + + logs *= (info.xir * info.xir).ln(); } if order.logxif > 0 { if approx_eq!(f64, info.xif, 1.0, ulps = 4) { continue; - } else { - logs *= (info.xif * info.xif).ln(); } + + logs *= (info.xif * info.xif).ln(); } for ((imu2, ix1, ix2), value) in subgrid.iter() { @@ -2090,7 +2093,7 @@ impl Grid { // TODO: to reduce memory footprint convert the ndarrays here } - let mut grid = Grid { + let mut grid = Self { subgrids: Array::from_iter(sub_fk_tables.into_iter().map(|table| { ImportOnlySubgridV2::new( SparseArray3::from_ndarray(&table.insert_axis(Axis(0)), 0, 1), From 9596e7721cf41de1a1702579e9579bc91f48fdd4 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 15:15:05 +0200 Subject: [PATCH 08/73] Make floating points assertions less strict --- pineappl/src/grid.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 4e3c8834..d1afa50a 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2766,6 +2766,7 @@ mod tests { #[test] #[ignore] fn grid_convolute_eko_for_lhcbwp8tev() { + use float_cmp::assert_approx_eq; use lhapdf::Pdf; use ndarray::{Array1, Array5}; use std::fs::File; @@ -2861,18 +2862,13 @@ mod tests { // .write(File::create("fk_table.pineappl").unwrap()) // .unwrap(); - assert_eq!( - evolved_results, - [ - 1526.1321420502966, - 1380.605564314246, - 1182.565055380693, - 947.3266541818663, - 702.6776451873732, - 477.8683182368509, - 229.2748278368886, - 58.35460083148634 - ] - ); + assert_approx_eq!(f64, evolved_results[0], 1526.1321420502966, ulps = 8); + assert_approx_eq!(f64, evolved_results[1], 1380.605564314246, ulps = 8); + assert_approx_eq!(f64, evolved_results[2], 1182.565055380693, ulps = 8); + assert_approx_eq!(f64, evolved_results[3], 947.3266541818663, ulps = 8); + assert_approx_eq!(f64, evolved_results[4], 702.6776451873732, ulps = 8); + assert_approx_eq!(f64, evolved_results[5], 477.8683182368509, ulps = 8); + assert_approx_eq!(f64, evolved_results[6], 229.2748278368886, ulps = 8); + assert_approx_eq!(f64, evolved_results[7], 58.35460083148634, ulps = 8); } } From 69f44286269ab7b91771e9c3544e2aa32b15f26d Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 21:36:09 +0200 Subject: [PATCH 09/73] Fix small but subtle bug If the subset of used factorization scales was smaller than the set of all factorization scales provided by the operator there would possibly have been a wrong evolution --- pineappl/src/grid.rs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index d1afa50a..35ad3ea9 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1974,25 +1974,12 @@ impl Grid { .enumerate() { for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { - let mut fac: Vec<_> = subgrids_o - .iter() - .flat_map(|subgrid| { - subgrid - .mu2_grid() - .iter() - .map(|mu2| mu2.fac) - .collect::>() - }) - .collect(); - fac.sort_by(|a, b| a.partial_cmp(b).unwrap()); - fac.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 4)); - let fac = fac; - let mut array = if let Some((nx1, nx2)) = subgrids_o.iter().find_map(|subgrid| { (!subgrid.is_empty()) .then(|| (subgrid.x1_grid().len(), subgrid.x2_grid().len())) }) { - Array3::::zeros((fac.len(), nx1, nx2)) + // TODO: in this way we allocate not the minimum number of dimensions + Array3::::zeros((info.fac1.len(), nx1, nx2)) } else { // `find_map` may fail if all grids are empty break; @@ -2045,7 +2032,8 @@ impl Grid { return Err(GridError::EvolutionFailure); }; - let mu2_index = fac + let mu2_index = info + .fac1 .iter() .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 4)) .unwrap(); From f5beb8ba3c118d17a48d14aa10de3b17b85abef4 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 21:53:07 +0200 Subject: [PATCH 10/73] Implement permutation of the EKO x1 entries --- pineappl/src/grid.rs | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 35ad3ea9..27f04109 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1931,17 +1931,39 @@ impl Grid { .map(|&(pid0_idx, pid1_idx)| (info.pids0[pid0_idx], info.pids1[pid1_idx])) .collect(); + // permutation between the grid x values and the operator x1 values + let x1_indices: Vec<_> = if let Some(x1_indices) = x1 + .iter() + .map(|&x1p| { + info.x1 + .iter() + .position(|&x1| approx_eq!(f64, x1p, x1, ulps = 4)) + }) + .collect() + { + x1_indices + } else { + // TODO: return better error - operator x1 values don't match grid's x1 values + return Err(GridError::EvolutionFailure); + }; + // create the corresponding operators accessible in the form [muf2, x0, x1] let operators: Vec<_> = pid_indices .iter() .map(|&(pid0_idx, pid1_idx)| { - let mut op = operator + let mut op = Array3::zeros((operator.dim().0, x1.len(), x1.len())); + // TODO: there must be better way than manually copying every entry + for ((i, j, k), &value) in operator .slice(s![.., pid1_idx, .., pid0_idx, ..]) - .permuted_axes([0, 2, 1]); - // TODO: implement the general case in which the process-scale x-grid points are - // correctly chosen - op.invert_axis(Axis(2)); - op.as_standard_layout().into_owned() + .permuted_axes([0, 2, 1]) + .indexed_iter() + { + // TODO: this doesn't work as soon as bins have different x1 grids because we + // optimized the size of the EKO using a trick - figure out the trick and fix + // this + op[[i, j, x1_indices[k]]] = value; + } + op }) .collect(); From f5c2cfea14afac468000ad62cb3e8307d3236bfb Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 6 Oct 2022 22:51:45 +0200 Subject: [PATCH 11/73] Fix assertion statement in `Grid::evolve` --- pineappl/src/grid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 27f04109..6f016570 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1904,7 +1904,7 @@ impl Grid { assert!(self .subgrids .iter() - .any(|subgrid| subgrid.is_empty() + .all(|subgrid| subgrid.is_empty() || (subgrid.x1_grid() == x1 && subgrid.x2_grid() == x1))); // list of all non-zero PID indices From 2ea81cc1b6e6464cf642a0b62d7bb191e7fe2105 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 7 Oct 2022 15:11:17 +0200 Subject: [PATCH 12/73] Fix another bug in `Grid::evolve` --- pineappl/src/grid.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 6f016570..124b86a6 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1952,16 +1952,9 @@ impl Grid { .iter() .map(|&(pid0_idx, pid1_idx)| { let mut op = Array3::zeros((operator.dim().0, x1.len(), x1.len())); - // TODO: there must be better way than manually copying every entry - for ((i, j, k), &value) in operator - .slice(s![.., pid1_idx, .., pid0_idx, ..]) - .permuted_axes([0, 2, 1]) - .indexed_iter() - { - // TODO: this doesn't work as soon as bins have different x1 grids because we - // optimized the size of the EKO using a trick - figure out the trick and fix - // this - op[[i, j, x1_indices[k]]] = value; + for (op_index, &x1_index) in x1_indices.iter().enumerate() { + op.slice_mut(s![.., .., op_index]) + .assign(&operator.slice(s![.., pid1_idx, x1_index, pid0_idx, ..])); } op }) From f3aeba74448a626ae818661827f9265a65655df2 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 7 Oct 2022 15:15:10 +0200 Subject: [PATCH 13/73] Add more checks of `Grid::evolve`'s arguments --- pineappl/src/grid.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 124b86a6..ae7a3bc1 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1884,10 +1884,18 @@ impl Grid { return Err(GridError::EvolutionFailure); } + if operator.dim().2 != info.x1.len() { + return Err(GridError::EvolutionFailure); + } + if operator.dim().3 != info.pids0.len() { return Err(GridError::EvolutionFailure); } + if operator.dim().4 != info.x0.len() { + return Err(GridError::EvolutionFailure); + } + let x1 = self .subgrids .iter() From 197d732baef024d0344a3e7411cf814124475e4e Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 7 Oct 2022 16:49:56 +0200 Subject: [PATCH 14/73] Split off a generic part of `Grid::evolve` --- pineappl/src/grid.rs | 119 +++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index ae7a3bc1..933ab89f 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1860,6 +1860,65 @@ impl Grid { FkTable::try_from(result).ok() } + // TODO: move this function into a separate module + fn pids_operators( + operator: &Array5, + info: &OperatorInfo, + x1: &[f64], + pid1_nonzero: &dyn Fn(i32) -> bool, + ) -> Result<(Vec<(i32, i32)>, Vec>), GridError> { + // list of all non-zero PID indices + let pid_indices: Vec<_> = (0..operator.dim().3) + .cartesian_product(0..operator.dim().1) + .filter(|&(pid0_idx, pid1_idx)| { + // 1) at least one element of the operator must be non-zero, and 2) the pid must be + // contained in the lumi somewhere + operator + .slice(s![.., pid1_idx, .., pid0_idx, ..]) + .iter() + .any(|&value| value != 0.0) + && pid1_nonzero(info.pids1[pid1_idx]) + }) + .collect(); + + // list of all non-zero PIDs + let pids: Vec<_> = pid_indices + .iter() + .map(|&(pid0_idx, pid1_idx)| (info.pids0[pid0_idx], info.pids1[pid1_idx])) + .collect(); + + // permutation between the grid x values and the operator x1 values + let x1_indices: Vec<_> = if let Some(x1_indices) = x1 + .iter() + .map(|&x1p| { + info.x1 + .iter() + .position(|&x1| approx_eq!(f64, x1p, x1, ulps = 4)) + }) + .collect() + { + x1_indices + } else { + // TODO: return better error - operator x1 values don't match grid's x1 values + return Err(GridError::EvolutionFailure); + }; + + // create the corresponding operators accessible in the form [muf2, x0, x1] + let operators: Vec<_> = pid_indices + .iter() + .map(|&(pid0_idx, pid1_idx)| { + let mut op = Array3::zeros((operator.dim().0, x1.len(), x1.len())); + for (op_index, &x1_index) in x1_indices.iter().enumerate() { + op.slice_mut(s![.., .., op_index]) + .assign(&operator.slice(s![.., pid1_idx, x1_index, pid0_idx, ..])); + } + op + }) + .collect(); + + Ok((pids, operators)) + } + /// Converts this `Grid` into an [`FkTable`] using an evolution kernel operator (EKO) given as /// `operator`. The dimensions and properties of this operator must be described using `info`. /// The parameter `order_mask` can be used to include or exclude orders from this operation, @@ -1915,60 +1974,12 @@ impl Grid { .all(|subgrid| subgrid.is_empty() || (subgrid.x1_grid() == x1 && subgrid.x2_grid() == x1))); - // list of all non-zero PID indices - let pid_indices: Vec<_> = (0..operator.dim().3) - .cartesian_product(0..operator.dim().1) - .filter(|&(pid0_idx, pid1_idx)| { - // 1) at least one element of the operator must be non-zero, and 2) the pid must be - // contained in the lumi somewhere - operator - .slice(s![.., pid1_idx, .., pid0_idx, ..]) - .iter() - .any(|&value| value != 0.0) - && self - .lumi - .iter() - .flat_map(LumiEntry::entry) - .any(|&(a, b, _)| a == info.pids1[pid1_idx] || b == info.pids1[pid1_idx]) - }) - .collect(); - - // list of all non-zero PIDs - let pids: Vec<_> = pid_indices - .iter() - .map(|&(pid0_idx, pid1_idx)| (info.pids0[pid0_idx], info.pids1[pid1_idx])) - .collect(); - - // permutation between the grid x values and the operator x1 values - let x1_indices: Vec<_> = if let Some(x1_indices) = x1 - .iter() - .map(|&x1p| { - info.x1 - .iter() - .position(|&x1| approx_eq!(f64, x1p, x1, ulps = 4)) - }) - .collect() - { - x1_indices - } else { - // TODO: return better error - operator x1 values don't match grid's x1 values - return Err(GridError::EvolutionFailure); - }; - - // create the corresponding operators accessible in the form [muf2, x0, x1] - let operators: Vec<_> = pid_indices - .iter() - .map(|&(pid0_idx, pid1_idx)| { - let mut op = Array3::zeros((operator.dim().0, x1.len(), x1.len())); - for (op_index, &x1_index) in x1_indices.iter().enumerate() { - op.slice_mut(s![.., .., op_index]) - .assign(&operator.slice(s![.., pid1_idx, x1_index, pid0_idx, ..])); - } - op - }) - .collect(); - - mem::drop(pid_indices); + let (pids, operators) = Self::pids_operators(operator, info, &x1, &|pid1| { + self.lumi + .iter() + .flat_map(LumiEntry::entry) + .any(|&(a, b, _)| a == pid1 || b == pid1) + })?; let mut pids0_filtered: Vec<_> = pids.iter().map(|&(pid0, _)| pid0).collect(); pids0_filtered.sort_unstable(); From 60788ff0163544c7c2027fada5f7db8a9d3c91c3 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 7 Oct 2022 16:58:27 +0200 Subject: [PATCH 15/73] Use different pids and operators for each initial state --- pineappl/src/grid.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 933ab89f..01a156bf 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1974,25 +1974,37 @@ impl Grid { .all(|subgrid| subgrid.is_empty() || (subgrid.x1_grid() == x1 && subgrid.x2_grid() == x1))); - let (pids, operators) = Self::pids_operators(operator, info, &x1, &|pid1| { + let (pids_a, operators_a) = Self::pids_operators(operator, info, &x1, &|pid1| { self.lumi .iter() .flat_map(LumiEntry::entry) - .any(|&(a, b, _)| a == pid1 || b == pid1) + .any(|&(a, _, _)| a == pid1) })?; - let mut pids0_filtered: Vec<_> = pids.iter().map(|&(pid0, _)| pid0).collect(); - pids0_filtered.sort_unstable(); - pids0_filtered.dedup(); - let pids0_filtered = pids0_filtered; + let (pids_b, operators_b) = Self::pids_operators(operator, info, &x1, &|pid1| { + self.lumi + .iter() + .flat_map(LumiEntry::entry) + .any(|&(_, b, _)| b == pid1) + })?; + + let mut pids0_a_filtered: Vec<_> = pids_a.iter().map(|&(pid0, _)| pid0).collect(); + pids0_a_filtered.sort_unstable(); + pids0_a_filtered.dedup(); + let pids0_a_filtered = pids0_a_filtered; + let mut pids0_b_filtered: Vec<_> = pids_b.iter().map(|&(pid0, _)| pid0).collect(); + pids0_b_filtered.sort_unstable(); + pids0_b_filtered.dedup(); + let pids0_b_filtered = pids0_b_filtered; - let lumi0: Vec<_> = pids0_filtered + let lumi0: Vec<_> = pids0_a_filtered .iter() .copied() - .cartesian_product(pids0_filtered.iter().copied()) + .cartesian_product(pids0_b_filtered.iter().copied()) .collect(); - mem::drop(pids0_filtered); + mem::drop(pids0_a_filtered); + mem::drop(pids0_b_filtered); //println!("{:#?}", lumi0); @@ -2085,9 +2097,10 @@ impl Grid { .iter() .zip(tables.iter_mut()) .filter_map(|(&(pida0, pidb0), fk_table)| { - pids.iter() - .zip(operators.iter()) - .cartesian_product(pids.iter().zip(operators.iter())) + pids_a + .iter() + .zip(operators_a.iter()) + .cartesian_product(pids_b.iter().zip(operators_b.iter())) .find_map(|((&(pa0, pa1), opa), (&(pb0, pb1), opb))| { (pa0 == pida0 && pa1 == pida1 && pb0 == pidb0 && pb1 == pidb1) .then(|| (opa, opb)) From 47a1f96dc7b053fc248e5609518e6f4351171d88 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sat, 8 Oct 2022 12:01:33 +0200 Subject: [PATCH 16/73] Remove commented lines --- pineappl/src/grid.rs | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 01a156bf..70f40599 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2006,18 +2006,15 @@ impl Grid { mem::drop(pids0_a_filtered); mem::drop(pids0_b_filtered); - //println!("{:#?}", lumi0); - let mut sub_fk_tables = Array2::from_shape_simple_fn((self.bin_info().bins(), lumi0.len()), || { Array2::zeros((info.x0.len(), info.x0.len())) }); - for (_bin, (subgrids_ol, mut tables)) in self + for (subgrids_ol, mut tables) in self .subgrids .axis_iter(Axis(1)) .zip(sub_fk_tables.axis_iter_mut(Axis(0))) - .enumerate() { for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { let mut array = if let Some((nx1, nx2)) = subgrids_o.iter().find_map(|subgrid| { @@ -2088,15 +2085,9 @@ impl Grid { } } - //println!("bin = {}, lumi = {}", bin, lumi1); - for &(pida1, pidb1, factor) in self.lumi[lumi1].entry() { - //println!("-- pida1 = {}, pidb1 = {}", pida1, pidb1); - - for (/*pida0, pidb0,*/ fk_table, opa, opb) in lumi0 - .iter() - .zip(tables.iter_mut()) - .filter_map(|(&(pida0, pidb0), fk_table)| { + for (fk_table, opa, opb) in lumi0.iter().zip(tables.iter_mut()).filter_map( + |(&(pida0, pidb0), fk_table)| { pids_a .iter() .zip(operators_a.iter()) @@ -2105,11 +2096,9 @@ impl Grid { (pa0 == pida0 && pa1 == pida1 && pb0 == pidb0 && pb1 == pidb1) .then(|| (opa, opb)) }) - .map(|(opa, opb)| (/*pida0, pidb0,*/ fk_table, opa, opb)) - }) - { - //println!("evolve {} -> {}, {} -> {}", pida1, pida0, pidb1, pidb0); - + .map(|(opa, opb)| (fk_table, opa, opb)) + }, + ) { let mut result = Array2::zeros((array.dim().1, array.dim().2)); for imu2 in 0..array.dim().0 { From 5b73e3987ee8d7a71f94bd00013fc382a4f2d375 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sat, 8 Oct 2022 12:21:21 +0200 Subject: [PATCH 17/73] Improve error reporting in `Grid::evolve` --- pineappl/src/grid.rs | 49 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 70f40599..b059afbf 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -264,8 +264,8 @@ pub enum GridError { supported_version: u64, }, /// Returned from [`Grid::evolve`] if the evolution failed. - #[error("TODO")] - EvolutionFailure, + #[error("failed to evolve grid: {0}")] + EvolutionFailure(String), } #[derive(Clone, Deserialize, Serialize)] @@ -1900,7 +1900,9 @@ impl Grid { x1_indices } else { // TODO: return better error - operator x1 values don't match grid's x1 values - return Err(GridError::EvolutionFailure); + return Err(GridError::EvolutionFailure( + "operator information does not match grid's x-grid values".to_string(), + )); }; // create the corresponding operators accessible in the form [muf2, x0, x1] @@ -1927,32 +1929,28 @@ impl Grid { /// /// # Errors /// - /// TODO + /// Returns a [`GridError::EvolutionFailure`] if either the `operator` or its `info` is + /// incompatible with this `Grid`. pub fn evolve( &self, operator: &Array5, info: &OperatorInfo, order_mask: &[bool], ) -> Result { - // TODO: improve the error message information - if operator.dim().0 != info.fac1.len() { - return Err(GridError::EvolutionFailure); - } - - if operator.dim().1 != info.pids1.len() { - return Err(GridError::EvolutionFailure); - } - - if operator.dim().2 != info.x1.len() { - return Err(GridError::EvolutionFailure); - } - - if operator.dim().3 != info.pids0.len() { - return Err(GridError::EvolutionFailure); - } + let op_info_dim = ( + info.fac1.len(), + info.pids1.len(), + info.x1.len(), + info.pids0.len(), + info.x0.len(), + ); - if operator.dim().4 != info.x0.len() { - return Err(GridError::EvolutionFailure); + if operator.dim() != op_info_dim { + return Err(GridError::EvolutionFailure(format!( + "operator information {:?} does not match the operator's dimensions: {:?}", + op_info_dim, + operator.dim(), + ))); } let x1 = self @@ -2071,10 +2069,13 @@ impl Grid { }) { alphas.powi(order.alphas.try_into().unwrap()) } else { - // TODO: improve this error message - return Err(GridError::EvolutionFailure); + return Err(GridError::EvolutionFailure(format!( + "could not find alphas for mur2 = {}", + mur2 + ))); }; + // TODO: get rid of the `unwrap` let mu2_index = info .fac1 .iter() From cbacfe193b44fb8d82e46280ed12344b06876477 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sat, 8 Oct 2022 13:00:03 +0200 Subject: [PATCH 18/73] Move parts of `Grid::evolve` to separate functions --- pineappl/src/grid.rs | 85 +++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index b059afbf..f2d02970 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1861,12 +1861,11 @@ impl Grid { } // TODO: move this function into a separate module - fn pids_operators( + fn pids( operator: &Array5, info: &OperatorInfo, - x1: &[f64], pid1_nonzero: &dyn Fn(i32) -> bool, - ) -> Result<(Vec<(i32, i32)>, Vec>), GridError> { + ) -> (Vec<(usize, usize)>, Vec<(i32, i32)>) { // list of all non-zero PID indices let pid_indices: Vec<_> = (0..operator.dim().3) .cartesian_product(0..operator.dim().1) @@ -1881,12 +1880,38 @@ impl Grid { }) .collect(); - // list of all non-zero PIDs - let pids: Vec<_> = pid_indices + // list of all non-zero (pid0, pid1) combinations + let pids = pid_indices .iter() .map(|&(pid0_idx, pid1_idx)| (info.pids0[pid0_idx], info.pids1[pid1_idx])) .collect(); + (pid_indices, pids) + } + + // TODO: move this function into a separate module + fn lumi0(pids_a: &[(i32, i32)], pids_b: &[(i32, i32)]) -> Vec<(i32, i32)> { + let mut pids0_a: Vec<_> = pids_a.iter().map(|&(pid0, _)| pid0).collect(); + pids0_a.sort_unstable(); + pids0_a.dedup(); + let mut pids0_b: Vec<_> = pids_b.iter().map(|&(pid0, _)| pid0).collect(); + pids0_b.sort_unstable(); + pids0_b.dedup(); + + pids0_a + .iter() + .copied() + .cartesian_product(pids0_b.iter().copied()) + .collect() + } + + // TODO: move this function into a separate module + fn operators( + operator: &Array5, + info: &OperatorInfo, + pid_indices: &[(usize, usize)], + x1: &[f64], + ) -> Result>, GridError> { // permutation between the grid x values and the operator x1 values let x1_indices: Vec<_> = if let Some(x1_indices) = x1 .iter() @@ -1918,7 +1943,7 @@ impl Grid { }) .collect(); - Ok((pids, operators)) + Ok(operators) } /// Converts this `Grid` into an [`FkTable`] using an evolution kernel operator (EKO) given as @@ -1953,6 +1978,21 @@ impl Grid { ))); } + let (pid_indices_a, pids_a) = Self::pids(operator, info, &|pid1| { + self.lumi + .iter() + .flat_map(LumiEntry::entry) + .any(|&(a, _, _)| a == pid1) + }); + let (pid_indices_b, pids_b) = Self::pids(operator, info, &|pid1| { + self.lumi + .iter() + .flat_map(LumiEntry::entry) + .any(|&(_, b, _)| b == pid1) + }); + + let lumi0 = Self::lumi0(&pids_a, &pids_b); + let x1 = self .subgrids .iter() @@ -1972,37 +2012,8 @@ impl Grid { .all(|subgrid| subgrid.is_empty() || (subgrid.x1_grid() == x1 && subgrid.x2_grid() == x1))); - let (pids_a, operators_a) = Self::pids_operators(operator, info, &x1, &|pid1| { - self.lumi - .iter() - .flat_map(LumiEntry::entry) - .any(|&(a, _, _)| a == pid1) - })?; - - let (pids_b, operators_b) = Self::pids_operators(operator, info, &x1, &|pid1| { - self.lumi - .iter() - .flat_map(LumiEntry::entry) - .any(|&(_, b, _)| b == pid1) - })?; - - let mut pids0_a_filtered: Vec<_> = pids_a.iter().map(|&(pid0, _)| pid0).collect(); - pids0_a_filtered.sort_unstable(); - pids0_a_filtered.dedup(); - let pids0_a_filtered = pids0_a_filtered; - let mut pids0_b_filtered: Vec<_> = pids_b.iter().map(|&(pid0, _)| pid0).collect(); - pids0_b_filtered.sort_unstable(); - pids0_b_filtered.dedup(); - let pids0_b_filtered = pids0_b_filtered; - - let lumi0: Vec<_> = pids0_a_filtered - .iter() - .copied() - .cartesian_product(pids0_b_filtered.iter().copied()) - .collect(); - - mem::drop(pids0_a_filtered); - mem::drop(pids0_b_filtered); + let operators_a = Self::operators(operator, info, &pid_indices_a, &x1)?; + let operators_b = Self::operators(operator, info, &pid_indices_b, &x1)?; let mut sub_fk_tables = Array2::from_shape_simple_fn((self.bin_info().bins(), lumi0.len()), || { From 5fb14a8b381b3adbe7399cae452a62a32a7e38dc Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sat, 8 Oct 2022 13:14:58 +0200 Subject: [PATCH 19/73] Make `Grid::evolve` more general --- pineappl/src/grid.rs | 50 +++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index f2d02970..e5077992 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1978,6 +1978,8 @@ impl Grid { ))); } + // TODO: here we assume that we convolute with two PDFs + let (pid_indices_a, pids_a) = Self::pids(operator, info, &|pid1| { self.lumi .iter() @@ -1993,28 +1995,6 @@ impl Grid { let lumi0 = Self::lumi0(&pids_a, &pids_b); - let x1 = self - .subgrids - .iter() - .find_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x1_grid())) - .unwrap_or_default(); - - // TODO: if all subgrids are empty return an empty FkTable - if x1.is_empty() { - todo!(); - } - - // TODO: here we assume that we convolute with two PDFs - // TODO: for the time being we assume that all x-grids are the same - lift this restriction - assert!(self - .subgrids - .iter() - .all(|subgrid| subgrid.is_empty() - || (subgrid.x1_grid() == x1 && subgrid.x2_grid() == x1))); - - let operators_a = Self::operators(operator, info, &pid_indices_a, &x1)?; - let operators_b = Self::operators(operator, info, &pid_indices_b, &x1)?; - let mut sub_fk_tables = Array2::from_shape_simple_fn((self.bin_info().bins(), lumi0.len()), || { Array2::zeros((info.x0.len(), info.x0.len())) @@ -2025,6 +2005,32 @@ impl Grid { .axis_iter(Axis(1)) .zip(sub_fk_tables.axis_iter_mut(Axis(0))) { + let x1_a = subgrids_ol + .iter() + .find_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x1_grid())) + .unwrap_or_default(); + let x1_b = subgrids_ol + .iter() + .find_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x2_grid())) + .unwrap_or_default(); + + if x1_a.is_empty() || x1_b.is_empty() { + continue; + } + + if subgrids_ol.iter().any(|subgrid| { + !subgrid.is_empty() && (subgrid.x1_grid() != x1_a || subgrid.x2_grid() != x1_b) + }) { + return Err(GridError::EvolutionFailure( + "subgrids do not share the same x-grid values".to_string(), + )); + } + + // TODO: here's some optimization potential: if `x1_a` and `x1_b` are the same share + // them and if they are the same over bins share them! + let operators_a = Self::operators(operator, info, &pid_indices_a, &x1_a)?; + let operators_b = Self::operators(operator, info, &pid_indices_b, &x1_b)?; + for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { let mut array = if let Some((nx1, nx2)) = subgrids_o.iter().find_map(|subgrid| { (!subgrid.is_empty()) From 26d72ce444e87291f7598e5c7a90fb4785d11c83 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sat, 8 Oct 2022 14:52:30 +0200 Subject: [PATCH 20/73] Reduce memory usage of `Grid::evolve` --- pineappl/src/grid.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index e5077992..a835ac8b 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1995,16 +1995,9 @@ impl Grid { let lumi0 = Self::lumi0(&pids_a, &pids_b); - let mut sub_fk_tables = - Array2::from_shape_simple_fn((self.bin_info().bins(), lumi0.len()), || { - Array2::zeros((info.x0.len(), info.x0.len())) - }); + let mut sub_fk_tables = Vec::with_capacity(self.bin_info().bins() * lumi0.len()); - for (subgrids_ol, mut tables) in self - .subgrids - .axis_iter(Axis(1)) - .zip(sub_fk_tables.axis_iter_mut(Axis(0))) - { + for subgrids_ol in self.subgrids.axis_iter(Axis(1)) { let x1_a = subgrids_ol .iter() .find_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x1_grid())) @@ -2031,6 +2024,8 @@ impl Grid { let operators_a = Self::operators(operator, info, &pid_indices_a, &x1_a)?; let operators_b = Self::operators(operator, info, &pid_indices_b, &x1_b)?; + let mut tables = vec![Array2::zeros((info.x0.len(), info.x0.len())); lumi0.len()]; + for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { let mut array = if let Some((nx1, nx2)) = subgrids_o.iter().find_map(|subgrid| { (!subgrid.is_empty()) @@ -2132,11 +2127,7 @@ impl Grid { } } - // TODO: to reduce memory footprint convert the ndarrays here - } - - let mut grid = Self { - subgrids: Array::from_iter(sub_fk_tables.into_iter().map(|table| { + sub_fk_tables.extend(tables.into_iter().map(|table| { ImportOnlySubgridV2::new( SparseArray3::from_ndarray(&table.insert_axis(Axis(0)), 0, 1), vec![Mu2 { @@ -2149,9 +2140,13 @@ impl Grid { info.x0.clone(), ) .into() - })) - .into_shape((1, self.bin_info().bins(), lumi0.len())) - .unwrap(), + })); + } + + let mut grid = Self { + subgrids: Array::from_iter(sub_fk_tables.into_iter()) + .into_shape((1, self.bin_info().bins(), lumi0.len())) + .unwrap(), lumi: lumi0.iter().map(|&(a, b)| lumi_entry![a, b, 1.0]).collect(), bin_limits: self.bin_limits.clone(), orders: vec![Order::new(0, 0, 0, 0)], From 3e476434b3b8b1a2423bafd79e9d8be44940e993 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sat, 8 Oct 2022 16:28:48 +0200 Subject: [PATCH 21/73] Fix two bugs in `Grid::evolve` --- pineappl/src/grid.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index a835ac8b..2ea131b0 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1934,7 +1934,7 @@ impl Grid { let operators: Vec<_> = pid_indices .iter() .map(|&(pid0_idx, pid1_idx)| { - let mut op = Array3::zeros((operator.dim().0, x1.len(), x1.len())); + let mut op = Array3::zeros((operator.dim().0, info.x0.len(), x1.len())); for (op_index, &x1_index) in x1_indices.iter().enumerate() { op.slice_mut(s![.., .., op_index]) .assign(&operator.slice(s![.., pid1_idx, x1_index, pid0_idx, ..])); @@ -2112,7 +2112,7 @@ impl Grid { .map(|(opa, opb)| (fk_table, opa, opb)) }, ) { - let mut result = Array2::zeros((array.dim().1, array.dim().2)); + let mut result = Array2::zeros((info.x0.len(), info.x0.len())); for imu2 in 0..array.dim().0 { let opa = opa.index_axis(Axis(0), imu2); From adc00477d5c034ed5e4117ca070caa5f7b59a1e0 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sat, 8 Oct 2022 17:32:58 +0200 Subject: [PATCH 22/73] Generalize `Grid::evolve` further --- pineappl/src/grid.rs | 211 +++++++++++++++++++++++-------------------- 1 file changed, 113 insertions(+), 98 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 2ea131b0..6cada786 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -16,7 +16,7 @@ use git_version::git_version; use indicatif::{ProgressBar, ProgressStyle}; use itertools::Itertools; use lz4_flex::frame::{FrameDecoder, FrameEncoder}; -use ndarray::{s, Array, Array2, Array3, Array5, Axis, Dimension}; +use ndarray::{s, Array1, Array2, Array3, Array5, ArrayView1, Axis, Dimension}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::cmp::Ordering; @@ -1918,7 +1918,7 @@ impl Grid { .map(|&x1p| { info.x1 .iter() - .position(|&x1| approx_eq!(f64, x1p, x1, ulps = 4)) + .position(|&x1| approx_eq!(f64, x1p, x1, ulps = 64)) }) .collect() { @@ -1946,6 +1946,110 @@ impl Grid { Ok(operators) } + fn ndarray_from_subgrid_orders( + &self, + info: &OperatorInfo, + subgrids: &ArrayView1, + order_mask: &[bool], + ) -> Result<(Vec, Vec, Array3), GridError> { + let mut x1_a: Vec<_> = subgrids + .iter() + .flat_map(|subgrid| subgrid.x1_grid().into_owned()) + .collect(); + let mut x1_b: Vec<_> = subgrids + .iter() + .flat_map(|subgrid| subgrid.x2_grid().into_owned()) + .collect(); + + x1_a.sort_by(|a, b| a.partial_cmp(b).unwrap()); + x1_a.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); + x1_b.sort_by(|a, b| a.partial_cmp(b).unwrap()); + x1_b.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); + + let mut array = Array3::::zeros((info.fac1.len(), x1_a.len(), x1_b.len())); + + // add subgrids for different orders, but the same bin and lumi, using the right + // couplings + for (subgrid, order) in subgrids + .iter() + .zip(self.orders.iter()) + .zip(order_mask.iter().chain(iter::repeat(&true))) + .filter_map(|((subgrid, order), &enabled)| { + (enabled && !subgrid.is_empty()).then(|| (subgrid, order)) + }) + { + let mut logs = 1.0; + + if order.logxir > 0 { + if approx_eq!(f64, info.xir, 1.0, ulps = 4) { + continue; + } + + logs *= (info.xir * info.xir).ln(); + } + + if order.logxif > 0 { + if approx_eq!(f64, info.xif, 1.0, ulps = 4) { + continue; + } + + logs *= (info.xif * info.xif).ln(); + } + + let xa_indices: Vec<_> = subgrid + .x1_grid() + .iter() + .map(|&xa| { + x1_a.iter() + .position(|&x1a| approx_eq!(f64, x1a, xa, ulps = 64)) + .unwrap() + }) + .collect(); + let xb_indices: Vec<_> = subgrid + .x2_grid() + .iter() + .map(|&xb| { + x1_b.iter() + .position(|&x1b| approx_eq!(f64, x1b, xb, ulps = 64)) + .unwrap() + }) + .collect(); + + for ((imu2, ix1, ix2), value) in subgrid.iter() { + let Mu2 { + ren: mur2, + fac: muf2, + } = subgrid.mu2_grid()[imu2]; + + let als = if let Some(alphas) = + info.ren1 + .iter() + .zip(info.alphas.iter()) + .find_map(|(&ren1, &alphas)| { + approx_eq!(f64, ren1, mur2, ulps = 4).then(|| alphas) + }) { + alphas.powi(order.alphas.try_into().unwrap()) + } else { + return Err(GridError::EvolutionFailure(format!( + "could not find alphas for mur2 = {}", + mur2 + ))); + }; + + // TODO: get rid of the `unwrap` + let mu2_index = info + .fac1 + .iter() + .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 4)) + .unwrap(); + + array[[mu2_index, xa_indices[ix1], xb_indices[ix2]]] += als * logs * value; + } + } + + Ok((x1_a, x1_b, array)) + } + /// Converts this `Grid` into an [`FkTable`] using an evolution kernel operator (EKO) given as /// `operator`. The dimensions and properties of this operator must be described using `info`. /// The parameter `order_mask` can be used to include or exclude orders from this operation, @@ -1998,105 +2102,16 @@ impl Grid { let mut sub_fk_tables = Vec::with_capacity(self.bin_info().bins() * lumi0.len()); for subgrids_ol in self.subgrids.axis_iter(Axis(1)) { - let x1_a = subgrids_ol - .iter() - .find_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x1_grid())) - .unwrap_or_default(); - let x1_b = subgrids_ol - .iter() - .find_map(|subgrid| (!subgrid.is_empty()).then(|| subgrid.x2_grid())) - .unwrap_or_default(); - - if x1_a.is_empty() || x1_b.is_empty() { - continue; - } - - if subgrids_ol.iter().any(|subgrid| { - !subgrid.is_empty() && (subgrid.x1_grid() != x1_a || subgrid.x2_grid() != x1_b) - }) { - return Err(GridError::EvolutionFailure( - "subgrids do not share the same x-grid values".to_string(), - )); - } - - // TODO: here's some optimization potential: if `x1_a` and `x1_b` are the same share - // them and if they are the same over bins share them! - let operators_a = Self::operators(operator, info, &pid_indices_a, &x1_a)?; - let operators_b = Self::operators(operator, info, &pid_indices_b, &x1_b)?; - let mut tables = vec![Array2::zeros((info.x0.len(), info.x0.len())); lumi0.len()]; for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { - let mut array = if let Some((nx1, nx2)) = subgrids_o.iter().find_map(|subgrid| { - (!subgrid.is_empty()) - .then(|| (subgrid.x1_grid().len(), subgrid.x2_grid().len())) - }) { - // TODO: in this way we allocate not the minimum number of dimensions - Array3::::zeros((info.fac1.len(), nx1, nx2)) - } else { - // `find_map` may fail if all grids are empty - break; - }; - - // add subgrids for different orders, but the same bin and lumi, using the right - // couplings - for (subgrid, order) in subgrids_o - .iter() - .zip(self.orders.iter()) - .zip(order_mask.iter().chain(iter::repeat(&true))) - .filter_map(|((subgrid, order), &enabled)| { - (enabled && !subgrid.is_empty()).then(|| (subgrid, order)) - }) - { - let mut logs = 1.0; - - if order.logxir > 0 { - if approx_eq!(f64, info.xir, 1.0, ulps = 4) { - continue; - } - - logs *= (info.xir * info.xir).ln(); - } - - if order.logxif > 0 { - if approx_eq!(f64, info.xif, 1.0, ulps = 4) { - continue; - } - - logs *= (info.xif * info.xif).ln(); - } - - for ((imu2, ix1, ix2), value) in subgrid.iter() { - let Mu2 { - ren: mur2, - fac: muf2, - } = subgrid.mu2_grid()[imu2]; + let (x1_a, x1_b, array) = + self.ndarray_from_subgrid_orders(info, &subgrids_o, order_mask)?; - let als = if let Some(alphas) = info - .ren1 - .iter() - .zip(info.alphas.iter()) - .find_map(|(&ren1, &alphas)| { - approx_eq!(f64, ren1, mur2, ulps = 4).then(|| alphas) - }) { - alphas.powi(order.alphas.try_into().unwrap()) - } else { - return Err(GridError::EvolutionFailure(format!( - "could not find alphas for mur2 = {}", - mur2 - ))); - }; - - // TODO: get rid of the `unwrap` - let mu2_index = info - .fac1 - .iter() - .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 4)) - .unwrap(); - - array[[mu2_index, ix1, ix2]] += als * logs * value; - } - } + // TODO: optimization potential: if `x1_a` and `x1_b` are the same cache them, if + // they are the same over bins and/or orders cache them too + let operators_a = Self::operators(operator, info, &pid_indices_a, &x1_a)?; + let operators_b = Self::operators(operator, info, &pid_indices_b, &x1_b)?; for &(pida1, pidb1, factor) in self.lumi[lumi1].entry() { for (fk_table, opa, opb) in lumi0.iter().zip(tables.iter_mut()).filter_map( @@ -2144,7 +2159,7 @@ impl Grid { } let mut grid = Self { - subgrids: Array::from_iter(sub_fk_tables.into_iter()) + subgrids: Array1::from_iter(sub_fk_tables.into_iter()) .into_shape((1, self.bin_info().bins(), lumi0.len())) .unwrap(), lumi: lumi0.iter().map(|&(a, b)| lumi_entry![a, b, 1.0]).collect(), From 4cc7771ed02f64bfcef8fcaa4a846f9cd7ba35c8 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sat, 8 Oct 2022 18:43:45 +0200 Subject: [PATCH 23/73] Increase tolerance in numerical comparisons --- pineappl/src/grid.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 6cada786..754feafe 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2026,7 +2026,7 @@ impl Grid { .iter() .zip(info.alphas.iter()) .find_map(|(&ren1, &alphas)| { - approx_eq!(f64, ren1, mur2, ulps = 4).then(|| alphas) + approx_eq!(f64, ren1, mur2, ulps = 64).then(|| alphas) }) { alphas.powi(order.alphas.try_into().unwrap()) } else { @@ -2040,7 +2040,7 @@ impl Grid { let mu2_index = info .fac1 .iter() - .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 4)) + .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 64)) .unwrap(); array[[mu2_index, xa_indices[ix1], xb_indices[ix2]]] += als * logs * value; From 9e4591dd6ebc5d57bccd7516ca649fc93f773d33 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sun, 9 Oct 2022 13:20:03 +0200 Subject: [PATCH 24/73] Update `Grid::evolve`'s unit test --- pineappl/src/grid.rs | 137 +++++++++++++++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 30 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 754feafe..6f310568 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2817,17 +2817,12 @@ mod tests { #[test] #[ignore] - fn grid_convolute_eko_for_lhcbwp8tev() { + fn evolve() { use float_cmp::assert_approx_eq; use lhapdf::Pdf; use ndarray::{Array1, Array5}; use std::fs::File; - let grid = "../LHCB_WP_8TEV.pineappl.lz4"; - let metadata = "../LHCB_WP_8TEV/metadata.yaml"; - let alphas = "../LHCB_WP_8TEV/alphas.npy"; - let operator = "../LHCB_WP_8TEV/operators.npy"; - #[derive(Deserialize)] struct Metadata { #[serde(rename = "Q2grid")] @@ -2847,9 +2842,30 @@ mod tests { targetpids: Vec, } + let setname = "NNPDF40_nlo_as_01180"; + + let grid = + "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003.pineappl.lz4"; + let metadata = + "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/metadata.yaml"; + let alphas = + "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/alphas.npy"; + let operator = + "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/operators.npy"; + + //let grid = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34.pineappl.lz4"; + //let metadata = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/metadata.yaml"; + //let alphas = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/alphas.npy"; + //let operator = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/operators.npy"; + + //let grid = "../LHCB_WP_8TEV.pineappl.lz4"; + //let metadata = "../LHCB_WP_8TEV/metadata.yaml"; + //let alphas = "../LHCB_WP_8TEV/alphas.npy"; + //let operator = "../LHCB_WP_8TEV/operators.npy"; + let grid = Grid::read(File::open(grid).unwrap()).unwrap(); - let lhapdf = Pdf::with_setname_and_nmem("NNPDF40_nlo_as_01180").unwrap(); + let lhapdf = Pdf::with_setname_and_nmem(setname).unwrap(); let mut pdf = |id, x, q2| lhapdf.xfx_q2(id, x, q2); let mut als = |q2| lhapdf.alphas_q2(q2); let mut cache = LumiCache::with_one(2212, &mut pdf, &mut als); @@ -2858,24 +2874,58 @@ mod tests { assert_eq!( results, [ - 877.9498750860583, - 823.5123400865052, - 735.605093586326, - 616.3465722662226, - 478.63703336207277, - 341.06729874517384, - 174.3688634669724, - 48.27440593682665 + 1469.0819829706113, + 4364.509970805006, + 2072.647269805865, + 742.6160478667135, + 312.195449854513, + 145.782031788469, + 72.64484245290579, + 38.88392569051013, + 17.093513927247354, + 6.157887576517187, + 2.4621639421455903, + 1.0817834362838417, + 0.5084171526510098, + 0.2520459057372801, + 0.10211930488819178, + 0.021141855492915994 ] ); + //assert_eq!( + // results, + // [ + // 134632.4480167966, + // 133472.53856965082, + // 130776.9197998554, + // 126991.17650299768, + // 121168.15135839234, + // 112761.75563082621, + // 98484.12455342771, + // 57843.82009866679 + // ] + //); + + //assert_eq!( + // results, + // [ + // 877.9498750860583, + // 823.5123400865052, + // 735.605093586326, + // 616.3465722662226, + // 478.63703336207277, + // 341.06729874517384, + // 174.3688634669724, + // 48.27440593682665 + // ] + //); + let metadata: Metadata = serde_yaml::from_reader(File::open(metadata).unwrap()).unwrap(); let alphas: Array1 = ndarray_npy::read_npy(alphas).unwrap(); let alphas = alphas.to_vec(); let operator: Array5 = ndarray_npy::read_npy(operator).unwrap(); - assert_eq!(operator.dim(), (1, 14, 50, 14, 50)); - let info = OperatorInfo { fac1: metadata.q2_grid.clone(), pids0: metadata.inputpids, @@ -2884,7 +2934,7 @@ mod tests { x1: metadata.targetgrid, fac0: metadata.q2_ref, ren1: metadata.q2_grid, // TODO: check whether this is true in the general case - alphas: alphas, + alphas, xir: 1.0, xif: 1.0, lumi_id_types: "pdg_mc_ids".to_string(), @@ -2910,17 +2960,44 @@ mod tests { .grid() .convolute(&mut cache, &[], &[], &[], &[(1.0, 1.0)]); - //fk_table - // .write(File::create("fk_table.pineappl").unwrap()) - // .unwrap(); - - assert_approx_eq!(f64, evolved_results[0], 1526.1321420502966, ulps = 8); - assert_approx_eq!(f64, evolved_results[1], 1380.605564314246, ulps = 8); - assert_approx_eq!(f64, evolved_results[2], 1182.565055380693, ulps = 8); - assert_approx_eq!(f64, evolved_results[3], 947.3266541818663, ulps = 8); - assert_approx_eq!(f64, evolved_results[4], 702.6776451873732, ulps = 8); - assert_approx_eq!(f64, evolved_results[5], 477.8683182368509, ulps = 8); - assert_approx_eq!(f64, evolved_results[6], 229.2748278368886, ulps = 8); - assert_approx_eq!(f64, evolved_results[7], 58.35460083148634, ulps = 8); + assert_eq!( + evolved_results, + [ + 1467.6009449768221, + 4359.87917180896, + 2070.4278159799974, + 741.9298754488171, + 311.9073865166957, + 145.65671641953438, + 72.58340237308579, + 38.85208071336316, + 17.080194246318936, + 6.153298093496777, + 2.4604627649049604, + 1.0810950528772425, + 0.5081137620517796, + 0.25190465608989626, + 0.10206534388970377, + 0.02113211970400249 + ] + ); + + //assert_approx_eq!(f64, evolved_results[0], 134500.65897999398, ulps = 8); + //assert_approx_eq!(f64, evolved_results[1], 133344.24845948347, ulps = 8); + //assert_approx_eq!(f64, evolved_results[2], 130663.70226447149, ulps = 32); + //assert_approx_eq!(f64, evolved_results[3], 126890.6156547337, ulps = 8); + //assert_approx_eq!(f64, evolved_results[4], 121090.7595443343, ulps = 8); + //assert_approx_eq!(f64, evolved_results[5], 112698.92115188896, ulps = 16); + //assert_approx_eq!(f64, evolved_results[6], 98421.19065191328, ulps = 8); + //assert_approx_eq!(f64, evolved_results[7], 57813.500329070215, ulps = 8); + + //assert_approx_eq!(f64, evolved_results[0], 1526.1321420502966, ulps = 8); + //assert_approx_eq!(f64, evolved_results[1], 1380.605564314246, ulps = 8); + //assert_approx_eq!(f64, evolved_results[2], 1182.565055380693, ulps = 8); + //assert_approx_eq!(f64, evolved_results[3], 947.3266541818663, ulps = 8); + //assert_approx_eq!(f64, evolved_results[4], 702.6776451873732, ulps = 8); + //assert_approx_eq!(f64, evolved_results[5], 477.8683182368509, ulps = 8); + //assert_approx_eq!(f64, evolved_results[6], 229.2748278368886, ulps = 8); + //assert_approx_eq!(f64, evolved_results[7], 58.35460083148634, ulps = 8); } } From e86ed0e9ab3f0fcf2948c0733377dbf41ab17ded Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sun, 9 Oct 2022 15:12:13 +0200 Subject: [PATCH 25/73] Remove outdated TODO comment --- pineappl/src/grid.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 6f310568..8e48344c 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1924,7 +1924,6 @@ impl Grid { { x1_indices } else { - // TODO: return better error - operator x1 values don't match grid's x1 values return Err(GridError::EvolutionFailure( "operator information does not match grid's x-grid values".to_string(), )); From 803b3937a05d8e119932d0e27e0083df4953a0aa Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sun, 9 Oct 2022 15:12:57 +0200 Subject: [PATCH 26/73] Improve readability of `Grid::operators` --- pineappl/src/grid.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 8e48344c..9af39248 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1933,12 +1933,12 @@ impl Grid { let operators: Vec<_> = pid_indices .iter() .map(|&(pid0_idx, pid1_idx)| { - let mut op = Array3::zeros((operator.dim().0, info.x0.len(), x1.len())); - for (op_index, &x1_index) in x1_indices.iter().enumerate() { - op.slice_mut(s![.., .., op_index]) - .assign(&operator.slice(s![.., pid1_idx, x1_index, pid0_idx, ..])); - } - op + operator + .slice(s![.., pid1_idx, .., pid0_idx, ..]) + .select(Axis(1), &x1_indices) + .permuted_axes([0, 2, 1]) + .as_standard_layout() + .into_owned() }) .collect(); From 6e841aece7292528631fd7cc3374c2223eb68568 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 10 Oct 2022 10:14:28 +0200 Subject: [PATCH 27/73] Add `Grid::has_pdf{1,2}` and `Grid::initial_state_{1,2}` --- pineappl/src/grid.rs | 96 +++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 9af39248..11f82fa8 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1346,31 +1346,9 @@ impl Grid { /// TODO #[must_use] pub fn axes(&self) -> Option { - // determine what and how many hadrons are in the initial state - let initial_state_1 = self - .key_values() - .map_or(Some("2212"), |kv| { - kv.get("initial_state_1").map(String::as_str) - }) - .map(str::parse::)? - .ok()?; - let initial_state_2 = self - .key_values() - .map_or(Some("2212"), |kv| { - kv.get("initial_state_2").map(String::as_str) - }) - .map(str::parse::)? - .ok()?; - // are the initial states hadrons? - let has_pdf1 = !self - .lumi() - .iter() - .all(|entry| entry.entry().iter().all(|&(a, _, _)| a == initial_state_1)); - let has_pdf2 = !self - .lumi() - .iter() - .all(|entry| entry.entry().iter().all(|&(_, b, _)| b == initial_state_2)); + let has_pdf1 = self.has_pdf1(); + let has_pdf2 = self.has_pdf1(); let mut mur2_grid = Vec::new(); let mut muf2_grid = Vec::new(); @@ -1467,30 +1445,12 @@ impl Grid { let operator = operator.as_standard_layout(); // determine what and how many hadrons are in the initial state - let initial_state_1 = self - .key_values() - .map_or(Some("2212"), |kv| { - kv.get("initial_state_1").map(String::as_str) - }) - .map(str::parse::)? - .ok()?; - let initial_state_2 = self - .key_values() - .map_or(Some("2212"), |kv| { - kv.get("initial_state_2").map(String::as_str) - }) - .map(str::parse::)? - .ok()?; + let initial_state_1 = self.initial_state_1(); + let initial_state_2 = self.initial_state_2(); // are the initial states hadrons? - let has_pdf1 = !self - .lumi() - .iter() - .all(|entry| entry.entry().iter().all(|&(a, _, _)| a == initial_state_1)); - let has_pdf2 = !self - .lumi() - .iter() - .all(|entry| entry.entry().iter().all(|&(_, b, _)| b == initial_state_2)); + let has_pdf1 = self.has_pdf1(); + let has_pdf2 = self.has_pdf1(); let pids1 = if has_pdf1 { eko_info.grid_axes.pids.clone() @@ -2285,6 +2245,50 @@ impl Grid { }) .collect(); } + + /// Returns `true` if the first initial state needs a convolution, `false` otherwise. + pub fn has_pdf1(&self) -> bool { + let initial_state_1 = self.initial_state_1(); + + !self + .lumi() + .iter() + .all(|entry| entry.entry().iter().all(|&(a, _, _)| a == initial_state_1)) + } + + /// Returns `true` if the second initial state needs a convolution, `false` otherwise. + pub fn has_pdf2(&self) -> bool { + let initial_state_2 = self.initial_state_2(); + + !self + .lumi() + .iter() + .all(|entry| entry.entry().iter().all(|&(_, b, _)| b == initial_state_2)) + } + + /// Returns the particle identifier of the first initial state. This is usually, but not always + /// a proton, which is represented by the PDG ID `2212`. + pub fn initial_state_1(&self) -> i32 { + self.key_values() + .map_or(Some("2212"), |kv| { + kv.get("initial_state_1").map(String::as_str) + }) + .map(str::parse) + .unwrap() + .unwrap() + } + + /// Returns the particle identifier of the second initial state. This is usually, but not + /// always a proton, which is represented by the PDG ID `2212`. + pub fn initial_state_2(&self) -> i32 { + self.key_values() + .map_or(Some("2212"), |kv| { + kv.get("initial_state_2").map(String::as_str) + }) + .map(str::parse) + .unwrap() + .unwrap() + } } #[cfg(test)] From f0e17012977b7b7bce3155250eb7be7bbca897e5 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 10 Oct 2022 10:16:25 +0200 Subject: [PATCH 28/73] Prepare for DIS evolutions --- pineappl/src/grid.rs | 79 +++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 11f82fa8..9951aca1 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2009,40 +2009,21 @@ impl Grid { Ok((x1_a, x1_b, array)) } - /// Converts this `Grid` into an [`FkTable`] using an evolution kernel operator (EKO) given as - /// `operator`. The dimensions and properties of this operator must be described using `info`. - /// The parameter `order_mask` can be used to include or exclude orders from this operation, - /// and must correspond to the ordering given by [`Grid::orders`]. Orders that are not given - /// are enabled, and in particular if `order_mask` is empty all orders are activated. - /// - /// # Errors - /// - /// Returns a [`GridError::EvolutionFailure`] if either the `operator` or its `info` is - /// incompatible with this `Grid`. - pub fn evolve( + fn evolve_with_one( + &self, + _operator: &Array5, + _info: &OperatorInfo, + _order_mask: &[bool], + ) -> Result { + todo!() + } + + fn evolve_with_two( &self, operator: &Array5, info: &OperatorInfo, order_mask: &[bool], ) -> Result { - let op_info_dim = ( - info.fac1.len(), - info.pids1.len(), - info.x1.len(), - info.pids0.len(), - info.x0.len(), - ); - - if operator.dim() != op_info_dim { - return Err(GridError::EvolutionFailure(format!( - "operator information {:?} does not match the operator's dimensions: {:?}", - op_info_dim, - operator.dim(), - ))); - } - - // TODO: here we assume that we convolute with two PDFs - let (pid_indices_a, pids_a) = Self::pids(operator, info, &|pid1| { self.lumi .iter() @@ -2131,10 +2112,48 @@ impl Grid { // write additional metadata grid.set_key_value("lumi_id_types", &info.lumi_id_types); - // TODO: convert unwrap to error Ok(FkTable::try_from(grid).unwrap()) } + /// Converts this `Grid` into an [`FkTable`] using an evolution kernel operator (EKO) given as + /// `operator`. The dimensions and properties of this operator must be described using `info`. + /// The parameter `order_mask` can be used to include or exclude orders from this operation, + /// and must correspond to the ordering given by [`Grid::orders`]. Orders that are not given + /// are enabled, and in particular if `order_mask` is empty all orders are activated. + /// + /// # Errors + /// + /// Returns a [`GridError::EvolutionFailure`] if either the `operator` or its `info` is + /// incompatible with this `Grid`. + pub fn evolve( + &self, + operator: &Array5, + info: &OperatorInfo, + order_mask: &[bool], + ) -> Result { + let op_info_dim = ( + info.fac1.len(), + info.pids1.len(), + info.x1.len(), + info.pids0.len(), + info.x0.len(), + ); + + if operator.dim() != op_info_dim { + return Err(GridError::EvolutionFailure(format!( + "operator information {:?} does not match the operator's dimensions: {:?}", + op_info_dim, + operator.dim(), + ))); + } + + if self.has_pdf1() && self.has_pdf2() { + self.evolve_with_two(operator, info, order_mask) + } else { + self.evolve_with_one(operator, info, order_mask) + } + } + /// Deletes bins with the corresponding `bin_indices`. Repeated indices and indices larger or /// equal the bin length are ignored. pub fn delete_bins(&mut self, bin_indices: &[usize]) { From bf18aac786c07f58a185838a71827f87bbf98513 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 10 Oct 2022 14:02:53 +0200 Subject: [PATCH 29/73] Move evolution code into separate module --- pineappl/src/evolution.rs | 235 +++++++++++++++++++++++++++++++++++ pineappl/src/grid.rs | 253 +++----------------------------------- pineappl/src/lib.rs | 1 + 3 files changed, 250 insertions(+), 239 deletions(-) create mode 100644 pineappl/src/evolution.rs diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs new file mode 100644 index 00000000..877591f7 --- /dev/null +++ b/pineappl/src/evolution.rs @@ -0,0 +1,235 @@ +//! Supporting classes and functions for [`Grid::evolve`]. + +use super::grid::{GridError, Order}; +use super::subgrid::{Mu2, Subgrid, SubgridEnum}; +use float_cmp::approx_eq; +use itertools::Itertools; +use ndarray::{s, Array3, Array5, ArrayView1, Axis}; +use std::iter; + +/// Information about the evolution kernel operator (EKO) passed to [`Grid::evolve`] as `operator`, +/// which is used to convert a [`Grid`] into an [`FkTable`]. The dimensions of the EKO must +/// correspond to the values given in [`fac1`], [`pids0`], [`x0`], [`pids1`] and [`x1`], exactly in +/// this order. Members with a `1` are defined at the squared factorization scales given in +/// [`fac1`] (often called process scales) and are found in the [`Grid`] that [`Grid::evolve`] is +/// called with. Members with a `0` are defined at the squared factorization scale [`fac0`] (often +/// called fitting scale or starting scale) and are found in the [`FkTable`] resulting from +/// [`Grid::evolve`]. +/// +/// The EKO may convert a `Grid` from a basis given by the particle identifiers [`pids1`] to a +/// possibly different basis given by [`pids0`]. This basis must also be identified using +/// [`lumi_id_types`], which tells [`FkTable::convolute`] how to perform a convolution. The members +/// [`ren1`] and [`alphas`] must be the strong couplings given at the respective renormalization +/// scales. Finally, [`xir`] and [`xif`] can be used to vary the renormalization and factorization +/// scales, respectively, around their central values. +pub struct OperatorInfo { + /// Squared factorization scales of the `Grid`. + pub fac1: Vec, + /// Particle identifiers of the `FkTable`. + pub pids0: Vec, + /// `x`-grid coordinates of the `FkTable` + pub x0: Vec, + /// Particle identifiers of the `Grid`. If the `Grid` contains more particle identifiers than + /// given here, the contributions of them are silently ignored. + pub pids1: Vec, + /// `x`-grid coordinates of the `Grid`. + pub x1: Vec, + + /// Squared factorization scale of the `FkTable`. + pub fac0: f64, + /// Renormalization scales of the `Grid`. + pub ren1: Vec, + /// Strong couplings corresponding to the order given in [`ren1`]. + pub alphas: Vec, + /// Multiplicative factor for the central renormalization scale. + pub xir: f64, + /// Multiplicative factor for the central factorization scale. + pub xif: f64, + /// Identifier of the particle basis for the `FkTable`. + pub lumi_id_types: String, +} + +pub(crate) fn pids( + operator: &Array5, + info: &OperatorInfo, + pid1_nonzero: &dyn Fn(i32) -> bool, +) -> (Vec<(usize, usize)>, Vec<(i32, i32)>) { + // list of all non-zero PID indices + let pid_indices: Vec<_> = (0..operator.dim().3) + .cartesian_product(0..operator.dim().1) + .filter(|&(pid0_idx, pid1_idx)| { + // 1) at least one element of the operator must be non-zero, and 2) the pid must be + // contained in the lumi somewhere + operator + .slice(s![.., pid1_idx, .., pid0_idx, ..]) + .iter() + .any(|&value| value != 0.0) + && pid1_nonzero(info.pids1[pid1_idx]) + }) + .collect(); + + // list of all non-zero (pid0, pid1) combinations + let pids = pid_indices + .iter() + .map(|&(pid0_idx, pid1_idx)| (info.pids0[pid0_idx], info.pids1[pid1_idx])) + .collect(); + + (pid_indices, pids) +} + +pub(crate) fn lumi0(pids_a: &[(i32, i32)], pids_b: &[(i32, i32)]) -> Vec<(i32, i32)> { + let mut pids0_a: Vec<_> = pids_a.iter().map(|&(pid0, _)| pid0).collect(); + pids0_a.sort_unstable(); + pids0_a.dedup(); + let mut pids0_b: Vec<_> = pids_b.iter().map(|&(pid0, _)| pid0).collect(); + pids0_b.sort_unstable(); + pids0_b.dedup(); + + pids0_a + .iter() + .copied() + .cartesian_product(pids0_b.iter().copied()) + .collect() +} + +pub(crate) fn operators( + operator: &Array5, + info: &OperatorInfo, + pid_indices: &[(usize, usize)], + x1: &[f64], +) -> Result>, GridError> { + // permutation between the grid x values and the operator x1 values + let x1_indices: Vec<_> = if let Some(x1_indices) = x1 + .iter() + .map(|&x1p| { + info.x1 + .iter() + .position(|&x1| approx_eq!(f64, x1p, x1, ulps = 64)) + }) + .collect() + { + x1_indices + } else { + return Err(GridError::EvolutionFailure( + "operator information does not match grid's x-grid values".to_string(), + )); + }; + + // create the corresponding operators accessible in the form [muf2, x0, x1] + let operators: Vec<_> = pid_indices + .iter() + .map(|&(pid0_idx, pid1_idx)| { + operator + .slice(s![.., pid1_idx, .., pid0_idx, ..]) + .select(Axis(1), &x1_indices) + .permuted_axes([0, 2, 1]) + .as_standard_layout() + .into_owned() + }) + .collect(); + + Ok(operators) +} + +pub(crate) fn ndarray_from_subgrid_orders( + info: &OperatorInfo, + subgrids: &ArrayView1, + orders: &[Order], + order_mask: &[bool], +) -> Result<(Vec, Vec, Array3), GridError> { + let mut x1_a: Vec<_> = subgrids + .iter() + .flat_map(|subgrid| subgrid.x1_grid().into_owned()) + .collect(); + let mut x1_b: Vec<_> = subgrids + .iter() + .flat_map(|subgrid| subgrid.x2_grid().into_owned()) + .collect(); + + x1_a.sort_by(|a, b| a.partial_cmp(b).unwrap()); + x1_a.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); + x1_b.sort_by(|a, b| a.partial_cmp(b).unwrap()); + x1_b.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); + + let mut array = Array3::::zeros((info.fac1.len(), x1_a.len(), x1_b.len())); + + // add subgrids for different orders, but the same bin and lumi, using the right + // couplings + for (subgrid, order) in subgrids + .iter() + .zip(orders.iter()) + .zip(order_mask.iter().chain(iter::repeat(&true))) + .filter_map(|((subgrid, order), &enabled)| { + (enabled && !subgrid.is_empty()).then(|| (subgrid, order)) + }) + { + let mut logs = 1.0; + + if order.logxir > 0 { + if approx_eq!(f64, info.xir, 1.0, ulps = 4) { + continue; + } + + logs *= (info.xir * info.xir).ln(); + } + + if order.logxif > 0 { + if approx_eq!(f64, info.xif, 1.0, ulps = 4) { + continue; + } + + logs *= (info.xif * info.xif).ln(); + } + + let xa_indices: Vec<_> = subgrid + .x1_grid() + .iter() + .map(|&xa| { + x1_a.iter() + .position(|&x1a| approx_eq!(f64, x1a, xa, ulps = 64)) + .unwrap() + }) + .collect(); + let xb_indices: Vec<_> = subgrid + .x2_grid() + .iter() + .map(|&xb| { + x1_b.iter() + .position(|&x1b| approx_eq!(f64, x1b, xb, ulps = 64)) + .unwrap() + }) + .collect(); + + for ((imu2, ix1, ix2), value) in subgrid.iter() { + let Mu2 { + ren: mur2, + fac: muf2, + } = subgrid.mu2_grid()[imu2]; + + let als = if let Some(alphas) = info + .ren1 + .iter() + .zip(info.alphas.iter()) + .find_map(|(&ren1, &alphas)| approx_eq!(f64, ren1, mur2, ulps = 64).then(|| alphas)) + { + alphas.powi(order.alphas.try_into().unwrap()) + } else { + return Err(GridError::EvolutionFailure(format!( + "could not find alphas for mur2 = {}", + mur2 + ))); + }; + + // TODO: get rid of the `unwrap` + let mu2_index = info + .fac1 + .iter() + .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 64)) + .unwrap(); + + array[[mu2_index, xa_indices[ix1], xb_indices[ix2]]] += als * logs * value; + } + } + + Ok((x1_a, x1_b, array)) +} diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 9951aca1..c0d78190 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2,6 +2,7 @@ use super::bin::{BinInfo, BinLimits, BinRemapper}; use super::empty_subgrid::EmptySubgridV1; +use super::evolution::{self, OperatorInfo}; use super::fk_table::FkTable; use super::import_only_subgrid::ImportOnlySubgridV2; use super::lagrange_subgrid::{LagrangeSparseSubgridV1, LagrangeSubgridV1, LagrangeSubgridV2}; @@ -16,7 +17,7 @@ use git_version::git_version; use indicatif::{ProgressBar, ProgressStyle}; use itertools::Itertools; use lz4_flex::frame::{FrameDecoder, FrameEncoder}; -use ndarray::{s, Array1, Array2, Array3, Array5, ArrayView1, Axis, Dimension}; +use ndarray::{s, Array1, Array2, Array3, Array5, Axis, Dimension}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::cmp::Ordering; @@ -388,48 +389,6 @@ pub struct EkoInfo { pub lumi_id_types: String, } -/// Information about the evolution kernel operator (EKO) passed to [`Grid::evolve`] as `operator`, -/// which is used to convert a [`Grid`] into an [`FkTable`]. The dimensions of the EKO must -/// correspond to the values given in [`fac1`], [`pids0`], [`x0`], [`pids1`] and [`x1`], exactly in -/// this order. Members with a `1` are defined at the squared factorization scales given in -/// [`fac1`] (often called process scales) and are found in the [`Grid`] that [`Grid::evolve`] is -/// called with. Members with a `0` are defined at the squared factorization scale [`fac0`] (often -/// called fitting scale or starting scale) and are found in the [`FkTable`] resulting from -/// [`Grid::evolve`]. -/// -/// The EKO may convert a `Grid` from a basis given by the particle identifiers [`pids1`] to a -/// possibly different basis given by [`pids0`]. This basis must also be identified using -/// [`lumi_id_types`], which tells [`FkTable::convolute`] how to perform a convolution. The members -/// [`ren1`] and [`alphas`] must be the strong couplings given at the respective renormalization -/// scales. Finally, [`xir`] and [`xif`] can be used to vary the renormalization and factorization -/// scales, respectively, around their central values. -pub struct OperatorInfo { - /// Squared factorization scales of the `Grid`. - pub fac1: Vec, - /// Particle identifiers of the `FkTable`. - pub pids0: Vec, - /// `x`-grid coordinates of the `FkTable` - pub x0: Vec, - /// Particle identifiers of the `Grid`. If the `Grid` contains more particle identifiers than - /// given here, the contributions of them are silently ignored. - pub pids1: Vec, - /// `x`-grid coordinates of the `Grid`. - pub x1: Vec, - - /// Squared factorization scale of the `FkTable`. - pub fac0: f64, - /// Renormalization scales of the `Grid`. - pub ren1: Vec, - /// Strong couplings corresponding to the order given in [`ren1`]. - pub alphas: Vec, - /// Multiplicative factor for the central renormalization scale. - pub xir: f64, - /// Multiplicative factor for the central factorization scale. - pub xif: f64, - /// Identifier of the particle basis for the `FkTable`. - pub lumi_id_types: String, -} - /// Main data structure of `PineAPPL`. This structure contains a `Subgrid` for each `LumiEntry`, /// bin, and coupling order it was created with. #[derive(Clone, Deserialize, Serialize)] @@ -1820,195 +1779,6 @@ impl Grid { FkTable::try_from(result).ok() } - // TODO: move this function into a separate module - fn pids( - operator: &Array5, - info: &OperatorInfo, - pid1_nonzero: &dyn Fn(i32) -> bool, - ) -> (Vec<(usize, usize)>, Vec<(i32, i32)>) { - // list of all non-zero PID indices - let pid_indices: Vec<_> = (0..operator.dim().3) - .cartesian_product(0..operator.dim().1) - .filter(|&(pid0_idx, pid1_idx)| { - // 1) at least one element of the operator must be non-zero, and 2) the pid must be - // contained in the lumi somewhere - operator - .slice(s![.., pid1_idx, .., pid0_idx, ..]) - .iter() - .any(|&value| value != 0.0) - && pid1_nonzero(info.pids1[pid1_idx]) - }) - .collect(); - - // list of all non-zero (pid0, pid1) combinations - let pids = pid_indices - .iter() - .map(|&(pid0_idx, pid1_idx)| (info.pids0[pid0_idx], info.pids1[pid1_idx])) - .collect(); - - (pid_indices, pids) - } - - // TODO: move this function into a separate module - fn lumi0(pids_a: &[(i32, i32)], pids_b: &[(i32, i32)]) -> Vec<(i32, i32)> { - let mut pids0_a: Vec<_> = pids_a.iter().map(|&(pid0, _)| pid0).collect(); - pids0_a.sort_unstable(); - pids0_a.dedup(); - let mut pids0_b: Vec<_> = pids_b.iter().map(|&(pid0, _)| pid0).collect(); - pids0_b.sort_unstable(); - pids0_b.dedup(); - - pids0_a - .iter() - .copied() - .cartesian_product(pids0_b.iter().copied()) - .collect() - } - - // TODO: move this function into a separate module - fn operators( - operator: &Array5, - info: &OperatorInfo, - pid_indices: &[(usize, usize)], - x1: &[f64], - ) -> Result>, GridError> { - // permutation between the grid x values and the operator x1 values - let x1_indices: Vec<_> = if let Some(x1_indices) = x1 - .iter() - .map(|&x1p| { - info.x1 - .iter() - .position(|&x1| approx_eq!(f64, x1p, x1, ulps = 64)) - }) - .collect() - { - x1_indices - } else { - return Err(GridError::EvolutionFailure( - "operator information does not match grid's x-grid values".to_string(), - )); - }; - - // create the corresponding operators accessible in the form [muf2, x0, x1] - let operators: Vec<_> = pid_indices - .iter() - .map(|&(pid0_idx, pid1_idx)| { - operator - .slice(s![.., pid1_idx, .., pid0_idx, ..]) - .select(Axis(1), &x1_indices) - .permuted_axes([0, 2, 1]) - .as_standard_layout() - .into_owned() - }) - .collect(); - - Ok(operators) - } - - fn ndarray_from_subgrid_orders( - &self, - info: &OperatorInfo, - subgrids: &ArrayView1, - order_mask: &[bool], - ) -> Result<(Vec, Vec, Array3), GridError> { - let mut x1_a: Vec<_> = subgrids - .iter() - .flat_map(|subgrid| subgrid.x1_grid().into_owned()) - .collect(); - let mut x1_b: Vec<_> = subgrids - .iter() - .flat_map(|subgrid| subgrid.x2_grid().into_owned()) - .collect(); - - x1_a.sort_by(|a, b| a.partial_cmp(b).unwrap()); - x1_a.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); - x1_b.sort_by(|a, b| a.partial_cmp(b).unwrap()); - x1_b.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); - - let mut array = Array3::::zeros((info.fac1.len(), x1_a.len(), x1_b.len())); - - // add subgrids for different orders, but the same bin and lumi, using the right - // couplings - for (subgrid, order) in subgrids - .iter() - .zip(self.orders.iter()) - .zip(order_mask.iter().chain(iter::repeat(&true))) - .filter_map(|((subgrid, order), &enabled)| { - (enabled && !subgrid.is_empty()).then(|| (subgrid, order)) - }) - { - let mut logs = 1.0; - - if order.logxir > 0 { - if approx_eq!(f64, info.xir, 1.0, ulps = 4) { - continue; - } - - logs *= (info.xir * info.xir).ln(); - } - - if order.logxif > 0 { - if approx_eq!(f64, info.xif, 1.0, ulps = 4) { - continue; - } - - logs *= (info.xif * info.xif).ln(); - } - - let xa_indices: Vec<_> = subgrid - .x1_grid() - .iter() - .map(|&xa| { - x1_a.iter() - .position(|&x1a| approx_eq!(f64, x1a, xa, ulps = 64)) - .unwrap() - }) - .collect(); - let xb_indices: Vec<_> = subgrid - .x2_grid() - .iter() - .map(|&xb| { - x1_b.iter() - .position(|&x1b| approx_eq!(f64, x1b, xb, ulps = 64)) - .unwrap() - }) - .collect(); - - for ((imu2, ix1, ix2), value) in subgrid.iter() { - let Mu2 { - ren: mur2, - fac: muf2, - } = subgrid.mu2_grid()[imu2]; - - let als = if let Some(alphas) = - info.ren1 - .iter() - .zip(info.alphas.iter()) - .find_map(|(&ren1, &alphas)| { - approx_eq!(f64, ren1, mur2, ulps = 64).then(|| alphas) - }) { - alphas.powi(order.alphas.try_into().unwrap()) - } else { - return Err(GridError::EvolutionFailure(format!( - "could not find alphas for mur2 = {}", - mur2 - ))); - }; - - // TODO: get rid of the `unwrap` - let mu2_index = info - .fac1 - .iter() - .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 64)) - .unwrap(); - - array[[mu2_index, xa_indices[ix1], xb_indices[ix2]]] += als * logs * value; - } - } - - Ok((x1_a, x1_b, array)) - } - fn evolve_with_one( &self, _operator: &Array5, @@ -2024,20 +1794,20 @@ impl Grid { info: &OperatorInfo, order_mask: &[bool], ) -> Result { - let (pid_indices_a, pids_a) = Self::pids(operator, info, &|pid1| { + let (pid_indices_a, pids_a) = evolution::pids(operator, info, &|pid1| { self.lumi .iter() .flat_map(LumiEntry::entry) .any(|&(a, _, _)| a == pid1) }); - let (pid_indices_b, pids_b) = Self::pids(operator, info, &|pid1| { + let (pid_indices_b, pids_b) = evolution::pids(operator, info, &|pid1| { self.lumi .iter() .flat_map(LumiEntry::entry) .any(|&(_, b, _)| b == pid1) }); - let lumi0 = Self::lumi0(&pids_a, &pids_b); + let lumi0 = evolution::lumi0(&pids_a, &pids_b); let mut sub_fk_tables = Vec::with_capacity(self.bin_info().bins() * lumi0.len()); @@ -2045,13 +1815,17 @@ impl Grid { let mut tables = vec![Array2::zeros((info.x0.len(), info.x0.len())); lumi0.len()]; for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { - let (x1_a, x1_b, array) = - self.ndarray_from_subgrid_orders(info, &subgrids_o, order_mask)?; + let (x1_a, x1_b, array) = evolution::ndarray_from_subgrid_orders( + info, + &subgrids_o, + &self.orders, + order_mask, + )?; // TODO: optimization potential: if `x1_a` and `x1_b` are the same cache them, if // they are the same over bins and/or orders cache them too - let operators_a = Self::operators(operator, info, &pid_indices_a, &x1_a)?; - let operators_b = Self::operators(operator, info, &pid_indices_b, &x1_b)?; + let operators_a = evolution::operators(operator, info, &pid_indices_a, &x1_a)?; + let operators_b = evolution::operators(operator, info, &pid_indices_b, &x1_b)?; for &(pida1, pidb1, factor) in self.lumi[lumi1].entry() { for (fk_table, opa, opb) in lumi0.iter().zip(tables.iter_mut()).filter_map( @@ -2841,6 +2615,7 @@ mod tests { #[ignore] fn evolve() { use float_cmp::assert_approx_eq; + use evolution::OperatorInfo; use lhapdf::Pdf; use ndarray::{Array1, Array5}; use std::fs::File; diff --git a/pineappl/src/lib.rs b/pineappl/src/lib.rs index e9318122..1c01cbae 100644 --- a/pineappl/src/lib.rs +++ b/pineappl/src/lib.rs @@ -9,6 +9,7 @@ mod convert; pub mod bin; pub mod empty_subgrid; +pub mod evolution; pub mod fk_table; pub mod grid; pub mod import_only_subgrid; From d0f0a98ed97ad57640587738a3ac1905ac619db8 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 10 Oct 2022 14:03:17 +0200 Subject: [PATCH 30/73] Fix warning --- pineappl/src/grid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index c0d78190..70a33439 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2614,7 +2614,7 @@ mod tests { #[test] #[ignore] fn evolve() { - use float_cmp::assert_approx_eq; + //use float_cmp::assert_approx_eq; use evolution::OperatorInfo; use lhapdf::Pdf; use ndarray::{Array1, Array5}; From 64fbc3247a239619123e2e95d43588f7f30521ee Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 13 Oct 2022 11:04:17 +0200 Subject: [PATCH 31/73] Rename `lumi0` to `lumi0_with_two` --- pineappl/src/evolution.rs | 2 +- pineappl/src/grid.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 877591f7..7f750d31 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -77,7 +77,7 @@ pub(crate) fn pids( (pid_indices, pids) } -pub(crate) fn lumi0(pids_a: &[(i32, i32)], pids_b: &[(i32, i32)]) -> Vec<(i32, i32)> { +pub(crate) fn lumi0_with_two(pids_a: &[(i32, i32)], pids_b: &[(i32, i32)]) -> Vec<(i32, i32)> { let mut pids0_a: Vec<_> = pids_a.iter().map(|&(pid0, _)| pid0).collect(); pids0_a.sort_unstable(); pids0_a.dedup(); diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 70a33439..1634a1e0 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1807,7 +1807,7 @@ impl Grid { .any(|&(_, b, _)| b == pid1) }); - let lumi0 = evolution::lumi0(&pids_a, &pids_b); + let lumi0 = evolution::lumi0_with_two(&pids_a, &pids_b); let mut sub_fk_tables = Vec::with_capacity(self.bin_info().bins() * lumi0.len()); From 69e1b00c068f0a74383a33bc20730ca9aaa6d63b Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 13 Oct 2022 11:04:52 +0200 Subject: [PATCH 32/73] Add first implementation of `Grid::evolve_with_one` --- pineappl/src/evolution.rs | 8 + pineappl/src/grid.rs | 300 ++++++++++++++++++++++++++++++++------ 2 files changed, 264 insertions(+), 44 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 7f750d31..925ecdb7 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -77,6 +77,14 @@ pub(crate) fn pids( (pid_indices, pids) } +pub(crate) fn lumi0_with_one(pids: &[(i32, i32)]) -> Vec { + let mut pids0: Vec<_> = pids.iter().map(|&(pid0, _)| pid0).collect(); + pids0.sort_unstable(); + pids0.dedup(); + + pids0 +} + pub(crate) fn lumi0_with_two(pids_a: &[(i32, i32)], pids_b: &[(i32, i32)]) -> Vec<(i32, i32)> { let mut pids0_a: Vec<_> = pids_a.iter().map(|&(pid0, _)| pid0).collect(); pids0_a.sort_unstable(); diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 1634a1e0..438e74e6 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1781,11 +1781,128 @@ impl Grid { fn evolve_with_one( &self, - _operator: &Array5, - _info: &OperatorInfo, - _order_mask: &[bool], + operator: &Array5, + info: &OperatorInfo, + order_mask: &[bool], ) -> Result { - todo!() + let has_pdf1 = self.has_pdf1(); + + let (pid_indices, pids) = evolution::pids(operator, info, &|pid| { + self.lumi + .iter() + .flat_map(LumiEntry::entry) + .any(|&(a, b, _)| if has_pdf1 { a } else { b } == pid) + }); + + let lumi0 = evolution::lumi0_with_one(&pids); + let mut sub_fk_tables = Vec::with_capacity(self.bin_info().bins() * lumi0.len()); + let new_axis = if has_pdf1 { 2 } else { 1 }; + + for subgrids_ol in self.subgrids.axis_iter(Axis(1)) { + let mut tables = vec![Array1::zeros(info.x0.len()); lumi0.len()]; + + for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { + let (x1_a, x1_b, array) = evolution::ndarray_from_subgrid_orders( + info, + &subgrids_o, + &self.orders, + order_mask, + )?; + + let x1 = if has_pdf1 { x1_a } else { x1_b }; + let operators = evolution::operators(operator, info, &pid_indices, &x1)?; + + for (&pid1, &factor) in + self.lumi[lumi1].entry().iter().map( + |(a, b, f)| { + if has_pdf1 { + (a, f) + } else { + (b, f) + } + }, + ) + { + for (fk_table, op) in + lumi0 + .iter() + .zip(tables.iter_mut()) + .filter_map(|(&pid0, fk_table)| { + pids.iter() + .zip(operators.iter()) + .find_map(|(&(p0, p1), op)| { + (p0 == pid0 && p1 == pid1).then(|| op) + }) + .map(|op| (fk_table, op)) + }) + { + let mut result = Array1::zeros(info.x0.len()); + + for imu2 in 0..array.dim().0 { + let op = op.index_axis(Axis(0), imu2); + + result += &op.dot( + &array + .index_axis(Axis(0), imu2) + .index_axis(Axis(new_axis - 1), 0), + ); + } + + fk_table.scaled_add(factor, &result); + } + } + } + + sub_fk_tables.extend(tables.into_iter().map(|table| { + ImportOnlySubgridV2::new( + SparseArray3::from_ndarray( + &table.insert_axis(Axis(0)).insert_axis(Axis(new_axis)), + 0, + 1, + ), + vec![Mu2 { + // TODO: FK tables don't depend on the renormalization scale + //ren: -1.0, + ren: info.fac0, + fac: info.fac0, + }], + info.x0.clone(), + info.x0.clone(), + ) + .into() + })); + } + + let pid = if has_pdf1 { + self.initial_state_2() + } else { + self.initial_state_1() + }; + + let mut grid = Self { + subgrids: Array1::from_iter(sub_fk_tables.into_iter()) + .into_shape((1, self.bin_info().bins(), lumi0.len())) + .unwrap(), + lumi: lumi0 + .iter() + .map(|&a| { + lumi_entry![ + if has_pdf1 { a } else { pid }, + if !has_pdf1 { a } else { pid }, + 1.0 + ] + }) + .collect(), + bin_limits: self.bin_limits.clone(), + orders: vec![Order::new(0, 0, 0, 0)], + subgrid_params: SubgridParams::default(), + more_members: self.more_members.clone(), + }; + + // write additional metadata + grid.set_key_value("lumi_id_types", &info.lumi_id_types); + + Ok(FkTable::try_from(grid).unwrap()) } fn evolve_with_two( @@ -2641,14 +2758,19 @@ mod tests { let setname = "NNPDF40_nlo_as_01180"; - let grid = - "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003.pineappl.lz4"; - let metadata = - "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/metadata.yaml"; - let alphas = - "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/alphas.npy"; - let operator = - "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/operators.npy"; + let grid = "../HERA_CC_318GEV_EP_SIGMARED.pineappl.lz4"; + let metadata = "../HERA_CC_318GEV_EP_SIGMARED/metadata.yaml"; + let alphas = "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy"; + let operator = "../HERA_CC_318GEV_EP_SIGMARED/operators.npy"; + + //let grid = + // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003.pineappl.lz4"; + //let metadata = + // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/metadata.yaml"; + //let alphas = + // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/alphas.npy"; + //let operator = + // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/operators.npy"; //let grid = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34.pineappl.lz4"; //let metadata = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/metadata.yaml"; @@ -2671,25 +2793,70 @@ mod tests { assert_eq!( results, [ - 1469.0819829706113, - 4364.509970805006, - 2072.647269805865, - 742.6160478667135, - 312.195449854513, - 145.782031788469, - 72.64484245290579, - 38.88392569051013, - 17.093513927247354, - 6.157887576517187, - 2.4621639421455903, - 1.0817834362838417, - 0.5084171526510098, - 0.2520459057372801, - 0.10211930488819178, - 0.021141855492915994 + 1.158872296528366, + 1.1204108571716151, + 0.8875902564141837, + 0.6064124901549366, + 0.46730446763293626, + 0.9175036665313503, + 0.9625683080629993, + 0.832097616454224, + 0.5840101875241862, + 0.45055068848064506, + 0.6688041946734723, + 0.6889352106823404, + 0.5297495101909169, + 0.41609405897210827, + 0.23143317308882982, + 0.5649694171604525, + 0.4792399077439775, + 0.3861828122239765, + 0.21793994357039714, + 0.08432403516120096, + 0.467724373428524, + 0.43253481860290705, + 0.3588386557913573, + 0.20658438492949507, + 0.36145545861402606, + 0.350280931434649, + 0.3095655884296923, + 0.18715074960942407, + 0.0737622486172105, + 0.2292088799939892, + 0.2277411334118036, + 0.15507169325765838, + 0.06400693681274111, + 0.1403126590329724, + 0.11639162212711233, + 0.052756148828243, + 0.05464232942385792, + 0.033578480958376296, + 0.01095350422009362 ] ); + //assert_eq!( + // results, + // [ + // 1469.0819829706113, + // 4364.509970805006, + // 2072.647269805865, + // 742.6160478667135, + // 312.195449854513, + // 145.782031788469, + // 72.64484245290579, + // 38.88392569051013, + // 17.093513927247354, + // 6.157887576517187, + // 2.4621639421455903, + // 1.0817834362838417, + // 0.5084171526510098, + // 0.2520459057372801, + // 0.10211930488819178, + // 0.021141855492915994 + // ] + //); + //assert_eq!( // results, // [ @@ -2760,25 +2927,70 @@ mod tests { assert_eq!( evolved_results, [ - 1467.6009449768221, - 4359.87917180896, - 2070.4278159799974, - 741.9298754488171, - 311.9073865166957, - 145.65671641953438, - 72.58340237308579, - 38.85208071336316, - 17.080194246318936, - 6.153298093496777, - 2.4604627649049604, - 1.0810950528772425, - 0.5081137620517796, - 0.25190465608989626, - 0.10206534388970377, - 0.02113211970400249 + 1.8170022921477553, + 1.572186789222731, + 1.0120743119644493, + 0.5513681196303996, + 0.369732897935647, + 1.4463393022497653, + 1.3434521752529411, + 0.9396007527971952, + 0.5265636855582448, + 0.35392024601127764, + 0.9476126904820632, + 0.7724575723596495, + 0.4732213954723062, + 0.3241042357593822, + 0.14208837561282434, + 0.6348291801851951, + 0.42639863308407194, + 0.2995555092631841, + 0.1332978572669808, + 0.040242587222404244, + 0.5291482249999523, + 0.3841371951752628, + 0.2776461765631634, + 0.12604952037651973, + 0.4158009739671785, + 0.31101583663344756, + 0.23888711855765635, + 0.11386513733409395, + 0.035056166504958824, + 0.2051492116806069, + 0.175643994922963, + 0.09413231582370057, + 0.030381614976052386, + 0.1089423164124738, + 0.07069503513298457, + 0.025079212588928746, + 0.03372105113135905, + 0.01616849864998008, + 0.005770141756592387 ] ); + //assert_eq!( + // evolved_results, + // [ + // 1467.6009449768221, + // 4359.87917180896, + // 2070.4278159799974, + // 741.9298754488171, + // 311.9073865166957, + // 145.65671641953438, + // 72.58340237308579, + // 38.85208071336316, + // 17.080194246318936, + // 6.153298093496777, + // 2.4604627649049604, + // 1.0810950528772425, + // 0.5081137620517796, + // 0.25190465608989626, + // 0.10206534388970377, + // 0.02113211970400249 + // ] + //); + //assert_approx_eq!(f64, evolved_results[0], 134500.65897999398, ulps = 8); //assert_approx_eq!(f64, evolved_results[1], 133344.24845948347, ulps = 8); //assert_approx_eq!(f64, evolved_results[2], 130663.70226447149, ulps = 32); From e7d162e974b955728d5dc1e22f24f93274186e5f Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 13 Oct 2022 14:51:29 +0200 Subject: [PATCH 33/73] Fix wrong x-grid values --- pineappl/src/grid.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 438e74e6..003d4eac 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1866,8 +1866,12 @@ impl Grid { ren: info.fac0, fac: info.fac0, }], - info.x0.clone(), - info.x0.clone(), + if has_pdf1 { info.x0.clone() } else { vec![1.0] }, + if !has_pdf1 { + info.x0.clone() + } else { + vec![1.0] + }, ) .into() })); From 6df9bf199c955e0d10a59425d4c4382655e3b9fd Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 13 Oct 2022 15:35:37 +0200 Subject: [PATCH 34/73] Fix serious bug in `Lumi::setup` This bug leads to wrong results in `Grid::convolute` if the same `lumi_cache` is used to convolute two grids with different subgrid muf2/mur2/x1/x2 points --- pineappl/src/lumi.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pineappl/src/lumi.rs b/pineappl/src/lumi.rs index 0c82a986..e3594b4a 100644 --- a/pineappl/src/lumi.rs +++ b/pineappl/src/lumi.rs @@ -164,6 +164,22 @@ enum Pdfs<'a> { }, } +impl<'a> Pdfs<'a> { + pub fn clear(&mut self) { + match self { + Self::One { xfx_cache, .. } => xfx_cache.clear(), + Self::Two { + xfx1_cache, + xfx2_cache, + .. + } => { + xfx1_cache.clear(); + xfx2_cache.clear(); + } + } + } +} + /// A cache for evaluating PDFs. Methods like [`Grid::convolute`] accept instances of this `struct` /// instead of the PDFs themselves. pub struct LumiCache<'a> { @@ -424,6 +440,8 @@ impl<'a> LumiCache<'a> { /// Clears the cache. pub fn clear(&mut self) { + self.alphas_cache.clear(); + self.pdfs.clear(); self.mur2_grid.clear(); self.muf2_grid.clear(); self.x_grid.clear(); From a06554db64c87da4f4c56174745e8a2d1c6be4d7 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 13 Oct 2022 15:38:42 +0200 Subject: [PATCH 35/73] Fix unit test --- pineappl/src/grid.rs | 86 ++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 003d4eac..57e05cbd 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2924,52 +2924,54 @@ mod tests { //let fk_table = grid.convolute_eko(operator, eko_info, &[]).unwrap(); let fk_table = grid.evolve(&operator, &info, &[]).unwrap(); - let evolved_results = fk_table - .grid() - .convolute(&mut cache, &[], &[], &[], &[(1.0, 1.0)]); + fk_table + .write(File::create("../fk_table.pineappl.lz4").unwrap()) + .unwrap(); + + let evolved_results = fk_table.convolute(&mut cache, &[], &[]); assert_eq!( evolved_results, [ - 1.8170022921477553, - 1.572186789222731, - 1.0120743119644493, - 0.5513681196303996, - 0.369732897935647, - 1.4463393022497653, - 1.3434521752529411, - 0.9396007527971952, - 0.5265636855582448, - 0.35392024601127764, - 0.9476126904820632, - 0.7724575723596495, - 0.4732213954723062, - 0.3241042357593822, - 0.14208837561282434, - 0.6348291801851951, - 0.42639863308407194, - 0.2995555092631841, - 0.1332978572669808, - 0.040242587222404244, - 0.5291482249999523, - 0.3841371951752628, - 0.2776461765631634, - 0.12604952037651973, - 0.4158009739671785, - 0.31101583663344756, - 0.23888711855765635, - 0.11386513733409395, - 0.035056166504958824, - 0.2051492116806069, - 0.175643994922963, - 0.09413231582370057, - 0.030381614976052386, - 0.1089423164124738, - 0.07069503513298457, - 0.025079212588928746, - 0.03372105113135905, - 0.01616849864998008, - 0.005770141756592387 + 1.1586791793006517, + 1.1202273184348848, + 0.8874599897872428, + 0.6063712625073608, + 0.4672874245885059, + 0.9173403727229149, + 0.962399631849818, + 0.8319677648956049, + 0.5839675146069822, + 0.4505325132086283, + 0.6686768094263615, + 0.6888210100292264, + 0.5297074425880604, + 0.41607535867486134, + 0.23142390114495495, + 0.5648727887895276, + 0.47919973616456246, + 0.38616444708721975, + 0.21793107752932925, + 0.08431941687497238, + 0.46764290121503427, + 0.43249701889959064, + 0.35882091245690373, + 0.20657579928724892, + 0.36139047088472026, + 0.35024730127068276, + 0.3095490328079981, + 0.1871428094003754, + 0.07375775279995289, + 0.22918160031673335, + 0.22772688522902013, + 0.15506498963894486, + 0.0640029182481115, + 0.14030150245012324, + 0.11638652740576161, + 0.052752620249130584, + 0.05463985560251649, + 0.03357575618674528, + 0.010951799924697785 ] ); From c63aa4c033e9cb51f5f34653a4cc4b33f76999a6 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 13 Oct 2022 15:49:44 +0200 Subject: [PATCH 36/73] Update changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93277ef2..0feb16fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- added new method `Grid::evolve`, which will succeed `Grid::convolute_eko` and + is more robust, faster and easier to understand + +### Fixed + +- fixed a bug in `LumiCache::setup`, which caused wrong results returned by + `Grid::convolute`, if `lumi_cache` is reused for a second grid with different + Q2/x1/x2 parameters + ## [0.5.7] - 05/10/2022 ### Fixed From a15d4b49842773d67f82b413f0a8a429a5c53b0a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 13 Oct 2022 23:12:48 +0200 Subject: [PATCH 37/73] Fix bug introduced in commit f0e1701 --- pineappl/src/grid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 57e05cbd..d637651b 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1409,7 +1409,7 @@ impl Grid { // are the initial states hadrons? let has_pdf1 = self.has_pdf1(); - let has_pdf2 = self.has_pdf1(); + let has_pdf2 = self.has_pdf2(); let pids1 = if has_pdf1 { eko_info.grid_axes.pids.clone() From 2eef5ced5b385c520c67c7ed68939949ac6aa160 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 13 Oct 2022 23:20:11 +0200 Subject: [PATCH 38/73] Relax numerical assertions --- pineappl/src/grid.rs | 85 +++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index d637651b..a08b7556 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2735,8 +2735,8 @@ mod tests { #[test] #[ignore] fn evolve() { - //use float_cmp::assert_approx_eq; use evolution::OperatorInfo; + use float_cmp::assert_approx_eq; use lhapdf::Pdf; use ndarray::{Array1, Array5}; use std::fs::File; @@ -2930,50 +2930,45 @@ mod tests { let evolved_results = fk_table.convolute(&mut cache, &[], &[]); - assert_eq!( - evolved_results, - [ - 1.1586791793006517, - 1.1202273184348848, - 0.8874599897872428, - 0.6063712625073608, - 0.4672874245885059, - 0.9173403727229149, - 0.962399631849818, - 0.8319677648956049, - 0.5839675146069822, - 0.4505325132086283, - 0.6686768094263615, - 0.6888210100292264, - 0.5297074425880604, - 0.41607535867486134, - 0.23142390114495495, - 0.5648727887895276, - 0.47919973616456246, - 0.38616444708721975, - 0.21793107752932925, - 0.08431941687497238, - 0.46764290121503427, - 0.43249701889959064, - 0.35882091245690373, - 0.20657579928724892, - 0.36139047088472026, - 0.35024730127068276, - 0.3095490328079981, - 0.1871428094003754, - 0.07375775279995289, - 0.22918160031673335, - 0.22772688522902013, - 0.15506498963894486, - 0.0640029182481115, - 0.14030150245012324, - 0.11638652740576161, - 0.052752620249130584, - 0.05463985560251649, - 0.03357575618674528, - 0.010951799924697785 - ] - ); + assert_approx_eq!(f64, evolved_results[0], 1.1586791793006517, ulps = 8); + assert_approx_eq!(f64, evolved_results[1], 1.1202273184348848, ulps = 8); + assert_approx_eq!(f64, evolved_results[2], 0.8874599897872428, ulps = 8); + assert_approx_eq!(f64, evolved_results[3], 0.6063712625073608, ulps = 8); + assert_approx_eq!(f64, evolved_results[4], 0.4672874245885059, ulps = 8); + assert_approx_eq!(f64, evolved_results[5], 0.9173403727229149, ulps = 8); + assert_approx_eq!(f64, evolved_results[6], 0.962399631849818, ulps = 8); + assert_approx_eq!(f64, evolved_results[7], 0.8319677648956049, ulps = 8); + assert_approx_eq!(f64, evolved_results[8], 0.5839675146069822, ulps = 8); + assert_approx_eq!(f64, evolved_results[9], 0.4505325132086283, ulps = 8); + assert_approx_eq!(f64, evolved_results[10], 0.6686768094263615, ulps = 8); + assert_approx_eq!(f64, evolved_results[11], 0.6888210100292264, ulps = 8); + assert_approx_eq!(f64, evolved_results[12], 0.5297074425880604, ulps = 8); + assert_approx_eq!(f64, evolved_results[13], 0.41607535867486134, ulps = 8); + assert_approx_eq!(f64, evolved_results[14], 0.23142390114495495, ulps = 8); + assert_approx_eq!(f64, evolved_results[15], 0.5648727887895276, ulps = 8); + assert_approx_eq!(f64, evolved_results[16], 0.47919973616456246, ulps = 8); + assert_approx_eq!(f64, evolved_results[17], 0.38616444708721975, ulps = 8); + assert_approx_eq!(f64, evolved_results[18], 0.21793107752932925, ulps = 8); + assert_approx_eq!(f64, evolved_results[19], 0.08431941687497238, ulps = 8); + assert_approx_eq!(f64, evolved_results[20], 0.46764290121503427, ulps = 8); + assert_approx_eq!(f64, evolved_results[21], 0.43249701889959064, ulps = 8); + assert_approx_eq!(f64, evolved_results[22], 0.35882091245690373, ulps = 8); + assert_approx_eq!(f64, evolved_results[23], 0.20657579928724892, ulps = 8); + assert_approx_eq!(f64, evolved_results[24], 0.36139047088472026, ulps = 8); + assert_approx_eq!(f64, evolved_results[25], 0.35024730127068276, ulps = 8); + assert_approx_eq!(f64, evolved_results[26], 0.3095490328079981, ulps = 8); + assert_approx_eq!(f64, evolved_results[27], 0.1871428094003754, ulps = 8); + assert_approx_eq!(f64, evolved_results[28], 0.07375775279995289, ulps = 8); + assert_approx_eq!(f64, evolved_results[29], 0.22918160031673335, ulps = 8); + assert_approx_eq!(f64, evolved_results[30], 0.22772688522902013, ulps = 8); + assert_approx_eq!(f64, evolved_results[31], 0.15506498963894486, ulps = 8); + assert_approx_eq!(f64, evolved_results[32], 0.0640029182481115, ulps = 8); + assert_approx_eq!(f64, evolved_results[33], 0.14030150245012324, ulps = 8); + assert_approx_eq!(f64, evolved_results[34], 0.11638652740576161, ulps = 8); + assert_approx_eq!(f64, evolved_results[35], 0.052752620249130584, ulps = 8); + assert_approx_eq!(f64, evolved_results[36], 0.05463985560251649, ulps = 8); + assert_approx_eq!(f64, evolved_results[37], 0.03357575618674528, ulps = 8); + assert_approx_eq!(f64, evolved_results[38], 0.010951799924697785, ulps = 8); //assert_eq!( // evolved_results, From efee28ffc22c34db62815628c3daf2d555f992c4 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Oct 2022 09:59:47 +0200 Subject: [PATCH 39/73] Cache operators in `Grid::evolve_with_one` --- pineappl/src/grid.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index a08b7556..b21f043f 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1798,6 +1798,9 @@ impl Grid { let mut sub_fk_tables = Vec::with_capacity(self.bin_info().bins() * lumi0.len()); let new_axis = if has_pdf1 { 2 } else { 1 }; + let mut last_x1 = Vec::new(); + let mut operators = Vec::new(); + for subgrids_ol in self.subgrids.axis_iter(Axis(1)) { let mut tables = vec![Array1::zeros(info.x0.len()); lumi0.len()]; @@ -1810,7 +1813,16 @@ impl Grid { )?; let x1 = if has_pdf1 { x1_a } else { x1_b }; - let operators = evolution::operators(operator, info, &pid_indices, &x1)?; + + if (last_x1.len() != x1.len()) + || last_x1 + .iter() + .zip(x1.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = 64)) + { + operators = evolution::operators(operator, info, &pid_indices, &x1)?; + last_x1 = x1; + } for (&pid1, &factor) in self.lumi[lumi1].entry().iter().map( From 8d5fdca8c66b5c2afeb24a09141d17752c78041e Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Oct 2022 11:12:43 +0200 Subject: [PATCH 40/73] Move `evolve_with_{one,two}` to module `evolution` --- pineappl/src/evolution.rs | 228 +++++++++++++++++++++++++++++++- pineappl/src/grid.rs | 267 +++----------------------------------- 2 files changed, 245 insertions(+), 250 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 925ecdb7..9909dcb1 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -1,10 +1,14 @@ //! Supporting classes and functions for [`Grid::evolve`]. -use super::grid::{GridError, Order}; +use super::grid::{Grid, GridError, Order}; +use super::import_only_subgrid::ImportOnlySubgridV2; +use super::lumi::LumiEntry; +use super::lumi_entry; +use super::sparse_array3::SparseArray3; use super::subgrid::{Mu2, Subgrid, SubgridEnum}; use float_cmp::approx_eq; use itertools::Itertools; -use ndarray::{s, Array3, Array5, ArrayView1, Axis}; +use ndarray::{s, Array1, Array2, Array3, Array5, ArrayView1, Axis}; use std::iter; /// Information about the evolution kernel operator (EKO) passed to [`Grid::evolve`] as `operator`, @@ -241,3 +245,223 @@ pub(crate) fn ndarray_from_subgrid_orders( Ok((x1_a, x1_b, array)) } + +pub(crate) fn evolve_with_one( + grid: &Grid, + operator: &Array5, + info: &OperatorInfo, + order_mask: &[bool], +) -> Result<(Array3, Vec), GridError> { + let has_pdf1 = grid.has_pdf1(); + + let (pid_indices, pids) = pids(operator, info, &|pid| { + grid.lumi() + .iter() + .flat_map(LumiEntry::entry) + .any(|&(a, b, _)| if has_pdf1 { a } else { b } == pid) + }); + + let lumi0 = lumi0_with_one(&pids); + let mut sub_fk_tables = Vec::with_capacity(grid.bin_info().bins() * lumi0.len()); + let new_axis = if has_pdf1 { 2 } else { 1 }; + + let mut last_x1 = Vec::new(); + let mut ops = Vec::new(); + + for subgrids_ol in grid.subgrids().axis_iter(Axis(1)) { + let mut tables = vec![Array1::zeros(info.x0.len()); lumi0.len()]; + + for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { + let (x1_a, x1_b, array) = + ndarray_from_subgrid_orders(info, &subgrids_o, &grid.orders(), order_mask)?; + + let x1 = if has_pdf1 { x1_a } else { x1_b }; + + if (last_x1.len() != x1.len()) + || last_x1 + .iter() + .zip(x1.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = 64)) + { + ops = operators(operator, info, &pid_indices, &x1)?; + last_x1 = x1; + } + + // TODO: get rid of array-index access + for (&pid1, &factor) in + grid.lumi()[lumi1].entry().iter().map( + |(a, b, f)| { + if has_pdf1 { + (a, f) + } else { + (b, f) + } + }, + ) + { + for (fk_table, op) in + lumi0 + .iter() + .zip(tables.iter_mut()) + .filter_map(|(&pid0, fk_table)| { + pids.iter() + .zip(ops.iter()) + .find_map(|(&(p0, p1), op)| (p0 == pid0 && p1 == pid1).then(|| op)) + .map(|op| (fk_table, op)) + }) + { + let mut result = Array1::zeros(info.x0.len()); + + for imu2 in 0..array.dim().0 { + let op = op.index_axis(Axis(0), imu2); + + result += &op.dot( + &array + .index_axis(Axis(0), imu2) + .index_axis(Axis(new_axis - 1), 0), + ); + } + + fk_table.scaled_add(factor, &result); + } + } + } + + sub_fk_tables.extend(tables.into_iter().map(|table| { + ImportOnlySubgridV2::new( + SparseArray3::from_ndarray( + &table.insert_axis(Axis(0)).insert_axis(Axis(new_axis)), + 0, + 1, + ), + vec![Mu2 { + // TODO: FK tables don't depend on the renormalization scale + //ren: -1.0, + ren: info.fac0, + fac: info.fac0, + }], + if has_pdf1 { info.x0.clone() } else { vec![1.0] }, + if !has_pdf1 { + info.x0.clone() + } else { + vec![1.0] + }, + ) + .into() + })); + } + + let pid = if has_pdf1 { + grid.initial_state_2() + } else { + grid.initial_state_1() + }; + + Ok(( + Array1::from_iter(sub_fk_tables.into_iter()) + .into_shape((1, grid.bin_info().bins(), lumi0.len())) + .unwrap(), + lumi0 + .iter() + .map(|&a| { + lumi_entry![ + if has_pdf1 { a } else { pid }, + if !has_pdf1 { a } else { pid }, + 1.0 + ] + }) + .collect(), + )) +} + +pub(crate) fn evolve_with_two( + grid: &Grid, + operator: &Array5, + info: &OperatorInfo, + order_mask: &[bool], +) -> Result<(Array3, Vec), GridError> { + let (pid_indices_a, pids_a) = pids(operator, info, &|pid1| { + grid.lumi() + .iter() + .flat_map(LumiEntry::entry) + .any(|&(a, _, _)| a == pid1) + }); + let (pid_indices_b, pids_b) = pids(operator, info, &|pid1| { + grid.lumi() + .iter() + .flat_map(LumiEntry::entry) + .any(|&(_, b, _)| b == pid1) + }); + + let lumi0 = lumi0_with_two(&pids_a, &pids_b); + + let mut sub_fk_tables = Vec::with_capacity(grid.bin_info().bins() * lumi0.len()); + + for subgrids_ol in grid.subgrids().axis_iter(Axis(1)) { + let mut tables = vec![Array2::zeros((info.x0.len(), info.x0.len())); lumi0.len()]; + + for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { + let (x1_a, x1_b, array) = + ndarray_from_subgrid_orders(info, &subgrids_o, &grid.orders(), order_mask)?; + + // TODO: optimization potential: if `x1_a` and `x1_b` are the same cache them, if + // they are the same over bins and/or orders cache them too + let operators_a = operators(operator, info, &pid_indices_a, &x1_a)?; + let operators_b = operators(operator, info, &pid_indices_b, &x1_b)?; + + // TODO: get rid of array-index access + for &(pida1, pidb1, factor) in grid.lumi()[lumi1].entry() { + for (fk_table, opa, opb) in + lumi0 + .iter() + .zip(tables.iter_mut()) + .filter_map(|(&(pida0, pidb0), fk_table)| { + pids_a + .iter() + .zip(operators_a.iter()) + .cartesian_product(pids_b.iter().zip(operators_b.iter())) + .find_map(|((&(pa0, pa1), opa), (&(pb0, pb1), opb))| { + (pa0 == pida0 && pa1 == pida1 && pb0 == pidb0 && pb1 == pidb1) + .then(|| (opa, opb)) + }) + .map(|(opa, opb)| (fk_table, opa, opb)) + }) + { + let mut result = Array2::zeros((info.x0.len(), info.x0.len())); + + for imu2 in 0..array.dim().0 { + let opa = opa.index_axis(Axis(0), imu2); + let opb = opb.index_axis(Axis(0), imu2); + let arr = array.index_axis(Axis(0), imu2); + + result += &opa.dot(&arr.dot(&opb.t())); + } + + fk_table.scaled_add(factor, &result); + } + } + } + + sub_fk_tables.extend(tables.into_iter().map(|table| { + ImportOnlySubgridV2::new( + SparseArray3::from_ndarray(&table.insert_axis(Axis(0)), 0, 1), + vec![Mu2 { + // TODO: FK tables don't depend on the renormalization scale + //ren: -1.0, + ren: info.fac0, + fac: info.fac0, + }], + info.x0.clone(), + info.x0.clone(), + ) + .into() + })); + } + + Ok(( + Array1::from_iter(sub_fk_tables.into_iter()) + .into_shape((1, grid.bin_info().bins(), lumi0.len())) + .unwrap(), + lumi0.iter().map(|&(a, b)| lumi_entry![a, b, 1.0]).collect(), + )) +} diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index b21f043f..d9ff2dd8 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -17,7 +17,7 @@ use git_version::git_version; use indicatif::{ProgressBar, ProgressStyle}; use itertools::Itertools; use lz4_flex::frame::{FrameDecoder, FrameEncoder}; -use ndarray::{s, Array1, Array2, Array3, Array5, Axis, Dimension}; +use ndarray::{s, Array3, Array5, Axis, Dimension}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::cmp::Ordering; @@ -1779,249 +1779,6 @@ impl Grid { FkTable::try_from(result).ok() } - fn evolve_with_one( - &self, - operator: &Array5, - info: &OperatorInfo, - order_mask: &[bool], - ) -> Result { - let has_pdf1 = self.has_pdf1(); - - let (pid_indices, pids) = evolution::pids(operator, info, &|pid| { - self.lumi - .iter() - .flat_map(LumiEntry::entry) - .any(|&(a, b, _)| if has_pdf1 { a } else { b } == pid) - }); - - let lumi0 = evolution::lumi0_with_one(&pids); - let mut sub_fk_tables = Vec::with_capacity(self.bin_info().bins() * lumi0.len()); - let new_axis = if has_pdf1 { 2 } else { 1 }; - - let mut last_x1 = Vec::new(); - let mut operators = Vec::new(); - - for subgrids_ol in self.subgrids.axis_iter(Axis(1)) { - let mut tables = vec![Array1::zeros(info.x0.len()); lumi0.len()]; - - for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { - let (x1_a, x1_b, array) = evolution::ndarray_from_subgrid_orders( - info, - &subgrids_o, - &self.orders, - order_mask, - )?; - - let x1 = if has_pdf1 { x1_a } else { x1_b }; - - if (last_x1.len() != x1.len()) - || last_x1 - .iter() - .zip(x1.iter()) - .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = 64)) - { - operators = evolution::operators(operator, info, &pid_indices, &x1)?; - last_x1 = x1; - } - - for (&pid1, &factor) in - self.lumi[lumi1].entry().iter().map( - |(a, b, f)| { - if has_pdf1 { - (a, f) - } else { - (b, f) - } - }, - ) - { - for (fk_table, op) in - lumi0 - .iter() - .zip(tables.iter_mut()) - .filter_map(|(&pid0, fk_table)| { - pids.iter() - .zip(operators.iter()) - .find_map(|(&(p0, p1), op)| { - (p0 == pid0 && p1 == pid1).then(|| op) - }) - .map(|op| (fk_table, op)) - }) - { - let mut result = Array1::zeros(info.x0.len()); - - for imu2 in 0..array.dim().0 { - let op = op.index_axis(Axis(0), imu2); - - result += &op.dot( - &array - .index_axis(Axis(0), imu2) - .index_axis(Axis(new_axis - 1), 0), - ); - } - - fk_table.scaled_add(factor, &result); - } - } - } - - sub_fk_tables.extend(tables.into_iter().map(|table| { - ImportOnlySubgridV2::new( - SparseArray3::from_ndarray( - &table.insert_axis(Axis(0)).insert_axis(Axis(new_axis)), - 0, - 1, - ), - vec![Mu2 { - // TODO: FK tables don't depend on the renormalization scale - //ren: -1.0, - ren: info.fac0, - fac: info.fac0, - }], - if has_pdf1 { info.x0.clone() } else { vec![1.0] }, - if !has_pdf1 { - info.x0.clone() - } else { - vec![1.0] - }, - ) - .into() - })); - } - - let pid = if has_pdf1 { - self.initial_state_2() - } else { - self.initial_state_1() - }; - - let mut grid = Self { - subgrids: Array1::from_iter(sub_fk_tables.into_iter()) - .into_shape((1, self.bin_info().bins(), lumi0.len())) - .unwrap(), - lumi: lumi0 - .iter() - .map(|&a| { - lumi_entry![ - if has_pdf1 { a } else { pid }, - if !has_pdf1 { a } else { pid }, - 1.0 - ] - }) - .collect(), - bin_limits: self.bin_limits.clone(), - orders: vec![Order::new(0, 0, 0, 0)], - subgrid_params: SubgridParams::default(), - more_members: self.more_members.clone(), - }; - - // write additional metadata - grid.set_key_value("lumi_id_types", &info.lumi_id_types); - - Ok(FkTable::try_from(grid).unwrap()) - } - - fn evolve_with_two( - &self, - operator: &Array5, - info: &OperatorInfo, - order_mask: &[bool], - ) -> Result { - let (pid_indices_a, pids_a) = evolution::pids(operator, info, &|pid1| { - self.lumi - .iter() - .flat_map(LumiEntry::entry) - .any(|&(a, _, _)| a == pid1) - }); - let (pid_indices_b, pids_b) = evolution::pids(operator, info, &|pid1| { - self.lumi - .iter() - .flat_map(LumiEntry::entry) - .any(|&(_, b, _)| b == pid1) - }); - - let lumi0 = evolution::lumi0_with_two(&pids_a, &pids_b); - - let mut sub_fk_tables = Vec::with_capacity(self.bin_info().bins() * lumi0.len()); - - for subgrids_ol in self.subgrids.axis_iter(Axis(1)) { - let mut tables = vec![Array2::zeros((info.x0.len(), info.x0.len())); lumi0.len()]; - - for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { - let (x1_a, x1_b, array) = evolution::ndarray_from_subgrid_orders( - info, - &subgrids_o, - &self.orders, - order_mask, - )?; - - // TODO: optimization potential: if `x1_a` and `x1_b` are the same cache them, if - // they are the same over bins and/or orders cache them too - let operators_a = evolution::operators(operator, info, &pid_indices_a, &x1_a)?; - let operators_b = evolution::operators(operator, info, &pid_indices_b, &x1_b)?; - - for &(pida1, pidb1, factor) in self.lumi[lumi1].entry() { - for (fk_table, opa, opb) in lumi0.iter().zip(tables.iter_mut()).filter_map( - |(&(pida0, pidb0), fk_table)| { - pids_a - .iter() - .zip(operators_a.iter()) - .cartesian_product(pids_b.iter().zip(operators_b.iter())) - .find_map(|((&(pa0, pa1), opa), (&(pb0, pb1), opb))| { - (pa0 == pida0 && pa1 == pida1 && pb0 == pidb0 && pb1 == pidb1) - .then(|| (opa, opb)) - }) - .map(|(opa, opb)| (fk_table, opa, opb)) - }, - ) { - let mut result = Array2::zeros((info.x0.len(), info.x0.len())); - - for imu2 in 0..array.dim().0 { - let opa = opa.index_axis(Axis(0), imu2); - let opb = opb.index_axis(Axis(0), imu2); - let arr = array.index_axis(Axis(0), imu2); - - result += &opa.dot(&arr.dot(&opb.t())); - } - - fk_table.scaled_add(factor, &result); - } - } - } - - sub_fk_tables.extend(tables.into_iter().map(|table| { - ImportOnlySubgridV2::new( - SparseArray3::from_ndarray(&table.insert_axis(Axis(0)), 0, 1), - vec![Mu2 { - // TODO: FK tables don't depend on the renormalization scale - //ren: -1.0, - ren: info.fac0, - fac: info.fac0, - }], - info.x0.clone(), - info.x0.clone(), - ) - .into() - })); - } - - let mut grid = Self { - subgrids: Array1::from_iter(sub_fk_tables.into_iter()) - .into_shape((1, self.bin_info().bins(), lumi0.len())) - .unwrap(), - lumi: lumi0.iter().map(|&(a, b)| lumi_entry![a, b, 1.0]).collect(), - bin_limits: self.bin_limits.clone(), - orders: vec![Order::new(0, 0, 0, 0)], - subgrid_params: SubgridParams::default(), - more_members: self.more_members.clone(), - }; - - // write additional metadata - grid.set_key_value("lumi_id_types", &info.lumi_id_types); - - Ok(FkTable::try_from(grid).unwrap()) - } - /// Converts this `Grid` into an [`FkTable`] using an evolution kernel operator (EKO) given as /// `operator`. The dimensions and properties of this operator must be described using `info`. /// The parameter `order_mask` can be used to include or exclude orders from this operation, @@ -2054,11 +1811,25 @@ impl Grid { ))); } - if self.has_pdf1() && self.has_pdf2() { - self.evolve_with_two(operator, info, order_mask) + let (subgrids, lumi) = if self.has_pdf1() && self.has_pdf2() { + evolution::evolve_with_two(self, operator, info, order_mask) } else { - self.evolve_with_one(operator, info, order_mask) - } + evolution::evolve_with_one(self, operator, info, order_mask) + }?; + + let mut grid = Self { + subgrids, + lumi, + bin_limits: self.bin_limits.clone(), + orders: vec![Order::new(0, 0, 0, 0)], + subgrid_params: SubgridParams::default(), + more_members: self.more_members.clone(), + }; + + // write additional metadata + grid.set_key_value("lumi_id_types", &info.lumi_id_types); + + Ok(FkTable::try_from(grid).unwrap()) } /// Deletes bins with the corresponding `bin_indices`. Repeated indices and indices larger or From fec9c0c16fb409a70c50cfb5417747e151fe8143 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Oct 2022 11:48:55 +0200 Subject: [PATCH 41/73] Change the order of members of `OperatorInfo` --- pineappl/src/evolution.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 9909dcb1..9e32cf7f 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -27,20 +27,20 @@ use std::iter; /// scales. Finally, [`xir`] and [`xif`] can be used to vary the renormalization and factorization /// scales, respectively, around their central values. pub struct OperatorInfo { - /// Squared factorization scales of the `Grid`. - pub fac1: Vec, + /// Squared factorization scale of the `FkTable`. + pub fac0: f64, /// Particle identifiers of the `FkTable`. pub pids0: Vec, /// `x`-grid coordinates of the `FkTable` pub x0: Vec, + /// Squared factorization scales of the `Grid`. + pub fac1: Vec, /// Particle identifiers of the `Grid`. If the `Grid` contains more particle identifiers than /// given here, the contributions of them are silently ignored. pub pids1: Vec, /// `x`-grid coordinates of the `Grid`. pub x1: Vec, - /// Squared factorization scale of the `FkTable`. - pub fac0: f64, /// Renormalization scales of the `Grid`. pub ren1: Vec, /// Strong couplings corresponding to the order given in [`ren1`]. From c7143c0a55ccb9602508a8a05906e0bc41d002ec Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Fri, 14 Oct 2022 13:06:53 +0200 Subject: [PATCH 42/73] Add Python bindings to evolve --- pineappl_py/pineappl/grid.py | 53 ++++++++++++++++++++++++++ pineappl_py/src/grid.rs | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/pineappl_py/pineappl/grid.py b/pineappl_py/pineappl/grid.py index 767a54a7..80478e59 100644 --- a/pineappl_py/pineappl/grid.py +++ b/pineappl_py/pineappl/grid.py @@ -298,6 +298,59 @@ def convolute_eko(self, operators, mur2_grid, alphas_values, lumi_id_types="pdg_ ) ) + def evolve(self, operators, mur2_grid, alphas_values, lumi_id_types="pdg_mc_ids", order_mask=(), xi=(1.0, 1.0)): + """ + Create an FKTable with the EKO. + + Convenience wrapper for :meth:`pineappl.pineappl.PyGrid.evolve()`. + + Parameters + ---------- + operators : dict + EKO Output + mur2_grid : list[float] + renormalization scales + alphas_values : list[float] + alpha_s values associated to the renormalization scales + lumi_id_types : str + kind of lumi types (e.g. "pdg_mc_ids" for flavor basis, "evol" + for evolution basis) + order_mask : list(bool) + Mask for selecting specific orders. The value `True` means the corresponding order + is included. An empty list corresponds to all orders being enabled. + xi : (float, float) + A tuple with the scale variation factors that should be used. + The first entry of a tuple corresponds to the variation of + the renormalization scale, the second entry to the variation of the factorization + scale. If only results for the central scale are need the tuple should be + `(1.0, 1.0)`. + + Returns + ------ + PyFkTable : + raw grid as an FKTable + """ + operator_grid = np.array( + [op["operators"] for op in operators["Q2grid"].values()] + ) + q2grid = list(operators["Q2grid"].keys()) + return FkTable( + self.raw.evolve( + np.array(operator_grid), + operators["q2_ref"], + np.array(operators["inputpids"], dtype=np.int32), + np.array(operators["inputgrid"]), + np.array(q2grid, dtype=np.float64), + np.array(operators["targetpids"], dtype=np.int32), + np.array(operators["targetgrid"]), + np.array(mur2_grid, dtype=np.float64), + np.array(alphas_values, dtype=np.float64), + xi, + lumi_id_types, + np.array(order_mask, dtype=bool), + ) + ) + @classmethod def read(cls, path): """ diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index c3846c77..db56a4a3 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -1,3 +1,4 @@ +use pineappl::evolution::OperatorInfo; use pineappl::grid::{EkoInfo, Grid, GridAxes, Ntuple, Order}; use pineappl::lumi::LumiCache; @@ -458,6 +459,77 @@ impl PyGrid { } } + /// Convolute with with an evolution operator. + /// + /// Parameters + /// ---------- + /// muf2_0 : float + /// reference scale + /// alphas : numpy.ndarray(float) + /// list with :math:`\alpha_s(Q2)` for the process scales + /// pids : numpy.ndarray(int) + /// sorting of the particles in the tensor + /// x_grid : numpy.ndarray(float) + /// interpolation grid + /// target_pids : numpy.ndarray(int) + /// sorting of the particles in the tensor for final FkTable + /// target_x_grid : numpy.ndarray(float) + /// final FKTable interpolation grid + /// mur2_grid : numpy.ndarray(float) + /// list of renormalization scales + /// muf2_grid : numpy.ndarray(float) + /// list of factorization scales + /// operator : numpy.ndarray(int, rank=5) + /// evolution tensor + /// orders_mask : numpy.ndarray(bool) + /// boolean mask to activate orders + /// + /// Returns + /// ------- + /// PyFkTable : + /// produced FK table + pub fn evolve( + &self, + operator: PyReadonlyArray5, + fac0: f64, + pids0: PyReadonlyArray1, + x0: PyReadonlyArray1, + fac1: PyReadonlyArray1, + pids1: PyReadonlyArray1, + x1: PyReadonlyArray1, + ren1: PyReadonlyArray1, + alphas: PyReadonlyArray1, + xi: (f64, f64), + lumi_id_types: String, + order_mask: PyReadonlyArray1, + ) -> PyFkTable { + let op_info = OperatorInfo { + fac0: fac0, + pids0: pids0.to_vec().unwrap(), + x0: x0.to_vec().unwrap(), + fac1: fac1.to_vec().unwrap(), + pids1: pids1.to_vec().unwrap(), + x1: x1.to_vec().unwrap(), + ren1: ren1.to_vec().unwrap(), + alphas: alphas.to_vec().unwrap(), + xir: xi.0, + xif: xi.1, + lumi_id_types: lumi_id_types, + }; + + let evolved_grid = self + .grid + .evolve( + &operator.as_array().to_owned(), + &op_info, + &order_mask.to_vec().unwrap(), + ) + .expect("Nothing returned from evolution."); + PyFkTable { + fk_table: evolved_grid, + } + } + /// Load grid from file. /// /// **Usage:** `pineko`, FKTable generation From 7b1eac38bfcb2e90d417133f52772645ac95fc74 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Oct 2022 15:32:36 +0200 Subject: [PATCH 43/73] Adjust documentation --- pineappl/src/grid.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index d9ff2dd8..e5decfc7 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1963,7 +1963,7 @@ impl Grid { .all(|entry| entry.entry().iter().all(|&(_, b, _)| b == initial_state_2)) } - /// Returns the particle identifier of the first initial state. This is usually, but not always + /// Returns the particle identifier of the first initial state. This is usually but not always /// a proton, which is represented by the PDG ID `2212`. pub fn initial_state_1(&self) -> i32 { self.key_values() @@ -1975,8 +1975,8 @@ impl Grid { .unwrap() } - /// Returns the particle identifier of the second initial state. This is usually, but not - /// always a proton, which is represented by the PDG ID `2212`. + /// Returns the particle identifier of the second initial state. This is usually but not always + /// a proton, which is represented by the PDG ID `2212`. pub fn initial_state_2(&self) -> i32 { self.key_values() .map_or(Some("2212"), |kv| { From c7ac8a200c37e4a12bcd9f26e15eb706e2b8cb0e Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Oct 2022 15:33:32 +0200 Subject: [PATCH 44/73] Add `NNPDF_POS_ANTI_UP_40` unit test --- pineappl/src/grid.rs | 222 +++++++++++++++++++++++++++---------------- 1 file changed, 140 insertions(+), 82 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index e5decfc7..a909c8a0 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2543,12 +2543,18 @@ mod tests { targetpids: Vec, } - let setname = "NNPDF40_nlo_as_01180"; + //let setname = "NNPDF40_nlo_as_01180"; - let grid = "../HERA_CC_318GEV_EP_SIGMARED.pineappl.lz4"; - let metadata = "../HERA_CC_318GEV_EP_SIGMARED/metadata.yaml"; + let setname = "NNPDF40_nnlo_as_01180"; + let grid = "../NNPDF_POS_ANTI_UP_40.pineappl.lz4"; + let metadata = "../NNPDF_POS_ANTI_UP_40/metadata.yaml"; let alphas = "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy"; - let operator = "../HERA_CC_318GEV_EP_SIGMARED/operators.npy"; + let operator = "../NNPDF_POS_ANTI_UP_40/operators.npy"; + + //let grid = "../HERA_CC_318GEV_EP_SIGMARED.pineappl.lz4"; + //let metadata = "../HERA_CC_318GEV_EP_SIGMARED/metadata.yaml"; + //let alphas = "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy"; + //let operator = "../HERA_CC_318GEV_EP_SIGMARED/operators.npy"; //let grid = // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003.pineappl.lz4"; @@ -2580,48 +2586,74 @@ mod tests { assert_eq!( results, [ - 1.158872296528366, - 1.1204108571716151, - 0.8875902564141837, - 0.6064124901549366, - 0.46730446763293626, - 0.9175036665313503, - 0.9625683080629993, - 0.832097616454224, - 0.5840101875241862, - 0.45055068848064506, - 0.6688041946734723, - 0.6889352106823404, - 0.5297495101909169, - 0.41609405897210827, - 0.23143317308882982, - 0.5649694171604525, - 0.4792399077439775, - 0.3861828122239765, - 0.21793994357039714, - 0.08432403516120096, - 0.467724373428524, - 0.43253481860290705, - 0.3588386557913573, - 0.20658438492949507, - 0.36145545861402606, - 0.350280931434649, - 0.3095655884296923, - 0.18715074960942407, - 0.0737622486172105, - 0.2292088799939892, - 0.2277411334118036, - 0.15507169325765838, - 0.06400693681274111, - 0.1403126590329724, - 0.11639162212711233, - 0.052756148828243, - 0.05464232942385792, - 0.033578480958376296, - 0.01095350422009362 + 1.24053558491532, + 1.0556043292537103, + 0.8982894541272358, + 0.764653254688176, + 0.6497645161935843, + 0.5455683653190757, + 0.44285618029811136, + 0.34236858231394923, + 0.23851111837499242, + 0.10826740305077837, + 0.053312425688123236, + 0.022300403914252444, + 0.007689357135047722, + 0.0030482582072498296, + 0.001778467203699489, + 0.0016533253586389347, + 0.001889830982843056, + 0.0014804650577204803, + 0.0006649270383861285, + 0.00014006028310118777 ] ); + //assert_eq!( + // results, + // [ + // 1.158872296528366, + // 1.1204108571716151, + // 0.8875902564141837, + // 0.6064124901549366, + // 0.46730446763293626, + // 0.9175036665313503, + // 0.9625683080629993, + // 0.832097616454224, + // 0.5840101875241862, + // 0.45055068848064506, + // 0.6688041946734723, + // 0.6889352106823404, + // 0.5297495101909169, + // 0.41609405897210827, + // 0.23143317308882982, + // 0.5649694171604525, + // 0.4792399077439775, + // 0.3861828122239765, + // 0.21793994357039714, + // 0.08432403516120096, + // 0.467724373428524, + // 0.43253481860290705, + // 0.3588386557913573, + // 0.20658438492949507, + // 0.36145545861402606, + // 0.350280931434649, + // 0.3095655884296923, + // 0.18715074960942407, + // 0.0737622486172105, + // 0.2292088799939892, + // 0.2277411334118036, + // 0.15507169325765838, + // 0.06400693681274111, + // 0.1403126590329724, + // 0.11639162212711233, + // 0.052756148828243, + // 0.05464232942385792, + // 0.033578480958376296, + // 0.01095350422009362 + // ] + //); + //assert_eq!( // results, // [ @@ -2713,45 +2745,71 @@ mod tests { let evolved_results = fk_table.convolute(&mut cache, &[], &[]); - assert_approx_eq!(f64, evolved_results[0], 1.1586791793006517, ulps = 8); - assert_approx_eq!(f64, evolved_results[1], 1.1202273184348848, ulps = 8); - assert_approx_eq!(f64, evolved_results[2], 0.8874599897872428, ulps = 8); - assert_approx_eq!(f64, evolved_results[3], 0.6063712625073608, ulps = 8); - assert_approx_eq!(f64, evolved_results[4], 0.4672874245885059, ulps = 8); - assert_approx_eq!(f64, evolved_results[5], 0.9173403727229149, ulps = 8); - assert_approx_eq!(f64, evolved_results[6], 0.962399631849818, ulps = 8); - assert_approx_eq!(f64, evolved_results[7], 0.8319677648956049, ulps = 8); - assert_approx_eq!(f64, evolved_results[8], 0.5839675146069822, ulps = 8); - assert_approx_eq!(f64, evolved_results[9], 0.4505325132086283, ulps = 8); - assert_approx_eq!(f64, evolved_results[10], 0.6686768094263615, ulps = 8); - assert_approx_eq!(f64, evolved_results[11], 0.6888210100292264, ulps = 8); - assert_approx_eq!(f64, evolved_results[12], 0.5297074425880604, ulps = 8); - assert_approx_eq!(f64, evolved_results[13], 0.41607535867486134, ulps = 8); - assert_approx_eq!(f64, evolved_results[14], 0.23142390114495495, ulps = 8); - assert_approx_eq!(f64, evolved_results[15], 0.5648727887895276, ulps = 8); - assert_approx_eq!(f64, evolved_results[16], 0.47919973616456246, ulps = 8); - assert_approx_eq!(f64, evolved_results[17], 0.38616444708721975, ulps = 8); - assert_approx_eq!(f64, evolved_results[18], 0.21793107752932925, ulps = 8); - assert_approx_eq!(f64, evolved_results[19], 0.08431941687497238, ulps = 8); - assert_approx_eq!(f64, evolved_results[20], 0.46764290121503427, ulps = 8); - assert_approx_eq!(f64, evolved_results[21], 0.43249701889959064, ulps = 8); - assert_approx_eq!(f64, evolved_results[22], 0.35882091245690373, ulps = 8); - assert_approx_eq!(f64, evolved_results[23], 0.20657579928724892, ulps = 8); - assert_approx_eq!(f64, evolved_results[24], 0.36139047088472026, ulps = 8); - assert_approx_eq!(f64, evolved_results[25], 0.35024730127068276, ulps = 8); - assert_approx_eq!(f64, evolved_results[26], 0.3095490328079981, ulps = 8); - assert_approx_eq!(f64, evolved_results[27], 0.1871428094003754, ulps = 8); - assert_approx_eq!(f64, evolved_results[28], 0.07375775279995289, ulps = 8); - assert_approx_eq!(f64, evolved_results[29], 0.22918160031673335, ulps = 8); - assert_approx_eq!(f64, evolved_results[30], 0.22772688522902013, ulps = 8); - assert_approx_eq!(f64, evolved_results[31], 0.15506498963894486, ulps = 8); - assert_approx_eq!(f64, evolved_results[32], 0.0640029182481115, ulps = 8); - assert_approx_eq!(f64, evolved_results[33], 0.14030150245012324, ulps = 8); - assert_approx_eq!(f64, evolved_results[34], 0.11638652740576161, ulps = 8); - assert_approx_eq!(f64, evolved_results[35], 0.052752620249130584, ulps = 8); - assert_approx_eq!(f64, evolved_results[36], 0.05463985560251649, ulps = 8); - assert_approx_eq!(f64, evolved_results[37], 0.03357575618674528, ulps = 8); - assert_approx_eq!(f64, evolved_results[38], 0.010951799924697785, ulps = 8); + assert_eq!( + evolved_results, + [ + 1.2207842700252995, + 1.045048066777534, + 0.8929558020715721, + 0.7616886315970761, + 0.6473998210787656, + 0.5429673354151222, + 0.4397140650493807, + 0.3388398929365999, + 0.2360361559509584, + 0.10965325070809523, + 0.0565065025445373, + 0.025950818992108653, + 0.010936975130524709, + 0.005500955939196705, + 0.003402371551444896, + 0.0025976596425020862, + 0.002333911364590294, + 0.001628487038508355, + 0.0006948686757361142, + 0.00014172972322202258 + ] + ); + + //assert_approx_eq!(f64, evolved_results[0], 1.1586791793006517, ulps = 8); + //assert_approx_eq!(f64, evolved_results[1], 1.1202273184348848, ulps = 8); + //assert_approx_eq!(f64, evolved_results[2], 0.8874599897872428, ulps = 8); + //assert_approx_eq!(f64, evolved_results[3], 0.6063712625073608, ulps = 8); + //assert_approx_eq!(f64, evolved_results[4], 0.4672874245885059, ulps = 8); + //assert_approx_eq!(f64, evolved_results[5], 0.9173403727229149, ulps = 8); + //assert_approx_eq!(f64, evolved_results[6], 0.962399631849818, ulps = 8); + //assert_approx_eq!(f64, evolved_results[7], 0.8319677648956049, ulps = 8); + //assert_approx_eq!(f64, evolved_results[8], 0.5839675146069822, ulps = 8); + //assert_approx_eq!(f64, evolved_results[9], 0.4505325132086283, ulps = 8); + //assert_approx_eq!(f64, evolved_results[10], 0.6686768094263615, ulps = 8); + //assert_approx_eq!(f64, evolved_results[11], 0.6888210100292264, ulps = 8); + //assert_approx_eq!(f64, evolved_results[12], 0.5297074425880604, ulps = 8); + //assert_approx_eq!(f64, evolved_results[13], 0.41607535867486134, ulps = 8); + //assert_approx_eq!(f64, evolved_results[14], 0.23142390114495495, ulps = 8); + //assert_approx_eq!(f64, evolved_results[15], 0.5648727887895276, ulps = 8); + //assert_approx_eq!(f64, evolved_results[16], 0.47919973616456246, ulps = 8); + //assert_approx_eq!(f64, evolved_results[17], 0.38616444708721975, ulps = 8); + //assert_approx_eq!(f64, evolved_results[18], 0.21793107752932925, ulps = 8); + //assert_approx_eq!(f64, evolved_results[19], 0.08431941687497238, ulps = 8); + //assert_approx_eq!(f64, evolved_results[20], 0.46764290121503427, ulps = 8); + //assert_approx_eq!(f64, evolved_results[21], 0.43249701889959064, ulps = 8); + //assert_approx_eq!(f64, evolved_results[22], 0.35882091245690373, ulps = 8); + //assert_approx_eq!(f64, evolved_results[23], 0.20657579928724892, ulps = 8); + //assert_approx_eq!(f64, evolved_results[24], 0.36139047088472026, ulps = 8); + //assert_approx_eq!(f64, evolved_results[25], 0.35024730127068276, ulps = 8); + //assert_approx_eq!(f64, evolved_results[26], 0.3095490328079981, ulps = 8); + //assert_approx_eq!(f64, evolved_results[27], 0.1871428094003754, ulps = 8); + //assert_approx_eq!(f64, evolved_results[28], 0.07375775279995289, ulps = 8); + //assert_approx_eq!(f64, evolved_results[29], 0.22918160031673335, ulps = 8); + //assert_approx_eq!(f64, evolved_results[30], 0.22772688522902013, ulps = 8); + //assert_approx_eq!(f64, evolved_results[31], 0.15506498963894486, ulps = 8); + //assert_approx_eq!(f64, evolved_results[32], 0.0640029182481115, ulps = 8); + //assert_approx_eq!(f64, evolved_results[33], 0.14030150245012324, ulps = 8); + //assert_approx_eq!(f64, evolved_results[34], 0.11638652740576161, ulps = 8); + //assert_approx_eq!(f64, evolved_results[35], 0.052752620249130584, ulps = 8); + //assert_approx_eq!(f64, evolved_results[36], 0.05463985560251649, ulps = 8); + //assert_approx_eq!(f64, evolved_results[37], 0.03357575618674528, ulps = 8); + //assert_approx_eq!(f64, evolved_results[38], 0.010951799924697785, ulps = 8); //assert_eq!( // evolved_results, From 5fbd46b6e3ca8ed5e81736211481b96bd1bc3567 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Oct 2022 17:22:39 +0200 Subject: [PATCH 45/73] Enable all tests --- pineappl/src/grid.rs | 503 ++++++++++++++++++++++--------------------- 1 file changed, 257 insertions(+), 246 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index a909c8a0..2582406d 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2515,13 +2515,18 @@ mod tests { assert_eq!(fk.bins(), 1); } - #[test] - #[ignore] - fn evolve() { - use evolution::OperatorInfo; + fn execute_evolve_test( + setname: &str, + grid: &str, + metadata: &str, + alphas: &str, + operator: &str, + ref_results: &[f64], + ref_evolved_results: &[f64], + ) { use float_cmp::assert_approx_eq; use lhapdf::Pdf; - use ndarray::{Array1, Array5}; + use ndarray::Array1; use std::fs::File; #[derive(Deserialize)] @@ -2543,38 +2548,6 @@ mod tests { targetpids: Vec, } - //let setname = "NNPDF40_nlo_as_01180"; - - let setname = "NNPDF40_nnlo_as_01180"; - let grid = "../NNPDF_POS_ANTI_UP_40.pineappl.lz4"; - let metadata = "../NNPDF_POS_ANTI_UP_40/metadata.yaml"; - let alphas = "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy"; - let operator = "../NNPDF_POS_ANTI_UP_40/operators.npy"; - - //let grid = "../HERA_CC_318GEV_EP_SIGMARED.pineappl.lz4"; - //let metadata = "../HERA_CC_318GEV_EP_SIGMARED/metadata.yaml"; - //let alphas = "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy"; - //let operator = "../HERA_CC_318GEV_EP_SIGMARED/operators.npy"; - - //let grid = - // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003.pineappl.lz4"; - //let metadata = - // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/metadata.yaml"; - //let alphas = - // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/alphas.npy"; - //let operator = - // "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/operators.npy"; - - //let grid = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34.pineappl.lz4"; - //let metadata = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/metadata.yaml"; - //let alphas = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/alphas.npy"; - //let operator = "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/operators.npy"; - - //let grid = "../LHCB_WP_8TEV.pineappl.lz4"; - //let metadata = "../LHCB_WP_8TEV/metadata.yaml"; - //let alphas = "../LHCB_WP_8TEV/alphas.npy"; - //let operator = "../LHCB_WP_8TEV/operators.npy"; - let grid = Grid::read(File::open(grid).unwrap()).unwrap(); let lhapdf = Pdf::with_setname_and_nmem(setname).unwrap(); @@ -2583,126 +2556,7 @@ mod tests { let mut cache = LumiCache::with_one(2212, &mut pdf, &mut als); let results = grid.convolute(&mut cache, &[], &[], &[], &[(1.0, 1.0)]); - assert_eq!( - results, - [ - 1.24053558491532, - 1.0556043292537103, - 0.8982894541272358, - 0.764653254688176, - 0.6497645161935843, - 0.5455683653190757, - 0.44285618029811136, - 0.34236858231394923, - 0.23851111837499242, - 0.10826740305077837, - 0.053312425688123236, - 0.022300403914252444, - 0.007689357135047722, - 0.0030482582072498296, - 0.001778467203699489, - 0.0016533253586389347, - 0.001889830982843056, - 0.0014804650577204803, - 0.0006649270383861285, - 0.00014006028310118777 - ] - ); - - //assert_eq!( - // results, - // [ - // 1.158872296528366, - // 1.1204108571716151, - // 0.8875902564141837, - // 0.6064124901549366, - // 0.46730446763293626, - // 0.9175036665313503, - // 0.9625683080629993, - // 0.832097616454224, - // 0.5840101875241862, - // 0.45055068848064506, - // 0.6688041946734723, - // 0.6889352106823404, - // 0.5297495101909169, - // 0.41609405897210827, - // 0.23143317308882982, - // 0.5649694171604525, - // 0.4792399077439775, - // 0.3861828122239765, - // 0.21793994357039714, - // 0.08432403516120096, - // 0.467724373428524, - // 0.43253481860290705, - // 0.3588386557913573, - // 0.20658438492949507, - // 0.36145545861402606, - // 0.350280931434649, - // 0.3095655884296923, - // 0.18715074960942407, - // 0.0737622486172105, - // 0.2292088799939892, - // 0.2277411334118036, - // 0.15507169325765838, - // 0.06400693681274111, - // 0.1403126590329724, - // 0.11639162212711233, - // 0.052756148828243, - // 0.05464232942385792, - // 0.033578480958376296, - // 0.01095350422009362 - // ] - //); - - //assert_eq!( - // results, - // [ - // 1469.0819829706113, - // 4364.509970805006, - // 2072.647269805865, - // 742.6160478667135, - // 312.195449854513, - // 145.782031788469, - // 72.64484245290579, - // 38.88392569051013, - // 17.093513927247354, - // 6.157887576517187, - // 2.4621639421455903, - // 1.0817834362838417, - // 0.5084171526510098, - // 0.2520459057372801, - // 0.10211930488819178, - // 0.021141855492915994 - // ] - //); - - //assert_eq!( - // results, - // [ - // 134632.4480167966, - // 133472.53856965082, - // 130776.9197998554, - // 126991.17650299768, - // 121168.15135839234, - // 112761.75563082621, - // 98484.12455342771, - // 57843.82009866679 - // ] - //); - - //assert_eq!( - // results, - // [ - // 877.9498750860583, - // 823.5123400865052, - // 735.605093586326, - // 616.3465722662226, - // 478.63703336207277, - // 341.06729874517384, - // 174.3688634669724, - // 48.27440593682665 - // ] - //); + assert_eq!(results, ref_results); let metadata: Metadata = serde_yaml::from_reader(File::open(metadata).unwrap()).unwrap(); let alphas: Array1 = ndarray_npy::read_npy(alphas).unwrap(); @@ -2738,16 +2592,253 @@ mod tests { //let fk_table = grid.convolute_eko(operator, eko_info, &[]).unwrap(); let fk_table = grid.evolve(&operator, &info, &[]).unwrap(); + let evolved_results = fk_table.convolute(&mut cache, &[], &[]); - fk_table - .write(File::create("../fk_table.pineappl.lz4").unwrap()) - .unwrap(); + assert_eq!(evolved_results.len(), ref_evolved_results.len()); - let evolved_results = fk_table.convolute(&mut cache, &[], &[]); + for (&result, &ref_result) in evolved_results.iter().zip(ref_evolved_results.iter()) { + assert_approx_eq!(f64, result, ref_result, ulps = 16); + } + } - assert_eq!( - evolved_results, - [ + #[test] + #[ignore] + fn evolve_hera_cc_318gev_ep_sigmared() { + execute_evolve_test( + "NNPDF40_nlo_as_01180", + "../HERA_CC_318GEV_EP_SIGMARED.pineappl.lz4", + "../HERA_CC_318GEV_EP_SIGMARED/metadata.yaml", + "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy", + "../HERA_CC_318GEV_EP_SIGMARED/operators.npy", + &[ + 1.158872296528366, + 1.1204108571716151, + 0.8875902564141837, + 0.6064124901549366, + 0.46730446763293626, + 0.9175036665313503, + 0.9625683080629993, + 0.832097616454224, + 0.5840101875241862, + 0.45055068848064506, + 0.6688041946734723, + 0.6889352106823404, + 0.5297495101909169, + 0.41609405897210827, + 0.23143317308882982, + 0.5649694171604525, + 0.4792399077439775, + 0.3861828122239765, + 0.21793994357039714, + 0.08432403516120096, + 0.467724373428524, + 0.43253481860290705, + 0.3588386557913573, + 0.20658438492949507, + 0.36145545861402606, + 0.350280931434649, + 0.3095655884296923, + 0.18715074960942407, + 0.0737622486172105, + 0.2292088799939892, + 0.2277411334118036, + 0.15507169325765838, + 0.06400693681274111, + 0.1403126590329724, + 0.11639162212711233, + 0.052756148828243, + 0.05464232942385792, + 0.033578480958376296, + 0.01095350422009362, + ], + &[ + 1.1586791793006517, + 1.1202273184348848, + 0.8874599897872428, + 0.6063712625073608, + 0.4672874245885059, + 0.9173403727229149, + 0.962399631849818, + 0.8319677648956049, + 0.5839675146069822, + 0.4505325132086283, + 0.6686768094263615, + 0.6888210100292264, + 0.5297074425880604, + 0.41607535867486134, + 0.23142390114495495, + 0.5648727887895276, + 0.47919973616456246, + 0.38616444708721975, + 0.21793107752932925, + 0.08431941687497238, + 0.46764290121503427, + 0.43249701889959064, + 0.35882091245690373, + 0.20657579928724892, + 0.36139047088472026, + 0.35024730127068276, + 0.3095490328079981, + 0.1871428094003754, + 0.07375775279995289, + 0.22918160031673335, + 0.22772688522902013, + 0.15506498963894486, + 0.0640029182481115, + 0.14030150245012324, + 0.11638652740576161, + 0.052752620249130584, + 0.05463985560251649, + 0.03357575618674528, + 0.010951799924697785, + ], + ); + } + + #[test] + #[ignore] + fn evolve_atlaswzrap36pb() { + execute_evolve_test( + "NNPDF40_nlo_as_01180", + "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34.pineappl.lz4", + "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/metadata.yaml", + "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/alphas.npy", + "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/operators.npy", + &[ + 134632.4480167966, + 133472.53856965082, + 130776.9197998554, + 126991.17650299768, + 121168.15135839234, + 112761.75563082621, + 98484.12455342771, + 57843.82009866679, + ], + &[ + 134500.65897999398, + 133344.24845948347, + 130663.70226447149, + 126890.6156547337, + 121090.7595443343, + 112698.92115188896, + 98421.19065191328, + 57813.500329070215, + ], + ); + } + + #[test] + #[ignore] + fn evolve_lhcb_wp_8tev() { + execute_evolve_test( + "NNPDF40_nlo_as_01180", + "../LHCB_WP_8TEV.pineappl.lz4", + "../LHCB_WP_8TEV/metadata.yaml", + "../LHCB_WP_8TEV/alphas.npy", + "../LHCB_WP_8TEV/operators.npy", + &[ + 877.9498750860583, + 823.5123400865052, + 735.605093586326, + 616.3465722662226, + 478.63703336207277, + 341.06729874517384, + 174.3688634669724, + 48.27440593682665, + ], + &[ + 877.710496991437, + 823.2923843876903, + 735.4119248950592, + 616.18687672059, + 478.5155078388758, + 340.9838587318582, + 174.33023801119046, + 48.2671526729747, + ], + ); + } + + #[test] + #[ignore] + fn evolve_atlas_wm_jet_8tev_pt() { + execute_evolve_test( + "NNPDF40_nlo_as_01180", + "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003.pineappl.lz4", + "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/metadata.yaml", + "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/alphas.npy", + "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/operators.npy", + &[ + 1469.0819829706113, + 4364.509970805006, + 2072.647269805865, + 742.6160478667135, + 312.195449854513, + 145.782031788469, + 72.64484245290579, + 38.88392569051013, + 17.093513927247354, + 6.157887576517187, + 2.4621639421455903, + 1.0817834362838417, + 0.5084171526510098, + 0.2520459057372801, + 0.10211930488819178, + 0.021141855492915994, + ], + &[ + 1467.6009449768221, + 4359.87917180896, + 2070.4278159799974, + 741.9298754488171, + 311.9073865166957, + 145.65671641953438, + 72.58340237308579, + 38.85208071336316, + 17.080194246318936, + 6.153298093496777, + 2.4604627649049604, + 1.0810950528772425, + 0.5081137620517796, + 0.25190465608989626, + 0.10206534388970377, + 0.02113211970400249, + ], + ); + } + + #[test] + #[ignore] + fn evolve_nnpdf_pos_anti_up_40() { + execute_evolve_test( + "NNPDF40_nnlo_as_01180", + "../NNPDF_POS_ANTI_UP_40.pineappl.lz4", + "../NNPDF_POS_ANTI_UP_40/metadata.yaml", + "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy", + "../NNPDF_POS_ANTI_UP_40/operators.npy", + &[ + 1.24053558491532, + 1.0556043292537103, + 0.8982894541272358, + 0.764653254688176, + 0.6497645161935843, + 0.5455683653190757, + 0.44285618029811136, + 0.34236858231394923, + 0.23851111837499242, + 0.10826740305077837, + 0.053312425688123236, + 0.022300403914252444, + 0.007689357135047722, + 0.0030482582072498296, + 0.001778467203699489, + 0.0016533253586389347, + 0.001889830982843056, + 0.0014804650577204803, + 0.0006649270383861285, + 0.00014006028310118777, + ], + &[ 1.2207842700252995, 1.045048066777534, 0.8929558020715721, @@ -2767,88 +2858,8 @@ mod tests { 0.002333911364590294, 0.001628487038508355, 0.0006948686757361142, - 0.00014172972322202258 - ] + 0.00014172972322202258, + ], ); - - //assert_approx_eq!(f64, evolved_results[0], 1.1586791793006517, ulps = 8); - //assert_approx_eq!(f64, evolved_results[1], 1.1202273184348848, ulps = 8); - //assert_approx_eq!(f64, evolved_results[2], 0.8874599897872428, ulps = 8); - //assert_approx_eq!(f64, evolved_results[3], 0.6063712625073608, ulps = 8); - //assert_approx_eq!(f64, evolved_results[4], 0.4672874245885059, ulps = 8); - //assert_approx_eq!(f64, evolved_results[5], 0.9173403727229149, ulps = 8); - //assert_approx_eq!(f64, evolved_results[6], 0.962399631849818, ulps = 8); - //assert_approx_eq!(f64, evolved_results[7], 0.8319677648956049, ulps = 8); - //assert_approx_eq!(f64, evolved_results[8], 0.5839675146069822, ulps = 8); - //assert_approx_eq!(f64, evolved_results[9], 0.4505325132086283, ulps = 8); - //assert_approx_eq!(f64, evolved_results[10], 0.6686768094263615, ulps = 8); - //assert_approx_eq!(f64, evolved_results[11], 0.6888210100292264, ulps = 8); - //assert_approx_eq!(f64, evolved_results[12], 0.5297074425880604, ulps = 8); - //assert_approx_eq!(f64, evolved_results[13], 0.41607535867486134, ulps = 8); - //assert_approx_eq!(f64, evolved_results[14], 0.23142390114495495, ulps = 8); - //assert_approx_eq!(f64, evolved_results[15], 0.5648727887895276, ulps = 8); - //assert_approx_eq!(f64, evolved_results[16], 0.47919973616456246, ulps = 8); - //assert_approx_eq!(f64, evolved_results[17], 0.38616444708721975, ulps = 8); - //assert_approx_eq!(f64, evolved_results[18], 0.21793107752932925, ulps = 8); - //assert_approx_eq!(f64, evolved_results[19], 0.08431941687497238, ulps = 8); - //assert_approx_eq!(f64, evolved_results[20], 0.46764290121503427, ulps = 8); - //assert_approx_eq!(f64, evolved_results[21], 0.43249701889959064, ulps = 8); - //assert_approx_eq!(f64, evolved_results[22], 0.35882091245690373, ulps = 8); - //assert_approx_eq!(f64, evolved_results[23], 0.20657579928724892, ulps = 8); - //assert_approx_eq!(f64, evolved_results[24], 0.36139047088472026, ulps = 8); - //assert_approx_eq!(f64, evolved_results[25], 0.35024730127068276, ulps = 8); - //assert_approx_eq!(f64, evolved_results[26], 0.3095490328079981, ulps = 8); - //assert_approx_eq!(f64, evolved_results[27], 0.1871428094003754, ulps = 8); - //assert_approx_eq!(f64, evolved_results[28], 0.07375775279995289, ulps = 8); - //assert_approx_eq!(f64, evolved_results[29], 0.22918160031673335, ulps = 8); - //assert_approx_eq!(f64, evolved_results[30], 0.22772688522902013, ulps = 8); - //assert_approx_eq!(f64, evolved_results[31], 0.15506498963894486, ulps = 8); - //assert_approx_eq!(f64, evolved_results[32], 0.0640029182481115, ulps = 8); - //assert_approx_eq!(f64, evolved_results[33], 0.14030150245012324, ulps = 8); - //assert_approx_eq!(f64, evolved_results[34], 0.11638652740576161, ulps = 8); - //assert_approx_eq!(f64, evolved_results[35], 0.052752620249130584, ulps = 8); - //assert_approx_eq!(f64, evolved_results[36], 0.05463985560251649, ulps = 8); - //assert_approx_eq!(f64, evolved_results[37], 0.03357575618674528, ulps = 8); - //assert_approx_eq!(f64, evolved_results[38], 0.010951799924697785, ulps = 8); - - //assert_eq!( - // evolved_results, - // [ - // 1467.6009449768221, - // 4359.87917180896, - // 2070.4278159799974, - // 741.9298754488171, - // 311.9073865166957, - // 145.65671641953438, - // 72.58340237308579, - // 38.85208071336316, - // 17.080194246318936, - // 6.153298093496777, - // 2.4604627649049604, - // 1.0810950528772425, - // 0.5081137620517796, - // 0.25190465608989626, - // 0.10206534388970377, - // 0.02113211970400249 - // ] - //); - - //assert_approx_eq!(f64, evolved_results[0], 134500.65897999398, ulps = 8); - //assert_approx_eq!(f64, evolved_results[1], 133344.24845948347, ulps = 8); - //assert_approx_eq!(f64, evolved_results[2], 130663.70226447149, ulps = 32); - //assert_approx_eq!(f64, evolved_results[3], 126890.6156547337, ulps = 8); - //assert_approx_eq!(f64, evolved_results[4], 121090.7595443343, ulps = 8); - //assert_approx_eq!(f64, evolved_results[5], 112698.92115188896, ulps = 16); - //assert_approx_eq!(f64, evolved_results[6], 98421.19065191328, ulps = 8); - //assert_approx_eq!(f64, evolved_results[7], 57813.500329070215, ulps = 8); - - //assert_approx_eq!(f64, evolved_results[0], 1526.1321420502966, ulps = 8); - //assert_approx_eq!(f64, evolved_results[1], 1380.605564314246, ulps = 8); - //assert_approx_eq!(f64, evolved_results[2], 1182.565055380693, ulps = 8); - //assert_approx_eq!(f64, evolved_results[3], 947.3266541818663, ulps = 8); - //assert_approx_eq!(f64, evolved_results[4], 702.6776451873732, ulps = 8); - //assert_approx_eq!(f64, evolved_results[5], 477.8683182368509, ulps = 8); - //assert_approx_eq!(f64, evolved_results[6], 229.2748278368886, ulps = 8); - //assert_approx_eq!(f64, evolved_results[7], 58.35460083148634, ulps = 8); } } From deb16229289ded5547feee9337e92fa3a8dbe36a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Oct 2022 17:36:39 +0200 Subject: [PATCH 46/73] Optimize factorization scale selection in `evolve_with_one` --- pineappl/src/evolution.rs | 88 +++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 22 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 9e32cf7f..05aa0b1e 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -107,9 +107,27 @@ pub(crate) fn lumi0_with_two(pids_a: &[(i32, i32)], pids_b: &[(i32, i32)]) -> Ve pub(crate) fn operators( operator: &Array5, info: &OperatorInfo, + fac1: &[f64], pid_indices: &[(usize, usize)], x1: &[f64], ) -> Result>, GridError> { + // permutation between the grid fac1 values and the operator fac1 values + let fac1_indices: Vec<_> = if let Some(fac1_indices) = fac1 + .iter() + .map(|&fac1p| { + info.fac1 + .iter() + .position(|&fac1| approx_eq!(f64, fac1p, fac1, ulps = 64)) + }) + .collect() + { + fac1_indices + } else { + return Err(GridError::EvolutionFailure( + "operator information does not match grid's factorization scale values".to_string(), + )); + }; + // permutation between the grid x values and the operator x1 values let x1_indices: Vec<_> = if let Some(x1_indices) = x1 .iter() @@ -133,6 +151,7 @@ pub(crate) fn operators( .map(|&(pid0_idx, pid1_idx)| { operator .slice(s![.., pid1_idx, .., pid0_idx, ..]) + .select(Axis(0), &fac1_indices) .select(Axis(1), &x1_indices) .permuted_axes([0, 2, 1]) .as_standard_layout() @@ -148,7 +167,20 @@ pub(crate) fn ndarray_from_subgrid_orders( subgrids: &ArrayView1, orders: &[Order], order_mask: &[bool], -) -> Result<(Vec, Vec, Array3), GridError> { +) -> Result<(Vec, Vec, Vec, Array3), GridError> { + // TODO: skip empty subgrids + + let mut fac1: Vec<_> = subgrids + .iter() + .flat_map(|subgrid| { + subgrid + .mu2_grid() + .into_owned() + .into_iter() + .map(|mu2| mu2.fac) + .collect::>() + }) + .collect(); let mut x1_a: Vec<_> = subgrids .iter() .flat_map(|subgrid| subgrid.x1_grid().into_owned()) @@ -158,12 +190,14 @@ pub(crate) fn ndarray_from_subgrid_orders( .flat_map(|subgrid| subgrid.x2_grid().into_owned()) .collect(); + fac1.sort_by(|a, b| a.partial_cmp(b).unwrap()); + fac1.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); x1_a.sort_by(|a, b| a.partial_cmp(b).unwrap()); x1_a.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); x1_b.sort_by(|a, b| a.partial_cmp(b).unwrap()); x1_b.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 64)); - let mut array = Array3::::zeros((info.fac1.len(), x1_a.len(), x1_b.len())); + let mut array = Array3::::zeros((fac1.len(), x1_a.len(), x1_b.len())); // add subgrids for different orders, but the same bin and lumi, using the right // couplings @@ -193,6 +227,15 @@ pub(crate) fn ndarray_from_subgrid_orders( logs *= (info.xif * info.xif).ln(); } + let fac1_indices: Vec<_> = subgrid + .mu2_grid() + .iter() + .map(|&Mu2 { fac, .. }| { + fac1.iter() + .position(|&scale| approx_eq!(f64, fac, scale, ulps = 64)) + .unwrap() + }) + .collect(); let xa_indices: Vec<_> = subgrid .x1_grid() .iter() @@ -212,11 +255,8 @@ pub(crate) fn ndarray_from_subgrid_orders( }) .collect(); - for ((imu2, ix1, ix2), value) in subgrid.iter() { - let Mu2 { - ren: mur2, - fac: muf2, - } = subgrid.mu2_grid()[imu2]; + for ((ifac1, ix1, ix2), value) in subgrid.iter() { + let Mu2 { ren: mur2, .. } = subgrid.mu2_grid()[ifac1]; let als = if let Some(alphas) = info .ren1 @@ -232,18 +272,11 @@ pub(crate) fn ndarray_from_subgrid_orders( ))); }; - // TODO: get rid of the `unwrap` - let mu2_index = info - .fac1 - .iter() - .position(|&fac| approx_eq!(f64, fac, muf2, ulps = 64)) - .unwrap(); - - array[[mu2_index, xa_indices[ix1], xb_indices[ix2]]] += als * logs * value; + array[[fac1_indices[ifac1], xa_indices[ix1], xb_indices[ix2]]] += als * logs * value; } } - Ok((x1_a, x1_b, array)) + Ok((fac1, x1_a, x1_b, array)) } pub(crate) fn evolve_with_one( @@ -266,24 +299,35 @@ pub(crate) fn evolve_with_one( let new_axis = if has_pdf1 { 2 } else { 1 }; let mut last_x1 = Vec::new(); + let mut last_fac1 = Vec::new(); let mut ops = Vec::new(); for subgrids_ol in grid.subgrids().axis_iter(Axis(1)) { let mut tables = vec![Array1::zeros(info.x0.len()); lumi0.len()]; for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { - let (x1_a, x1_b, array) = + let (fac1, x1_a, x1_b, array) = ndarray_from_subgrid_orders(info, &subgrids_o, &grid.orders(), order_mask)?; let x1 = if has_pdf1 { x1_a } else { x1_b }; - if (last_x1.len() != x1.len()) + if x1.is_empty() { + continue; + } + + if (last_fac1.len() != fac1.len()) + || last_fac1 + .iter() + .zip(fac1.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = 64)) + || (last_x1.len() != x1.len()) || last_x1 .iter() .zip(x1.iter()) .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = 64)) { - ops = operators(operator, info, &pid_indices, &x1)?; + ops = operators(operator, info, &fac1, &pid_indices, &x1)?; + last_fac1 = fac1; last_x1 = x1; } @@ -401,13 +445,13 @@ pub(crate) fn evolve_with_two( let mut tables = vec![Array2::zeros((info.x0.len(), info.x0.len())); lumi0.len()]; for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { - let (x1_a, x1_b, array) = + let (fac1, x1_a, x1_b, array) = ndarray_from_subgrid_orders(info, &subgrids_o, &grid.orders(), order_mask)?; // TODO: optimization potential: if `x1_a` and `x1_b` are the same cache them, if // they are the same over bins and/or orders cache them too - let operators_a = operators(operator, info, &pid_indices_a, &x1_a)?; - let operators_b = operators(operator, info, &pid_indices_b, &x1_b)?; + let operators_a = operators(operator, info, &fac1, &pid_indices_a, &x1_a)?; + let operators_b = operators(operator, info, &fac1, &pid_indices_b, &x1_b)?; // TODO: get rid of array-index access for &(pida1, pidb1, factor) in grid.lumi()[lumi1].entry() { From 540cdf296fad53e5f66915b50af329efecd05530 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Oct 2022 18:01:16 +0200 Subject: [PATCH 47/73] Add CHORUS_CC_NB_PB_SIGMARED unit test --- pineappl/src/grid.rs | 1226 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1226 insertions(+) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 2582406d..2d9b9145 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2862,4 +2862,1230 @@ mod tests { ], ); } + + #[test] + #[ignore] + fn evolve_chorus_cc_nb_pb_sigmared() { + execute_evolve_test( + "NNPDF40_nlo_as_01180", + "../CHORUS_CC_NB_PB_SIGMARED.pineappl.lz4", + "../CHORUS_CC_NB_PB_SIGMARED/metadata.yaml", + "../CHORUS_CC_NB_PB_SIGMARED/alphas.npy", + "../CHORUS_CC_NB_PB_SIGMARED/operators.npy", + &[ + 0.17508418054652689, + 0.2695273897938339, + 0.23765585105922482, + 0.25169985216985463, + 0.3441821600653684, + 0.3036860496902356, + 0.23681995980798465, + 0.42195630412804347, + 0.34270475962218155, + 0.40787940477815376, + 0.3132748894380318, + 0.2577807128549423, + 0.4300117620481792, + 0.43819261599661424, + 0.40225026401919767, + 0.5845553253061538, + 0.3593543733351632, + 0.27124972491279786, + 0.5536384436876284, + 0.42654101852129855, + 0.6640122148055845, + 0.5768259324369139, + 0.586191593826013, + 0.39093894579856103, + 0.7031461953731108, + 0.543154270152632, + 0.48743175575755404, + 0.48144934089502267, + 0.5929176631119987, + 0.41005526792552716, + 0.8318257880948878, + 0.7230182190621122, + 0.8515005407535482, + 0.7831785444888832, + 0.5261111093752395, + 0.614809628004991, + 0.7163592480665573, + 0.7596144675276578, + 0.5265857916523599, + 0.9945270628537345, + 0.6916650300420164, + 0.7773664402348859, + 0.547006181338868, + 0.9333286158343123, + 0.6936364669791876, + 0.9719407903384734, + 0.656861275827149, + 0.5439580179066053, + 1.1348808424845245, + 0.7975487381974588, + 0.9350502432439056, + 0.5558717571090206, + 1.139608410113371, + 0.9749761310145566, + 0.9473294807096161, + 1.2924478860309754, + 0.6763055089242359, + 1.1487852454645615, + 0.7380675797619043, + 0.5418437412727434, + 0.7643540773865097, + 1.1836666045484023, + 0.8825207229758716, + 0.8378868368156698, + 0.9458420189262449, + 1.0717847698282192, + 1.1317647499274746, + 0.679484167316982, + 1.3505945482579, + 1.1560798218905395, + 1.015468845847213, + 0.9373101587601604, + 1.1614862224122455, + 0.738431687759785, + 0.8452181806489453, + 1.3857792588478974, + 1.036177724313531, + 0.7583172253276966, + 0.9049773173534823, + 1.4478265180633512, + 1.2966739403264655, + 1.5135613517314832, + 1.0337045110443905, + 1.1252182889654128, + 1.1888702235492254, + 0.7092876883785939, + 0.8290400203545237, + 1.350013991301613, + 0.967448732398068, + 1.4878146949120024, + 1.2530927139381476, + 1.530228415350425, + 0.7011085242557515, + 1.3445830308171336, + 0.8626417692613555, + 1.1915801548973077, + 1.0086814810585862, + 0.8920774478992273, + 0.9847734708434532, + 1.1776858163648567, + 1.2729869484971787, + 1.0972889655410152, + 0.988412982615934, + 1.1325311352467975, + 1.2177953834502937, + 1.460937502136669, + 1.6804277138399746, + 1.576247446853074, + 1.3279307482373712, + 0.8737981370721432, + 0.6168649653436493, + 0.7870608360027186, + 0.9257553976220181, + 1.4511510723212608, + 1.0433665740952258, + 1.4109408679024265, + 0.9143982683572018, + 1.6300600868911526, + 1.054494230406241, + 1.1887441685274223, + 0.7482989409408192, + 1.0685501763604146, + 1.097104591267553, + 1.4698679072389773, + 1.218960950634183, + 1.2410987909994937, + 0.7129852945507955, + 1.5884922274685551, + 1.2525099961522117, + 0.749992569612053, + 1.1168068534203335, + 0.8761441221105105, + 0.8218718329015258, + 1.3415655577236016, + 0.9216633349011075, + 0.7978099753009874, + 1.449914680736598, + 1.4768574326730393, + 1.0643666911240752, + 0.8986610109026638, + 0.9931605057645142, + 0.611909644587469, + 0.9587418333694464, + 1.4655537300020285, + 1.2153816186491477, + 0.9511722729956501, + 0.6470100275601826, + 1.2832897617135286, + 0.7469847754293129, + 1.1175530181004367, + 1.322063983692295, + 1.0814404270774267, + 1.1238631252990405, + 0.7464032635717058, + 1.4975034508853429, + 1.6001798413799317, + 1.2806206728943808, + 0.7726802678146308, + 0.7593136740492077, + 0.5018542523697478, + 0.6285650525184223, + 0.9176468626653805, + 0.8636077728845849, + 1.0888724586268557, + 0.6758126769417545, + 1.3509038027384432, + 0.9297974499651537, + 1.4616942865839717, + 1.5099712863567014, + 1.3172747295603051, + 0.9897254333927065, + 0.8602656242958056, + 1.0036866991746578, + 1.210801321026721, + 0.7950043225996786, + 0.7306772036442314, + 1.1553078694407823, + 1.3082308332888373, + 1.0700709437093272, + 1.1508593937386442, + 0.9307773207273198, + 0.7871843081182327, + 0.6686964066774572, + 1.1313991064024929, + 0.6226175413667078, + 0.48911763992073976, + 0.5626797887982953, + 1.301874007142872, + 0.7902143928142813, + 1.528717300988022, + 1.3573117482938861, + 0.9356426747990623, + 0.5588958418980426, + 0.9395033314179385, + 0.7666937986475366, + 0.5110051440927045, + 0.9057735106618026, + 1.1130045579045142, + 0.5887318238011767, + 0.9866413295914536, + 0.725836209651192, + 1.1855835835560118, + 1.2970432635941802, + 1.0381924269928706, + 1.4546096807856124, + 1.1319609699293744, + 0.9155145612483051, + 0.8495706756372534, + 1.3692865321955805, + 0.5127815290378634, + 0.627399176593509, + 0.3789663321519362, + 0.6852968908549385, + 1.3185532293864661, + 1.056993701095617, + 0.665324593722263, + 0.46777024528292577, + 1.205346037778319, + 0.7924999144790976, + 0.8873298512070742, + 0.709459280784969, + 0.8276159355969919, + 1.3618625223069039, + 0.8101756783666472, + 1.1379919536339014, + 0.6297152151085044, + 0.37781204993042583, + 0.35560079573069786, + 0.7719036007569298, + 0.407314923597201, + 0.937990215357849, + 0.9417295550225834, + 0.40841083934057804, + 1.0657294306252212, + 1.1308969315823405, + 0.6048407945325175, + 1.1168346609759434, + 0.9606822425660947, + 0.9824349108378805, + 0.48960123994054394, + 0.5418283022915388, + 0.8412707228195404, + 0.7117366128115412, + 1.2792981029926656, + 1.200431062908973, + 0.7901172745397984, + 0.8981280632102917, + 0.5452045610826048, + 0.8663590225461809, + 0.6929932191811116, + 0.2588265140046349, + 0.7039942227014601, + 0.2742217803379954, + 0.504459105427192, + 0.5199522596034711, + 0.62597953911183, + 1.0435944866226887, + 0.6577885116272207, + 0.5650099068699643, + 0.4490846780324496, + 1.3430785271464998, + 1.142262454236171, + 0.6346986016397684, + 0.2865953219020086, + 0.19530973756051623, + 1.1447112538933928, + 1.367662564206789, + 0.38102312219626017, + 0.8292656866455711, + 0.777267398358757, + 0.28600508105457895, + 0.9761630463697777, + 0.622849462267499, + 0.2522951919540529, + 0.9468827960067999, + 0.43794101157049925, + 0.7010075046093125, + 0.1189023400415132, + 1.1959293031659233, + 0.849477208474895, + 1.0934360288790417, + 0.9773565293132962, + 0.48927275636415846, + 0.8313096442494344, + 0.3744253232382924, + 0.5268564446869717, + 0.33802865605582194, + 0.5249430384660696, + 0.6243972273466691, + 0.39888029626494703, + 0.19384371833083308, + 1.1450998582660805, + 0.08919399238257084, + 0.7866933793052904, + 0.6739693625567023, + 0.39447603928009467, + 1.032870458279164, + 0.6517181805823248, + 0.5462278142839979, + 0.43468982370668574, + 0.8807666292883145, + 0.535583589662179, + 0.30725075320625195, + 0.24400838454393775, + 0.7217194179540221, + 0.49943753457265216, + 0.9879848350716192, + 0.6397539331394319, + 0.19004703184019897, + 0.8430736944274474, + 1.1646912559844074, + 0.9500374153431089, + 0.4431011097650916, + 0.1358517225098266, + 0.3816983503496567, + 0.2734027662570491, + 0.7816697296690134, + 0.17264102023330116, + 0.6397732061925886, + 0.9727134547847681, + 0.4884817541453219, + 0.5153534913286036, + 0.6884565112874529, + 0.2821889370605011, + 0.18171114275940467, + 1.0238646640222304, + 0.5312036757045824, + 0.13708018059931698, + 0.10908203203508102, + 1.187844330026233, + 0.8234678520136302, + 0.867250037405063, + 0.5280545412466593, + 0.29298765566069757, + 0.2331119684994854, + 0.8207829720762455, + 0.3714881071395831, + 0.32529299461879857, + 0.5299622465209836, + 0.6218875130630758, + 0.27761677944132257, + 0.7344117376273341, + 0.4952243643300778, + 0.3926592728605549, + 0.8535099583622792, + 0.6442397533753098, + 0.4180782333604763, + 0.2409433056320422, + 0.7824022300069466, + 0.3027927077223924, + 0.6550368059503859, + 0.38444900185065894, + 1.1482329600700933, + 0.9519789512388735, + 0.060580882253723545, + 0.3816923021118775, + 0.19257650866758338, + 0.6438276289212486, + 0.11148017924313727, + 0.9684765768161862, + 0.08028721882900387, + 0.7842496487219783, + 0.09193695829466855, + 0.4482665888923368, + 0.2721624183103696, + 0.8561621559270862, + 0.28192108332583904, + 0.12812530881831327, + 0.1022029969166139, + 0.4869392994935116, + 0.502027655826873, + 0.1859802642666868, + 0.8121893548777561, + 0.3688192118317807, + 0.3154642616461757, + 0.6756161354062145, + 0.2786542931017233, + 0.17239019126750388, + 0.38764494496793006, + 1.0091693564839619, + 0.5082684416248578, + 0.7784557875594005, + 0.3034748623167903, + 0.5190743285546534, + 0.640507464448423, + 0.37666056704261075, + 0.22098632205470153, + 0.12755794902012385, + 0.48984474758340746, + 0.16601973443100057, + 0.5339786133263489, + 0.6185863797916844, + 0.27139680627083085, + 0.6361388553735544, + 0.20029926006564597, + 0.40163959663315296, + 0.232581415954885, + 0.7857430698310202, + 0.04064886014154843, + 0.6461618251759489, + 0.12143335100382315, + 0.9537647916055934, + 0.3810457264475656, + 0.11662315870272344, + 0.2707718275731995, + 0.19113966967629645, + 0.8048973447935833, + 0.07456956855621856, + 0.9609457914314185, + 0.4524011968793949, + 0.6654620677686393, + 0.27564461841532323, + 0.1654134978047173, + 0.09489139248107531, + 0.05538962624230017, + 0.7748124999748075, + 0.628763751660673, + 0.8385779629812827, + 0.26552252771486734, + 0.4846269413293837, + 0.3652365816241996, + 0.48863177584806516, + 0.18269227749188724, + 0.3041157980083019, + 0.10846041314090618, + 0.5362714057914194, + 0.6154381782036658, + 0.2664502831484185, + 0.38151419595140723, + 0.08726360691339036, + 0.6474703306111875, + 0.3036088813982311, + 0.36751657132302845, + 0.6294436265357662, + 0.1999183403172808, + 0.3891576520469917, + 0.22606778328384097, + 0.5097187036589822, + 0.12855778273226898, + 0.20936169478422986, + 0.12168225162688405, + 0.4838776323831572, + 0.16095027922066846, + 0.1897001511733311, + 0.07049009502330647, + 0.6570565217492003, + 0.3796506374040504, + 0.26867643894376625, + 0.11555836381974315, + 0.11193452442863465, + 0.6124842654624286, + 0.03778605693724704, + 0.7929431374080002, + 0.482283545810485, + 0.4782938175685489, + 0.17995502424142656, + 0.27181577867628687, + 0.15758542000860468, + 0.0570704314503577, + 0.6237387262108742, + 0.37924948437600586, + 0.08822802545228833, + 0.05196026936795638, + 0.7682964482449042, + 0.6105628167239305, + 0.502247236341904, + 0.1282941652548714, + 0.20080098532881438, + 0.11723141671996572, + 0.3611032638350682, + 0.2928802761150611, + 0.10587639125688059, + 0.2605471585193985, + 0.47886783088384827, + 0.15692300068049003, + 0.37499375353688147, + 0.08378971160423875, + 0.19897434129308406, + 0.218483801202603, + 0.3029957359976254, + 0.3582195132912819, + 0.3883811178827541, + 0.11628629425078416, + 0.19238242893327612, + 0.49003417113436026, + 0.4709207945548197, + 0.06675558654324969, + 0.025843406464136125, + 0.6474140875944007, + 0.2729289452234853, + 0.06531514680112217, + 0.4999824947905057, + 0.19450942266987922, + 0.08409306192210333, + 0.0501535763684259, + 0.48090644016409956, + 0.03652336440852907, + 0.17813366010665932, + 0.36400284358607593, + 0.28423070003244144, + 0.10402113897321216, + 0.27180502351511204, + 0.15049751807593523, + 0.05606619217111426, + 0.37370508841136557, + 0.08174997490641407, + 0.6201553441862678, + 0.3638735923280538, + 0.13189451721353904, + 0.35224849290304794, + 0.07012011109529989, + 0.11272110606715918, + 0.15236037922378579, + 0.25583632878103524, + 0.20370906009562176, + 0.21102859757421724, + 0.08042145551388168, + 0.11450808703206192, + 0.26940817822191465, + 0.06446058846330588, + 0.1890298072014, + 0.03516964099665347, + 0.3599724405816431, + 0.27750749150097737, + 0.06254585379774286, + 0.02463075395239731, + 0.45778222082838066, + 0.03490060843046899, + 0.3687153235755149, + 0.2676057440791352, + 0.1448204818805799, + 0.054476341129201536, + 0.0472651730338768, + 0.34624971790901565, + 0.4891481722249711, + 0.18450967020066855, + 0.17425792234569298, + 0.10133976826252562, + 0.25085886777306265, + 0.07848085739266623, + 0.06964059808513534, + 0.20529122630381336, + 0.12990903317526245, + 0.10766326009632754, + 0.14754395256487632, + 0.1862446006894729, + 0.03444040744713824, + 0.05948520227285855, + 0.023683713683422248, + 0.26406670855428793, + 0.14031929958532208, + 0.11243166358818434, + 0.06323600590529867, + 0.07507376362968197, + 0.24669876664761947, + 0.03307057280674311, + 0.2670564213867311, + 0.1710786276382489, + 0.05254919080349757, + 0.20059387111543683, + 0.044513590783645134, + 0.336679961089545, + 0.1038077051293141, + 0.0984517782779149, + 0.14371966777063166, + 0.0751842143887107, + 0.01559259099045098, + 0.03674273528485569, + 0.06885967441174741, + 0.057104823205109886, + 0.11063730228417895, + 0.03346893151645903, + 0.16837710274585108, + 0.02257444055398897, + 0.13343891534204733, + 0.06178162633117294, + 0.1007073467373077, + 0.042471442225472444, + 0.14055238322835578, + 0.031280948168247946, + 0.09609437285090261, + 0.050536303503963736, + 0.0726264120189156, + 0.1931878072042266, + 0.014980558154686598, + 0.036290411970244844, + 0.05355538573472793, + 0.04086359640260389, + 0.060520864856410284, + 0.03238209739944476, + 0.09410569269679359, + 0.021457164768928578, + 0.0299296085548296, + 0.07054524627613962, + 0.04893630055839461, + 0.09591344047647017, + 0.019902630830190192, + 0.014331642222965658, + 0.028851213767815274, + 0.03147715582928427, + 0.020593742773379987, + 0.0476119046649274, + 0.038431402299134304, + 0.01381143270758339, + 0.019893155135724604, + ], + &[ + 0.9846578039527537, + 1.1428160730074823, + 1.0157400591515289, + 0.9373047460961609, + 1.2103085838284144, + 1.07380338424002, + 0.7684689940081988, + 1.279756177030059, + 1.0152905000655528, + 1.1642827825647268, + 0.9054185397460988, + 0.7151559537863046, + 1.2343265971792428, + 1.0889723034278065, + 1.081155071172186, + 1.4074796700349008, + 0.8576943116723308, + 0.6600110308254856, + 1.272255932823374, + 0.9872479868239301, + 1.48432129739738, + 1.292121409884949, + 1.1839710135536405, + 0.7993933215340576, + 1.3624497500745392, + 1.0573263376094482, + 0.9340313158568363, + 0.9789908470120022, + 1.1496188075755744, + 0.7371970725332893, + 1.5406978615602802, + 1.3409488760478188, + 1.4355946161127415, + 1.2822835235784886, + 0.8676653081121799, + 0.9958318374399315, + 1.1410369005167196, + 1.3182029010165506, + 0.8742080239576873, + 1.5889255647986937, + 1.1285775441215042, + 1.2050474209514361, + 0.8006725383236973, + 1.4023158074558837, + 1.0441470853256825, + 1.3624965351669247, + 0.9256393810106471, + 0.7758755383370003, + 1.5551757094613372, + 1.0746134793831859, + 1.2332230932981874, + 0.7397398556906186, + 1.5862474289981363, + 1.3582616089812056, + 1.2521507744659113, + 1.6692556717199287, + 0.8570755114661468, + 1.4337975388185895, + 0.9366317385884309, + 0.6892153354401825, + 0.9823830541760954, + 1.4694780271336392, + 1.0972377744467945, + 1.0024251445418058, + 1.1724516252065078, + 1.3092148177448175, + 1.3130180505985327, + 0.7944817393203242, + 1.6197648163527454, + 1.3871576038465498, + 1.1648716107615382, + 1.0933977811302296, + 1.3105855965735682, + 0.8357125958674643, + 0.9308538130211269, + 1.5240726616291256, + 1.1412385927939876, + 0.8430627416646357, + 0.9865171167043952, + 1.5542168162471084, + 1.381798359764537, + 1.6458954233797203, + 1.0882356398263828, + 1.2024386157072753, + 1.2404177637653306, + 0.7465751526915569, + 0.865106603000001, + 1.4196734539347613, + 1.0180342736330041, + 1.5706646267023336, + 1.3231267552483184, + 1.5678119587857564, + 0.7201741664521962, + 1.3633041525327652, + 0.877309242102593, + 1.2240152798288562, + 1.020741963826803, + 0.9095039353275298, + 0.993604922759415, + 1.1869976325063978, + 1.275979707723701, + 1.1069931861796032, + 0.9980747423260864, + 1.1347014742230916, + 1.224588890765672, + 1.4591906825445102, + 1.6842968910850602, + 1.580170115049403, + 1.331250106457184, + 0.8743784539888663, + 0.6173438080570497, + 0.7867406929390685, + 0.9256099944955801, + 1.4511603892005631, + 1.0433756041894395, + 1.4110659168537616, + 0.9144772304267657, + 1.63025852876531, + 1.0546189730754731, + 1.1888734107091454, + 0.7483261051844592, + 1.0686505480953365, + 1.0970869647500705, + 1.4698861489035782, + 1.2189723306112468, + 1.2411587048698787, + 0.7130206006744954, + 1.5885268972221829, + 1.2525099247497116, + 0.7499926314230843, + 1.1168067383099014, + 0.876141993434363, + 0.8218642824510636, + 1.3415625634379356, + 0.9216610372261911, + 0.7978053893083532, + 1.449899126372724, + 1.476847705332237, + 1.0643599107324762, + 0.8986551842761088, + 0.9931546498056035, + 0.6119077542415317, + 0.958730452956305, + 1.4655467087600806, + 1.2153748480769544, + 0.9511690438337452, + 0.6470062788930065, + 1.2832716066971843, + 0.7469753236357717, + 1.1175355594302643, + 1.3220588863624538, + 1.0814358527904078, + 1.1238587216600255, + 0.7464007136663318, + 1.4974883808022084, + 1.6001740492661205, + 1.280607710647327, + 0.7726731654727896, + 0.7593100064751936, + 0.5018511539303819, + 0.628556346863019, + 0.9176382441374444, + 0.8635928996889607, + 1.088862050999555, + 0.6758071866581457, + 1.3508994977747555, + 0.9297936838034961, + 1.4616832908047759, + 1.5099417817784118, + 1.317248522833804, + 0.9897145568742565, + 0.8602587005242931, + 1.0036652631960274, + 1.2107885670764857, + 0.7949929843297018, + 0.7306809216448841, + 1.155281584464726, + 1.3082212623693805, + 1.0700622574801901, + 1.1508563395440718, + 0.9307748891420934, + 0.7871674899326594, + 0.6686885422849159, + 1.1313931149408478, + 0.62261286017232, + 0.48910638298216746, + 0.5626842094670441, + 1.3018566581004074, + 0.7902048244877213, + 1.5286966610628414, + 1.357305719686446, + 0.9356373989108703, + 0.5588945325201345, + 0.9394911004201509, + 0.7666886089854141, + 0.5109959784084821, + 0.9057518975700104, + 1.1129879282777555, + 0.588724232779656, + 0.9866267010492198, + 0.7258346814276995, + 1.1855512905528838, + 1.2970296895337297, + 1.0381642497510992, + 1.4545924111511648, + 1.1319581558817173, + 0.9155125549602462, + 0.8495586859659635, + 1.36924665875997, + 0.5127759686453649, + 0.6273850877628259, + 0.37895345058066043, + 0.6852864849654823, + 1.3185309443011708, + 1.0569801115861845, + 0.6653130207412206, + 0.46775802407243866, + 1.2053292541014717, + 0.7924848019354067, + 0.8873330176345925, + 0.709463728750861, + 0.8275941505981728, + 1.3618545740162549, + 0.8101625400764274, + 1.137984443388146, + 0.6297091701401701, + 0.37780105841922934, + 0.3555889579323264, + 0.7718967693611626, + 0.4073147972841343, + 0.9379627144439735, + 0.9417215253305974, + 0.40841887927808795, + 1.0656964423715485, + 1.1308745373618423, + 0.6048295878380807, + 1.116831432639867, + 0.9606624861471456, + 0.9824167577119173, + 0.4895856564395406, + 0.5418360230853796, + 0.8412559814492886, + 0.7117348654791876, + 1.2792802912893553, + 1.2004116653663646, + 0.790099763177358, + 0.8981249071897095, + 0.5452031847098657, + 0.8663640824453414, + 0.6929997931282208, + 0.2588219479216775, + 0.7039791205320579, + 0.2742098731754484, + 0.5044456800268781, + 0.5199457102788779, + 0.6259626435336597, + 1.0435773559241601, + 0.6577737778175918, + 0.5649906498610809, + 0.4490682528462317, + 1.3430483894075582, + 1.1422534120289813, + 0.6346914252671366, + 0.2865947310563475, + 0.1953062739024531, + 1.1446845911181278, + 1.3676514520743444, + 0.3810067177635386, + 0.8292443239788192, + 0.7772584922116912, + 0.28601703850852, + 0.9761373392785603, + 0.6228324356458697, + 0.25228338634547637, + 0.9468728734844488, + 0.43793381623448996, + 0.7010041274302387, + 0.11890725155914843, + 1.1959078247835222, + 0.8494843519713849, + 1.093429820886188, + 0.9773360735547205, + 0.4892548842151652, + 0.8312922239345566, + 0.37441121542620937, + 0.5268667040132265, + 0.3380138730026699, + 0.5249354739703403, + 0.624378470809524, + 0.39887809500471666, + 0.1938428421936126, + 1.1450895383784212, + 0.0891971965278184, + 0.7866736607280926, + 0.6739781420218406, + 0.39448788345605695, + 1.0328511371871365, + 0.6517015758940885, + 0.546206443863707, + 0.434671546446116, + 0.8807609660496004, + 0.5355802222926985, + 0.3072459351055423, + 0.244004851993911, + 0.7216983581765535, + 0.49942189332714976, + 0.9879551615628381, + 0.6397449531622061, + 0.19006204680893152, + 0.8430472055480123, + 1.1646546766435881, + 0.9500261049935138, + 0.44309295746946314, + 0.1358508368580552, + 0.3816798883703529, + 0.27338858345420075, + 0.7816594872622985, + 0.17262952798760126, + 0.6397509940282039, + 0.9726910710714768, + 0.4884622629659889, + 0.5153657418426606, + 0.6884509239552447, + 0.28218636625825777, + 0.18170891100341025, + 1.0238439287023562, + 0.5311811833193738, + 0.13708520263317062, + 0.10908610193612234, + 1.1878206615564184, + 0.8234762987257431, + 0.8672424312807067, + 0.5280495815684301, + 0.29298241979657735, + 0.2331079650356981, + 0.820763509785017, + 0.37147228895234624, + 0.3252756847422742, + 0.5299536379931126, + 0.6218668446139202, + 0.27763204938804253, + 0.7343860672871082, + 0.4952074058083206, + 0.3926552058993296, + 0.8534805047331688, + 0.644221492210066, + 0.4180578029425472, + 0.240928330943711, + 0.7823803899835161, + 0.3027738899198869, + 0.655047593734567, + 0.3844632038265053, + 1.1482202916378605, + 0.9519668772892353, + 0.06058343369547032, + 0.38167253670303064, + 0.19257382120816555, + 0.6438172091646727, + 0.11146891090483704, + 0.9684526984060637, + 0.08029077342204308, + 0.784238199792356, + 0.09193586513484762, + 0.4482575170750042, + 0.2721469210969564, + 0.8561533830245281, + 0.2819164066773412, + 0.12813046873071404, + 0.10220710512214042, + 0.48691833789062233, + 0.5020412820874053, + 0.18599812753581396, + 0.8121687517652941, + 0.36880251167109485, + 0.3154454270385834, + 0.6756084201143353, + 0.2786501203117945, + 0.1723867699420482, + 0.387639637609794, + 1.0091468735648987, + 0.508242653901033, + 0.7784327379188821, + 0.30345497136360333, + 0.5190677038536843, + 0.640519131922536, + 0.376675995333094, + 0.22098157991684783, + 0.1275551497757849, + 0.4898267085245536, + 0.16600542275125038, + 0.5339688360762072, + 0.6185641988968787, + 0.27141389525603604, + 0.6361194803550576, + 0.2002839895666459, + 0.40161785054677474, + 0.23256506030896762, + 0.7857309561801054, + 0.04065046670367107, + 0.6461505408858991, + 0.12143921594383017, + 0.9537508522799212, + 0.3810247878512162, + 0.11664293801399515, + 0.2707557030633519, + 0.19113601535066962, + 0.8048760900903663, + 0.07457312461046703, + 0.9609205429919944, + 0.4523912217352152, + 0.665453663970266, + 0.2756399732493783, + 0.16540985711143172, + 0.09489567150271352, + 0.055392149520247014, + 0.7747885225815303, + 0.6287763081282781, + 0.8385676335778723, + 0.26551657566497, + 0.4846048820850437, + 0.3652190692671813, + 0.4886462194400875, + 0.1827114511884209, + 0.304095413528203, + 0.10844705733961149, + 0.5362608855801766, + 0.6154151421132362, + 0.2664682045031514, + 0.3815082477808231, + 0.08726084978323194, + 0.6474589415643739, + 0.30358803667695256, + 0.3675329660581807, + 0.6294234133875171, + 0.19990241405851114, + 0.38913394620793723, + 0.22604998240670895, + 0.5097114350346291, + 0.12855446997582357, + 0.20935662686035392, + 0.12167883056579297, + 0.4838588368279654, + 0.1609349028517144, + 0.1896934654087842, + 0.0704866079064006, + 0.6570342740496697, + 0.3796227170901338, + 0.2686507535162928, + 0.11557361441637819, + 0.11191723380548069, + 0.6124495482858422, + 0.037777293458026176, + 0.7928897019411747, + 0.48224943390257385, + 0.47826025307398207, + 0.17995845261781546, + 0.2717920010683322, + 0.15754196870719447, + 0.057054577712252835, + 0.6236890174560398, + 0.3791564610675984, + 0.08820066551006676, + 0.0519446513225905, + 0.7682570978380291, + 0.6105065905277058, + 0.502204521901495, + 0.12828104113130173, + 0.20074218906532487, + 0.11719705552286333, + 0.3610660680354089, + 0.29280769673410617, + 0.10584569115912862, + 0.2605410204316948, + 0.47882891946942724, + 0.15688498146540839, + 0.37496548143410047, + 0.08376904903991991, + 0.19895111534561313, + 0.21844432385379636, + 0.3029691060288074, + 0.35821569226438876, + 0.3883537708422474, + 0.11630035287251823, + 0.19236766318623888, + 0.4900043001447056, + 0.47089459397751593, + 0.06673990712378386, + 0.025838069420445763, + 0.6473659837086239, + 0.27289944730778637, + 0.0652972997883429, + 0.4999458645441742, + 0.19446263958430418, + 0.08407243442038238, + 0.05014174910893161, + 0.48087086803902285, + 0.03651659529935935, + 0.1781423051559216, + 0.3639734316244291, + 0.2841810936875253, + 0.1039990891343954, + 0.2717878667136994, + 0.150470552840648, + 0.05605613940226065, + 0.37368633362850345, + 0.08173837509096951, + 0.620123808420381, + 0.3638271009783325, + 0.1318876928617264, + 0.35225359836990383, + 0.07014080377359379, + 0.1127095422717575, + 0.15234170453324902, + 0.25585073477479553, + 0.20369121020089143, + 0.21101041848590366, + 0.08042702010861291, + 0.11452904880661925, + 0.26938952867501825, + 0.06444846126207517, + 0.18902512048581, + 0.035168215493436586, + 0.3599526410857824, + 0.27748698962877094, + 0.06255033639861617, + 0.024632615880804905, + 0.4577961549745699, + 0.0349031735372127, + 0.3687082462467413, + 0.26760007827270466, + 0.14481846478948573, + 0.05447485419554104, + 0.0472685671673231, + 0.3462658925090089, + 0.4891394297692007, + 0.18450728997176272, + 0.17427770797339237, + 0.10132569893693144, + 0.2508769475567074, + 0.07847918438097932, + 0.06966274513561732, + 0.20527245136019176, + 0.1299055869072704, + 0.1076613674931596, + 0.1475275362546755, + 0.1862405092051298, + 0.03443920650065171, + 0.0594897375351457, + 0.023685523090850816, + 0.2640614762666253, + 0.14031786384774558, + 0.11245293194014107, + 0.06322288701673176, + 0.07507968155152947, + 0.246716946916963, + 0.033073183194136144, + 0.2670346358960148, + 0.17109854489275034, + 0.05254813042832415, + 0.2005747243295308, + 0.0445170914555632, + 0.336695887032949, + 0.10380654121052656, + 0.09843676344528281, + 0.1437025649636455, + 0.07518308738816534, + 0.015593708397882409, + 0.03673027551266197, + 0.06888206764359746, + 0.05710916700940627, + 0.11065863757864756, + 0.033468000516455834, + 0.16839696705440485, + 0.022576171498287372, + 0.13343838317306927, + 0.06176774676398228, + 0.10070683579684733, + 0.04247506594430676, + 0.1405350156684872, + 0.031283580385173926, + 0.09607887943495196, + 0.050535646007401284, + 0.07262585482828961, + 0.1931678793222537, + 0.014981629285630805, + 0.036277308422216936, + 0.05355986280268147, + 0.04086694668560617, + 0.06050650034922825, + 0.0323814211886023, + 0.09408973918545771, + 0.021458813392771746, + 0.02993210736141958, + 0.07054484943455624, + 0.04893586040241371, + 0.09591350510261923, + 0.019902048716216418, + 0.014332669765393097, + 0.028853689269610825, + 0.031476696135032706, + 0.020595366637073804, + 0.0476115689696842, + 0.03843480451999081, + 0.013812447488514188, + 0.019894872558384832, + ], + ); + } } From 9d9d40a5f3fec8f6b64c77e6abff62804aab002a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sun, 16 Oct 2022 14:14:01 +0200 Subject: [PATCH 48/73] Cache EKOs for double-hadronic evolutions --- pineappl/src/evolution.rs | 42 ++++++++++++++++++++++++++++++++++----- pineappl/src/grid.rs | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 05aa0b1e..e2bebb32 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -438,9 +438,14 @@ pub(crate) fn evolve_with_two( }); let lumi0 = lumi0_with_two(&pids_a, &pids_b); - let mut sub_fk_tables = Vec::with_capacity(grid.bin_info().bins() * lumi0.len()); + let mut last_fac1 = Vec::new(); + let mut last_x1a = Vec::new(); + let mut last_x1b = Vec::new(); + let mut operators_a = Vec::new(); + let mut operators_b = Vec::new(); + for subgrids_ol in grid.subgrids().axis_iter(Axis(1)) { let mut tables = vec![Array2::zeros((info.x0.len(), info.x0.len())); lumi0.len()]; @@ -448,10 +453,37 @@ pub(crate) fn evolve_with_two( let (fac1, x1_a, x1_b, array) = ndarray_from_subgrid_orders(info, &subgrids_o, &grid.orders(), order_mask)?; - // TODO: optimization potential: if `x1_a` and `x1_b` are the same cache them, if - // they are the same over bins and/or orders cache them too - let operators_a = operators(operator, info, &fac1, &pid_indices_a, &x1_a)?; - let operators_b = operators(operator, info, &fac1, &pid_indices_b, &x1_b)?; + let fac1_diff = (last_fac1.len() != fac1.len()) + || last_fac1 + .iter() + .zip(fac1.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = 64)); + + if fac1_diff + || (last_x1a.len() != x1_a.len()) + || last_x1a + .iter() + .zip(x1_a.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = 64)) + { + operators_a = operators(operator, info, &fac1, &pid_indices_a, &x1_a)?; + last_x1a = x1_a; + } + + if fac1_diff + || (last_x1b.len() != x1_b.len()) + || last_x1b + .iter() + .zip(x1_b.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = 64)) + { + operators_b = operators(operator, info, &fac1, &pid_indices_b, &x1_b)?; + last_x1b = x1_b; + } + + if fac1_diff { + last_fac1 = fac1; + }; // TODO: get rid of array-index access for &(pida1, pidb1, factor) in grid.lumi()[lumi1].entry() { diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 2d9b9145..e36cd558 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -4088,4 +4088,46 @@ mod tests { ], ); } + + #[test] + #[ignore] + fn evolve_atlaspht15() { + execute_evolve_test( + "NNPDF40_nlo_as_01180", + "../ATLASPHT15-ATLASPHT15_Et_3bin.pineappl.lz4", + "../ATLASPHT15-ATLASPHT15_Et_3bin/metadata.yaml", + "../ATLASPHT15-ATLASPHT15_Et_3bin/alphas.npy", + "../ATLASPHT15-ATLASPHT15_Et_3bin/operators.npy", + &[ + 847.6443451935788, + 389.2518461733433, + 197.52262245783854, + 85.5341661018376, + 30.87251252799057, + 12.857919383339262, + 5.881543988434407, + 2.5226447467912503, + 0.9852473741631275, + 0.33567120929573163, + 0.1103227781235781, + 0.03105085344647281, + 0.005857170880761543, + ], + &[ + 846.9388599419221, + 388.9452263757685, + 197.35723798133498, + 85.45945643409014, + 30.84568815110067, + 12.847951715560423, + 5.876789744699159, + 2.5205570958215677, + 0.9845342100753295, + 0.33542931711292495, + 0.11024603718181779, + 0.031033712901365054, + 0.005854961951848535, + ], + ); + } } From 1c88c99927be92716b46060ff33107b44d89eb75 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sun, 16 Oct 2022 14:15:01 +0200 Subject: [PATCH 49/73] Print warnings if evolved grids differ too much --- pineappl/src/grid.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index e36cd558..cbfe6911 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2596,6 +2596,16 @@ mod tests { assert_eq!(evolved_results.len(), ref_evolved_results.len()); + for (bin, diff) in results + .iter() + .zip(evolved_results.iter()) + .map(|(a, b)| (b / a - 1.0) * 1000.0) + .enumerate() + .filter(|&(_, diff)| diff > 1.0) + { + println!("WARNING: bin {} diff {}", bin, diff); + } + for (&result, &ref_result) in evolved_results.iter().zip(ref_evolved_results.iter()) { assert_approx_eq!(f64, result, ref_result, ulps = 16); } From feb1e1973cb3a35e8179538ce650b1a0fb51ef4a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sun, 16 Oct 2022 18:54:39 +0200 Subject: [PATCH 50/73] Do not use alphas if its power is zero --- pineappl/src/evolution.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index e2bebb32..dd48cae9 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -258,7 +258,9 @@ pub(crate) fn ndarray_from_subgrid_orders( for ((ifac1, ix1, ix2), value) in subgrid.iter() { let Mu2 { ren: mur2, .. } = subgrid.mu2_grid()[ifac1]; - let als = if let Some(alphas) = info + let als = if order.alphas == 0 { + 1.0 + } else if let Some(alphas) = info .ren1 .iter() .zip(info.alphas.iter()) From c56f38ce2a9777502775d92707a82ece0685652e Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sun, 16 Oct 2022 18:55:39 +0200 Subject: [PATCH 51/73] Add new subcommand `evolve` --- pineappl_cli/Cargo.toml | 6 +- pineappl_cli/src/evolve.rs | 181 +++++++++++++++++++++++++++++++++++++ pineappl_cli/src/main.rs | 2 + 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 pineappl_cli/src/evolve.rs diff --git a/pineappl_cli/Cargo.toml b/pineappl_cli/Cargo.toml index 87069206..9b33c6b7 100644 --- a/pineappl_cli/Cargo.toml +++ b/pineappl_cli/Cargo.toml @@ -20,13 +20,17 @@ flate2 = { optional = true, version = "1.0.22" } git-version = "0.3.5" itertools = "0.10.1" lhapdf = "0.2.1" +lz4_flex = { optional = true, version = "0.9.2" } ndarray = "0.15.4" +ndarray-npy = { optional = true, version = "0.8.1" } num_cpus = "1.13.0" pineappl = { path = "../pineappl", version = "0.5.7" } pineappl_applgrid = { optional = true, path = "../pineappl_applgrid", version = "0.2.0" } pineappl_fastnlo = { optional = true, path = "../pineappl_fastnlo", version = "0.2.0" } prettytable-rs = { default-features = false, features = ["win_crlf"], version = "0.8.0" } rayon = "1.5.1" +serde = { features = ["derive"], optional = true, version = "1.0.130" } +serde_yaml = { optional = true, version = "0.9.13" } tar = { optional = true, version = "0.4.38" } [dev-dependencies] @@ -44,4 +48,4 @@ rustc-args = [ "--cfg feature=\"docs-only\"" ] [features] applgrid = ["pineappl_applgrid"] fastnlo = ["pineappl_fastnlo"] -fktable = ["flate2", "tar"] +fktable = ["flate2", "lz4_flex", "ndarray-npy", "serde", "serde_yaml", "tar"] diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs new file mode 100644 index 00000000..dfd0a11d --- /dev/null +++ b/pineappl_cli/src/evolve.rs @@ -0,0 +1,181 @@ +use super::helpers::{self, ConvoluteMode, Subcommand}; +use anyhow::{anyhow, Result}; +use clap::{Parser, ValueHint}; +use pineappl::fk_table::FkTable; +use pineappl::grid::Grid; +use std::path::{Path, PathBuf}; + +#[cfg(feature = "fktable")] +fn evolve_grid(grid: &Grid, eko: &Path) -> Result { + use lz4_flex::frame::FrameDecoder; + use ndarray::{Array1, Array5}; + use ndarray_npy::ReadNpyExt; + use pineappl::evolution::OperatorInfo; + use serde::Deserialize; + use std::fs::File; + use std::io::BufReader; + use tar::Archive; + + #[derive(Default, Deserialize)] + struct Metadata { + #[serde(rename = "Q2grid")] + q2_grid: Vec, + #[allow(dead_code)] + eko_version: String, + inputgrid: Vec, + inputpids: Vec, + #[allow(dead_code)] + interpolation_is_log: bool, + #[allow(dead_code)] + interpolation_polynomial_degree: usize, + #[allow(dead_code)] + interpolation_xgrid: Vec, + q2_ref: f64, + targetgrid: Vec, + targetpids: Vec, + } + + let mut archive = Archive::new(File::open(eko)?); + + let mut alphas = Vec::new(); + let mut operator = Default::default(); + let mut metadata: Metadata = Default::default(); + + for entry in archive.entries()? { + let file = entry?; + let path = file.header().path()?; + + if let Some(file_name) = path.file_name() { + // TODO: get rid of the unwrap + match file_name.to_str().unwrap() { + "metadata.yaml" => metadata = serde_yaml::from_reader(file)?, + "operators.npy.lz4" => { + operator = Array5::::read_npy(FrameDecoder::new(BufReader::new(file)))? + } + "alphas.npy.lz4" => { + alphas = + Array1::::read_npy(FrameDecoder::new(BufReader::new(file)))?.to_vec() + } + _ => {} + } + } + } + + // TODO: handle errors when files in the EKO are not present + + let info = OperatorInfo { + fac1: metadata.q2_grid.clone(), + pids0: metadata.inputpids, + x0: metadata.inputgrid, + pids1: metadata.targetpids, + x1: metadata.targetgrid, + fac0: metadata.q2_ref, + ren1: metadata.q2_grid, // TODO: check whether this is true in the general case + alphas, + xir: 1.0, // TODO: make this a CLI option + xif: 1.0, // TODO: make this a CLI option + lumi_id_types: "pdg_mc_ids".to_string(), // TODO: determine this from the operator + }; + + Ok(grid.evolve(&operator, &info, &[])?) +} + +#[cfg(not(feature = "fktable"))] +fn evolve_grid(_: &Grid, _: &Path) -> Result { + Err(anyhow!( + "you need to install `pineappl` with feature `fktable`" + )) +} + +/// Evolves a PineAPPL grid together with an evolution kernel operator to an FK table. +#[derive(Parser)] +pub struct Opts { + /// Path to the input grid. + #[clap(parse(from_os_str), value_hint = ValueHint::FilePath)] + input: PathBuf, + /// Path to the evolution kernel operator. + #[clap(parse(from_os_str), value_hint = ValueHint::FilePath)] + eko: PathBuf, + /// Path to the converted grid. + #[clap(parse(from_os_str), value_hint = ValueHint::FilePath)] + output: PathBuf, + /// LHAPDF id or name of the PDF set to check the converted grid with. + #[clap(validator = helpers::validate_pdfset)] + pdfset: String, + /// Relative threshold between the table and the converted grid when comparison fails. + #[clap(default_value = "1e-3", long)] + accuracy: f64, + /// Set the number of fractional digits shown for absolute numbers. + #[clap(default_value_t = 7, long = "digits-abs", value_name = "ABS")] + digits_abs: usize, + /// Set the number of fractional digits shown for relative numbers. + #[clap(default_value_t = 7, long = "digits-rel", value_name = "REL")] + digits_rel: usize, +} + +impl Subcommand for Opts { + fn run(&self) -> Result<()> { + use prettytable::{cell, row}; + + let grid = helpers::read_grid(&self.input)?; + let fk_table = evolve_grid(&grid, &self.eko)?; + + let mut different = false; + let mut pdf = helpers::create_pdf(&self.pdfset)?; + + let results = helpers::convolute( + &grid, + &mut pdf, + &[], + &[], + &[], + 1, + ConvoluteMode::Normal, + false, + ); + let evolved_results = helpers::convolute( + fk_table.grid(), + &mut pdf, + &[], + &[], + &[], + 1, + ConvoluteMode::Normal, + false, + ); + + // if both grids don't have the same number of bins there's a bug in the program + assert_eq!(results.len(), evolved_results.len()); + + let mut table = helpers::create_table(); + table.set_titles(row![c => "b", "FkTable", "Grid", "rel. diff"]); + + for (bin, (one, two)) in results + .into_iter() + .zip(evolved_results.into_iter()) + .enumerate() + { + // catches the case where both results are zero + let rel_diff = if one == two { 0.0 } else { two / one - 1.0 }; + + if rel_diff.abs() > self.accuracy { + different = true; + } + + table.add_row(row![ + bin.to_string(), + r->format!("{:.*e}", self.digits_abs, one), + r->format!("{:.*e}", self.digits_abs, two), + r->format!("{:.*e}", self.digits_rel, rel_diff) + ]); + } + + table.printstd(); + + if different { + Err(anyhow!("grids are different")) + } else { + helpers::write_grid(&self.output, fk_table.grid()) + } + } +} diff --git a/pineappl_cli/src/main.rs b/pineappl_cli/src/main.rs index 79126bae..b4b622d3 100644 --- a/pineappl_cli/src/main.rs +++ b/pineappl_cli/src/main.rs @@ -4,6 +4,7 @@ mod channels; mod convolute; mod delete; mod diff; +mod evolve; mod helpers; mod import; mod info; @@ -56,6 +57,7 @@ enum SubcommandEnum { Convolute(convolute::Opts), Delete(delete::Opts), Diff(diff::Opts), + Evolve(evolve::Opts), Import(import::Opts), Info(info::Opts), Merge(merge::Opts), From 55e3ccbc0c58f19bfc17f81bf05d34dcf3d3a51a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Sun, 16 Oct 2022 19:22:14 +0200 Subject: [PATCH 52/73] Fix tests --- pineappl_cli/src/evolve.rs | 2 +- pineappl_cli/tests/main.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index dfd0a11d..59eacbf0 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -87,7 +87,7 @@ fn evolve_grid(_: &Grid, _: &Path) -> Result { )) } -/// Evolves a PineAPPL grid together with an evolution kernel operator to an FK table. +/// Evolve a grid with an evolution kernel operator to an FK table. #[derive(Parser)] pub struct Opts { /// Path to the input grid. diff --git a/pineappl_cli/tests/main.rs b/pineappl_cli/tests/main.rs index 499f1f1d..86523356 100644 --- a/pineappl_cli/tests/main.rs +++ b/pineappl_cli/tests/main.rs @@ -17,6 +17,7 @@ SUBCOMMANDS: convolute Convolutes a PineAPPL grid with a PDF set delete Deletes parts from a PineAPPL grid diff Compares the numerical content of two grids with each other + evolve Evolve a grid with an evolution kernel operator to an FK table import Converts APPLgrid/fastNLO/FastKernel files to PineAPPL grids info Shows information about the grid merge Merges one or more PineAPPL grids together From a98c53e57dc6ea8aa905b30d6380fc3f45b0cc21 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 17 Oct 2022 13:25:46 +0200 Subject: [PATCH 53/73] Remove ignored unit tests --- pineappl/src/grid.rs | 1626 ------------------------------------------ 1 file changed, 1626 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index cbfe6911..b1a1ba5b 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -2514,1630 +2514,4 @@ mod tests { assert_eq!(fk.bins(), 1); } - - fn execute_evolve_test( - setname: &str, - grid: &str, - metadata: &str, - alphas: &str, - operator: &str, - ref_results: &[f64], - ref_evolved_results: &[f64], - ) { - use float_cmp::assert_approx_eq; - use lhapdf::Pdf; - use ndarray::Array1; - use std::fs::File; - - #[derive(Deserialize)] - struct Metadata { - #[serde(rename = "Q2grid")] - q2_grid: Vec, - #[allow(dead_code)] - eko_version: String, - inputgrid: Vec, - inputpids: Vec, - #[allow(dead_code)] - interpolation_is_log: bool, - #[allow(dead_code)] - interpolation_polynomial_degree: usize, - #[allow(dead_code)] - interpolation_xgrid: Vec, - q2_ref: f64, - targetgrid: Vec, - targetpids: Vec, - } - - let grid = Grid::read(File::open(grid).unwrap()).unwrap(); - - let lhapdf = Pdf::with_setname_and_nmem(setname).unwrap(); - let mut pdf = |id, x, q2| lhapdf.xfx_q2(id, x, q2); - let mut als = |q2| lhapdf.alphas_q2(q2); - let mut cache = LumiCache::with_one(2212, &mut pdf, &mut als); - let results = grid.convolute(&mut cache, &[], &[], &[], &[(1.0, 1.0)]); - - assert_eq!(results, ref_results); - - let metadata: Metadata = serde_yaml::from_reader(File::open(metadata).unwrap()).unwrap(); - let alphas: Array1 = ndarray_npy::read_npy(alphas).unwrap(); - let alphas = alphas.to_vec(); - let operator: Array5 = ndarray_npy::read_npy(operator).unwrap(); - - let info = OperatorInfo { - fac1: metadata.q2_grid.clone(), - pids0: metadata.inputpids, - x0: metadata.inputgrid, - pids1: metadata.targetpids, - x1: metadata.targetgrid, - fac0: metadata.q2_ref, - ren1: metadata.q2_grid, // TODO: check whether this is true in the general case - alphas, - xir: 1.0, - xif: 1.0, - lumi_id_types: "pdg_mc_ids".to_string(), - }; - - //let mut grid_axes = grid.axes().unwrap(); - //grid_axes.pids = metadata.targetpids.clone(); // TODO: which one them? - //let eko_info = EkoInfo { - // muf2_0: metadata.q2_ref, - // alphas, - // xir: 1.0, - // xif: 1.0, - // target_x_grid: metadata.inputgrid, - // target_pids: metadata.targetpids, - // grid_axes, - // lumi_id_types: "pdg_mc_ids".to_string(), - //}; - - //let fk_table = grid.convolute_eko(operator, eko_info, &[]).unwrap(); - let fk_table = grid.evolve(&operator, &info, &[]).unwrap(); - let evolved_results = fk_table.convolute(&mut cache, &[], &[]); - - assert_eq!(evolved_results.len(), ref_evolved_results.len()); - - for (bin, diff) in results - .iter() - .zip(evolved_results.iter()) - .map(|(a, b)| (b / a - 1.0) * 1000.0) - .enumerate() - .filter(|&(_, diff)| diff > 1.0) - { - println!("WARNING: bin {} diff {}", bin, diff); - } - - for (&result, &ref_result) in evolved_results.iter().zip(ref_evolved_results.iter()) { - assert_approx_eq!(f64, result, ref_result, ulps = 16); - } - } - - #[test] - #[ignore] - fn evolve_hera_cc_318gev_ep_sigmared() { - execute_evolve_test( - "NNPDF40_nlo_as_01180", - "../HERA_CC_318GEV_EP_SIGMARED.pineappl.lz4", - "../HERA_CC_318GEV_EP_SIGMARED/metadata.yaml", - "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy", - "../HERA_CC_318GEV_EP_SIGMARED/operators.npy", - &[ - 1.158872296528366, - 1.1204108571716151, - 0.8875902564141837, - 0.6064124901549366, - 0.46730446763293626, - 0.9175036665313503, - 0.9625683080629993, - 0.832097616454224, - 0.5840101875241862, - 0.45055068848064506, - 0.6688041946734723, - 0.6889352106823404, - 0.5297495101909169, - 0.41609405897210827, - 0.23143317308882982, - 0.5649694171604525, - 0.4792399077439775, - 0.3861828122239765, - 0.21793994357039714, - 0.08432403516120096, - 0.467724373428524, - 0.43253481860290705, - 0.3588386557913573, - 0.20658438492949507, - 0.36145545861402606, - 0.350280931434649, - 0.3095655884296923, - 0.18715074960942407, - 0.0737622486172105, - 0.2292088799939892, - 0.2277411334118036, - 0.15507169325765838, - 0.06400693681274111, - 0.1403126590329724, - 0.11639162212711233, - 0.052756148828243, - 0.05464232942385792, - 0.033578480958376296, - 0.01095350422009362, - ], - &[ - 1.1586791793006517, - 1.1202273184348848, - 0.8874599897872428, - 0.6063712625073608, - 0.4672874245885059, - 0.9173403727229149, - 0.962399631849818, - 0.8319677648956049, - 0.5839675146069822, - 0.4505325132086283, - 0.6686768094263615, - 0.6888210100292264, - 0.5297074425880604, - 0.41607535867486134, - 0.23142390114495495, - 0.5648727887895276, - 0.47919973616456246, - 0.38616444708721975, - 0.21793107752932925, - 0.08431941687497238, - 0.46764290121503427, - 0.43249701889959064, - 0.35882091245690373, - 0.20657579928724892, - 0.36139047088472026, - 0.35024730127068276, - 0.3095490328079981, - 0.1871428094003754, - 0.07375775279995289, - 0.22918160031673335, - 0.22772688522902013, - 0.15506498963894486, - 0.0640029182481115, - 0.14030150245012324, - 0.11638652740576161, - 0.052752620249130584, - 0.05463985560251649, - 0.03357575618674528, - 0.010951799924697785, - ], - ); - } - - #[test] - #[ignore] - fn evolve_atlaswzrap36pb() { - execute_evolve_test( - "NNPDF40_nlo_as_01180", - "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34.pineappl.lz4", - "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/metadata.yaml", - "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/alphas.npy", - "../ATLASWZRAP36PB-ATLAS-arXiv:1109.5141-Z0_eta34/operators.npy", - &[ - 134632.4480167966, - 133472.53856965082, - 130776.9197998554, - 126991.17650299768, - 121168.15135839234, - 112761.75563082621, - 98484.12455342771, - 57843.82009866679, - ], - &[ - 134500.65897999398, - 133344.24845948347, - 130663.70226447149, - 126890.6156547337, - 121090.7595443343, - 112698.92115188896, - 98421.19065191328, - 57813.500329070215, - ], - ); - } - - #[test] - #[ignore] - fn evolve_lhcb_wp_8tev() { - execute_evolve_test( - "NNPDF40_nlo_as_01180", - "../LHCB_WP_8TEV.pineappl.lz4", - "../LHCB_WP_8TEV/metadata.yaml", - "../LHCB_WP_8TEV/alphas.npy", - "../LHCB_WP_8TEV/operators.npy", - &[ - 877.9498750860583, - 823.5123400865052, - 735.605093586326, - 616.3465722662226, - 478.63703336207277, - 341.06729874517384, - 174.3688634669724, - 48.27440593682665, - ], - &[ - 877.710496991437, - 823.2923843876903, - 735.4119248950592, - 616.18687672059, - 478.5155078388758, - 340.9838587318582, - 174.33023801119046, - 48.2671526729747, - ], - ); - } - - #[test] - #[ignore] - fn evolve_atlas_wm_jet_8tev_pt() { - execute_evolve_test( - "NNPDF40_nlo_as_01180", - "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003.pineappl.lz4", - "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/metadata.yaml", - "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/alphas.npy", - "../ATLAS_WM_JET_8TEV_PT-atlas-atlas-wjets-arxiv-1711.03296-xsec003/operators.npy", - &[ - 1469.0819829706113, - 4364.509970805006, - 2072.647269805865, - 742.6160478667135, - 312.195449854513, - 145.782031788469, - 72.64484245290579, - 38.88392569051013, - 17.093513927247354, - 6.157887576517187, - 2.4621639421455903, - 1.0817834362838417, - 0.5084171526510098, - 0.2520459057372801, - 0.10211930488819178, - 0.021141855492915994, - ], - &[ - 1467.6009449768221, - 4359.87917180896, - 2070.4278159799974, - 741.9298754488171, - 311.9073865166957, - 145.65671641953438, - 72.58340237308579, - 38.85208071336316, - 17.080194246318936, - 6.153298093496777, - 2.4604627649049604, - 1.0810950528772425, - 0.5081137620517796, - 0.25190465608989626, - 0.10206534388970377, - 0.02113211970400249, - ], - ); - } - - #[test] - #[ignore] - fn evolve_nnpdf_pos_anti_up_40() { - execute_evolve_test( - "NNPDF40_nnlo_as_01180", - "../NNPDF_POS_ANTI_UP_40.pineappl.lz4", - "../NNPDF_POS_ANTI_UP_40/metadata.yaml", - "../HERA_CC_318GEV_EP_SIGMARED/alphas.npy", - "../NNPDF_POS_ANTI_UP_40/operators.npy", - &[ - 1.24053558491532, - 1.0556043292537103, - 0.8982894541272358, - 0.764653254688176, - 0.6497645161935843, - 0.5455683653190757, - 0.44285618029811136, - 0.34236858231394923, - 0.23851111837499242, - 0.10826740305077837, - 0.053312425688123236, - 0.022300403914252444, - 0.007689357135047722, - 0.0030482582072498296, - 0.001778467203699489, - 0.0016533253586389347, - 0.001889830982843056, - 0.0014804650577204803, - 0.0006649270383861285, - 0.00014006028310118777, - ], - &[ - 1.2207842700252995, - 1.045048066777534, - 0.8929558020715721, - 0.7616886315970761, - 0.6473998210787656, - 0.5429673354151222, - 0.4397140650493807, - 0.3388398929365999, - 0.2360361559509584, - 0.10965325070809523, - 0.0565065025445373, - 0.025950818992108653, - 0.010936975130524709, - 0.005500955939196705, - 0.003402371551444896, - 0.0025976596425020862, - 0.002333911364590294, - 0.001628487038508355, - 0.0006948686757361142, - 0.00014172972322202258, - ], - ); - } - - #[test] - #[ignore] - fn evolve_chorus_cc_nb_pb_sigmared() { - execute_evolve_test( - "NNPDF40_nlo_as_01180", - "../CHORUS_CC_NB_PB_SIGMARED.pineappl.lz4", - "../CHORUS_CC_NB_PB_SIGMARED/metadata.yaml", - "../CHORUS_CC_NB_PB_SIGMARED/alphas.npy", - "../CHORUS_CC_NB_PB_SIGMARED/operators.npy", - &[ - 0.17508418054652689, - 0.2695273897938339, - 0.23765585105922482, - 0.25169985216985463, - 0.3441821600653684, - 0.3036860496902356, - 0.23681995980798465, - 0.42195630412804347, - 0.34270475962218155, - 0.40787940477815376, - 0.3132748894380318, - 0.2577807128549423, - 0.4300117620481792, - 0.43819261599661424, - 0.40225026401919767, - 0.5845553253061538, - 0.3593543733351632, - 0.27124972491279786, - 0.5536384436876284, - 0.42654101852129855, - 0.6640122148055845, - 0.5768259324369139, - 0.586191593826013, - 0.39093894579856103, - 0.7031461953731108, - 0.543154270152632, - 0.48743175575755404, - 0.48144934089502267, - 0.5929176631119987, - 0.41005526792552716, - 0.8318257880948878, - 0.7230182190621122, - 0.8515005407535482, - 0.7831785444888832, - 0.5261111093752395, - 0.614809628004991, - 0.7163592480665573, - 0.7596144675276578, - 0.5265857916523599, - 0.9945270628537345, - 0.6916650300420164, - 0.7773664402348859, - 0.547006181338868, - 0.9333286158343123, - 0.6936364669791876, - 0.9719407903384734, - 0.656861275827149, - 0.5439580179066053, - 1.1348808424845245, - 0.7975487381974588, - 0.9350502432439056, - 0.5558717571090206, - 1.139608410113371, - 0.9749761310145566, - 0.9473294807096161, - 1.2924478860309754, - 0.6763055089242359, - 1.1487852454645615, - 0.7380675797619043, - 0.5418437412727434, - 0.7643540773865097, - 1.1836666045484023, - 0.8825207229758716, - 0.8378868368156698, - 0.9458420189262449, - 1.0717847698282192, - 1.1317647499274746, - 0.679484167316982, - 1.3505945482579, - 1.1560798218905395, - 1.015468845847213, - 0.9373101587601604, - 1.1614862224122455, - 0.738431687759785, - 0.8452181806489453, - 1.3857792588478974, - 1.036177724313531, - 0.7583172253276966, - 0.9049773173534823, - 1.4478265180633512, - 1.2966739403264655, - 1.5135613517314832, - 1.0337045110443905, - 1.1252182889654128, - 1.1888702235492254, - 0.7092876883785939, - 0.8290400203545237, - 1.350013991301613, - 0.967448732398068, - 1.4878146949120024, - 1.2530927139381476, - 1.530228415350425, - 0.7011085242557515, - 1.3445830308171336, - 0.8626417692613555, - 1.1915801548973077, - 1.0086814810585862, - 0.8920774478992273, - 0.9847734708434532, - 1.1776858163648567, - 1.2729869484971787, - 1.0972889655410152, - 0.988412982615934, - 1.1325311352467975, - 1.2177953834502937, - 1.460937502136669, - 1.6804277138399746, - 1.576247446853074, - 1.3279307482373712, - 0.8737981370721432, - 0.6168649653436493, - 0.7870608360027186, - 0.9257553976220181, - 1.4511510723212608, - 1.0433665740952258, - 1.4109408679024265, - 0.9143982683572018, - 1.6300600868911526, - 1.054494230406241, - 1.1887441685274223, - 0.7482989409408192, - 1.0685501763604146, - 1.097104591267553, - 1.4698679072389773, - 1.218960950634183, - 1.2410987909994937, - 0.7129852945507955, - 1.5884922274685551, - 1.2525099961522117, - 0.749992569612053, - 1.1168068534203335, - 0.8761441221105105, - 0.8218718329015258, - 1.3415655577236016, - 0.9216633349011075, - 0.7978099753009874, - 1.449914680736598, - 1.4768574326730393, - 1.0643666911240752, - 0.8986610109026638, - 0.9931605057645142, - 0.611909644587469, - 0.9587418333694464, - 1.4655537300020285, - 1.2153816186491477, - 0.9511722729956501, - 0.6470100275601826, - 1.2832897617135286, - 0.7469847754293129, - 1.1175530181004367, - 1.322063983692295, - 1.0814404270774267, - 1.1238631252990405, - 0.7464032635717058, - 1.4975034508853429, - 1.6001798413799317, - 1.2806206728943808, - 0.7726802678146308, - 0.7593136740492077, - 0.5018542523697478, - 0.6285650525184223, - 0.9176468626653805, - 0.8636077728845849, - 1.0888724586268557, - 0.6758126769417545, - 1.3509038027384432, - 0.9297974499651537, - 1.4616942865839717, - 1.5099712863567014, - 1.3172747295603051, - 0.9897254333927065, - 0.8602656242958056, - 1.0036866991746578, - 1.210801321026721, - 0.7950043225996786, - 0.7306772036442314, - 1.1553078694407823, - 1.3082308332888373, - 1.0700709437093272, - 1.1508593937386442, - 0.9307773207273198, - 0.7871843081182327, - 0.6686964066774572, - 1.1313991064024929, - 0.6226175413667078, - 0.48911763992073976, - 0.5626797887982953, - 1.301874007142872, - 0.7902143928142813, - 1.528717300988022, - 1.3573117482938861, - 0.9356426747990623, - 0.5588958418980426, - 0.9395033314179385, - 0.7666937986475366, - 0.5110051440927045, - 0.9057735106618026, - 1.1130045579045142, - 0.5887318238011767, - 0.9866413295914536, - 0.725836209651192, - 1.1855835835560118, - 1.2970432635941802, - 1.0381924269928706, - 1.4546096807856124, - 1.1319609699293744, - 0.9155145612483051, - 0.8495706756372534, - 1.3692865321955805, - 0.5127815290378634, - 0.627399176593509, - 0.3789663321519362, - 0.6852968908549385, - 1.3185532293864661, - 1.056993701095617, - 0.665324593722263, - 0.46777024528292577, - 1.205346037778319, - 0.7924999144790976, - 0.8873298512070742, - 0.709459280784969, - 0.8276159355969919, - 1.3618625223069039, - 0.8101756783666472, - 1.1379919536339014, - 0.6297152151085044, - 0.37781204993042583, - 0.35560079573069786, - 0.7719036007569298, - 0.407314923597201, - 0.937990215357849, - 0.9417295550225834, - 0.40841083934057804, - 1.0657294306252212, - 1.1308969315823405, - 0.6048407945325175, - 1.1168346609759434, - 0.9606822425660947, - 0.9824349108378805, - 0.48960123994054394, - 0.5418283022915388, - 0.8412707228195404, - 0.7117366128115412, - 1.2792981029926656, - 1.200431062908973, - 0.7901172745397984, - 0.8981280632102917, - 0.5452045610826048, - 0.8663590225461809, - 0.6929932191811116, - 0.2588265140046349, - 0.7039942227014601, - 0.2742217803379954, - 0.504459105427192, - 0.5199522596034711, - 0.62597953911183, - 1.0435944866226887, - 0.6577885116272207, - 0.5650099068699643, - 0.4490846780324496, - 1.3430785271464998, - 1.142262454236171, - 0.6346986016397684, - 0.2865953219020086, - 0.19530973756051623, - 1.1447112538933928, - 1.367662564206789, - 0.38102312219626017, - 0.8292656866455711, - 0.777267398358757, - 0.28600508105457895, - 0.9761630463697777, - 0.622849462267499, - 0.2522951919540529, - 0.9468827960067999, - 0.43794101157049925, - 0.7010075046093125, - 0.1189023400415132, - 1.1959293031659233, - 0.849477208474895, - 1.0934360288790417, - 0.9773565293132962, - 0.48927275636415846, - 0.8313096442494344, - 0.3744253232382924, - 0.5268564446869717, - 0.33802865605582194, - 0.5249430384660696, - 0.6243972273466691, - 0.39888029626494703, - 0.19384371833083308, - 1.1450998582660805, - 0.08919399238257084, - 0.7866933793052904, - 0.6739693625567023, - 0.39447603928009467, - 1.032870458279164, - 0.6517181805823248, - 0.5462278142839979, - 0.43468982370668574, - 0.8807666292883145, - 0.535583589662179, - 0.30725075320625195, - 0.24400838454393775, - 0.7217194179540221, - 0.49943753457265216, - 0.9879848350716192, - 0.6397539331394319, - 0.19004703184019897, - 0.8430736944274474, - 1.1646912559844074, - 0.9500374153431089, - 0.4431011097650916, - 0.1358517225098266, - 0.3816983503496567, - 0.2734027662570491, - 0.7816697296690134, - 0.17264102023330116, - 0.6397732061925886, - 0.9727134547847681, - 0.4884817541453219, - 0.5153534913286036, - 0.6884565112874529, - 0.2821889370605011, - 0.18171114275940467, - 1.0238646640222304, - 0.5312036757045824, - 0.13708018059931698, - 0.10908203203508102, - 1.187844330026233, - 0.8234678520136302, - 0.867250037405063, - 0.5280545412466593, - 0.29298765566069757, - 0.2331119684994854, - 0.8207829720762455, - 0.3714881071395831, - 0.32529299461879857, - 0.5299622465209836, - 0.6218875130630758, - 0.27761677944132257, - 0.7344117376273341, - 0.4952243643300778, - 0.3926592728605549, - 0.8535099583622792, - 0.6442397533753098, - 0.4180782333604763, - 0.2409433056320422, - 0.7824022300069466, - 0.3027927077223924, - 0.6550368059503859, - 0.38444900185065894, - 1.1482329600700933, - 0.9519789512388735, - 0.060580882253723545, - 0.3816923021118775, - 0.19257650866758338, - 0.6438276289212486, - 0.11148017924313727, - 0.9684765768161862, - 0.08028721882900387, - 0.7842496487219783, - 0.09193695829466855, - 0.4482665888923368, - 0.2721624183103696, - 0.8561621559270862, - 0.28192108332583904, - 0.12812530881831327, - 0.1022029969166139, - 0.4869392994935116, - 0.502027655826873, - 0.1859802642666868, - 0.8121893548777561, - 0.3688192118317807, - 0.3154642616461757, - 0.6756161354062145, - 0.2786542931017233, - 0.17239019126750388, - 0.38764494496793006, - 1.0091693564839619, - 0.5082684416248578, - 0.7784557875594005, - 0.3034748623167903, - 0.5190743285546534, - 0.640507464448423, - 0.37666056704261075, - 0.22098632205470153, - 0.12755794902012385, - 0.48984474758340746, - 0.16601973443100057, - 0.5339786133263489, - 0.6185863797916844, - 0.27139680627083085, - 0.6361388553735544, - 0.20029926006564597, - 0.40163959663315296, - 0.232581415954885, - 0.7857430698310202, - 0.04064886014154843, - 0.6461618251759489, - 0.12143335100382315, - 0.9537647916055934, - 0.3810457264475656, - 0.11662315870272344, - 0.2707718275731995, - 0.19113966967629645, - 0.8048973447935833, - 0.07456956855621856, - 0.9609457914314185, - 0.4524011968793949, - 0.6654620677686393, - 0.27564461841532323, - 0.1654134978047173, - 0.09489139248107531, - 0.05538962624230017, - 0.7748124999748075, - 0.628763751660673, - 0.8385779629812827, - 0.26552252771486734, - 0.4846269413293837, - 0.3652365816241996, - 0.48863177584806516, - 0.18269227749188724, - 0.3041157980083019, - 0.10846041314090618, - 0.5362714057914194, - 0.6154381782036658, - 0.2664502831484185, - 0.38151419595140723, - 0.08726360691339036, - 0.6474703306111875, - 0.3036088813982311, - 0.36751657132302845, - 0.6294436265357662, - 0.1999183403172808, - 0.3891576520469917, - 0.22606778328384097, - 0.5097187036589822, - 0.12855778273226898, - 0.20936169478422986, - 0.12168225162688405, - 0.4838776323831572, - 0.16095027922066846, - 0.1897001511733311, - 0.07049009502330647, - 0.6570565217492003, - 0.3796506374040504, - 0.26867643894376625, - 0.11555836381974315, - 0.11193452442863465, - 0.6124842654624286, - 0.03778605693724704, - 0.7929431374080002, - 0.482283545810485, - 0.4782938175685489, - 0.17995502424142656, - 0.27181577867628687, - 0.15758542000860468, - 0.0570704314503577, - 0.6237387262108742, - 0.37924948437600586, - 0.08822802545228833, - 0.05196026936795638, - 0.7682964482449042, - 0.6105628167239305, - 0.502247236341904, - 0.1282941652548714, - 0.20080098532881438, - 0.11723141671996572, - 0.3611032638350682, - 0.2928802761150611, - 0.10587639125688059, - 0.2605471585193985, - 0.47886783088384827, - 0.15692300068049003, - 0.37499375353688147, - 0.08378971160423875, - 0.19897434129308406, - 0.218483801202603, - 0.3029957359976254, - 0.3582195132912819, - 0.3883811178827541, - 0.11628629425078416, - 0.19238242893327612, - 0.49003417113436026, - 0.4709207945548197, - 0.06675558654324969, - 0.025843406464136125, - 0.6474140875944007, - 0.2729289452234853, - 0.06531514680112217, - 0.4999824947905057, - 0.19450942266987922, - 0.08409306192210333, - 0.0501535763684259, - 0.48090644016409956, - 0.03652336440852907, - 0.17813366010665932, - 0.36400284358607593, - 0.28423070003244144, - 0.10402113897321216, - 0.27180502351511204, - 0.15049751807593523, - 0.05606619217111426, - 0.37370508841136557, - 0.08174997490641407, - 0.6201553441862678, - 0.3638735923280538, - 0.13189451721353904, - 0.35224849290304794, - 0.07012011109529989, - 0.11272110606715918, - 0.15236037922378579, - 0.25583632878103524, - 0.20370906009562176, - 0.21102859757421724, - 0.08042145551388168, - 0.11450808703206192, - 0.26940817822191465, - 0.06446058846330588, - 0.1890298072014, - 0.03516964099665347, - 0.3599724405816431, - 0.27750749150097737, - 0.06254585379774286, - 0.02463075395239731, - 0.45778222082838066, - 0.03490060843046899, - 0.3687153235755149, - 0.2676057440791352, - 0.1448204818805799, - 0.054476341129201536, - 0.0472651730338768, - 0.34624971790901565, - 0.4891481722249711, - 0.18450967020066855, - 0.17425792234569298, - 0.10133976826252562, - 0.25085886777306265, - 0.07848085739266623, - 0.06964059808513534, - 0.20529122630381336, - 0.12990903317526245, - 0.10766326009632754, - 0.14754395256487632, - 0.1862446006894729, - 0.03444040744713824, - 0.05948520227285855, - 0.023683713683422248, - 0.26406670855428793, - 0.14031929958532208, - 0.11243166358818434, - 0.06323600590529867, - 0.07507376362968197, - 0.24669876664761947, - 0.03307057280674311, - 0.2670564213867311, - 0.1710786276382489, - 0.05254919080349757, - 0.20059387111543683, - 0.044513590783645134, - 0.336679961089545, - 0.1038077051293141, - 0.0984517782779149, - 0.14371966777063166, - 0.0751842143887107, - 0.01559259099045098, - 0.03674273528485569, - 0.06885967441174741, - 0.057104823205109886, - 0.11063730228417895, - 0.03346893151645903, - 0.16837710274585108, - 0.02257444055398897, - 0.13343891534204733, - 0.06178162633117294, - 0.1007073467373077, - 0.042471442225472444, - 0.14055238322835578, - 0.031280948168247946, - 0.09609437285090261, - 0.050536303503963736, - 0.0726264120189156, - 0.1931878072042266, - 0.014980558154686598, - 0.036290411970244844, - 0.05355538573472793, - 0.04086359640260389, - 0.060520864856410284, - 0.03238209739944476, - 0.09410569269679359, - 0.021457164768928578, - 0.0299296085548296, - 0.07054524627613962, - 0.04893630055839461, - 0.09591344047647017, - 0.019902630830190192, - 0.014331642222965658, - 0.028851213767815274, - 0.03147715582928427, - 0.020593742773379987, - 0.0476119046649274, - 0.038431402299134304, - 0.01381143270758339, - 0.019893155135724604, - ], - &[ - 0.9846578039527537, - 1.1428160730074823, - 1.0157400591515289, - 0.9373047460961609, - 1.2103085838284144, - 1.07380338424002, - 0.7684689940081988, - 1.279756177030059, - 1.0152905000655528, - 1.1642827825647268, - 0.9054185397460988, - 0.7151559537863046, - 1.2343265971792428, - 1.0889723034278065, - 1.081155071172186, - 1.4074796700349008, - 0.8576943116723308, - 0.6600110308254856, - 1.272255932823374, - 0.9872479868239301, - 1.48432129739738, - 1.292121409884949, - 1.1839710135536405, - 0.7993933215340576, - 1.3624497500745392, - 1.0573263376094482, - 0.9340313158568363, - 0.9789908470120022, - 1.1496188075755744, - 0.7371970725332893, - 1.5406978615602802, - 1.3409488760478188, - 1.4355946161127415, - 1.2822835235784886, - 0.8676653081121799, - 0.9958318374399315, - 1.1410369005167196, - 1.3182029010165506, - 0.8742080239576873, - 1.5889255647986937, - 1.1285775441215042, - 1.2050474209514361, - 0.8006725383236973, - 1.4023158074558837, - 1.0441470853256825, - 1.3624965351669247, - 0.9256393810106471, - 0.7758755383370003, - 1.5551757094613372, - 1.0746134793831859, - 1.2332230932981874, - 0.7397398556906186, - 1.5862474289981363, - 1.3582616089812056, - 1.2521507744659113, - 1.6692556717199287, - 0.8570755114661468, - 1.4337975388185895, - 0.9366317385884309, - 0.6892153354401825, - 0.9823830541760954, - 1.4694780271336392, - 1.0972377744467945, - 1.0024251445418058, - 1.1724516252065078, - 1.3092148177448175, - 1.3130180505985327, - 0.7944817393203242, - 1.6197648163527454, - 1.3871576038465498, - 1.1648716107615382, - 1.0933977811302296, - 1.3105855965735682, - 0.8357125958674643, - 0.9308538130211269, - 1.5240726616291256, - 1.1412385927939876, - 0.8430627416646357, - 0.9865171167043952, - 1.5542168162471084, - 1.381798359764537, - 1.6458954233797203, - 1.0882356398263828, - 1.2024386157072753, - 1.2404177637653306, - 0.7465751526915569, - 0.865106603000001, - 1.4196734539347613, - 1.0180342736330041, - 1.5706646267023336, - 1.3231267552483184, - 1.5678119587857564, - 0.7201741664521962, - 1.3633041525327652, - 0.877309242102593, - 1.2240152798288562, - 1.020741963826803, - 0.9095039353275298, - 0.993604922759415, - 1.1869976325063978, - 1.275979707723701, - 1.1069931861796032, - 0.9980747423260864, - 1.1347014742230916, - 1.224588890765672, - 1.4591906825445102, - 1.6842968910850602, - 1.580170115049403, - 1.331250106457184, - 0.8743784539888663, - 0.6173438080570497, - 0.7867406929390685, - 0.9256099944955801, - 1.4511603892005631, - 1.0433756041894395, - 1.4110659168537616, - 0.9144772304267657, - 1.63025852876531, - 1.0546189730754731, - 1.1888734107091454, - 0.7483261051844592, - 1.0686505480953365, - 1.0970869647500705, - 1.4698861489035782, - 1.2189723306112468, - 1.2411587048698787, - 0.7130206006744954, - 1.5885268972221829, - 1.2525099247497116, - 0.7499926314230843, - 1.1168067383099014, - 0.876141993434363, - 0.8218642824510636, - 1.3415625634379356, - 0.9216610372261911, - 0.7978053893083532, - 1.449899126372724, - 1.476847705332237, - 1.0643599107324762, - 0.8986551842761088, - 0.9931546498056035, - 0.6119077542415317, - 0.958730452956305, - 1.4655467087600806, - 1.2153748480769544, - 0.9511690438337452, - 0.6470062788930065, - 1.2832716066971843, - 0.7469753236357717, - 1.1175355594302643, - 1.3220588863624538, - 1.0814358527904078, - 1.1238587216600255, - 0.7464007136663318, - 1.4974883808022084, - 1.6001740492661205, - 1.280607710647327, - 0.7726731654727896, - 0.7593100064751936, - 0.5018511539303819, - 0.628556346863019, - 0.9176382441374444, - 0.8635928996889607, - 1.088862050999555, - 0.6758071866581457, - 1.3508994977747555, - 0.9297936838034961, - 1.4616832908047759, - 1.5099417817784118, - 1.317248522833804, - 0.9897145568742565, - 0.8602587005242931, - 1.0036652631960274, - 1.2107885670764857, - 0.7949929843297018, - 0.7306809216448841, - 1.155281584464726, - 1.3082212623693805, - 1.0700622574801901, - 1.1508563395440718, - 0.9307748891420934, - 0.7871674899326594, - 0.6686885422849159, - 1.1313931149408478, - 0.62261286017232, - 0.48910638298216746, - 0.5626842094670441, - 1.3018566581004074, - 0.7902048244877213, - 1.5286966610628414, - 1.357305719686446, - 0.9356373989108703, - 0.5588945325201345, - 0.9394911004201509, - 0.7666886089854141, - 0.5109959784084821, - 0.9057518975700104, - 1.1129879282777555, - 0.588724232779656, - 0.9866267010492198, - 0.7258346814276995, - 1.1855512905528838, - 1.2970296895337297, - 1.0381642497510992, - 1.4545924111511648, - 1.1319581558817173, - 0.9155125549602462, - 0.8495586859659635, - 1.36924665875997, - 0.5127759686453649, - 0.6273850877628259, - 0.37895345058066043, - 0.6852864849654823, - 1.3185309443011708, - 1.0569801115861845, - 0.6653130207412206, - 0.46775802407243866, - 1.2053292541014717, - 0.7924848019354067, - 0.8873330176345925, - 0.709463728750861, - 0.8275941505981728, - 1.3618545740162549, - 0.8101625400764274, - 1.137984443388146, - 0.6297091701401701, - 0.37780105841922934, - 0.3555889579323264, - 0.7718967693611626, - 0.4073147972841343, - 0.9379627144439735, - 0.9417215253305974, - 0.40841887927808795, - 1.0656964423715485, - 1.1308745373618423, - 0.6048295878380807, - 1.116831432639867, - 0.9606624861471456, - 0.9824167577119173, - 0.4895856564395406, - 0.5418360230853796, - 0.8412559814492886, - 0.7117348654791876, - 1.2792802912893553, - 1.2004116653663646, - 0.790099763177358, - 0.8981249071897095, - 0.5452031847098657, - 0.8663640824453414, - 0.6929997931282208, - 0.2588219479216775, - 0.7039791205320579, - 0.2742098731754484, - 0.5044456800268781, - 0.5199457102788779, - 0.6259626435336597, - 1.0435773559241601, - 0.6577737778175918, - 0.5649906498610809, - 0.4490682528462317, - 1.3430483894075582, - 1.1422534120289813, - 0.6346914252671366, - 0.2865947310563475, - 0.1953062739024531, - 1.1446845911181278, - 1.3676514520743444, - 0.3810067177635386, - 0.8292443239788192, - 0.7772584922116912, - 0.28601703850852, - 0.9761373392785603, - 0.6228324356458697, - 0.25228338634547637, - 0.9468728734844488, - 0.43793381623448996, - 0.7010041274302387, - 0.11890725155914843, - 1.1959078247835222, - 0.8494843519713849, - 1.093429820886188, - 0.9773360735547205, - 0.4892548842151652, - 0.8312922239345566, - 0.37441121542620937, - 0.5268667040132265, - 0.3380138730026699, - 0.5249354739703403, - 0.624378470809524, - 0.39887809500471666, - 0.1938428421936126, - 1.1450895383784212, - 0.0891971965278184, - 0.7866736607280926, - 0.6739781420218406, - 0.39448788345605695, - 1.0328511371871365, - 0.6517015758940885, - 0.546206443863707, - 0.434671546446116, - 0.8807609660496004, - 0.5355802222926985, - 0.3072459351055423, - 0.244004851993911, - 0.7216983581765535, - 0.49942189332714976, - 0.9879551615628381, - 0.6397449531622061, - 0.19006204680893152, - 0.8430472055480123, - 1.1646546766435881, - 0.9500261049935138, - 0.44309295746946314, - 0.1358508368580552, - 0.3816798883703529, - 0.27338858345420075, - 0.7816594872622985, - 0.17262952798760126, - 0.6397509940282039, - 0.9726910710714768, - 0.4884622629659889, - 0.5153657418426606, - 0.6884509239552447, - 0.28218636625825777, - 0.18170891100341025, - 1.0238439287023562, - 0.5311811833193738, - 0.13708520263317062, - 0.10908610193612234, - 1.1878206615564184, - 0.8234762987257431, - 0.8672424312807067, - 0.5280495815684301, - 0.29298241979657735, - 0.2331079650356981, - 0.820763509785017, - 0.37147228895234624, - 0.3252756847422742, - 0.5299536379931126, - 0.6218668446139202, - 0.27763204938804253, - 0.7343860672871082, - 0.4952074058083206, - 0.3926552058993296, - 0.8534805047331688, - 0.644221492210066, - 0.4180578029425472, - 0.240928330943711, - 0.7823803899835161, - 0.3027738899198869, - 0.655047593734567, - 0.3844632038265053, - 1.1482202916378605, - 0.9519668772892353, - 0.06058343369547032, - 0.38167253670303064, - 0.19257382120816555, - 0.6438172091646727, - 0.11146891090483704, - 0.9684526984060637, - 0.08029077342204308, - 0.784238199792356, - 0.09193586513484762, - 0.4482575170750042, - 0.2721469210969564, - 0.8561533830245281, - 0.2819164066773412, - 0.12813046873071404, - 0.10220710512214042, - 0.48691833789062233, - 0.5020412820874053, - 0.18599812753581396, - 0.8121687517652941, - 0.36880251167109485, - 0.3154454270385834, - 0.6756084201143353, - 0.2786501203117945, - 0.1723867699420482, - 0.387639637609794, - 1.0091468735648987, - 0.508242653901033, - 0.7784327379188821, - 0.30345497136360333, - 0.5190677038536843, - 0.640519131922536, - 0.376675995333094, - 0.22098157991684783, - 0.1275551497757849, - 0.4898267085245536, - 0.16600542275125038, - 0.5339688360762072, - 0.6185641988968787, - 0.27141389525603604, - 0.6361194803550576, - 0.2002839895666459, - 0.40161785054677474, - 0.23256506030896762, - 0.7857309561801054, - 0.04065046670367107, - 0.6461505408858991, - 0.12143921594383017, - 0.9537508522799212, - 0.3810247878512162, - 0.11664293801399515, - 0.2707557030633519, - 0.19113601535066962, - 0.8048760900903663, - 0.07457312461046703, - 0.9609205429919944, - 0.4523912217352152, - 0.665453663970266, - 0.2756399732493783, - 0.16540985711143172, - 0.09489567150271352, - 0.055392149520247014, - 0.7747885225815303, - 0.6287763081282781, - 0.8385676335778723, - 0.26551657566497, - 0.4846048820850437, - 0.3652190692671813, - 0.4886462194400875, - 0.1827114511884209, - 0.304095413528203, - 0.10844705733961149, - 0.5362608855801766, - 0.6154151421132362, - 0.2664682045031514, - 0.3815082477808231, - 0.08726084978323194, - 0.6474589415643739, - 0.30358803667695256, - 0.3675329660581807, - 0.6294234133875171, - 0.19990241405851114, - 0.38913394620793723, - 0.22604998240670895, - 0.5097114350346291, - 0.12855446997582357, - 0.20935662686035392, - 0.12167883056579297, - 0.4838588368279654, - 0.1609349028517144, - 0.1896934654087842, - 0.0704866079064006, - 0.6570342740496697, - 0.3796227170901338, - 0.2686507535162928, - 0.11557361441637819, - 0.11191723380548069, - 0.6124495482858422, - 0.037777293458026176, - 0.7928897019411747, - 0.48224943390257385, - 0.47826025307398207, - 0.17995845261781546, - 0.2717920010683322, - 0.15754196870719447, - 0.057054577712252835, - 0.6236890174560398, - 0.3791564610675984, - 0.08820066551006676, - 0.0519446513225905, - 0.7682570978380291, - 0.6105065905277058, - 0.502204521901495, - 0.12828104113130173, - 0.20074218906532487, - 0.11719705552286333, - 0.3610660680354089, - 0.29280769673410617, - 0.10584569115912862, - 0.2605410204316948, - 0.47882891946942724, - 0.15688498146540839, - 0.37496548143410047, - 0.08376904903991991, - 0.19895111534561313, - 0.21844432385379636, - 0.3029691060288074, - 0.35821569226438876, - 0.3883537708422474, - 0.11630035287251823, - 0.19236766318623888, - 0.4900043001447056, - 0.47089459397751593, - 0.06673990712378386, - 0.025838069420445763, - 0.6473659837086239, - 0.27289944730778637, - 0.0652972997883429, - 0.4999458645441742, - 0.19446263958430418, - 0.08407243442038238, - 0.05014174910893161, - 0.48087086803902285, - 0.03651659529935935, - 0.1781423051559216, - 0.3639734316244291, - 0.2841810936875253, - 0.1039990891343954, - 0.2717878667136994, - 0.150470552840648, - 0.05605613940226065, - 0.37368633362850345, - 0.08173837509096951, - 0.620123808420381, - 0.3638271009783325, - 0.1318876928617264, - 0.35225359836990383, - 0.07014080377359379, - 0.1127095422717575, - 0.15234170453324902, - 0.25585073477479553, - 0.20369121020089143, - 0.21101041848590366, - 0.08042702010861291, - 0.11452904880661925, - 0.26938952867501825, - 0.06444846126207517, - 0.18902512048581, - 0.035168215493436586, - 0.3599526410857824, - 0.27748698962877094, - 0.06255033639861617, - 0.024632615880804905, - 0.4577961549745699, - 0.0349031735372127, - 0.3687082462467413, - 0.26760007827270466, - 0.14481846478948573, - 0.05447485419554104, - 0.0472685671673231, - 0.3462658925090089, - 0.4891394297692007, - 0.18450728997176272, - 0.17427770797339237, - 0.10132569893693144, - 0.2508769475567074, - 0.07847918438097932, - 0.06966274513561732, - 0.20527245136019176, - 0.1299055869072704, - 0.1076613674931596, - 0.1475275362546755, - 0.1862405092051298, - 0.03443920650065171, - 0.0594897375351457, - 0.023685523090850816, - 0.2640614762666253, - 0.14031786384774558, - 0.11245293194014107, - 0.06322288701673176, - 0.07507968155152947, - 0.246716946916963, - 0.033073183194136144, - 0.2670346358960148, - 0.17109854489275034, - 0.05254813042832415, - 0.2005747243295308, - 0.0445170914555632, - 0.336695887032949, - 0.10380654121052656, - 0.09843676344528281, - 0.1437025649636455, - 0.07518308738816534, - 0.015593708397882409, - 0.03673027551266197, - 0.06888206764359746, - 0.05710916700940627, - 0.11065863757864756, - 0.033468000516455834, - 0.16839696705440485, - 0.022576171498287372, - 0.13343838317306927, - 0.06176774676398228, - 0.10070683579684733, - 0.04247506594430676, - 0.1405350156684872, - 0.031283580385173926, - 0.09607887943495196, - 0.050535646007401284, - 0.07262585482828961, - 0.1931678793222537, - 0.014981629285630805, - 0.036277308422216936, - 0.05355986280268147, - 0.04086694668560617, - 0.06050650034922825, - 0.0323814211886023, - 0.09408973918545771, - 0.021458813392771746, - 0.02993210736141958, - 0.07054484943455624, - 0.04893586040241371, - 0.09591350510261923, - 0.019902048716216418, - 0.014332669765393097, - 0.028853689269610825, - 0.031476696135032706, - 0.020595366637073804, - 0.0476115689696842, - 0.03843480451999081, - 0.013812447488514188, - 0.019894872558384832, - ], - ); - } - - #[test] - #[ignore] - fn evolve_atlaspht15() { - execute_evolve_test( - "NNPDF40_nlo_as_01180", - "../ATLASPHT15-ATLASPHT15_Et_3bin.pineappl.lz4", - "../ATLASPHT15-ATLASPHT15_Et_3bin/metadata.yaml", - "../ATLASPHT15-ATLASPHT15_Et_3bin/alphas.npy", - "../ATLASPHT15-ATLASPHT15_Et_3bin/operators.npy", - &[ - 847.6443451935788, - 389.2518461733433, - 197.52262245783854, - 85.5341661018376, - 30.87251252799057, - 12.857919383339262, - 5.881543988434407, - 2.5226447467912503, - 0.9852473741631275, - 0.33567120929573163, - 0.1103227781235781, - 0.03105085344647281, - 0.005857170880761543, - ], - &[ - 846.9388599419221, - 388.9452263757685, - 197.35723798133498, - 85.45945643409014, - 30.84568815110067, - 12.847951715560423, - 5.876789744699159, - 2.5205570958215677, - 0.9845342100753295, - 0.33542931711292495, - 0.11024603718181779, - 0.031033712901365054, - 0.005854961951848535, - ], - ); - } } From de501f4657a11d1a5da2a2e1f94f0896b4660424 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 17 Oct 2022 13:41:22 +0200 Subject: [PATCH 54/73] Comment out ignored unit test --- pineappl/src/bin.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pineappl/src/bin.rs b/pineappl/src/bin.rs index a504d5dd..27579f67 100644 --- a/pineappl/src/bin.rs +++ b/pineappl/src/bin.rs @@ -902,14 +902,14 @@ mod test { assert_eq!(remapper.slices(), [(0, 1)]); } - #[test] - #[ignore] // FIXME: there's a bug in the `slices` method - #[should_panic] - fn bin_remapper_merge_bins_panic() { - let mut remapper = - BinRemapper::new(vec![1.0; 3], vec![(0.0, 0.25), (0.5, 0.75), (0.75, 1.0)]).unwrap(); - - //assert_eq!(remapper.slices(), [(0, 1), (1, 3)]); - remapper.merge_bins(0..3).unwrap(); - } + //#[test] + //#[ignore] // FIXME: there's a bug in the `slices` method + //#[should_panic] + //fn bin_remapper_merge_bins_panic() { + // let mut remapper = + // BinRemapper::new(vec![1.0; 3], vec![(0.0, 0.25), (0.5, 0.75), (0.75, 1.0)]).unwrap(); + + // //assert_eq!(remapper.slices(), [(0, 1), (1, 3)]); + // remapper.merge_bins(0..3).unwrap(); + //} } From f91e7cab61bd8327401ecdb9f8a516c87de79be8 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 17 Oct 2022 13:59:38 +0200 Subject: [PATCH 55/73] Test evolutions with `LHCB_WP_8TEV` --- .github/actions/lhapdf/action.yaml | 1 + .github/workflows/rust.yml | 6 ++- pineappl_cli/tests/evolve.rs | 66 ++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 pineappl_cli/tests/evolve.rs diff --git a/.github/actions/lhapdf/action.yaml b/.github/actions/lhapdf/action.yaml index bbff0f3b..6dd9692d 100644 --- a/.github/actions/lhapdf/action.yaml +++ b/.github/actions/lhapdf/action.yaml @@ -27,4 +27,5 @@ runs: lhapdf update lhapdf install NNPDF31_nlo_as_0118_luxqed lhapdf install NNPDF40_nnlo_as_01180 + lhapdf install NNPDF40_nlo_as_01180 shell: bash diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3b31431a..b227cee3 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -42,11 +42,15 @@ jobs: with: default: true toolchain: nightly + - name: Download test data + run: | + wget -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.pineappl.lz4' + wget -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.tar' - name: Run tests uses: actions-rs/cargo@v1 with: command: test - args: --all-features --verbose -- --skip import_applgrid --skip import_photon_grid + args: --all-features --verbose -- --include-ignored --skip import_applgrid --skip import_photon_grid env: CARGO_INCREMENTAL: '0' RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs new file mode 100644 index 00000000..079c6a3b --- /dev/null +++ b/pineappl_cli/tests/evolve.rs @@ -0,0 +1,66 @@ +use assert_cmd::Command; +use assert_fs::NamedTempFile; + +const HELP_STR: &str = "pineappl-evolve +Evolve a grid with an evolution kernel operator to an FK table + +USAGE: + pineappl evolve [OPTIONS] + +ARGS: + Path to the input grid + Path to the evolution kernel operator + Path to the converted grid + LHAPDF id or name of the PDF set to check the converted grid with + +OPTIONS: + --accuracy Relative threshold between the table and the converted grid when + comparison fails [default: 1e-3] + --digits-abs Set the number of fractional digits shown for absolute numbers + [default: 7] + --digits-rel Set the number of fractional digits shown for relative numbers + [default: 7] + -h, --help Print help information +"; + +const LHCB_WP_7TEV_STR: &str = "b FkTable Grid rel. diff +-+-----------+-----------+------------- +0 7.7911994e2 7.7891206e2 -2.6680685e-4 +1 7.1170872e2 7.1152118e2 -2.6351282e-4 +2 6.1766223e2 6.1750067e2 -2.6157398e-4 +3 4.9817054e2 4.9804168e2 -2.5866843e-4 +4 3.7040220e2 3.7030899e2 -2.5164930e-4 +5 2.5123713e2 2.5117697e2 -2.3945309e-4 +6 1.1883712e2 1.1881217e2 -2.0989153e-4 +7 2.9013827e1 2.9010212e1 -1.2459216e-4 +"; + +#[test] +fn help() { + Command::cargo_bin("pineappl") + .unwrap() + .args(&["evolve", "--help"]) + .assert() + .success() + .stdout(HELP_STR); +} + +#[test] +#[ignore] +fn lhcb_wp_7tev() { + let output = NamedTempFile::new("fktable1.lz4").unwrap(); + + Command::cargo_bin("pineappl") + .unwrap() + .args(&[ + "--silence-lhapdf", + "evolve", + "../test-data/LHCB_WP_7TEV.pineappl.lz4", + "../test-data/LHCB_WP_7TEV.tar", + output.path().to_str().unwrap(), + "NNPDF40_nlo_as_01180", + ]) + .assert() + .success() + .stdout(LHCB_WP_7TEV_STR); +} From 6511fe744d240080ee34907f46e979f82348c237 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 17 Oct 2022 14:20:23 +0200 Subject: [PATCH 56/73] Reduce verbosity of wget in CI --- .github/workflows/rust.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b227cee3..7718f48c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -44,8 +44,8 @@ jobs: toolchain: nightly - name: Download test data run: | - wget -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.pineappl.lz4' - wget -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.tar' + wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.pineappl.lz4' + wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.tar' - name: Run tests uses: actions-rs/cargo@v1 with: From 5f485fff0a4ee71c7b17e5cbb1202ce13bcb1860 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 17 Oct 2022 14:20:49 +0200 Subject: [PATCH 57/73] Test DIS evolution --- .github/workflows/rust.yml | 2 ++ pineappl_cli/tests/evolve.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7718f48c..e198190c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -44,6 +44,8 @@ jobs: toolchain: nightly - name: Download test data run: | + wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.pineappl.lz4' + wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.tar' wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.pineappl.lz4' wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.tar' - name: Run tests diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index 079c6a3b..43a79fd2 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -23,6 +23,16 @@ OPTIONS: -h, --help Print help information "; +const E906NLO_BIN_00_STR: &str = "b FkTable Grid rel. diff +-+------------+------------+------------- +0 1.0659807e-1 1.0657910e-1 -1.7800240e-4 +1 1.0659807e-1 1.0657910e-1 -1.7800240e-4 +2 1.0659807e-1 1.0657910e-1 -1.7800240e-4 +3 1.0659807e-1 1.0657910e-1 -1.7800240e-4 +4 3.2698655e0 3.2710283e0 3.5561489e-4 +5 1.6039253e0 1.6047363e0 5.0563376e-4 +"; + const LHCB_WP_7TEV_STR: &str = "b FkTable Grid rel. diff -+-----------+-----------+------------- 0 7.7911994e2 7.7891206e2 -2.6680685e-4 @@ -64,3 +74,23 @@ fn lhcb_wp_7tev() { .success() .stdout(LHCB_WP_7TEV_STR); } + +#[test] +#[ignore] +fn e906nlo_bin_00() { + let output = NamedTempFile::new("fktable2.lz4").unwrap(); + + Command::cargo_bin("pineappl") + .unwrap() + .args(&[ + "--silence-lhapdf", + "evolve", + "../test-data/E906nlo_bin_00.pineappl.lz4", + "../test-data/E906nlo_bin_00.tar", + output.path().to_str().unwrap(), + "NNPDF40_nlo_as_01180", + ]) + .assert() + .success() + .stdout(E906NLO_BIN_00_STR); +} From 4e13e5ff5ddfd6e9499e405aa4b91090c8b05726 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 17 Oct 2022 14:54:09 +0200 Subject: [PATCH 58/73] Add real DIS test --- .github/workflows/rust.yml | 2 + pineappl_cli/tests/evolve.rs | 71 ++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e198190c..6e765f6a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -48,6 +48,8 @@ jobs: wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.tar' wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.pineappl.lz4' wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.tar' + wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/NUTEV_CC_NU_FE_SIGMARED.pineappl.lz4' + wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/NUTEV_CC_NU_FE_SIGMARED.tar' - name: Run tests uses: actions-rs/cargo@v1 with: diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index 43a79fd2..092424af 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -45,6 +45,55 @@ const LHCB_WP_7TEV_STR: &str = "b FkTable Grid rel. diff 7 2.9013827e1 2.9010212e1 -1.2459216e-4 "; +const NUTEV_CC_NU_FE_SIGMARED_STR: &str = "b FkTable Grid rel. diff +--+-----------+-----------+------------- +0 8.2920022e0 1.1046839e1 3.3222819e-1 +1 1.3975037e1 1.4232414e1 1.8416931e-2 +2 1.9422915e1 1.8434111e1 -5.0909145e-2 +3 1.4891673e1 1.4867720e1 -1.6084417e-3 +4 1.4086222e1 1.4088115e1 1.3438079e-4 +5 2.2998409e1 2.2998443e1 1.4697729e-6 +6 2.1899598e1 2.1899091e1 -2.3138103e-5 +7 1.5578822e1 1.5578334e1 -3.1319781e-5 +8 2.2226765e1 2.2225956e1 -3.6375906e-5 +9 1.3669291e1 1.3669038e1 -1.8446253e-5 +10 2.5946596e1 2.5945504e1 -4.2110358e-5 +11 1.8363999e1 1.8363361e1 -3.4704937e-5 +12 1.5819602e1 1.5819077e1 -3.3204532e-5 +13 2.5959140e1 2.5957783e1 -5.2285210e-5 +14 2.0457793e1 2.0456964e1 -4.0496689e-5 +15 1.1393262e1 1.1392626e1 -5.5781822e-5 +16 1.4106814e1 1.4106786e1 -1.9959280e-6 +17 1.9464293e1 1.9463520e1 -3.9713070e-5 +18 1.5721645e1 1.5721550e1 -6.0470703e-6 +19 1.4033170e1 1.4033158e1 -8.5170032e-7 +20 1.9366211e1 1.9365482e1 -3.7645378e-5 +21 2.1174542e1 2.1173688e1 -4.0315154e-5 +22 1.6606739e1 1.6606635e1 -6.2333155e-6 +23 1.1354320e1 1.1353660e1 -5.8066443e-5 +24 5.5456589e0 5.5455822e0 -1.3826910e-5 +25 1.2257404e1 1.2256637e1 -6.2534396e-5 +26 1.5838419e1 1.5838379e1 -2.5004885e-6 +27 2.0844501e1 2.0844671e1 8.1437423e-6 +28 1.1127050e1 1.1126496e1 -4.9723938e-5 +29 1.3257033e1 1.3256687e1 -2.6046580e-5 +30 1.6809659e1 1.6810591e1 5.5429049e-5 +31 1.7616888e1 1.7618088e1 6.8090881e-5 +32 5.8908612e0 5.8906267e0 -3.9802439e-5 +33 1.2668418e1 1.2667676e1 -5.8532882e-5 +34 6.1718100e0 6.1715800e0 -3.7259928e-5 +35 1.6993748e1 1.6993216e1 -3.1306297e-5 +36 5.5089321e0 5.5087361e0 -3.5579336e-5 +37 1.2163126e1 1.2162352e1 -6.3616512e-5 +38 1.2575328e1 1.2574501e1 -6.5776146e-5 +39 5.9912886e0 5.9910701e0 -3.6479256e-5 +40 5.5396399e0 5.5394441e0 -3.5343558e-5 +41 1.2035714e1 1.2034895e1 -6.7972844e-5 +42 5.1605061e0 5.1603299e0 -3.4143438e-5 +43 5.3541916e0 5.3540055e0 -3.4757362e-5 +44 4.9727490e0 4.9725844e0 -3.3105968e-5 +"; + #[test] fn help() { Command::cargo_bin("pineappl") @@ -94,3 +143,25 @@ fn e906nlo_bin_00() { .success() .stdout(E906NLO_BIN_00_STR); } + +#[test] +#[ignore] +fn nutev_cc_nu_fe_sigmared() { + let output = NamedTempFile::new("fktable3.lz4").unwrap(); + + // TODO: find out the reason why this evolution fails + Command::cargo_bin("pineappl") + .unwrap() + .args(&[ + "--silence-lhapdf", + "evolve", + "../test-data/NUTEV_CC_NU_FE_SIGMARED.pineappl.lz4", + "../test-data/NUTEV_CC_NU_FE_SIGMARED.tar", + output.path().to_str().unwrap(), + "NNPDF40_nlo_as_01180", + ]) + .assert() + .failure() + .stderr("Error: grids are different\n") + .stdout(NUTEV_CC_NU_FE_SIGMARED_STR); +} From 8d5842385ae2fa5cc43f72da0706300020ab0b2d Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 17 Oct 2022 15:03:03 +0200 Subject: [PATCH 59/73] Cache test data in CI --- .github/workflows/rust.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6e765f6a..c7745d0f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -42,14 +42,21 @@ jobs: with: default: true toolchain: nightly + - name: Get test data + id: cache-test-data + uses: actions/cache@v3 + with: + path: test-data + key: test-data-v1 - name: Download test data + if: steps.cache-test-data.outputs.cache-hit != 'true' run: | - wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.pineappl.lz4' - wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.tar' - wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.pineappl.lz4' - wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.tar' - wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/NUTEV_CC_NU_FE_SIGMARED.pineappl.lz4' - wget --no-verbose -P test-data 'https://data.nnpdf.science/pineappl/test-data/NUTEV_CC_NU_FE_SIGMARED.tar' + wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.pineappl.lz4' + wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.tar' + wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.pineappl.lz4' + wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.tar' + wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/NUTEV_CC_NU_FE_SIGMARED.pineappl.lz4' + wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/NUTEV_CC_NU_FE_SIGMARED.tar' - name: Run tests uses: actions-rs/cargo@v1 with: From 5407d6d33043de475a13b24cafb6b51de8bc5469 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Tue, 18 Oct 2022 12:23:08 +0200 Subject: [PATCH 60/73] Update Python doc --- pineappl_py/src/grid.rs | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index db56a4a3..620afe2b 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -459,29 +459,33 @@ impl PyGrid { } } - /// Convolute with with an evolution operator. + /// Convolute with grid with an evolution operator. /// /// Parameters /// ---------- - /// muf2_0 : float + /// operator : numpy.ndarray(int, rank=5) + /// evolution tensor + /// fac0 : float /// reference scale - /// alphas : numpy.ndarray(float) - /// list with :math:`\alpha_s(Q2)` for the process scales - /// pids : numpy.ndarray(int) - /// sorting of the particles in the tensor - /// x_grid : numpy.ndarray(float) - /// interpolation grid - /// target_pids : numpy.ndarray(int) + /// pids0 : numpy.ndarray(int) /// sorting of the particles in the tensor for final FkTable - /// target_x_grid : numpy.ndarray(float) + /// x0 : numpy.ndarray(float) /// final FKTable interpolation grid - /// mur2_grid : numpy.ndarray(float) - /// list of renormalization scales - /// muf2_grid : numpy.ndarray(float) + /// fac1 : numpy.ndarray(float) /// list of factorization scales - /// operator : numpy.ndarray(int, rank=5) - /// evolution tensor - /// orders_mask : numpy.ndarray(bool) + /// pids1 : numpy.ndarray(int) + /// sorting of the particles in the grid + /// x1 : numpy.ndarray(float) + /// interpolation grid at process level + /// ren1 : numpy.ndarray(float) + /// list of renormalization scales + /// alphas : numpy.ndarray(float) + /// list with :math:`\alpha_s(Q2)` for the process scales + /// xi : (float, float) + /// factorization and renormalization variation + /// lumi_id_types : str + /// type of luminosity identifier + /// order_mask : numpy.ndarray(bool) /// boolean mask to activate orders /// /// Returns From 7b6fdb2100e1bd240d2401e3118fc3f58bce156e Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Tue, 18 Oct 2022 14:15:19 +0200 Subject: [PATCH 61/73] Add gluon exception --- pineappl/src/evolution.rs | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index dd48cae9..48250915 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -53,9 +53,24 @@ pub struct OperatorInfo { pub lumi_id_types: String, } +fn gluon_has_pid_zero(grid: &Grid) -> bool { + if grid.key_values().map_or(false, |key_values| { + key_values + .get("lumi_id_types") + .map_or(false, |value| value == "pdg_mc_ids") + }) { + grid.lumi() + .iter() + .any(|entry| entry.entry().iter().any(|&(a, b, _)| (a == 0) || (b == 0))) + } else { + false + } +} + pub(crate) fn pids( operator: &Array5, info: &OperatorInfo, + gluon_has_pid_zero: bool, pid1_nonzero: &dyn Fn(i32) -> bool, ) -> (Vec<(usize, usize)>, Vec<(i32, i32)>) { // list of all non-zero PID indices @@ -75,7 +90,16 @@ pub(crate) fn pids( // list of all non-zero (pid0, pid1) combinations let pids = pid_indices .iter() - .map(|&(pid0_idx, pid1_idx)| (info.pids0[pid0_idx], info.pids1[pid1_idx])) + .map(|&(pid0_idx, pid1_idx)| { + ( + info.pids0[pid0_idx], + if gluon_has_pid_zero && info.pids1[pid1_idx] == 21 { + 0 + } else { + info.pids1[pid1_idx] + }, + ) + }) .collect(); (pid_indices, pids) @@ -287,9 +311,10 @@ pub(crate) fn evolve_with_one( info: &OperatorInfo, order_mask: &[bool], ) -> Result<(Array3, Vec), GridError> { + let gluon_has_pid_zero = gluon_has_pid_zero(grid); let has_pdf1 = grid.has_pdf1(); - let (pid_indices, pids) = pids(operator, info, &|pid| { + let (pid_indices, pids) = pids(operator, info, gluon_has_pid_zero, &|pid| { grid.lumi() .iter() .flat_map(LumiEntry::entry) @@ -426,13 +451,15 @@ pub(crate) fn evolve_with_two( info: &OperatorInfo, order_mask: &[bool], ) -> Result<(Array3, Vec), GridError> { - let (pid_indices_a, pids_a) = pids(operator, info, &|pid1| { + let gluon_has_pid_zero = gluon_has_pid_zero(grid); + + let (pid_indices_a, pids_a) = pids(operator, info, gluon_has_pid_zero, &|pid1| { grid.lumi() .iter() .flat_map(LumiEntry::entry) .any(|&(a, _, _)| a == pid1) }); - let (pid_indices_b, pids_b) = pids(operator, info, &|pid1| { + let (pid_indices_b, pids_b) = pids(operator, info, gluon_has_pid_zero, &|pid1| { grid.lumi() .iter() .flat_map(LumiEntry::entry) From 8c4274ed74b997137f48843ad08689bfac868baf Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Tue, 18 Oct 2022 14:37:36 +0200 Subject: [PATCH 62/73] Add missing to gluon exception --- pineappl/src/evolution.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 48250915..857ab2c6 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -83,7 +83,11 @@ pub(crate) fn pids( .slice(s![.., pid1_idx, .., pid0_idx, ..]) .iter() .any(|&value| value != 0.0) - && pid1_nonzero(info.pids1[pid1_idx]) + && pid1_nonzero(if gluon_has_pid_zero && info.pids1[pid1_idx] == 21 { + 0 + } else { + info.pids1[pid1_idx] + }) }) .collect(); From 7884fa106a87703a35f7dd6ac43eb0a6fc599fac Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Tue, 18 Oct 2022 14:38:16 +0200 Subject: [PATCH 63/73] Fix clippy warnings --- pineappl/src/evolution.rs | 16 ++++++---------- pineappl/src/grid.rs | 4 ++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 857ab2c6..95563655 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -203,8 +203,8 @@ pub(crate) fn ndarray_from_subgrid_orders( .flat_map(|subgrid| { subgrid .mu2_grid() - .into_owned() - .into_iter() + .iter() + .cloned() .map(|mu2| mu2.fac) .collect::>() }) @@ -338,7 +338,7 @@ pub(crate) fn evolve_with_one( for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { let (fac1, x1_a, x1_b, array) = - ndarray_from_subgrid_orders(info, &subgrids_o, &grid.orders(), order_mask)?; + ndarray_from_subgrid_orders(info, &subgrids_o, grid.orders(), order_mask)?; let x1 = if has_pdf1 { x1_a } else { x1_b }; @@ -416,11 +416,7 @@ pub(crate) fn evolve_with_one( fac: info.fac0, }], if has_pdf1 { info.x0.clone() } else { vec![1.0] }, - if !has_pdf1 { - info.x0.clone() - } else { - vec![1.0] - }, + if has_pdf1 { vec![1.0] } else { info.x0.clone() }, ) .into() })); @@ -441,7 +437,7 @@ pub(crate) fn evolve_with_one( .map(|&a| { lumi_entry![ if has_pdf1 { a } else { pid }, - if !has_pdf1 { a } else { pid }, + if has_pdf1 { pid } else { a }, 1.0 ] }) @@ -484,7 +480,7 @@ pub(crate) fn evolve_with_two( for (lumi1, subgrids_o) in subgrids_ol.axis_iter(Axis(1)).enumerate() { let (fac1, x1_a, x1_b, array) = - ndarray_from_subgrid_orders(info, &subgrids_o, &grid.orders(), order_mask)?; + ndarray_from_subgrid_orders(info, &subgrids_o, grid.orders(), order_mask)?; let fac1_diff = (last_fac1.len() != fac1.len()) || last_fac1 diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index b1a1ba5b..c86de481 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1944,6 +1944,7 @@ impl Grid { } /// Returns `true` if the first initial state needs a convolution, `false` otherwise. + #[must_use] pub fn has_pdf1(&self) -> bool { let initial_state_1 = self.initial_state_1(); @@ -1954,6 +1955,7 @@ impl Grid { } /// Returns `true` if the second initial state needs a convolution, `false` otherwise. + #[must_use] pub fn has_pdf2(&self) -> bool { let initial_state_2 = self.initial_state_2(); @@ -1965,6 +1967,7 @@ impl Grid { /// Returns the particle identifier of the first initial state. This is usually but not always /// a proton, which is represented by the PDG ID `2212`. + #[must_use] pub fn initial_state_1(&self) -> i32 { self.key_values() .map_or(Some("2212"), |kv| { @@ -1977,6 +1980,7 @@ impl Grid { /// Returns the particle identifier of the second initial state. This is usually but not always /// a proton, which is represented by the PDG ID `2212`. + #[must_use] pub fn initial_state_2(&self) -> i32 { self.key_values() .map_or(Some("2212"), |kv| { From 932e073924b8d499e37f8915d340c92e8369bc9a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Tue, 18 Oct 2022 14:50:35 +0200 Subject: [PATCH 64/73] Add integration test for gluon exception --- pineappl_cli/tests/evolve.rs | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index 092424af..63d0b71b 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -33,6 +33,28 @@ const E906NLO_BIN_00_STR: &str = "b FkTable Grid rel. diff 5 1.6039253e0 1.6047363e0 5.0563376e-4 "; +const LHCB_DY_8TEV_STR: &str = "b FkTable Grid rel. diff +--+------------+------------+------------- +0 8.1098384e0 8.1077663e0 -2.5550537e-4 +1 2.3743076e1 2.3737363e1 -2.4059398e-4 +2 3.8047878e1 3.8038820e1 -2.3808089e-4 +3 5.0883597e1 5.0870965e1 -2.4825643e-4 +4 6.1803061e1 6.1786970e1 -2.6035384e-4 +5 7.0086849e1 7.0068287e1 -2.6483200e-4 +6 7.5526963e1 7.5506936e1 -2.6516554e-4 +7 7.7701083e1 7.7680621e1 -2.6334886e-4 +8 7.6395213e1 7.6375564e1 -2.5721140e-4 +9 7.1337740e1 7.1320163e1 -2.4638218e-4 +10 6.1083107e1 6.1068812e1 -2.3403347e-4 +11 4.7617019e1 4.7606056e1 -2.3023324e-4 +12 3.4090165e1 3.4081756e1 -2.4667862e-4 +13 2.2027068e1 2.2021463e1 -2.5446838e-4 +14 1.2535284e1 1.2532680e1 -2.0773561e-4 +15 5.9288895e0 5.9282771e0 -1.0328299e-4 +16 1.3830183e0 1.3832217e0 1.4703176e-4 +17 5.1352256e-2 5.1398317e-2 8.9695182e-4 +"; + const LHCB_WP_7TEV_STR: &str = "b FkTable Grid rel. diff -+-----------+-----------+------------- 0 7.7911994e2 7.7891206e2 -2.6680685e-4 @@ -165,3 +187,23 @@ fn nutev_cc_nu_fe_sigmared() { .stderr("Error: grids are different\n") .stdout(NUTEV_CC_NU_FE_SIGMARED_STR); } + +#[test] +#[ignore] +fn lhcb_dy_8tev() { + let output = NamedTempFile::new("fktable4.lz4").unwrap(); + + Command::cargo_bin("pineappl") + .unwrap() + .args(&[ + "--silence-lhapdf", + "evolve", + "../test-data/LHCB_DY_8TEV.pineappl.lz4", + "../test-data/LHCB_DY_8TEV.tar", + output.path().to_str().unwrap(), + "NNPDF40_nlo_as_01180", + ]) + .assert() + .success() + .stdout(LHCB_DY_8TEV_STR); +} From ea0f67261bd4955cc30aa8add6914a31addb5334 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Tue, 18 Oct 2022 14:53:09 +0200 Subject: [PATCH 65/73] Add missing test data to CI --- .github/workflows/rust.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c7745d0f..e319d5cc 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -47,12 +47,14 @@ jobs: uses: actions/cache@v3 with: path: test-data - key: test-data-v1 + key: test-data-v2 - name: Download test data if: steps.cache-test-data.outputs.cache-hit != 'true' run: | wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.pineappl.lz4' wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/E906nlo_bin_00.tar' + wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_DY_8TEV.pineappl.lz4' + wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_DY_8TEV.tar' wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.pineappl.lz4' wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/LHCB_WP_7TEV.tar' wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/NUTEV_CC_NU_FE_SIGMARED.pineappl.lz4' From 1d45b833cb40d098ab424d3d73e3f7e33be37772 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Tue, 18 Oct 2022 15:52:38 +0200 Subject: [PATCH 66/73] Add parameters `xir` and `xif` to `evolve` subcommand --- pineappl_cli/src/evolve.rs | 20 +++++++++++++------- pineappl_cli/src/helpers.rs | 32 +++++++++++++++++++++++++++----- pineappl_cli/tests/evolve.rs | 2 ++ 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 59eacbf0..a511d7d4 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -6,7 +6,7 @@ use pineappl::grid::Grid; use std::path::{Path, PathBuf}; #[cfg(feature = "fktable")] -fn evolve_grid(grid: &Grid, eko: &Path) -> Result { +fn evolve_grid(grid: &Grid, eko: &Path, xir: f64, xif: f64) -> Result { use lz4_flex::frame::FrameDecoder; use ndarray::{Array1, Array5}; use ndarray_npy::ReadNpyExt; @@ -72,8 +72,8 @@ fn evolve_grid(grid: &Grid, eko: &Path) -> Result { fac0: metadata.q2_ref, ren1: metadata.q2_grid, // TODO: check whether this is true in the general case alphas, - xir: 1.0, // TODO: make this a CLI option - xif: 1.0, // TODO: make this a CLI option + xir, + xif, lumi_id_types: "pdg_mc_ids".to_string(), // TODO: determine this from the operator }; @@ -81,7 +81,7 @@ fn evolve_grid(grid: &Grid, eko: &Path) -> Result { } #[cfg(not(feature = "fktable"))] -fn evolve_grid(_: &Grid, _: &Path) -> Result { +fn evolve_grid(_: &Grid, _: &Path, _: f64, _: f64) -> Result { Err(anyhow!( "you need to install `pineappl` with feature `fktable`" )) @@ -111,6 +111,12 @@ pub struct Opts { /// Set the number of fractional digits shown for relative numbers. #[clap(default_value_t = 7, long = "digits-rel", value_name = "REL")] digits_rel: usize, + /// Rescale the renormalization scale with this factor. + #[clap(default_value_t = 1.0, long)] + xir: f64, + /// Rescale the factorization scale with this factor. + #[clap(default_value_t = 1.0, long)] + xif: f64, } impl Subcommand for Opts { @@ -118,7 +124,7 @@ impl Subcommand for Opts { use prettytable::{cell, row}; let grid = helpers::read_grid(&self.input)?; - let fk_table = evolve_grid(&grid, &self.eko)?; + let fk_table = evolve_grid(&grid, &self.eko, self.xir, self.xif)?; let mut different = false; let mut pdf = helpers::create_pdf(&self.pdfset)?; @@ -133,13 +139,13 @@ impl Subcommand for Opts { ConvoluteMode::Normal, false, ); - let evolved_results = helpers::convolute( + let evolved_results = helpers::convolute_scales( fk_table.grid(), &mut pdf, &[], &[], &[], - 1, + &[(self.xir, self.xif)], ConvoluteMode::Normal, false, ); diff --git a/pineappl_cli/src/helpers.rs b/pineappl_cli/src/helpers.rs index 091b65b7..a32c793d 100644 --- a/pineappl_cli/src/helpers.rs +++ b/pineappl_cli/src/helpers.rs @@ -128,13 +128,13 @@ pub enum ConvoluteMode { Normal, } -pub fn convolute( +pub fn convolute_scales( grid: &Grid, lhapdf: &mut Pdf, orders: &[(u32, u32)], bins: &[usize], lumis: &[bool], - scales: usize, + scales: &[(f64, f64)], mode: ConvoluteMode, force_positive: bool, ) -> Vec { @@ -171,11 +171,11 @@ pub fn convolute( }; let mut alphas = |q2| lhapdf.alphas_q2(q2); let mut cache = LumiCache::with_one(pdf_pdg_id, &mut pdf, &mut alphas); - let mut results = grid.convolute(&mut cache, &orders, bins, lumis, &SCALES_VECTOR[0..scales]); + let mut results = grid.convolute(&mut cache, &orders, bins, lumis, scales); match mode { ConvoluteMode::Asymmetry => results - .chunks_exact(results.len() / scales) + .chunks_exact(results.len() / scales.len()) .flat_map(|chunk| { let vec: Vec<_> = chunk[chunk.len() / 2..] .iter() @@ -195,7 +195,7 @@ pub fn convolute( .iter() .enumerate() .filter(|(index, _)| (bins.is_empty() || bins.contains(index))) - .flat_map(|(_, norm)| iter::repeat(norm).take(scales)), + .flat_map(|(_, norm)| iter::repeat(norm).take(scales.len())), ) .for_each(|(value, norm)| *value *= norm); @@ -205,6 +205,28 @@ pub fn convolute( } } +pub fn convolute( + grid: &Grid, + lhapdf: &mut Pdf, + orders: &[(u32, u32)], + bins: &[usize], + lumis: &[bool], + scales: usize, + mode: ConvoluteMode, + force_positive: bool, +) -> Vec { + convolute_scales( + grid, + lhapdf, + orders, + bins, + lumis, + &SCALES_VECTOR[0..scales], + mode, + force_positive, + ) +} + pub fn convolute_limits(grid: &Grid, bins: &[usize], mode: ConvoluteMode) -> Vec> { let limits: Vec<_> = grid .bin_info() diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index 63d0b71b..b4a5a9f6 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -21,6 +21,8 @@ OPTIONS: --digits-rel Set the number of fractional digits shown for relative numbers [default: 7] -h, --help Print help information + --xif Rescale the factorization scale with this factor [default: 1] + --xir Rescale the renormalization scale with this factor [default: 1] "; const E906NLO_BIN_00_STR: &str = "b FkTable Grid rel. diff From 2de87b3e9571b420ec7292e4d97228e7dfdcfe22 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Tue, 18 Oct 2022 16:09:10 +0200 Subject: [PATCH 67/73] Fix scale-variation in `Grid::evolve` --- pineappl/src/evolution.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 95563655..de9a79a7 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -205,7 +205,7 @@ pub(crate) fn ndarray_from_subgrid_orders( .mu2_grid() .iter() .cloned() - .map(|mu2| mu2.fac) + .map(|mu2| info.xif * info.xif * mu2.fac) .collect::>() }) .collect(); @@ -284,7 +284,7 @@ pub(crate) fn ndarray_from_subgrid_orders( .collect(); for ((ifac1, ix1, ix2), value) in subgrid.iter() { - let Mu2 { ren: mur2, .. } = subgrid.mu2_grid()[ifac1]; + let mur2 = info.xir * info.xir * subgrid.mu2_grid()[ifac1].ren; let als = if order.alphas == 0 { 1.0 From 701a8d67a8a65a0a0dc50fb8887895fd6ed42e10 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Tue, 18 Oct 2022 16:18:34 +0200 Subject: [PATCH 68/73] Replace `unwrap` calls with meaningful error messages --- pineappl/src/evolution.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index de9a79a7..22539e20 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -255,33 +255,40 @@ pub(crate) fn ndarray_from_subgrid_orders( logs *= (info.xif * info.xif).ln(); } + // TODO: use `try_collect` once stabilized let fac1_indices: Vec<_> = subgrid .mu2_grid() .iter() .map(|&Mu2 { fac, .. }| { fac1.iter() .position(|&scale| approx_eq!(f64, fac, scale, ulps = 64)) - .unwrap() + .ok_or_else(|| { + GridError::EvolutionFailure(format!("no operator for muf2 = {} found", fac)) + }) }) - .collect(); + .collect::>()?; let xa_indices: Vec<_> = subgrid .x1_grid() .iter() .map(|&xa| { x1_a.iter() .position(|&x1a| approx_eq!(f64, x1a, xa, ulps = 64)) - .unwrap() + .ok_or_else(|| { + GridError::EvolutionFailure(format!("no operator for x1 = {} found", xa)) + }) }) - .collect(); + .collect::>()?; let xb_indices: Vec<_> = subgrid .x2_grid() .iter() .map(|&xb| { x1_b.iter() .position(|&x1b| approx_eq!(f64, x1b, xb, ulps = 64)) - .unwrap() + .ok_or_else(|| { + GridError::EvolutionFailure(format!("no operator for x1 = {} found", xb)) + }) }) - .collect(); + .collect::>()?; for ((ifac1, ix1, ix2), value) in subgrid.iter() { let mur2 = info.xir * info.xir * subgrid.mu2_grid()[ifac1].ren; From 8de3a3eb2b94867db866a60a5a2e65f5444199a8 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 19 Oct 2022 10:19:44 +0200 Subject: [PATCH 69/73] Use strong coupling from LHAPDF In newer EKO file formats the strong coupling is not stored anymore --- pineappl_cli/src/evolve.rs | 26 +++--- pineappl_cli/tests/evolve.rs | 154 +++++++++++++++++------------------ 2 files changed, 91 insertions(+), 89 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index a511d7d4..be59fbee 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -1,14 +1,15 @@ use super::helpers::{self, ConvoluteMode, Subcommand}; use anyhow::{anyhow, Result}; use clap::{Parser, ValueHint}; +use lhapdf::Pdf; use pineappl::fk_table::FkTable; use pineappl::grid::Grid; use std::path::{Path, PathBuf}; #[cfg(feature = "fktable")] -fn evolve_grid(grid: &Grid, eko: &Path, xir: f64, xif: f64) -> Result { +fn evolve_grid(grid: &Grid, eko: &Path, pdf: &Pdf, xir: f64, xif: f64) -> Result { use lz4_flex::frame::FrameDecoder; - use ndarray::{Array1, Array5}; + use ndarray::Array5; use ndarray_npy::ReadNpyExt; use pineappl::evolution::OperatorInfo; use serde::Deserialize; @@ -37,7 +38,6 @@ fn evolve_grid(grid: &Grid, eko: &Path, xir: f64, xif: f64) -> Result { let mut archive = Archive::new(File::open(eko)?); - let mut alphas = Vec::new(); let mut operator = Default::default(); let mut metadata: Metadata = Default::default(); @@ -52,10 +52,6 @@ fn evolve_grid(grid: &Grid, eko: &Path, xir: f64, xif: f64) -> Result { "operators.npy.lz4" => { operator = Array5::::read_npy(FrameDecoder::new(BufReader::new(file)))? } - "alphas.npy.lz4" => { - alphas = - Array1::::read_npy(FrameDecoder::new(BufReader::new(file)))?.to_vec() - } _ => {} } } @@ -63,6 +59,12 @@ fn evolve_grid(grid: &Grid, eko: &Path, xir: f64, xif: f64) -> Result { // TODO: handle errors when files in the EKO are not present + let alphas: Vec<_> = metadata + .q2_grid + .iter() + .map(|&mur2| pdf.alphas_q2(mur2)) + .collect(); + let info = OperatorInfo { fac1: metadata.q2_grid.clone(), pids0: metadata.inputpids, @@ -81,7 +83,7 @@ fn evolve_grid(grid: &Grid, eko: &Path, xir: f64, xif: f64) -> Result { } #[cfg(not(feature = "fktable"))] -fn evolve_grid(_: &Grid, _: &Path, _: f64, _: f64) -> Result { +fn evolve_grid(_: &Grid, _: &Path, _: &Pdf, _: f64, _: f64) -> Result { Err(anyhow!( "you need to install `pineappl` with feature `fktable`" )) @@ -124,11 +126,7 @@ impl Subcommand for Opts { use prettytable::{cell, row}; let grid = helpers::read_grid(&self.input)?; - let fk_table = evolve_grid(&grid, &self.eko, self.xir, self.xif)?; - - let mut different = false; let mut pdf = helpers::create_pdf(&self.pdfset)?; - let results = helpers::convolute( &grid, &mut pdf, @@ -139,6 +137,8 @@ impl Subcommand for Opts { ConvoluteMode::Normal, false, ); + + let fk_table = evolve_grid(&grid, &self.eko, &pdf, self.xir, self.xif)?; let evolved_results = helpers::convolute_scales( fk_table.grid(), &mut pdf, @@ -156,6 +156,8 @@ impl Subcommand for Opts { let mut table = helpers::create_table(); table.set_titles(row![c => "b", "FkTable", "Grid", "rel. diff"]); + let mut different = false; + for (bin, (one, two)) in results .into_iter() .zip(evolved_results.into_iter()) diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index b4a5a9f6..2a348b49 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -27,95 +27,95 @@ OPTIONS: const E906NLO_BIN_00_STR: &str = "b FkTable Grid rel. diff -+------------+------------+------------- -0 1.0659807e-1 1.0657910e-1 -1.7800240e-4 -1 1.0659807e-1 1.0657910e-1 -1.7800240e-4 -2 1.0659807e-1 1.0657910e-1 -1.7800240e-4 -3 1.0659807e-1 1.0657910e-1 -1.7800240e-4 -4 3.2698655e0 3.2710283e0 3.5561489e-4 -5 1.6039253e0 1.6047363e0 5.0563376e-4 +0 1.0659807e-1 1.0657904e-1 -1.7851986e-4 +1 1.0659807e-1 1.0657904e-1 -1.7851986e-4 +2 1.0659807e-1 1.0657904e-1 -1.7851986e-4 +3 1.0659807e-1 1.0657904e-1 -1.7851986e-4 +4 3.2698655e0 3.2711890e0 4.0477586e-4 +5 1.6039253e0 1.6047566e0 5.1825508e-4 "; const LHCB_DY_8TEV_STR: &str = "b FkTable Grid rel. diff --+------------+------------+------------- -0 8.1098384e0 8.1077663e0 -2.5550537e-4 -1 2.3743076e1 2.3737363e1 -2.4059398e-4 -2 3.8047878e1 3.8038820e1 -2.3808089e-4 -3 5.0883597e1 5.0870965e1 -2.4825643e-4 -4 6.1803061e1 6.1786970e1 -2.6035384e-4 -5 7.0086849e1 7.0068287e1 -2.6483200e-4 -6 7.5526963e1 7.5506936e1 -2.6516554e-4 -7 7.7701083e1 7.7680621e1 -2.6334886e-4 -8 7.6395213e1 7.6375564e1 -2.5721140e-4 -9 7.1337740e1 7.1320163e1 -2.4638218e-4 -10 6.1083107e1 6.1068812e1 -2.3403347e-4 -11 4.7617019e1 4.7606056e1 -2.3023324e-4 -12 3.4090165e1 3.4081756e1 -2.4667862e-4 -13 2.2027068e1 2.2021463e1 -2.5446838e-4 -14 1.2535284e1 1.2532680e1 -2.0773561e-4 -15 5.9288895e0 5.9282771e0 -1.0328299e-4 -16 1.3830183e0 1.3832217e0 1.4703176e-4 -17 5.1352256e-2 5.1398317e-2 8.9695182e-4 +0 8.1098384e0 8.1077630e0 -2.5590382e-4 +1 2.3743076e1 2.3737354e1 -2.4098617e-4 +2 3.8047878e1 3.8038806e1 -2.3845892e-4 +3 5.0883597e1 5.0870947e1 -2.4861381e-4 +4 6.1803061e1 6.1786949e1 -2.6069774e-4 +5 7.0086849e1 7.0068265e1 -2.6515654e-4 +6 7.5526963e1 7.5506912e1 -2.6547375e-4 +7 7.7701083e1 7.7680598e1 -2.6364145e-4 +8 7.6395213e1 7.6375543e1 -2.5748535e-4 +9 7.1337740e1 7.1320146e1 -2.4662671e-4 +10 6.1083107e1 6.1068797e1 -2.3427659e-4 +11 4.7617019e1 4.7606042e1 -2.3050924e-4 +12 3.4090165e1 3.4081746e1 -2.4697095e-4 +13 2.2027068e1 2.2021456e1 -2.5477395e-4 +14 1.2535284e1 1.2532676e1 -2.0805599e-4 +15 5.9288895e0 5.9282752e0 -1.0361570e-4 +16 1.3830183e0 1.3832212e0 1.4667630e-4 +17 5.1352256e-2 5.1398297e-2 8.9657766e-4 "; const LHCB_WP_7TEV_STR: &str = "b FkTable Grid rel. diff -+-----------+-----------+------------- -0 7.7911994e2 7.7891206e2 -2.6680685e-4 -1 7.1170872e2 7.1152118e2 -2.6351282e-4 -2 6.1766223e2 6.1750067e2 -2.6157398e-4 -3 4.9817054e2 4.9804168e2 -2.5866843e-4 -4 3.7040220e2 3.7030899e2 -2.5164930e-4 -5 2.5123713e2 2.5117697e2 -2.3945309e-4 -6 1.1883712e2 1.1881217e2 -2.0989153e-4 -7 2.9013827e1 2.9010212e1 -1.2459216e-4 +0 7.7911994e2 7.7891224e2 -2.6657796e-4 +1 7.1170872e2 7.1152134e2 -2.6328724e-4 +2 6.1766223e2 6.1750081e2 -2.6134276e-4 +3 4.9817054e2 4.9804180e2 -2.5843329e-4 +4 3.7040220e2 3.7030908e2 -2.5140875e-4 +5 2.5123713e2 2.5117703e2 -2.3920571e-4 +6 1.1883712e2 1.1881220e2 -2.0962990e-4 +7 2.9013827e1 2.9010220e1 -1.2430486e-4 "; const NUTEV_CC_NU_FE_SIGMARED_STR: &str = "b FkTable Grid rel. diff --+-----------+-----------+------------- -0 8.2920022e0 1.1046839e1 3.3222819e-1 -1 1.3975037e1 1.4232414e1 1.8416931e-2 -2 1.9422915e1 1.8434111e1 -5.0909145e-2 -3 1.4891673e1 1.4867720e1 -1.6084417e-3 -4 1.4086222e1 1.4088115e1 1.3438079e-4 -5 2.2998409e1 2.2998443e1 1.4697729e-6 -6 2.1899598e1 2.1899091e1 -2.3138103e-5 -7 1.5578822e1 1.5578334e1 -3.1319781e-5 -8 2.2226765e1 2.2225956e1 -3.6375906e-5 -9 1.3669291e1 1.3669038e1 -1.8446253e-5 -10 2.5946596e1 2.5945504e1 -4.2110358e-5 -11 1.8363999e1 1.8363361e1 -3.4704937e-5 -12 1.5819602e1 1.5819077e1 -3.3204532e-5 -13 2.5959140e1 2.5957783e1 -5.2285210e-5 -14 2.0457793e1 2.0456964e1 -4.0496689e-5 -15 1.1393262e1 1.1392626e1 -5.5781822e-5 -16 1.4106814e1 1.4106786e1 -1.9959280e-6 -17 1.9464293e1 1.9463520e1 -3.9713070e-5 -18 1.5721645e1 1.5721550e1 -6.0470703e-6 -19 1.4033170e1 1.4033158e1 -8.5170032e-7 -20 1.9366211e1 1.9365482e1 -3.7645378e-5 -21 2.1174542e1 2.1173688e1 -4.0315154e-5 -22 1.6606739e1 1.6606635e1 -6.2333155e-6 -23 1.1354320e1 1.1353660e1 -5.8066443e-5 -24 5.5456589e0 5.5455822e0 -1.3826910e-5 -25 1.2257404e1 1.2256637e1 -6.2534396e-5 -26 1.5838419e1 1.5838379e1 -2.5004885e-6 -27 2.0844501e1 2.0844671e1 8.1437423e-6 -28 1.1127050e1 1.1126496e1 -4.9723938e-5 -29 1.3257033e1 1.3256687e1 -2.6046580e-5 -30 1.6809659e1 1.6810591e1 5.5429049e-5 -31 1.7616888e1 1.7618088e1 6.8090881e-5 -32 5.8908612e0 5.8906267e0 -3.9802439e-5 -33 1.2668418e1 1.2667676e1 -5.8532882e-5 -34 6.1718100e0 6.1715800e0 -3.7259928e-5 -35 1.6993748e1 1.6993216e1 -3.1306297e-5 -36 5.5089321e0 5.5087361e0 -3.5579336e-5 -37 1.2163126e1 1.2162352e1 -6.3616512e-5 -38 1.2575328e1 1.2574501e1 -6.5776146e-5 -39 5.9912886e0 5.9910701e0 -3.6479256e-5 -40 5.5396399e0 5.5394441e0 -3.5343558e-5 -41 1.2035714e1 1.2034895e1 -6.7972844e-5 -42 5.1605061e0 5.1603299e0 -3.4143438e-5 -43 5.3541916e0 5.3540055e0 -3.4757362e-5 -44 4.9727490e0 4.9725844e0 -3.3105968e-5 +0 8.2920022e0 1.0954648e1 3.2111014e-1 +1 1.3975037e1 1.4236502e1 1.8709416e-2 +2 1.9422915e1 1.8431736e1 -5.1031421e-2 +3 1.4891673e1 1.4867911e1 -1.5956063e-3 +4 1.4086222e1 1.4087867e1 1.1676254e-4 +5 2.2998409e1 2.2998414e1 2.3434412e-7 +6 2.1899598e1 2.1899098e1 -2.2841392e-5 +7 1.5578822e1 1.5578327e1 -3.1774716e-5 +8 2.2226765e1 2.2225948e1 -3.6746158e-5 +9 1.3669291e1 1.3669040e1 -1.8302270e-5 +10 2.5946596e1 2.5945509e1 -4.1912903e-5 +11 1.8363999e1 1.8363357e1 -3.4940966e-5 +12 1.5819602e1 1.5819075e1 -3.3330771e-5 +13 2.5959140e1 2.5957771e1 -5.2747753e-5 +14 2.0457793e1 2.0456973e1 -4.0087031e-5 +15 1.1393262e1 1.1392625e1 -5.5841791e-5 +16 1.4106814e1 1.4106781e1 -2.3548459e-6 +17 1.9464293e1 1.9463530e1 -3.9217573e-5 +18 1.5721645e1 1.5721553e1 -5.8661712e-6 +19 1.4033170e1 1.4033163e1 -4.8582905e-7 +20 1.9366211e1 1.9365473e1 -3.8125440e-5 +21 2.1174542e1 2.1173681e1 -4.0655919e-5 +22 1.6606739e1 1.6606637e1 -6.1144617e-6 +23 1.1354320e1 1.1353662e1 -5.7937744e-5 +24 5.5456589e0 5.5455826e0 -1.3762742e-5 +25 1.2257404e1 1.2256635e1 -6.2679973e-5 +26 1.5838419e1 1.5838375e1 -2.8058203e-6 +27 2.0844501e1 2.0844372e1 -6.2280076e-6 +28 1.1127050e1 1.1126384e1 -5.9865346e-5 +29 1.3257033e1 1.3256528e1 -3.8071417e-5 +30 1.6809659e1 1.6810166e1 3.0140970e-5 +31 1.7616888e1 1.7617649e1 4.3196882e-5 +32 5.8908612e0 5.8906261e0 -3.9897551e-5 +33 1.2668418e1 1.2667673e1 -5.8804601e-5 +34 6.1718100e0 6.1715801e0 -3.7253769e-5 +35 1.6993748e1 1.6993214e1 -3.1436426e-5 +36 5.5089321e0 5.5087362e0 -3.5567214e-5 +37 1.2163126e1 1.2162354e1 -6.3452698e-5 +38 1.2575328e1 1.2574503e1 -6.5657683e-5 +39 5.9912886e0 5.9910700e0 -3.6491168e-5 +40 5.5396399e0 5.5394441e0 -3.5344028e-5 +41 1.2035714e1 1.2034895e1 -6.7998362e-5 +42 5.1605061e0 5.1603299e0 -3.4144995e-5 +43 5.3541916e0 5.3540055e0 -3.4756819e-5 +44 4.9727490e0 4.9725844e0 -3.3104317e-5 "; #[test] From 143a3948fd5393f435a32f1863802b1807c1e5f3 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 19 Oct 2022 10:21:55 +0200 Subject: [PATCH 70/73] Remove TODO - evolution succeeds The reason why the comparison fails is that there are bins with a factorization scale below the PDFs fitting scale --- pineappl_cli/tests/evolve.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index 2a348b49..de31bd4c 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -173,7 +173,6 @@ fn e906nlo_bin_00() { fn nutev_cc_nu_fe_sigmared() { let output = NamedTempFile::new("fktable3.lz4").unwrap(); - // TODO: find out the reason why this evolution fails Command::cargo_bin("pineappl") .unwrap() .args(&[ From f4b97c3c1c4fb30c20b3187d60858ce7585461fa Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 19 Oct 2022 10:25:54 +0200 Subject: [PATCH 71/73] Disable tests unless `--features=fktable` is enabled --- pineappl_cli/tests/evolve.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index de31bd4c..30a6db51 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "fktable")] + use assert_cmd::Command; use assert_fs::NamedTempFile; From 99e53ed620a667f9400f972bdae33e5ce95b0b10 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 19 Oct 2022 09:16:58 +0200 Subject: [PATCH 72/73] Use chinese food mind game construction https://youtu.be/CkdyU_eUm1U --- pineappl/src/evolution.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 22539e20..95cdafc3 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -54,17 +54,16 @@ pub struct OperatorInfo { } fn gluon_has_pid_zero(grid: &Grid) -> bool { - if grid.key_values().map_or(false, |key_values| { - key_values - .get("lumi_id_types") - .map_or(false, |value| value == "pdg_mc_ids") - }) { - grid.lumi() - .iter() - .any(|entry| entry.entry().iter().any(|&(a, b, _)| (a == 0) || (b == 0))) - } else { - false - } + grid.key_values() + .and_then(|key_values| key_values.get("lumi_id_types")) + .and_then(|value| { + (value == "pdg_mc_ids").then(|| { + grid.lumi() + .iter() + .any(|entry| entry.entry().iter().any(|&(a, b, _)| (a == 0) || (b == 0))) + }) + }) + .unwrap_or(false) } pub(crate) fn pids( From f841dff2274fc4062e07179d1f9fc9a086bfe298 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 21 Oct 2022 10:34:40 +0200 Subject: [PATCH 73/73] Fix the right factorization scale choice --- pineappl/src/evolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 95cdafc3..1f3f7347 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -260,7 +260,7 @@ pub(crate) fn ndarray_from_subgrid_orders( .iter() .map(|&Mu2 { fac, .. }| { fac1.iter() - .position(|&scale| approx_eq!(f64, fac, scale, ulps = 64)) + .position(|&scale| approx_eq!(f64, info.xif * info.xif * fac, scale, ulps = 64)) .ok_or_else(|| { GridError::EvolutionFailure(format!("no operator for muf2 = {} found", fac)) })