From 1962fe292a68d23501c8339be09352a74cdee1fb Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Thu, 30 May 2024 13:02:47 +0200 Subject: [PATCH 01/38] implement some brute force skeleton --- pineappl/src/evolution.rs | 11 ++++---- pineappl/src/grid.rs | 56 ++++++++++++++++++++++++++++++++++++-- pineappl_cli/src/evolve.rs | 14 +++++++++- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 480bcb8c..3a751916 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -524,7 +524,8 @@ pub(crate) fn evolve_slice_with_one( pub(crate) fn evolve_slice_with_two( grid: &Grid, - operator: &ArrayView4, + operator_a: &ArrayView4, + operator_b: &ArrayView4, info: &OperatorSliceInfo, order_mask: &[bool], xi: (f64, f64), @@ -532,13 +533,13 @@ pub(crate) fn evolve_slice_with_two( ) -> Result<(Array3, Vec), GridError> { let gluon_has_pid_zero = gluon_has_pid_zero(grid); - let (pid_indices_a, pids_a) = pid_slices(operator, info, gluon_has_pid_zero, &|pid1| { + let (pid_indices_a, pids_a) = pid_slices(operator_a, info, gluon_has_pid_zero, &|pid1| { grid.lumi() .iter() .flat_map(LumiEntry::entry) .any(|&(a, _, _)| a == pid1) })?; - let (pid_indices_b, pids_b) = pid_slices(operator, info, gluon_has_pid_zero, &|pid1| { + let (pid_indices_b, pids_b) = pid_slices(operator_b, info, gluon_has_pid_zero, &|pid1| { grid.lumi() .iter() .flat_map(LumiEntry::entry) @@ -572,7 +573,7 @@ pub(crate) fn evolve_slice_with_two( .zip(x1_a.iter()) .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) { - operators_a = operator_slices(operator, info, &pid_indices_a, &x1_a)?; + operators_a = operator_slices(operator_a, info, &pid_indices_a, &x1_a)?; last_x1a = x1_a; } @@ -582,7 +583,7 @@ pub(crate) fn evolve_slice_with_two( .zip(x1_b.iter()) .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) { - operators_b = operator_slices(operator, info, &pid_indices_b, &x1_b)?; + operators_b = operator_slices(operator_b, info, &pid_indices_b, &x1_b)?; last_x1b = x1_b; } diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 23c0a19e..35c9e0cf 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1384,6 +1384,7 @@ impl Grid { } } + /// TODO: Fix to account for the different EKOs /// 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, @@ -1402,6 +1403,23 @@ impl Grid { order_mask: &[bool], ) -> Result { self.evolve_with_slice_iter( + info.fac1 + .iter() + .zip(operator.axis_iter(Axis(0))) + .map(|(&fac1, op)| { + Ok::<_, GridError>(( + OperatorSliceInfo { + fac0: info.fac0, + pids0: info.pids0.clone(), + x0: info.x0.clone(), + fac1, + pids1: info.pids1.clone(), + x1: info.x1.clone(), + lumi_id_types: info.lumi_id_types.clone(), + }, + CowArray::from(op), + )) + }), info.fac1 .iter() .zip(operator.axis_iter(Axis(0))) @@ -1446,16 +1464,21 @@ impl Grid { pub fn evolve_with_slice_iter<'a, E: Into>( &self, slices: impl IntoIterator), E>>, + extra_slices: impl IntoIterator), E>>, order_mask: &[bool], xi: (f64, f64), alphas_table: &AlphasTable, ) -> Result { use super::evolution::EVOLVE_INFO_TOL_ULPS; + use itertools::izip; let mut lhs: Option = None; let mut fac1 = Vec::new(); - for result in slices { + // TODO: simplify the ugly repetition below + // TODO: what to do about the info? Shoulb they be the same? + for (result, extra_result) in izip!(slices, extra_slices) { + // Deal with the main EKO let (info, operator) = result.map_err(|err| GridError::Other(err.into()))?; let op_info_dim = ( @@ -1475,10 +1498,39 @@ impl Grid { let view = operator.view(); + // Deal with the additional EKO + let (extra_info, extra_operator) = + extra_result.map_err(|err| GridError::Other(err.into()))?; + + let op_info_dim_extra = ( + extra_info.pids1.len(), + extra_info.x1.len(), + extra_info.pids0.len(), + extra_info.x0.len(), + ); + + if extra_operator.dim() != op_info_dim_extra { + return Err(GridError::EvolutionFailure(format!( + "operator information {:?} does not match the operator's dimensions: {:?}", + op_info_dim_extra, + extra_operator.dim(), + ))); + } + + let extra_view = extra_operator.view(); + let (subgrids, lumi) = if self.convolutions()[0] != Convolution::None && self.convolutions()[1] != Convolution::None { - evolution::evolve_slice_with_two(self, &view, &info, order_mask, xi, alphas_table) + evolution::evolve_slice_with_two( + self, + &view, + &extra_view, + &info, + order_mask, + xi, + alphas_table, + ) } else { evolution::evolve_slice_with_one(self, &view, &info, order_mask, xi, alphas_table) }?; diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index e8726b88..cb38dab6 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -425,6 +425,7 @@ mod eko { fn evolve_grid( grid: &Grid, eko: &Path, + extra_eko: &Path, pdf: &Pdf, orders: &[(u32, u32)], xir: f64, @@ -446,8 +447,10 @@ fn evolve_grid( .collect(); let mut eko_slices = EkoSlices::new(eko)?; + let mut extra_eko_slices = EkoSlices::new(extra_eko)?; let alphas_table = AlphasTable::from_grid(grid, xir, &|q2| pdf.alphas_q2(q2)); + // TODO: Take care of the old EKO behavior if use_old_evolve { if let EkoSlices::V0 { fac1, @@ -475,7 +478,13 @@ fn evolve_grid( unimplemented!(); } } else { - Ok(grid.evolve_with_slice_iter(&mut eko_slices, &order_mask, (xir, xif), &alphas_table)?) + Ok(grid.evolve_with_slice_iter( + &mut eko_slices, + extra_eko_slices, + &order_mask, + (xir, xif), + &alphas_table, + )?) } } @@ -483,6 +492,7 @@ fn evolve_grid( fn evolve_grid( _: &Grid, _: &Path, + _: &Path, _: &Pdf, _: &[(u32, u32)], _: f64, @@ -554,9 +564,11 @@ impl Subcommand for Opts { cfg, ); + // TODO: properly pass the additional EKO from input args let fk_table = evolve_grid( &grid, &self.eko, + &self.eko, &pdf, &self.orders, self.xir, From 95b3bc36c477d379744b0dd1ad834d45b10e15b0 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Thu, 30 May 2024 15:40:56 +0200 Subject: [PATCH 02/38] reflect changes to python interface --- pineappl/src/grid.rs | 8 +++++--- pineappl_py/pineappl/grid.py | 1 + pineappl_py/src/grid.rs | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 35c9e0cf..5408e503 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1385,6 +1385,7 @@ impl Grid { } /// TODO: Fix to account for the different EKOs + /// TODO: Does the info have to be different? /// 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, @@ -1398,14 +1399,15 @@ impl Grid { #[deprecated(since = "0.7.4", note = "use evolve_with_slice_iter instead")] pub fn evolve( &self, - operator: ArrayView5, + operator_a: ArrayView5, + operator_b: ArrayView5, info: &OperatorInfo, order_mask: &[bool], ) -> Result { self.evolve_with_slice_iter( info.fac1 .iter() - .zip(operator.axis_iter(Axis(0))) + .zip(operator_a.axis_iter(Axis(0))) .map(|(&fac1, op)| { Ok::<_, GridError>(( OperatorSliceInfo { @@ -1422,7 +1424,7 @@ impl Grid { }), info.fac1 .iter() - .zip(operator.axis_iter(Axis(0))) + .zip(operator_b.axis_iter(Axis(0))) .map(|(&fac1, op)| { Ok::<_, GridError>(( OperatorSliceInfo { diff --git a/pineappl_py/pineappl/grid.py b/pineappl_py/pineappl/grid.py index b0b6c4cc..c78cb39c 100644 --- a/pineappl_py/pineappl/grid.py +++ b/pineappl_py/pineappl/grid.py @@ -344,6 +344,7 @@ def evolve( self.raw.evolve( np.array(operator_grid), operators["q2_ref"], + operators["q2_ref"], # TODO: Modify the input EKO np.array(operators["inputpids"], dtype=np.int32), np.array(operators["inputgrid"]), np.array(q2grid, dtype=np.float64), diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 3f7dd959..43256da3 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -458,7 +458,8 @@ impl PyGrid { /// produced FK table pub fn evolve( &self, - operator: PyReadonlyArray5, + operator_a: PyReadonlyArray5, + operator_b: PyReadonlyArray5, fac0: f64, pids0: PyReadonlyArray1, x0: PyReadonlyArray1, @@ -488,7 +489,8 @@ impl PyGrid { let evolved_grid = self .grid .evolve( - operator.as_array(), + operator_a.as_array(), + operator_b.as_array(), &op_info, order_mask.as_slice().unwrap(), ) From a4bfa50347dbaeb407602cc001a2af31176cf115 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Fri, 31 May 2024 23:01:19 +0200 Subject: [PATCH 03/38] just makes things work for the time being --- pineappl_cli/src/evolve.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index cb38dab6..2881177a 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -450,7 +450,7 @@ fn evolve_grid( let mut extra_eko_slices = EkoSlices::new(extra_eko)?; let alphas_table = AlphasTable::from_grid(grid, xir, &|q2| pdf.alphas_q2(q2)); - // TODO: Take care of the old EKO behavior + // TODO: Modify old Evolve to account for multiple EKOs if use_old_evolve { if let EkoSlices::V0 { fac1, @@ -473,14 +473,14 @@ fn evolve_grid( }; #[allow(deprecated)] - Ok(grid.evolve(operator.view(), &op_info, &order_mask)?) + Ok(grid.evolve(operator.view(), operator.view(), &op_info, &order_mask)?) } else { unimplemented!(); } } else { Ok(grid.evolve_with_slice_iter( &mut eko_slices, - extra_eko_slices, + &mut extra_eko_slices, &order_mask, (xir, xif), &alphas_table, From 2b58ae266cec4ba52756a2805baf2392458b541c Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Sun, 2 Jun 2024 14:05:04 +0200 Subject: [PATCH 04/38] address changes in old evolve --- pineappl_cli/src/evolve.rs | 43 +++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 2881177a..c969a772 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -450,7 +450,8 @@ fn evolve_grid( let mut extra_eko_slices = EkoSlices::new(extra_eko)?; let alphas_table = AlphasTable::from_grid(grid, xir, &|q2| pdf.alphas_q2(q2)); - // TODO: Modify old Evolve to account for multiple EKOs + // TODO: Check that cloning the `alphas_table` does not cause performance + // issue when cloned. if use_old_evolve { if let EkoSlices::V0 { fac1, @@ -458,6 +459,9 @@ fn evolve_grid( operator, } = eko_slices { + // TODO: Check if the `operator` object is actually mutable + let original_operator = operator; + let op_info = OperatorInfo { fac0: info.fac0, pids0: info.pids0.clone(), @@ -465,15 +469,44 @@ fn evolve_grid( fac1, pids1: info.pids1.clone(), x1: info.x1.clone(), - ren1: alphas_table.ren1, - alphas: alphas_table.alphas, + ren1: alphas_table.ren1.clone(), + alphas: alphas_table.alphas.clone(), xir, xif, lumi_id_types: info.lumi_id_types, }; - #[allow(deprecated)] - Ok(grid.evolve(operator.view(), operator.view(), &op_info, &order_mask)?) + if let EkoSlices::V0 { + fac1, + info, + operator, + } = extra_eko_slices + { + // TODO: change the info object + let _extra_op_info = OperatorInfo { + fac0: info.fac0, + pids0: info.pids0.clone(), + x0: info.x0.clone(), + fac1, + pids1: info.pids1.clone(), + x1: info.x1.clone(), + ren1: alphas_table.ren1.clone(), + alphas: alphas_table.alphas.clone(), + xir, + xif, + lumi_id_types: info.lumi_id_types, + }; + + #[allow(deprecated)] + Ok(grid.evolve( + original_operator.view(), + operator.view(), + &op_info, + &order_mask, + )?) + } else { + unimplemented!(); + } } else { unimplemented!(); } From c11b3883ce13602ff307eeb8ea240afc18187765 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Sun, 2 Jun 2024 16:09:55 +0200 Subject: [PATCH 05/38] propagate different info in places that should matter --- pineappl/src/evolution.rs | 51 +++++++++++---------- pineappl/src/grid.rs | 94 +++++++++++++++++++------------------- pineappl_cli/src/evolve.rs | 23 +++++----- 3 files changed, 87 insertions(+), 81 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 3a751916..6f5cb264 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -524,27 +524,30 @@ pub(crate) fn evolve_slice_with_one( pub(crate) fn evolve_slice_with_two( grid: &Grid, - operator_a: &ArrayView4, - operator_b: &ArrayView4, - info: &OperatorSliceInfo, + input_operator_a: &ArrayView4, + input_operator_b: &ArrayView4, + info_a: &OperatorSliceInfo, + info_b: &OperatorSliceInfo, order_mask: &[bool], xi: (f64, f64), alphas_table: &AlphasTable, ) -> Result<(Array3, Vec), GridError> { let gluon_has_pid_zero = gluon_has_pid_zero(grid); - let (pid_indices_a, pids_a) = pid_slices(operator_a, info, gluon_has_pid_zero, &|pid1| { - grid.lumi() - .iter() - .flat_map(LumiEntry::entry) - .any(|&(a, _, _)| a == pid1) - })?; - let (pid_indices_b, pids_b) = pid_slices(operator_b, info, gluon_has_pid_zero, &|pid1| { - grid.lumi() - .iter() - .flat_map(LumiEntry::entry) - .any(|&(_, b, _)| b == pid1) - })?; + let (pid_indices_a, pids_a) = + pid_slices(input_operator_a, info_a, gluon_has_pid_zero, &|pid1| { + grid.lumi() + .iter() + .flat_map(LumiEntry::entry) + .any(|&(a, _, _)| a == pid1) + })?; + let (pid_indices_b, pids_b) = + pid_slices(input_operator_b, info_a, gluon_has_pid_zero, &|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()); @@ -555,11 +558,11 @@ pub(crate) fn evolve_slice_with_two( 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()]; + let mut tables = vec![Array2::zeros((info_a.x0.len(), info_a.x0.len())); lumi0.len()]; for (subgrids_o, lumi1) in subgrids_ol.axis_iter(Axis(1)).zip(grid.lumi()) { let (x1_a, x1_b, array) = ndarray_from_subgrid_orders_slice( - info, + info_a, &subgrids_o, grid.orders(), order_mask, @@ -573,7 +576,7 @@ pub(crate) fn evolve_slice_with_two( .zip(x1_a.iter()) .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) { - operators_a = operator_slices(operator_a, info, &pid_indices_a, &x1_a)?; + operators_a = operator_slices(input_operator_a, info_a, &pid_indices_a, &x1_a)?; last_x1a = x1_a; } @@ -583,11 +586,11 @@ pub(crate) fn evolve_slice_with_two( .zip(x1_b.iter()) .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) { - operators_b = operator_slices(operator_b, info, &pid_indices_b, &x1_b)?; + operators_b = operator_slices(input_operator_b, info_b, &pid_indices_b, &x1_b)?; last_x1b = x1_b; } - let mut tmp = Array2::zeros((last_x1a.len(), info.x0.len())); + let mut tmp = Array2::zeros((last_x1a.len(), info_a.x0.len())); for &(pida1, pidb1, factor) in lumi1.entry() { for (fk_table, opa, opb) in @@ -621,11 +624,11 @@ pub(crate) fn evolve_slice_with_two( vec![Mu2 { // TODO: FK tables don't depend on the renormalization scale //ren: -1.0, - ren: info.fac0, - fac: info.fac0, + ren: info_a.fac0, + fac: info_a.fac0, }], - info.x0.clone(), - info.x0.clone(), + info_a.x0.clone(), + info_a.x0.clone(), ) .into() })); diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 5408e503..2985733e 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1401,49 +1401,52 @@ impl Grid { &self, operator_a: ArrayView5, operator_b: ArrayView5, - info: &OperatorInfo, + info_a: &OperatorInfo, + info_b: &OperatorInfo, order_mask: &[bool], ) -> Result { self.evolve_with_slice_iter( - info.fac1 + info_a + .fac1 .iter() .zip(operator_a.axis_iter(Axis(0))) .map(|(&fac1, op)| { Ok::<_, GridError>(( OperatorSliceInfo { - fac0: info.fac0, - pids0: info.pids0.clone(), - x0: info.x0.clone(), + fac0: info_a.fac0, + pids0: info_a.pids0.clone(), + x0: info_a.x0.clone(), fac1, - pids1: info.pids1.clone(), - x1: info.x1.clone(), - lumi_id_types: info.lumi_id_types.clone(), + pids1: info_a.pids1.clone(), + x1: info_a.x1.clone(), + lumi_id_types: info_a.lumi_id_types.clone(), }, CowArray::from(op), )) }), - info.fac1 + info_b + .fac1 .iter() .zip(operator_b.axis_iter(Axis(0))) .map(|(&fac1, op)| { Ok::<_, GridError>(( OperatorSliceInfo { - fac0: info.fac0, - pids0: info.pids0.clone(), - x0: info.x0.clone(), + fac0: info_b.fac0, + pids0: info_b.pids0.clone(), + x0: info_b.x0.clone(), fac1, - pids1: info.pids1.clone(), - x1: info.x1.clone(), - lumi_id_types: info.lumi_id_types.clone(), + pids1: info_b.pids1.clone(), + x1: info_b.x1.clone(), + lumi_id_types: info_b.lumi_id_types.clone(), }, CowArray::from(op), )) }), order_mask, - (info.xir, info.xif), + (info_a.xir, info_a.xif), &AlphasTable { - ren1: info.ren1.clone(), - alphas: info.alphas.clone(), + ren1: info_a.ren1.clone(), + alphas: info_a.alphas.clone(), }, ) } @@ -1465,8 +1468,8 @@ impl Grid { /// return an error. pub fn evolve_with_slice_iter<'a, E: Into>( &self, - slices: impl IntoIterator), E>>, - extra_slices: impl IntoIterator), E>>, + slices_a: impl IntoIterator), E>>, + slices_b: impl IntoIterator), E>>, order_mask: &[bool], xi: (f64, f64), alphas_table: &AlphasTable, @@ -1478,22 +1481,21 @@ impl Grid { let mut fac1 = Vec::new(); // TODO: simplify the ugly repetition below - // TODO: what to do about the info? Shoulb they be the same? - for (result, extra_result) in izip!(slices, extra_slices) { + for (result_a, result_b) in izip!(slices_a, slices_b) { // Deal with the main EKO - let (info, operator) = result.map_err(|err| GridError::Other(err.into()))?; + let (info_a, operator) = result_a.map_err(|err| GridError::Other(err.into()))?; - let op_info_dim = ( - info.pids1.len(), - info.x1.len(), - info.pids0.len(), - info.x0.len(), + let op_info_dim_a = ( + info_a.pids1.len(), + info_a.x1.len(), + info_a.pids0.len(), + info_a.x0.len(), ); - if operator.dim() != op_info_dim { + if operator.dim() != op_info_dim_a { return Err(GridError::EvolutionFailure(format!( "operator information {:?} does not match the operator's dimensions: {:?}", - op_info_dim, + op_info_dim_a, operator.dim(), ))); } @@ -1501,25 +1503,24 @@ impl Grid { let view = operator.view(); // Deal with the additional EKO - let (extra_info, extra_operator) = - extra_result.map_err(|err| GridError::Other(err.into()))?; - - let op_info_dim_extra = ( - extra_info.pids1.len(), - extra_info.x1.len(), - extra_info.pids0.len(), - extra_info.x0.len(), + let (info_b, operator_b) = result_b.map_err(|err| GridError::Other(err.into()))?; + + let op_info_dim_b = ( + info_b.pids1.len(), + info_b.x1.len(), + info_b.pids0.len(), + info_b.x0.len(), ); - if extra_operator.dim() != op_info_dim_extra { + if operator_b.dim() != op_info_dim_b { return Err(GridError::EvolutionFailure(format!( "operator information {:?} does not match the operator's dimensions: {:?}", - op_info_dim_extra, - extra_operator.dim(), + op_info_dim_b, + operator_b.dim(), ))); } - let extra_view = extra_operator.view(); + let extra_view = operator_b.view(); let (subgrids, lumi) = if self.convolutions()[0] != Convolution::None && self.convolutions()[1] != Convolution::None @@ -1528,13 +1529,14 @@ impl Grid { self, &view, &extra_view, - &info, + &info_a, + &info_b, order_mask, xi, alphas_table, ) } else { - evolution::evolve_slice_with_one(self, &view, &info, order_mask, xi, alphas_table) + evolution::evolve_slice_with_one(self, &view, &info_a, order_mask, xi, alphas_table) }?; let mut rhs = Self { @@ -1547,7 +1549,7 @@ impl Grid { }; // write additional metadata - rhs.set_key_value("lumi_id_types", &info.lumi_id_types); + rhs.set_key_value("lumi_id_types", &info_a.lumi_id_types); if let Some(lhs) = &mut lhs { lhs.merge(rhs)?; @@ -1555,7 +1557,7 @@ impl Grid { lhs = Some(rhs); } - fac1.push(info.fac1); + fac1.push(info_a.fac1); } // UNWRAP: if we can't compare two numbers there's a bug diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index c969a772..8347f779 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -424,8 +424,8 @@ mod eko { #[cfg(feature = "evolve")] fn evolve_grid( grid: &Grid, - eko: &Path, - extra_eko: &Path, + eko_a: &Path, + eko_b: &Path, pdf: &Pdf, orders: &[(u32, u32)], xir: f64, @@ -446,8 +446,8 @@ fn evolve_grid( }) .collect(); - let mut eko_slices = EkoSlices::new(eko)?; - let mut extra_eko_slices = EkoSlices::new(extra_eko)?; + let mut eko_slices_a = EkoSlices::new(eko_a)?; + let mut eko_slices_b = EkoSlices::new(eko_b)?; let alphas_table = AlphasTable::from_grid(grid, xir, &|q2| pdf.alphas_q2(q2)); // TODO: Check that cloning the `alphas_table` does not cause performance @@ -457,12 +457,12 @@ fn evolve_grid( fac1, info, operator, - } = eko_slices + } = eko_slices_a { // TODO: Check if the `operator` object is actually mutable let original_operator = operator; - let op_info = OperatorInfo { + let op_info_a = OperatorInfo { fac0: info.fac0, pids0: info.pids0.clone(), x0: info.x0.clone(), @@ -480,10 +480,10 @@ fn evolve_grid( fac1, info, operator, - } = extra_eko_slices + } = eko_slices_b { // TODO: change the info object - let _extra_op_info = OperatorInfo { + let op_info_b = OperatorInfo { fac0: info.fac0, pids0: info.pids0.clone(), x0: info.x0.clone(), @@ -501,7 +501,8 @@ fn evolve_grid( Ok(grid.evolve( original_operator.view(), operator.view(), - &op_info, + &op_info_a, + &op_info_b, &order_mask, )?) } else { @@ -512,8 +513,8 @@ fn evolve_grid( } } else { Ok(grid.evolve_with_slice_iter( - &mut eko_slices, - &mut extra_eko_slices, + &mut eko_slices_a, + &mut eko_slices_b, &order_mask, (xir, xif), &alphas_table, From 16244d253d41152790a7cce5fd51c9fa27cf19ba Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Sun, 2 Jun 2024 16:09:55 +0200 Subject: [PATCH 06/38] propagate different info in places that should matter --- pineappl_py/src/grid.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 43256da3..4405c030 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -424,6 +424,7 @@ impl PyGrid { } /// Convolute with grid with an evolution operator. + /// TODO: Modify the passed `info` from higher level (pineko) /// /// Parameters /// ---------- @@ -492,6 +493,7 @@ impl PyGrid { operator_a.as_array(), operator_b.as_array(), &op_info, + &op_info, order_mask.as_slice().unwrap(), ) .expect("Nothing returned from evolution."); From 97aa73e6febc29cf1f87320e41decbc81736735c Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Sun, 2 Jun 2024 17:10:57 +0200 Subject: [PATCH 07/38] fixes issues during merging --- pineappl/src/grid.rs | 14 ++------------ pineappl_cli/src/evolve.rs | 2 +- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 72d25b58..d54402e9 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1445,8 +1445,6 @@ impl Grid { fac1, pids1: info_b.pids1.clone(), x1: info_b.x1.clone(), - pids1: info_b.pids1.clone(), - x1: info_b.x1.clone(), pid_basis: info_b.pid_basis, }, CowArray::from(op), @@ -1512,7 +1510,6 @@ impl Grid { let view = operator.view(); -<<<<<<< HEAD // Deal with the additional EKO let (info_b, operator_b) = result_b.map_err(|err| GridError::Other(err.into()))?; @@ -1533,10 +1530,7 @@ impl Grid { let extra_view = operator_b.view(); - let (subgrids, lumi) = if self.convolutions()[0] != Convolution::None -======= let (subgrids, channels) = if self.convolutions()[0] != Convolution::None ->>>>>>> master && self.convolutions()[1] != Convolution::None { evolution::evolve_slice_with_two( @@ -1562,13 +1556,9 @@ impl Grid { more_members: self.more_members.clone(), }; -<<<<<<< HEAD - // write additional metadata - rhs.set_key_value("lumi_id_types", &info_a.lumi_id_types); -======= // TODO: use a new constructor to set this information - rhs.set_pid_basis(info.pid_basis); ->>>>>>> master + // TODO: Verify if we need to differentiate `info` here + rhs.set_pid_basis(info_a.pid_basis); if let Some(lhs) = &mut lhs { lhs.merge(rhs)?; diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index f10c066c..af6e7ef0 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -494,7 +494,7 @@ fn evolve_grid( alphas: alphas_table.alphas.clone(), xir, xif, - lumi_id_types: info.lumi_id_types, + pid_basis: info.pid_basis, }; #[allow(deprecated)] From d2e6e1faf3c7f009ae4b1ae45b3eef035293d6dd Mon Sep 17 00:00:00 2001 From: Tanjona Rabemananjara Date: Mon, 3 Jun 2024 08:17:01 +0200 Subject: [PATCH 08/38] fixed some ambiguities and clean up a bit --- pineappl/src/grid.rs | 8 +++----- pineappl_cli/src/evolve.rs | 1 + pineappl_py/pineappl/grid.py | 34 ++++++++++++++++++++++------------ pineappl_py/src/grid.rs | 21 +++++++++++++++++---- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index d54402e9..7f94d2f7 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1392,8 +1392,6 @@ impl Grid { } } - /// TODO: Fix to account for the different EKOs - /// TODO: Does the info have to be different? /// 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, @@ -1488,9 +1486,9 @@ impl Grid { let mut lhs: Option = None; let mut fac1 = Vec::new(); - // TODO: simplify the ugly repetition below + // TODO: simplify the ugly repetition below by offloading some ops into fn for (result_a, result_b) in izip!(slices_a, slices_b) { - // Deal with the main EKO + // Operate on `slices_a` let (info_a, operator) = result_a.map_err(|err| GridError::Other(err.into()))?; let op_info_dim_a = ( @@ -1510,7 +1508,7 @@ impl Grid { let view = operator.view(); - // Deal with the additional EKO + // Operate on `slices_b` let (info_b, operator_b) = result_b.map_err(|err| GridError::Other(err.into()))?; let op_info_dim_b = ( diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index af6e7ef0..143f87cb 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -538,6 +538,7 @@ fn evolve_grid( )) } +/// TODO: pass the additional EKO as an optional input args /// Evolve a grid with an evolution kernel operator to an FK table. #[derive(Parser)] pub struct Opts { diff --git a/pineappl_py/pineappl/grid.py b/pineappl_py/pineappl/grid.py index c78cb39c..0a5c9b7a 100644 --- a/pineappl_py/pineappl/grid.py +++ b/pineappl_py/pineappl/grid.py @@ -299,9 +299,10 @@ def convolve_with_two( def evolve( self, - operators, + operators_a, mur2_grid, alphas_values, + operators_b=None, lumi_id_types="pdg_mc_ids", order_mask=(), xi=(1.0, 1.0), @@ -312,12 +313,14 @@ def evolve( Parameters ---------- - operators : dict + operators_a : dict EKO Output mur2_grid : list[float] renormalization scales alphas_values : list[float] alpha_s values associated to the renormalization scales + operator_b: Optional[dict] + an optional EKO Output lumi_id_types : str kind of lumi types (e.g. "pdg_mc_ids" for flavor basis, "evol" for evolution basis) @@ -336,20 +339,27 @@ def evolve( PyFkTable : raw grid as an FKTable """ - operator_grid = np.array( - [op["operators"] for op in operators["Q2grid"].values()] + operator_grid_a = np.array( + [op["operators"] for op in operators_a["Q2grid"].values()] ) - q2grid = list(operators["Q2grid"].keys()) + if operators_b is not None: + operator_grid_b = np.array( + [op["operators"] for op in operators_b["Q2grid"].values()] + ) + else: + operator_grid_b = operator_grid_a + + q2grid = list(operators_a["Q2grid"].keys()) return FkTable( self.raw.evolve( - np.array(operator_grid), - operators["q2_ref"], - operators["q2_ref"], # TODO: Modify the input EKO - np.array(operators["inputpids"], dtype=np.int32), - np.array(operators["inputgrid"]), + np.array(operator_grid_a), + np.array(operator_grid_b), + operators_a["q2_ref"], + np.array(operators_a["inputpids"], dtype=np.int32), + np.array(operators_a["inputgrid"]), np.array(q2grid, dtype=np.float64), - np.array(operators["targetpids"], dtype=np.int32), - np.array(operators["targetgrid"]), + np.array(operators_a["targetpids"], dtype=np.int32), + np.array(operators_a["targetgrid"]), np.array(mur2_grid, dtype=np.float64), np.array(alphas_values, dtype=np.float64), xi, diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index b7071c1a..985ea2f7 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -422,7 +422,6 @@ impl PyGrid { } /// Convolute with grid with an evolution operator. - /// TODO: Modify the passed `info` from higher level (pineko) /// /// Parameters /// ---------- @@ -471,7 +470,21 @@ impl PyGrid { lumi_id_types: String, order_mask: PyReadonlyArray1, ) -> PyFkTable { - let op_info = OperatorInfo { + let op_info_a = 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, + pid_basis: lumi_id_types.parse().unwrap(), + }; + + let op_info_b = OperatorInfo { fac0: fac0, pids0: pids0.to_vec().unwrap(), x0: x0.to_vec().unwrap(), @@ -490,8 +503,8 @@ impl PyGrid { .evolve( operator_a.as_array(), operator_b.as_array(), - &op_info, - &op_info, + &op_info_a, + &op_info_b, order_mask.as_slice().unwrap(), ) .expect("Nothing returned from evolution."); From 4222163499b1bb1c5f01895ed599c98177e26018 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Mon, 3 Jun 2024 13:32:29 +0200 Subject: [PATCH 09/38] apply some rewordings --- pineappl/src/grid.rs | 1 + pineappl_cli/src/evolve.rs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 7f94d2f7..c6db6ec5 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1564,6 +1564,7 @@ impl Grid { lhs = Some(rhs); } + // NOTE: The following should be shared by the 2 EKOs(?) fac1.push(info_a.fac1); } diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 143f87cb..af6e7ef0 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -538,7 +538,6 @@ fn evolve_grid( )) } -/// TODO: pass the additional EKO as an optional input args /// Evolve a grid with an evolution kernel operator to an FK table. #[derive(Parser)] pub struct Opts { From 6549de829cb96006dbf176a99af9a4be1a323a14 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Tue, 4 Jun 2024 17:01:27 +0200 Subject: [PATCH 10/38] add convolve_with_two method for py interface --- pineappl_py/src/fk_table.rs | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 60abdbe8..7bae6d22 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -244,6 +244,50 @@ impl PyFkTable { .into_pyarray(py) } + /// Convolute grid with two pdfs. + /// + /// **Usage:** `pineko`, `nnpdf` + /// + /// Parameters + /// ---------- + /// pdg_id1 : integer + /// PDG Monte Carlo ID of the hadronic particle `xfx1` is the PDF for + /// xfx1 : callable + /// lhapdf like callable with arguments `pid, x, Q2` returning x*pdf for :math:`x`-grid + /// pdg_id2 : integer + /// PDG Monte Carlo ID of the hadronic particle `xfx2` is the PDF for + /// xfx2 : callable + /// lhapdf like callable with arguments `pid, x, Q2` returning x*pdf for :math:`x`-grid + /// + /// Returns + /// ------- + /// numpy.ndarray(float) : + /// cross sections for all bins + #[pyo3(signature = (pdg_id1, xfx1, pdg_id2, xfx2, bin_indices = None, lumi_mask= None))] + pub fn convolve_with_two<'py>( + &self, + pdg_id1: i32, + xfx1: &PyAny, + pdg_id2: i32, + xfx2: &PyAny, + bin_indices: Option>, + lumi_mask: Option>, + py: Python<'py>, + ) -> &'py PyArray1 { + let mut xfx1 = |id, x, q2| f64::extract(xfx1.call1((id, x, q2)).unwrap()).unwrap(); + let mut xfx2 = |id, x, q2| f64::extract(xfx2.call1((id, x, q2)).unwrap()).unwrap(); + let mut alphas = |_| 1.0; + let mut lumi_cache = + LumiCache::with_two(pdg_id1, &mut xfx1, pdg_id2, &mut xfx2, &mut alphas); + self.fk_table + .convolve( + &mut lumi_cache, + &bin_indices.map_or(vec![], |b| b.to_vec().unwrap()), + &lumi_mask.map_or(vec![], |l| l.to_vec().unwrap()), + ) + .into_pyarray(py) + } + /// Optimize FK table storage /// /// In order to perform any relevant optimization, assumptions are needed, and they are passed From 685303da86e7470713c556cdf612c4c8599279de Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Wed, 5 Jun 2024 16:12:00 +0200 Subject: [PATCH 11/38] fix a typo in passing the info --- 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 cbf7f685..12a5d812 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -540,7 +540,7 @@ pub(crate) fn evolve_slice_with_two( .any(|&(a, _, _)| a == pid1) })?; let (pid_indices_b, pids_b) = - pid_slices(input_operator_b, info_a, gluon_has_pid_zero, &|pid1| { + pid_slices(input_operator_b, info_b, gluon_has_pid_zero, &|pid1| { grid.channels() .iter() .flat_map(Channel::entry) From 80d97398b5e4566da60f69fcd97354f98ee587f9 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Fri, 7 Jun 2024 20:51:16 +0200 Subject: [PATCH 12/38] working version: remove pending todos and add a few notes --- pineappl/src/evolution.rs | 1 + pineappl/src/grid.rs | 25 ++++++++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 12a5d812..6fb0d4ea 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -556,6 +556,7 @@ pub(crate) fn evolve_slice_with_two( let mut operators_b = Vec::new(); for subgrids_ol in grid.subgrids().axis_iter(Axis(1)) { + // NOTE: `info_a.x0.len()` and `info_b.x0.len()` are the same let mut tables = vec![Array2::zeros((info_a.x0.len(), info_a.x0.len())); channels0.len()]; for (subgrids_o, channel1) in subgrids_ol.axis_iter(Axis(1)).zip(grid.channels()) { diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index c6db6ec5..b5085508 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1489,7 +1489,7 @@ impl Grid { // TODO: simplify the ugly repetition below by offloading some ops into fn for (result_a, result_b) in izip!(slices_a, slices_b) { // Operate on `slices_a` - let (info_a, operator) = result_a.map_err(|err| GridError::Other(err.into()))?; + let (info_a, operator_a) = result_a.map_err(|err| GridError::Other(err.into()))?; let op_info_dim_a = ( info_a.pids1.len(), @@ -1498,15 +1498,15 @@ impl Grid { info_a.x0.len(), ); - if operator.dim() != op_info_dim_a { + if operator_a.dim() != op_info_dim_a { return Err(GridError::EvolutionFailure(format!( "operator information {:?} does not match the operator's dimensions: {:?}", op_info_dim_a, - operator.dim(), + operator_a.dim(), ))); } - let view = operator.view(); + let view_a = operator_a.view(); // Operate on `slices_b` let (info_b, operator_b) = result_b.map_err(|err| GridError::Other(err.into()))?; @@ -1526,15 +1526,15 @@ impl Grid { ))); } - let extra_view = operator_b.view(); + let view_b = operator_b.view(); let (subgrids, channels) = if self.convolutions()[0] != Convolution::None && self.convolutions()[1] != Convolution::None { evolution::evolve_slice_with_two( self, - &view, - &extra_view, + &view_a, + &view_b, &info_a, &info_b, order_mask, @@ -1542,7 +1542,14 @@ impl Grid { alphas_table, ) } else { - evolution::evolve_slice_with_one(self, &view, &info_a, order_mask, xi, alphas_table) + evolution::evolve_slice_with_one( + self, + &view_a, + &info_a, + order_mask, + xi, + alphas_table, + ) }?; let mut rhs = Self { @@ -1555,7 +1562,7 @@ impl Grid { }; // TODO: use a new constructor to set this information - // TODO: Verify if we need to differentiate `info` here + // NOTE: `info_a.pid_basis` and `info_b.pid_basis` are the same rhs.set_pid_basis(info_a.pid_basis); if let Some(lhs) = &mut lhs { From 5630f708fc96138afee785eba3f5a57caa5ac292 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Thu, 13 Jun 2024 01:53:21 +0200 Subject: [PATCH 13/38] extend CLI and try tests --- .github/workflows/rust.yml | 5 +- maintainer/generate-coverage.sh | 3 + maintainer/pineappl-ci/script.sh | 4 +- pineappl_cli/src/evolve.rs | 114 ++++++++++++++++++++++--------- pineappl_cli/src/helpers.rs | 35 ++++++++-- pineappl_cli/tests/evolve.rs | 33 +++++++++ 6 files changed, 156 insertions(+), 38 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a2751695..65238a88 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -23,7 +23,7 @@ jobs: uses: actions/cache@v3 with: path: test-data - key: test-data-v11 + key: test-data-v12 - name: Download test data if: steps.cache-test-data.outputs.cache-hit != 'true' run: | @@ -53,6 +53,9 @@ jobs: curl -s -C - -O 'https://ploughshare.web.cern.ch/ploughshare/db/applfast/applfast-h1-dijets-appl-arxiv-0010054/grids/applfast-h1-dijets-appl-arxiv-0010054-xsec000.appl' curl -s -C - -O 'https://ploughshare.web.cern.ch/ploughshare/db/applfast/applfast-h1-incjets-fnlo-arxiv-0706.3722/grids/applfast-h1-incjets-fnlo-arxiv-0706.3722-xsec000.tab.gz' curl -s -C - -O 'https://ploughshare.web.cern.ch/ploughshare/db/atlas/atlas-atlas-wpm-arxiv-1109.5141/grids/atlas-atlas-wpm-arxiv-1109.5141-xsec001.appl' + curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4' + curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL_PolPDF.tar' + curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL_UnpolPDF.tar' - name: Set RUSTDOCFLAGS run: | diff --git a/maintainer/generate-coverage.sh b/maintainer/generate-coverage.sh index 6f1b2ac4..bba5931d 100755 --- a/maintainer/generate-coverage.sh +++ b/maintainer/generate-coverage.sh @@ -27,6 +27,9 @@ wget --no-verbose --no-clobber -P test-data 'https://ploughshare.web.cern.ch/plo wget --no-verbose --no-clobber -P test-data 'https://ploughshare.web.cern.ch/ploughshare/db/applfast/applfast-h1-dijets-appl-arxiv-0010054/grids/applfast-h1-dijets-appl-arxiv-0010054-xsec000.appl' wget --no-verbose --no-clobber -P test-data 'https://ploughshare.web.cern.ch/ploughshare/db/applfast/applfast-h1-incjets-fnlo-arxiv-0706.3722/grids/applfast-h1-incjets-fnlo-arxiv-0706.3722-xsec000.tab.gz' wget --no-verbose --no-clobber -P test-data 'https://ploughshare.web.cern.ch/ploughshare/db/atlas/atlas-atlas-wpm-arxiv-1109.5141/grids/atlas-atlas-wpm-arxiv-1109.5141-xsec001.appl' +wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4' +wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL_PolPDF.tar' +wget --no-verbose --no-clobber -P test-data 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL_UnpolPDF.tar' # we compile with different flags and don't want to destroy the other target directory export CARGO_TARGET_DIR="$(mktemp -d)" diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index c5b61312..cfd36a98 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -49,9 +49,11 @@ ldconfig cd .. # install PDF sets -for pdf in NNPDF31_nlo_as_0118_luxqed NNPDF40_nnlo_as_01180 NNPDF40_nlo_as_01180; do +for pdf in NNPDF31_nlo_as_0118_luxqed NNPDF40_nnlo_as_01180 NNPDF40_nlo_as_01180 NNPDF40_nlo_pch_as_01180; do curl "https://lhapdfsets.web.cern.ch/current/${pdf}.tar.gz" | tar xzf - -C /usr/local/share/LHAPDF done +# Download PDF set available only on the NNPDF server +curl "https://data.nnpdf.science/pineappl/pdfs/240608-tr-pol-nlo-100.tar.gz" | tar xzf - -C /usr/local/share/LHAPDF # install zlib compiled with `-fPIC` curl "https://www.zlib.net/zlib-${ZLIB_V}.tar.gz" | tar xzf - diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index af6e7ef0..a37853ca 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -553,6 +553,12 @@ pub struct Opts { /// LHAPDF id or name of the PDF set to check the converted grid with. #[arg(value_parser = helpers::parse_pdfset)] pdfset: String, + /// Additional path to the 2nd evolution kernel operator. + #[arg(value_hint = ValueHint::FilePath, long)] + ekob: Option, + /// LHAPDF id or name of the 2nd PDF set to check the converted grid with. + #[arg(value_parser = helpers::parse_pdfset, long)] + pdfsetb: Option, /// Relative threshold between the table and the converted grid when comparison fails. #[arg(default_value = "1e-3", long)] accuracy: f64, @@ -587,38 +593,82 @@ impl Subcommand for Opts { let grid = helpers::read_grid(&self.input)?; let mut pdf = helpers::create_pdf(&self.pdfset)?; - let results = helpers::convolve_scales( - &grid, - &mut pdf, - &self.orders, - &[], - &[], - &[(self.xir, self.xif)], - ConvoluteMode::Normal, - cfg, - ); - - // TODO: properly pass the additional EKO from input args - let fk_table = evolve_grid( - &grid, - &self.eko, - &self.eko, - &pdf, - &self.orders, - self.xir, - self.xif, - self.use_old_evolve, - )?; - let evolved_results = helpers::convolve_scales( - fk_table.grid(), - &mut pdf, - &[], - &[], - &[], - &[(1.0, 1.0)], - ConvoluteMode::Normal, - cfg, - ); + + let fk_table: FkTable; + if let Some(ekob) = &self.ekob { + fk_table = evolve_grid( + &grid, + &self.eko, + ekob, + &pdf, + &self.orders, + self.xir, + self.xif, + self.use_old_evolve, + )?; + } else { + fk_table = evolve_grid( + &grid, + &self.eko, + &self.eko, + &pdf, + &self.orders, + self.xir, + self.xif, + self.use_old_evolve, + )?; + } + + let results: Vec; + let evolved_results: Vec; + if let Some(tmp_pdfb) = &self.pdfsetb { + let mut pdfb = helpers::create_pdf(tmp_pdfb)?; + results = helpers::convolve_scales( + &grid, + &mut pdf, + &self.orders, + &[], + &[], + &[(self.xir, self.xif)], + ConvoluteMode::Normal, + cfg, + Some(&mut pdfb), + ); + evolved_results = helpers::convolve_scales( + fk_table.grid(), + &mut pdf, + &[], + &[], + &[], + &[(1.0, 1.0)], + ConvoluteMode::Normal, + cfg, + Some(&mut pdfb), + ); + } else { + results = helpers::convolve_scales( + &grid, + &mut pdf, + &self.orders, + &[], + &[], + &[(self.xir, self.xif)], + ConvoluteMode::Normal, + cfg, + None, + ); + evolved_results = helpers::convolve_scales( + fk_table.grid(), + &mut pdf, + &[], + &[], + &[], + &[(1.0, 1.0)], + ConvoluteMode::Normal, + cfg, + None, + ); + } // 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()); diff --git a/pineappl_cli/src/helpers.rs b/pineappl_cli/src/helpers.rs index 7947da34..278120ae 100644 --- a/pineappl_cli/src/helpers.rs +++ b/pineappl_cli/src/helpers.rs @@ -134,6 +134,7 @@ pub fn convolve_scales( scales: &[(f64, f64)], mode: ConvoluteMode, cfg: &GlobalConfiguration, + lhapdfb: Option<&mut Pdf>, ) -> Vec { let orders: Vec<_> = grid .orders() @@ -146,6 +147,10 @@ pub fn convolve_scales( }) .collect(); + // Quantities defined to be shared by the PDFs + let x_max = lhapdf.x_max(); + let x_min = lhapdf.x_min(); + // if the field 'Particle' is missing we assume it's a proton PDF let pdf_pdg_id = lhapdf .set() @@ -157,8 +162,6 @@ pub fn convolve_scales( lhapdf.set_force_positive(1); } - let x_max = lhapdf.x_max(); - let x_min = lhapdf.x_min(); let mut pdf = |id, x, q2| { if !cfg.allow_extrapolation && (x < x_min || x > x_max) { 0.0 @@ -166,9 +169,32 @@ pub fn convolve_scales( lhapdf.xfx_q2(id, x, q2) } }; + 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.convolve(&mut cache, &orders, bins, channels, scales); + + let mut cache; + let mut results; + if let Some(tmp_lhapdfb) = lhapdfb { + let pdf_pdg_idb = tmp_lhapdfb + .set() + .entry("Particle") + .map_or(Ok(2212), |string| string.parse::()) + .unwrap(); + let mut pdfb = |id, x, q2| { + if !cfg.allow_extrapolation && (x < x_min || x > x_max) { + 0.0 + } else { + tmp_lhapdfb.xfx_q2(id, x, q2) + } + }; + // let mut cache = LumiCache::with_one(pdf_pdg_id, &mut pdf, &mut alphas); + cache = LumiCache::with_two(pdf_pdg_id, &mut pdf, pdf_pdg_idb, &mut pdfb, &mut alphas); + results = grid.convolve(&mut cache, &orders, bins, channels, scales); + } else { + // let mut cache = LumiCache::with_one(pdf_pdg_id, &mut pdf, &mut alphas); + cache = LumiCache::with_one(pdf_pdg_id, &mut pdf, &mut alphas); + results = grid.convolve(&mut cache, &orders, bins, channels, scales); + } match mode { ConvoluteMode::Asymmetry => { @@ -229,6 +255,7 @@ pub fn convolve( &SCALES_VECTOR[0..scales], mode, cfg, + None, ) } diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index 5173c15b..8b628f6a 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -171,6 +171,16 @@ const CMS_TTB_8TEV_2D_TTM_TRAP_TOT_STR: &str = "b Grid FkTable rel. 0 2.1596192e2 2.1590144e2 -2.8005486e-4 "; +const STAR_WMWP_510GEV_WM_AL_POL: &str = "b Grid FkTable rel. diff +-+-----------+-----------+------------- +0 8.0318967e2 8.0327463e2 1.0578078e-4 +1 5.8647900e3 5.8646218e3 -2.8680797e-5 +2 1.4206825e4 1.4206381e4 -3.1254383e-5 +3 2.0815526e4 2.0814997e4 -2.5446033e-5 +4 1.9517370e4 1.9516283e4 -5.5658012e-5 +5 7.5310726e3 7.5296943e3 -1.8301933e-4 +"; + #[test] fn help() { Command::cargo_bin("pineappl") @@ -482,3 +492,26 @@ fn cms_ttb_8tev_2d_ttm_trap_tot() { .success() .stdout(CMS_TTB_8TEV_2D_TTM_TRAP_TOT_STR); } + +#[test] +fn star_wmwp_510gev_wm_al_pol() { + let output = NamedTempFile::new("fktable6.lz4").unwrap(); + + Command::cargo_bin("pineappl") + .unwrap() + .args([ + "evolve", + "--orders=as2,as3,as4", + "../test-data/STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4", + "../test-data/STAR_WMWP_510GEV_WM-AL-POL_PolPDF.tar", + output.path().to_str().unwrap(), + "240608-tr-pol-nlo-100", + "--ekob", + "STAR_WMWP_510GEV_WM-AL-POL_UnpolPDF.tar", + "--pdfsetb", + "NNPDF40_nlo_pch_as_01180", + ]) + .assert() + .success() + .stdout(STAR_WMWP_510GEV_WM_AL_POL); +} From b45532806090fc2ced1562408a33f2429f2d8342 Mon Sep 17 00:00:00 2001 From: Tanjona Rabemananjara Date: Thu, 13 Jun 2024 10:26:29 +0200 Subject: [PATCH 14/38] move downloading of pPDF into rust-yml --- .github/workflows/rust.yml | 3 ++- maintainer/pineappl-ci/script.sh | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 65238a88..fefaea1e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -24,7 +24,7 @@ jobs: with: path: test-data key: test-data-v12 - - name: Download test data + - name: Download test data and additional PDFs if: steps.cache-test-data.outputs.cache-hit != 'true' run: | test -d test-data || mkdir test-data @@ -56,6 +56,7 @@ jobs: curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4' curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL_PolPDF.tar' curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL_UnpolPDF.tar' + curl "https://data.nnpdf.science/pineappl/pdfs/240608-tr-pol-nlo-100.tar.gz" | tar xzf - -C /usr/local/share/LHAPDF - name: Set RUSTDOCFLAGS run: | diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index cfd36a98..f93240fe 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -52,8 +52,6 @@ cd .. for pdf in NNPDF31_nlo_as_0118_luxqed NNPDF40_nnlo_as_01180 NNPDF40_nlo_as_01180 NNPDF40_nlo_pch_as_01180; do curl "https://lhapdfsets.web.cern.ch/current/${pdf}.tar.gz" | tar xzf - -C /usr/local/share/LHAPDF done -# Download PDF set available only on the NNPDF server -curl "https://data.nnpdf.science/pineappl/pdfs/240608-tr-pol-nlo-100.tar.gz" | tar xzf - -C /usr/local/share/LHAPDF # install zlib compiled with `-fPIC` curl "https://www.zlib.net/zlib-${ZLIB_V}.tar.gz" | tar xzf - From e236b3c4dc8415577d0142bce450084d97a0231f Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Thu, 13 Jun 2024 12:06:21 +0200 Subject: [PATCH 15/38] fix minor inconsistencies in tests --- pineappl_cli/tests/evolve.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index 8b628f6a..b75e31bc 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -14,6 +14,8 @@ Arguments: LHAPDF id or name of the PDF set to check the converted grid with Options: + --ekob Additional path to the 2nd evolution kernel operator + --pdfsetb LHAPDF id or name of the 2nd PDF set to check the converted grid with --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] @@ -173,12 +175,12 @@ const CMS_TTB_8TEV_2D_TTM_TRAP_TOT_STR: &str = "b Grid FkTable rel. const STAR_WMWP_510GEV_WM_AL_POL: &str = "b Grid FkTable rel. diff -+-----------+-----------+------------- -0 8.0318967e2 8.0327463e2 1.0578078e-4 -1 5.8647900e3 5.8646218e3 -2.8680797e-5 -2 1.4206825e4 1.4206381e4 -3.1254383e-5 -3 2.0815526e4 2.0814997e4 -2.5446033e-5 -4 1.9517370e4 1.9516283e4 -5.5658012e-5 -5 7.5310726e3 7.5296943e3 -1.8301933e-4 +0 3.2222870e2 3.2226654e2 1.1745654e-4 +1 1.8038157e3 1.8037829e3 -1.8192479e-5 +2 3.4767572e3 3.4762728e3 -1.3933339e-4 +3 4.3157563e3 4.3154783e3 -6.4409623e-5 +4 3.6443947e3 3.6443481e3 -1.2807044e-5 +5 5.8386697e2 5.8336795e2 -8.5468266e-4 "; #[test] @@ -501,15 +503,12 @@ fn star_wmwp_510gev_wm_al_pol() { .unwrap() .args([ "evolve", - "--orders=as2,as3,as4", "../test-data/STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4", "../test-data/STAR_WMWP_510GEV_WM-AL-POL_PolPDF.tar", output.path().to_str().unwrap(), "240608-tr-pol-nlo-100", - "--ekob", - "STAR_WMWP_510GEV_WM-AL-POL_UnpolPDF.tar", - "--pdfsetb", - "NNPDF40_nlo_pch_as_01180", + "--ekob=../test-data/STAR_WMWP_510GEV_WM-AL-POL_UnpolPDF.tar", + "--pdfsetb=NNPDF40_nlo_pch_as_01180", ]) .assert() .success() From 9c6621858abf0949e32592ff0bc871c0a1cc6943 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Mon, 1 Jul 2024 19:06:24 +0200 Subject: [PATCH 16/38] account for multi-pdfs convolution feature --- pineappl_cli/src/evolve.rs | 77 +++++++++++------------------------- pineappl_cli/src/helpers.rs | 2 - pineappl_cli/tests/evolve.rs | 4 +- 3 files changed, 23 insertions(+), 60 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index db520baf..336ef443 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -555,9 +555,6 @@ pub struct Opts { /// Additional path to the 2nd evolution kernel operator. #[arg(value_hint = ValueHint::FilePath, long)] ekob: Option, - /// LHAPDF id or name of the 2nd PDF set to check the converted grid with. - #[arg(value_parser = helpers::parse_pdfset, long)] - pdfsetb: Option, /// Relative threshold between the table and the converted grid when comparison fails. #[arg(default_value = "1e-3", long)] accuracy: f64, @@ -592,6 +589,16 @@ impl Subcommand for Opts { let grid = helpers::read_grid(&self.input)?; let mut conv_funs = helpers::create_conv_funs(&self.conv_funs)?; + let results = helpers::convolve_scales( + &grid, + &mut conv_funs, + &self.orders, + &[], + &[], + &[(self.xir, self.xif)], + ConvoluteMode::Normal, + cfg, + ); let fk_table: FkTable; if let Some(ekob) = &self.ekob { @@ -599,7 +606,7 @@ impl Subcommand for Opts { &grid, &self.eko, ekob, - &pdf, + &conv_funs[cfg.use_alphas_from], &self.orders, self.xir, self.xif, @@ -610,7 +617,7 @@ impl Subcommand for Opts { &grid, &self.eko, &self.eko, - &pdf, + &conv_funs[cfg.use_alphas_from], &self.orders, self.xir, self.xif, @@ -618,56 +625,16 @@ impl Subcommand for Opts { )?; } - let results: Vec; - let evolved_results: Vec; - if let Some(tmp_pdfb) = &self.pdfsetb { - let mut pdfb = helpers::create_pdf(tmp_pdfb)?; - results = helpers::convolve_scales( - &grid, - &mut conv_funs, - &self.orders, - &[], - &[], - &[(self.xir, self.xif)], - ConvoluteMode::Normal, - cfg, - Some(&mut pdfb), - ); - evolved_results = helpers::convolve_scales( - fk_table.grid(), - &mut pdf, - &[], - &[], - &[], - &[(1.0, 1.0)], - ConvoluteMode::Normal, - cfg, - Some(&mut pdfb), - ); - } else { - results = helpers::convolve_scales( - &grid, - &mut conv_funs[cfg.use_alphas_from], - &self.orders, - &[], - &[], - &[(self.xir, self.xif)], - ConvoluteMode::Normal, - cfg, - None, - ); - evolved_results = helpers::convolve_scales( - fk_table.grid(), - &mut conv_funs, - &[], - &[], - &[], - &[(1.0, 1.0)], - ConvoluteMode::Normal, - cfg, - None, - ); - } + let evolved_results = helpers::convolve_scales( + fk_table.grid(), + &mut conv_funs, + &[], + &[], + &[], + &[(1.0, 1.0)], + ConvoluteMode::Normal, + cfg, + ); // 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()); diff --git a/pineappl_cli/src/helpers.rs b/pineappl_cli/src/helpers.rs index 8268d06b..d1871f19 100644 --- a/pineappl_cli/src/helpers.rs +++ b/pineappl_cli/src/helpers.rs @@ -190,7 +190,6 @@ pub fn convolve_scales( scales: &[(f64, f64)], mode: ConvoluteMode, cfg: &GlobalConfiguration, - lhapdfb: Option<&mut Pdf>, ) -> Vec { let orders: Vec<_> = grid .orders() @@ -345,7 +344,6 @@ pub fn convolve( &SCALES_VECTOR[0..scales], mode, cfg, - None, ) } diff --git a/pineappl_cli/tests/evolve.rs b/pineappl_cli/tests/evolve.rs index b76885ef..fcf25ad3 100644 --- a/pineappl_cli/tests/evolve.rs +++ b/pineappl_cli/tests/evolve.rs @@ -15,7 +15,6 @@ Arguments: Options: --ekob Additional path to the 2nd evolution kernel operator - --pdfsetb LHAPDF id or name of the 2nd PDF set to check the converted grid with --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] @@ -506,9 +505,8 @@ fn star_wmwp_510gev_wm_al_pol() { "../test-data/STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4", "../test-data/STAR_WMWP_510GEV_WM-AL-POL_PolPDF.tar", output.path().to_str().unwrap(), - "240608-tr-pol-nlo-100", + "240608-tr-pol-nlo-100,NNPDF40_nlo_pch_as_01180", "--ekob=../test-data/STAR_WMWP_510GEV_WM-AL-POL_UnpolPDF.tar", - "--pdfsetb=NNPDF40_nlo_pch_as_01180", ]) .assert() .success() From 57a996f0f49cab47e94d0b858d4047bfce87e624 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Fri, 5 Jul 2024 15:40:45 +0200 Subject: [PATCH 17/38] remove external download of polarized set --- .github/workflows/rust.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 74a511cb..cbef1bb9 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -58,7 +58,6 @@ jobs: curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4' curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL_PolPDF.tar' curl -s -C - -O 'https://data.nnpdf.science/pineappl/test-data/STAR_WMWP_510GEV_WM-AL-POL_UnpolPDF.tar' - curl "https://data.nnpdf.science/pineappl/pdfs/240608-tr-pol-nlo-100.tar.gz" | tar xzf - -C /usr/local/share/LHAPDF - name: Set RUSTDOCFLAGS run: | From fed2a2b7f6233f9f27367fc18efd8c9d3428c954 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 5 Jul 2024 09:34:50 +0200 Subject: [PATCH 18/38] Fix release workflow --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b96886b3..07b06b8f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,6 +9,8 @@ on: env: # this is make the `gh` binary work GH_TOKEN: ${{ github.token }} + # avoid node20, which doesn't run in our container: https://github.com/actions/checkout/issues/1809 + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: # create a release on github From d007dc6d045602ef91be423ff7e5d7375433a685 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 5 Jul 2024 09:41:26 +0200 Subject: [PATCH 19/38] Fix CIs --- .github/workflows/capi.yaml | 5 +++++ .github/workflows/msrv.yml | 3 +++ .github/workflows/release.yml | 3 ++- .github/workflows/rust.yml | 3 +++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/capi.yaml b/.github/workflows/capi.yaml index 1d70c36b..316c89c1 100644 --- a/.github/workflows/capi.yaml +++ b/.github/workflows/capi.yaml @@ -5,6 +5,11 @@ on: branches-ignore: - pycli +env: + # our GLIBC version is too old to support Node 20: + # https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true + jobs: capi: runs-on: ubuntu-latest diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index c236f28a..068baa8b 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -7,6 +7,9 @@ on: env: CARGO_TERM_COLOR: always + # our GLIBC version is too old to support Node 20: + # https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: build: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 07b06b8f..99dfe6fc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,8 @@ on: env: # this is make the `gh` binary work GH_TOKEN: ${{ github.token }} - # avoid node20, which doesn't run in our container: https://github.com/actions/checkout/issues/1809 + # our GLIBC version is too old to support Node 20: + # https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index cbef1bb9..6b69dfa4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -11,6 +11,9 @@ defaults: env: CARGO_TERM_COLOR: always + # our GLIBC version is too old to support Node 20: + # https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: build: From 6978daa86477cd2c20597b08c5f88f6fe808ad0a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 10:29:59 +0200 Subject: [PATCH 20/38] Restore old methods and add new ones with different names --- pineappl/src/evolution.rs | 114 +++++++++++++++++++++++++++++ pineappl/src/grid.rs | 137 ++++++++++++++++++++++++++++++++++- pineappl_cli/src/evolve.rs | 45 ++---------- pineappl_py/pineappl/grid.py | 60 +++++++++++++++ pineappl_py/src/grid.rs | 77 +++++++++++++++++++- 5 files changed, 391 insertions(+), 42 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 789642e0..d86c3d1a 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -522,6 +522,120 @@ pub(crate) fn evolve_slice_with_one( } pub(crate) fn evolve_slice_with_two( + grid: &Grid, + operator: &ArrayView4, + info: &OperatorSliceInfo, + order_mask: &[bool], + xi: (f64, f64), + alphas_table: &AlphasTable, +) -> Result<(Array3, Vec), GridError> { + let gluon_has_pid_zero = gluon_has_pid_zero(grid); + + let (pid_indices_a, pids_a) = pid_slices(operator, info, gluon_has_pid_zero, &|pid1| { + grid.channels() + .iter() + .flat_map(Channel::entry) + .any(|&(a, _, _)| a == pid1) + })?; + let (pid_indices_b, pids_b) = pid_slices(operator, info, gluon_has_pid_zero, &|pid1| { + grid.channels() + .iter() + .flat_map(Channel::entry) + .any(|&(_, b, _)| b == pid1) + })?; + + let channels0 = channels0_with_two(&pids_a, &pids_b); + let mut sub_fk_tables = Vec::with_capacity(grid.bin_info().bins() * channels0.len()); + + 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())); channels0.len()]; + + for (subgrids_o, channel1) in subgrids_ol.axis_iter(Axis(1)).zip(grid.channels()) { + let (x1_a, x1_b, array) = ndarray_from_subgrid_orders_slice( + info, + &subgrids_o, + grid.orders(), + order_mask, + xi, + alphas_table, + )?; + + if (last_x1a.len() != x1_a.len()) + || last_x1a + .iter() + .zip(x1_a.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) + { + operators_a = operator_slices(operator, info, &pid_indices_a, &x1_a)?; + last_x1a = x1_a; + } + + if (last_x1b.len() != x1_b.len()) + || last_x1b + .iter() + .zip(x1_b.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) + { + operators_b = operator_slices(operator, info, &pid_indices_b, &x1_b)?; + last_x1b = x1_b; + } + + let mut tmp = Array2::zeros((last_x1a.len(), info.x0.len())); + + for &(pida1, pidb1, factor) in channel1.entry() { + for (fk_table, opa, opb) in channels0.iter().zip(tables.iter_mut()).filter_map( + |(&(pida0, pidb0), fk_table)| { + pids_a + .iter() + .zip(operators_a.iter()) + .find_map(|(&(pa0, pa1), opa)| { + (pa0 == pida0 && pa1 == pida1).then_some(opa) + }) + .zip(pids_b.iter().zip(operators_b.iter()).find_map( + |(&(pb0, pb1), opb)| (pb0 == pidb0 && pb1 == pidb1).then_some(opb), + )) + .map(|(opa, opb)| (fk_table, opa, opb)) + }, + ) { + linalg::general_mat_mul(1.0, &array, &opb.t(), 0.0, &mut tmp); + linalg::general_mat_mul(factor, opa, &tmp, 1.0, fk_table); + } + } + } + + sub_fk_tables.extend(tables.into_iter().map(|table| { + ImportOnlySubgridV2::new( + SparseArray3::from_ndarray(table.insert_axis(Axis(0)).view(), 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_shape((1, grid.bin_info().bins(), channels0.len())) + .unwrap(), + channels0 + .iter() + .map(|&(a, b)| channel![a, b, 1.0]) + .collect(), + )) +} + +pub(crate) fn evolve_slice_with_two2( grid: &Grid, input_operator_a: &ArrayView4, input_operator_b: &ArrayView4, diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index cf6ac800..7e02d5b8 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1354,6 +1354,40 @@ impl Grid { /// incompatible with this `Grid`. #[deprecated(since = "0.7.4", note = "use evolve_with_slice_iter instead")] pub fn evolve( + &self, + operator: ArrayView5, + info: &OperatorInfo, + order_mask: &[bool], + ) -> Result { + self.evolve_with_slice_iter( + info.fac1 + .iter() + .zip(operator.axis_iter(Axis(0))) + .map(|(&fac1, op)| { + Ok::<_, GridError>(( + OperatorSliceInfo { + fac0: info.fac0, + pids0: info.pids0.clone(), + x0: info.x0.clone(), + fac1, + pids1: info.pids1.clone(), + x1: info.x1.clone(), + pid_basis: info.pid_basis, + }, + CowArray::from(op), + )) + }), + order_mask, + (info.xir, info.xif), + &AlphasTable { + ren1: info.ren1.clone(), + alphas: info.alphas.clone(), + }, + ) + } + + #[deprecated(since = "0.8.1", note = "use evolve_slice_with_two2 instead")] + pub fn evolve2( &self, operator_a: ArrayView5, operator_b: ArrayView5, @@ -1361,7 +1395,7 @@ impl Grid { info_b: &OperatorInfo, order_mask: &[bool], ) -> Result { - self.evolve_with_slice_iter( + self.evolve_with_slice_iter2( info_a .fac1 .iter() @@ -1423,6 +1457,105 @@ impl Grid { /// incompatible with this `Grid`. Returns a [`GridError::Other`] if the iterator from `slices` /// return an error. pub fn evolve_with_slice_iter<'a, E: Into>( + &self, + slices: impl IntoIterator), E>>, + order_mask: &[bool], + xi: (f64, f64), + alphas_table: &AlphasTable, + ) -> Result { + use super::evolution::EVOLVE_INFO_TOL_ULPS; + + let mut lhs: Option = None; + let mut fac1 = Vec::new(); + + for result in slices { + let (info, operator) = result.map_err(|err| GridError::Other(err.into()))?; + + let op_info_dim = ( + 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(), + ))); + } + + let view = operator.view(); + + let (subgrids, channels) = if self.convolutions()[0] != Convolution::None + && self.convolutions()[1] != Convolution::None + { + evolution::evolve_slice_with_two(self, &view, &info, order_mask, xi, alphas_table) + } else { + evolution::evolve_slice_with_one(self, &view, &info, order_mask, xi, alphas_table) + }?; + + let mut rhs = Self { + subgrids, + channels, + bin_limits: self.bin_limits.clone(), + orders: vec![Order::new(0, 0, 0, 0)], + subgrid_params: SubgridParams::default(), + more_members: self.more_members.clone(), + }; + + // TODO: use a new constructor to set this information + rhs.set_pid_basis(info.pid_basis); + + if let Some(lhs) = &mut lhs { + lhs.merge(rhs)?; + } else { + lhs = Some(rhs); + } + + fac1.push(info.fac1); + } + + // UNWRAP: if we can't compare two numbers there's a bug + fac1.sort_by(|a, b| a.partial_cmp(b).unwrap_or_else(|| unreachable!())); + + // make sure we've evolved all slices + if let Some(muf2) = self + .evolve_info(order_mask) + .fac1 + .into_iter() + .map(|mu2| xi.1 * xi.1 * mu2) + .find(|&grid_mu2| { + !fac1 + .iter() + .any(|&eko_mu2| approx_eq!(f64, grid_mu2, eko_mu2, ulps = EVOLVE_INFO_TOL_ULPS)) + }) + { + return Err(GridError::EvolutionFailure(format!( + "no operator for muf2 = {muf2} found in {fac1:?}" + ))); + } + + // TODO: convert this unwrap into error + let grid = lhs.unwrap(); + + // UNWRAP: merging evolved slices should be a proper FkTable again + Ok(FkTable::try_from(grid).unwrap_or_else(|_| unreachable!())) + } + + /// Converts this `Grid` into an [`FkTable`] using `slices` that must iterate over a [`Result`] + /// of tuples of an [`OperatorSliceInfo`] and the corresponding sliced operator. 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`. Returns a [`GridError::Other`] if the iterator from `slices` + /// return an error. + pub fn evolve_with_slice_iter2<'a, E: Into>( &self, slices_a: impl IntoIterator), E>>, slices_b: impl IntoIterator), E>>, @@ -1481,7 +1614,7 @@ impl Grid { let (subgrids, channels) = if self.convolutions()[0] != Convolution::None && self.convolutions()[1] != Convolution::None { - evolution::evolve_slice_with_two( + evolution::evolve_slice_with_two2( self, &view_a, &view_b, diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 336ef443..3aa89a38 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -459,60 +459,27 @@ fn evolve_grid( operator, } = eko_slices_a { - // TODO: Check if the `operator` object is actually mutable - let original_operator = operator; - - let op_info_a = OperatorInfo { + let op_info = OperatorInfo { fac0: info.fac0, pids0: info.pids0.clone(), x0: info.x0.clone(), fac1, pids1: info.pids1.clone(), x1: info.x1.clone(), - ren1: alphas_table.ren1.clone(), - alphas: alphas_table.alphas.clone(), + ren1: alphas_table.ren1, + alphas: alphas_table.alphas, xir, xif, pid_basis: info.pid_basis, }; - if let EkoSlices::V0 { - fac1, - info, - operator, - } = eko_slices_b - { - // TODO: change the info object - let op_info_b = OperatorInfo { - fac0: info.fac0, - pids0: info.pids0.clone(), - x0: info.x0.clone(), - fac1, - pids1: info.pids1.clone(), - x1: info.x1.clone(), - ren1: alphas_table.ren1.clone(), - alphas: alphas_table.alphas.clone(), - xir, - xif, - pid_basis: info.pid_basis, - }; - - #[allow(deprecated)] - Ok(grid.evolve( - original_operator.view(), - operator.view(), - &op_info_a, - &op_info_b, - &order_mask, - )?) - } else { - unimplemented!(); - } + #[allow(deprecated)] + Ok(grid.evolve(operator.view(), &op_info, &order_mask)?) } else { unimplemented!(); } } else { - Ok(grid.evolve_with_slice_iter( + Ok(grid.evolve_with_slice_iter2( &mut eko_slices_a, &mut eko_slices_b, &order_mask, diff --git a/pineappl_py/pineappl/grid.py b/pineappl_py/pineappl/grid.py index 0a5c9b7a..40ff31b2 100644 --- a/pineappl_py/pineappl/grid.py +++ b/pineappl_py/pineappl/grid.py @@ -297,7 +297,67 @@ def convolve_with_two( xi, ) + 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), + ) + ) + + def evolve2( self, operators_a, mur2_grid, diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 6065d0f4..e797cd82 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -453,6 +453,81 @@ impl PyGrid { /// 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, + pid_basis: lumi_id_types.parse().unwrap(), + }; + + let evolved_grid = self + .grid + .evolve( + operator.as_array(), + &op_info, + order_mask.as_slice().unwrap(), + ) + .expect("Nothing returned from evolution."); + PyFkTable { + fk_table: evolved_grid, + } + } + + /// Convolute with grid with an evolution operator. + /// + /// Parameters + /// ---------- + /// operator : numpy.ndarray(int, rank=5) + /// evolution tensor + /// fac0 : float + /// reference scale + /// pids0 : numpy.ndarray(int) + /// sorting of the particles in the tensor for final FkTable + /// x0 : numpy.ndarray(float) + /// final FKTable interpolation grid + /// fac1 : numpy.ndarray(float) + /// list of factorization scales + /// 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 + /// ------- + /// PyFkTable : + /// produced FK table + pub fn evolve2( &self, operator_a: PyReadonlyArray5, operator_b: PyReadonlyArray5, @@ -498,7 +573,7 @@ impl PyGrid { let evolved_grid = self .grid - .evolve( + .evolve2( operator_a.as_array(), operator_b.as_array(), &op_info_a, From cc82f9e8aa5b3c3c8090894833d883706f116553 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 11:04:34 +0200 Subject: [PATCH 21/38] Add missing documentation to `Grid::evolve2` --- pineappl/src/grid.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 7e02d5b8..c46356bf 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1386,7 +1386,8 @@ impl Grid { ) } - #[deprecated(since = "0.8.1", note = "use evolve_slice_with_two2 instead")] + /// Do not use this method, it is scheduled to be removed before this branch is merged. + #[deprecated(since = "0.8.0", note = "use evolve_slice_with_two2 instead")] pub fn evolve2( &self, operator_a: ArrayView5, From 246cadb10bc205d5615c38326a2898a4f6b9f3c7 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 11:05:53 +0200 Subject: [PATCH 22/38] Change `unimplemented` to an error --- pineappl_cli/src/evolve.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 3aa89a38..55344281 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -1,6 +1,6 @@ use super::helpers::{self, ConvFuns, ConvoluteMode}; use super::{GlobalConfiguration, Subcommand}; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, bail, Result}; use clap::{Parser, ValueHint}; use lhapdf::Pdf; use pineappl::fk_table::FkTable; @@ -476,7 +476,7 @@ fn evolve_grid( #[allow(deprecated)] Ok(grid.evolve(operator.view(), &op_info, &order_mask)?) } else { - unimplemented!(); + bail!("`--use-old-evolve` can only be used with a specific EKO format") } } else { Ok(grid.evolve_with_slice_iter2( From 1fb7e8199a8de9f6627b10d2bf7a160530ee88a9 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 11:06:38 +0200 Subject: [PATCH 23/38] Prepare evolvution for more than two EKOs --- pineappl_cli/src/evolve.rs | 72 ++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 55344281..528a35c6 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -424,8 +424,7 @@ mod eko { #[cfg(feature = "evolve")] fn evolve_grid( grid: &Grid, - eko_a: &Path, - eko_b: &Path, + ekos: &[&Path], use_alphas_from: &Pdf, orders: &[(u32, u32)], xir: f64, @@ -446,18 +445,20 @@ fn evolve_grid( }) .collect(); - let mut eko_slices_a = EkoSlices::new(eko_a)?; - let mut eko_slices_b = EkoSlices::new(eko_b)?; + let mut eko_slices: Vec<_> = ekos + .iter() + .map(|eko| EkoSlices::new(eko)) + .collect::>()?; let alphas_table = AlphasTable::from_grid(grid, xir, &|q2| use_alphas_from.alphas_q2(q2)); - // TODO: Check that cloning the `alphas_table` does not cause performance - // issue when cloned. if use_old_evolve { + assert_eq!(eko_slices.len(), 0); + if let EkoSlices::V0 { fac1, info, operator, - } = eko_slices_a + } = eko_slices.remove(0) { let op_info = OperatorInfo { fac0: info.fac0, @@ -479,13 +480,19 @@ fn evolve_grid( bail!("`--use-old-evolve` can only be used with a specific EKO format") } } else { - Ok(grid.evolve_with_slice_iter2( - &mut eko_slices_a, - &mut eko_slices_b, - &order_mask, - (xir, xif), - &alphas_table, - )?) + match eko_slices.as_mut_slice() { + [eko] => { + Ok(grid.evolve_with_slice_iter(eko, &order_mask, (xir, xif), &alphas_table)?) + } + [eko_a, eko_b] => Ok(grid.evolve_with_slice_iter2( + eko_a, + eko_b, + &order_mask, + (xir, xif), + &alphas_table, + )?), + _ => unimplemented!("evolution with {} is not implemented", eko_slices.len()), + } } } @@ -567,30 +574,19 @@ impl Subcommand for Opts { cfg, ); - let fk_table: FkTable; - if let Some(ekob) = &self.ekob { - fk_table = evolve_grid( - &grid, - &self.eko, - ekob, - &conv_funs[cfg.use_alphas_from], - &self.orders, - self.xir, - self.xif, - self.use_old_evolve, - )?; - } else { - fk_table = evolve_grid( - &grid, - &self.eko, - &self.eko, - &conv_funs[cfg.use_alphas_from], - &self.orders, - self.xir, - self.xif, - self.use_old_evolve, - )?; - } + let fk_table = evolve_grid( + &grid, + &if let Some(ekob) = &self.ekob { + vec![self.eko.as_path(), ekob.as_path()] + } else { + vec![self.eko.as_path()] + }, + &conv_funs[cfg.use_alphas_from], + &self.orders, + self.xir, + self.xif, + self.use_old_evolve, + )?; let evolved_results = helpers::convolve_scales( fk_table.grid(), From d0b895176a74c5f3b4a9b0b4a5cd5d86c0647aa1 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 11:10:20 +0200 Subject: [PATCH 24/38] Fix warning and compilation error --- pineappl_cli/src/evolve.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 528a35c6..2f0d37c7 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -1,6 +1,6 @@ use super::helpers::{self, ConvFuns, ConvoluteMode}; use super::{GlobalConfiguration, Subcommand}; -use anyhow::{anyhow, bail, Result}; +use anyhow::{anyhow, Result}; use clap::{Parser, ValueHint}; use lhapdf::Pdf; use pineappl::fk_table::FkTable; @@ -431,6 +431,7 @@ fn evolve_grid( xif: f64, use_old_evolve: bool, ) -> Result { + use anyhow::bail; use eko::EkoSlices; use pineappl::evolution::{AlphasTable, OperatorInfo}; @@ -499,8 +500,7 @@ fn evolve_grid( #[cfg(not(feature = "evolve"))] fn evolve_grid( _: &Grid, - _: &Path, - _: &Path, + _: &[&Path], _: &Pdf, _: &[(u32, u32)], _: f64, From b7d55f89b66bbf643cb91a04cafb2fc656b53159 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 11:10:49 +0200 Subject: [PATCH 25/38] Fix panic message --- pineappl_cli/src/evolve.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 2f0d37c7..514d1e00 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -492,7 +492,10 @@ fn evolve_grid( (xir, xif), &alphas_table, )?), - _ => unimplemented!("evolution with {} is not implemented", eko_slices.len()), + _ => unimplemented!( + "evolution with {} EKOs is not implemented", + eko_slices.len() + ), } } } From 8153abe17fdbcdb20856463183b70e5637ebb322 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 11:13:58 +0200 Subject: [PATCH 26/38] Undo whitespace changes --- pineappl_py/pineappl/grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl_py/pineappl/grid.py b/pineappl_py/pineappl/grid.py index 40ff31b2..be073842 100644 --- a/pineappl_py/pineappl/grid.py +++ b/pineappl_py/pineappl/grid.py @@ -297,7 +297,6 @@ def convolve_with_two( xi, ) - def evolve( self, operators, @@ -308,6 +307,7 @@ def evolve( xi=(1.0, 1.0), ): """Create an FKTable with the EKO. + Convenience wrapper for :meth:`pineappl.pineappl.PyGrid.evolve()`. Parameters From 3bf44d010e032bd123227b3d91cad4521b9024a4 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 11:16:44 +0200 Subject: [PATCH 27/38] Shorten CI job name --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6b69dfa4..8475011c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -29,7 +29,7 @@ jobs: with: path: test-data key: test-data-v12 - - name: Download test data and additional PDFs + - name: Download test data if: steps.cache-test-data.outputs.cache-hit != 'true' run: | test -d test-data || mkdir test-data From 6081b979ff2b0448797ced6a5beedd267d8ceb6a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 13:50:51 +0200 Subject: [PATCH 28/38] Call the right evolution method --- pineappl_py/pineappl/grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl_py/pineappl/grid.py b/pineappl_py/pineappl/grid.py index 6f0d8efd..8d646dbb 100644 --- a/pineappl_py/pineappl/grid.py +++ b/pineappl_py/pineappl/grid.py @@ -411,7 +411,7 @@ def evolve2( q2grid = list(operators_a["Q2grid"].keys()) return FkTable( - self.raw.evolve( + self.raw.evolve2( np.array(operator_grid_a), np.array(operator_grid_b), operators_a["q2_ref"], From 65a8bfbc68c4d20011047cecdd570af9d1b9bd7c Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 13:51:54 +0200 Subject: [PATCH 29/38] Fix wrong assertion statement --- pineappl_cli/src/evolve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 514d1e00..739cc3dc 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -453,7 +453,7 @@ fn evolve_grid( let alphas_table = AlphasTable::from_grid(grid, xir, &|q2| use_alphas_from.alphas_q2(q2)); if use_old_evolve { - assert_eq!(eko_slices.len(), 0); + assert_eq!(eko_slices.len(), 1); if let EkoSlices::V0 { fac1, From 4a8f7a492118aea8abf74650c9e0757f6027c895 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 13:52:41 +0200 Subject: [PATCH 30/38] Propagate new changes from master to `evolve_slice_with_two2` --- pineappl/src/evolution.rs | 161 +++++++++++++++++++++----------------- pineappl/src/grid.rs | 22 +++--- 2 files changed, 101 insertions(+), 82 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index c450a07b..4b09f06a 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -636,46 +636,60 @@ pub(crate) fn evolve_slice_with_two( pub(crate) fn evolve_slice_with_two2( grid: &Grid, - input_operator_a: &ArrayView4, - input_operator_b: &ArrayView4, - info_a: &OperatorSliceInfo, - info_b: &OperatorSliceInfo, + operators: &[ArrayView4], + infos: &[OperatorSliceInfo], order_mask: &[bool], xi: (f64, f64), alphas_table: &AlphasTable, ) -> Result<(Array3, Vec), GridError> { let gluon_has_pid_zero = gluon_has_pid_zero(grid); - let (pid_indices_a, pids_a) = - pid_slices(input_operator_a, info_a, gluon_has_pid_zero, &|pid1| { - grid.channels() - .iter() - .flat_map(Channel::entry) - .any(|&(a, _, _)| a == pid1) - })?; - let (pid_indices_b, pids_b) = - pid_slices(input_operator_b, info_b, gluon_has_pid_zero, &|pid1| { - grid.channels() - .iter() - .flat_map(Channel::entry) - .any(|&(_, b, _)| b == pid1) - })?; + // TODO: assert that infos[0].fac0 == infos[1].fac0 + + // TODO: generalize by iterating up to `n` + let (pid_indices, pids01): (Vec<_>, Vec<_>) = izip!(0..2, operators, infos) + .map(|(d, operator, info)| { + pid_slices(operator, info, gluon_has_pid_zero, &|pid1| { + grid.channels() + .iter() + .flat_map(Channel::entry) + .any(|tuple| match d { + // TODO: `Channel::entry` should return a tuple of a `Vec` and an `f64` + 0 => tuple.0 == pid1, + 1 => tuple.1 == pid1, + _ => unreachable!(), + }) + }) + }) + .collect::, _>>()? + .into_iter() + .unzip(); + + let mut channels0: Vec<_> = pids01 + .iter() + .map(|pids| pids.iter().map(|&(pid0, _)| pid0)) + .multi_cartesian_product() + .collect(); + channels0.sort_unstable(); + channels0.dedup(); + let channels0 = channels0; - let channels0 = channels0_with_two(&pids_a, &pids_b); let mut sub_fk_tables = Vec::with_capacity(grid.bin_info().bins() * channels0.len()); - let mut last_x1a = Vec::new(); - let mut last_x1b = Vec::new(); - let mut operators_a = Vec::new(); - let mut operators_b = Vec::new(); + // TODO: generalize to `n` + let mut last_x1 = vec![Vec::new(); 2]; + let mut eko_slices = vec![Vec::new(); 2]; - for subgrids_ol in grid.subgrids().axis_iter(Axis(1)) { - // NOTE: `info_a.x0.len()` and `info_b.x0.len()` are the same - let mut tables = vec![Array2::zeros((info_a.x0.len(), info_a.x0.len())); channels0.len()]; + for subgrids_oc in grid.subgrids().axis_iter(Axis(1)) { + assert_eq!(infos[0].x0.len(), infos[1].x0.len()); - for (subgrids_o, channel1) in subgrids_ol.axis_iter(Axis(1)).zip(grid.channels()) { - let (x1_a, x1_b, array) = ndarray_from_subgrid_orders_slice( - info_a, + let mut tables = + vec![Array2::zeros((infos[0].x0.len(), infos[1].x0.len())); channels0.len()]; + + for (subgrids_o, channel1) in subgrids_oc.axis_iter(Axis(1)).zip(grid.channels()) { + let (x1, array) = ndarray_from_subgrid_orders_slice( + &infos[0], + // TODO: generalize this function to also accept `info[1]` &subgrids_o, grid.orders(), order_mask, @@ -683,45 +697,52 @@ pub(crate) fn evolve_slice_with_two2( alphas_table, )?; - if (last_x1a.len() != x1_a.len()) - || last_x1a - .iter() - .zip(x1_a.iter()) - .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) - { - operators_a = operator_slices(input_operator_a, info_a, &pid_indices_a, &x1_a)?; - last_x1a = x1_a; + for (last_x1, x1, pid_indices, slices, operator, info) in izip!( + &mut last_x1, + x1, + &pid_indices, + &mut eko_slices, + operators, + infos + ) { + if (last_x1.len() != x1.len()) + || last_x1 + .iter() + .zip(x1.iter()) + .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) + { + *slices = operator_slices(operator, info, pid_indices, &x1)?; + *last_x1 = x1; + } } - if (last_x1b.len() != x1_b.len()) - || last_x1b - .iter() - .zip(x1_b.iter()) - .any(|(&lhs, &rhs)| !approx_eq!(f64, lhs, rhs, ulps = EVOLUTION_TOL_ULPS)) - { - operators_b = operator_slices(input_operator_b, info_b, &pid_indices_b, &x1_b)?; - last_x1b = x1_b; - } + let mut tmp = Array2::zeros((last_x1[0].len(), infos[1].x0.len())); - let mut tmp = Array2::zeros((last_x1a.len(), info_a.x0.len())); - - for &(pida1, pidb1, factor) in channel1.entry() { - for (fk_table, opa, opb) in channels0.iter().zip(tables.iter_mut()).filter_map( - |(&(pida0, pidb0), fk_table)| { - pids_a - .iter() - .zip(operators_a.iter()) - .find_map(|(&(pa0, pa1), opa)| { - (pa0 == pida0 && pa1 == pida1).then_some(opa) - }) - .zip(pids_b.iter().zip(operators_b.iter()).find_map( - |(&(pb0, pb1), opb)| (pb0 == pidb0 && pb1 == pidb1).then_some(opb), - )) - .map(|(opa, opb)| (fk_table, opa, opb)) - }, - ) { - linalg::general_mat_mul(1.0, &array, &opb.t(), 0.0, &mut tmp); - linalg::general_mat_mul(factor, opa, &tmp, 1.0, fk_table); + for (pids1, factor) in channel1 + .entry() + .iter() + .map(|&(pida1, pidb1, factor)| ([pida1, pidb1], factor)) + { + for (fk_table, ops) in + channels0 + .iter() + .zip(tables.iter_mut()) + .filter_map(|(pids0, fk_table)| { + izip!(pids0, &pids1, &pids01, &eko_slices) + .map(|(&pid0, &pid1, pids, slices)| { + pids.iter().zip(slices).find_map(|(&(p0, p1), op)| { + ((p0 == pid0) && (p1 == pid1)).then_some(op) + }) + }) + // TODO: avoid using `collect` + .collect::>>() + .map(|ops| (fk_table, ops)) + }) + { + // tmp = array * ops[1]^T + linalg::general_mat_mul(1.0, &array, &ops[1].t(), 0.0, &mut tmp); + // fk_table += factor * ops[0] * tmp + linalg::general_mat_mul(factor, ops[0], &tmp, 1.0, fk_table); } } } @@ -732,11 +753,11 @@ pub(crate) fn evolve_slice_with_two2( vec![Mu2 { // TODO: FK tables don't depend on the renormalization scale //ren: -1.0, - ren: info_a.fac0, - fac: info_a.fac0, + ren: infos[0].fac0, + fac: infos[0].fac0, }], - info_a.x0.clone(), - info_a.x0.clone(), + infos[0].x0.clone(), + infos[1].x0.clone(), ) .into() })); @@ -748,7 +769,7 @@ pub(crate) fn evolve_slice_with_two2( .unwrap(), channels0 .iter() - .map(|&(a, b)| channel![a, b, 1.0]) + .map(|c| channel![c[0], c[1], 1.0]) .collect(), )) } diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index c46356bf..665a2bc3 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1590,8 +1590,6 @@ impl Grid { ))); } - let view_a = operator_a.view(); - // Operate on `slices_b` let (info_b, operator_b) = result_b.map_err(|err| GridError::Other(err.into()))?; @@ -1610,17 +1608,16 @@ impl Grid { ))); } - let view_b = operator_b.view(); + let views = [operator_a.view(), operator_b.view()]; + let infos = [info_a, info_b]; let (subgrids, channels) = if self.convolutions()[0] != Convolution::None && self.convolutions()[1] != Convolution::None { evolution::evolve_slice_with_two2( self, - &view_a, - &view_b, - &info_a, - &info_b, + &views, + &infos, order_mask, xi, alphas_table, @@ -1628,8 +1625,8 @@ impl Grid { } else { evolution::evolve_slice_with_one( self, - &view_a, - &info_a, + &views[0], + &infos[1], order_mask, xi, alphas_table, @@ -1645,9 +1642,10 @@ impl Grid { more_members: self.more_members.clone(), }; + assert_eq!(infos[0].pid_basis, infos[1].pid_basis); + // TODO: use a new constructor to set this information - // NOTE: `info_a.pid_basis` and `info_b.pid_basis` are the same - rhs.set_pid_basis(info_a.pid_basis); + rhs.set_pid_basis(infos[0].pid_basis); if let Some(lhs) = &mut lhs { lhs.merge(rhs)?; @@ -1656,7 +1654,7 @@ impl Grid { } // NOTE: The following should be shared by the 2 EKOs(?) - fac1.push(info_a.fac1); + fac1.push(infos[0].fac1); } // UNWRAP: if we can't compare two numbers there's a bug From 6585ab611d5cd8ac4b3b23d2bfd25a6f121af25a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 14:57:29 +0200 Subject: [PATCH 31/38] Generalize `ndarray_from_subgrid_orders_slice` function --- pineappl/src/evolution.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/pineappl/src/evolution.rs b/pineappl/src/evolution.rs index 4b09f06a..5829ead6 100644 --- a/pineappl/src/evolution.rs +++ b/pineappl/src/evolution.rs @@ -269,7 +269,7 @@ fn operator_slices( type X1aX1bOp2Tuple = (Vec>, Array2); fn ndarray_from_subgrid_orders_slice( - info: &OperatorSliceInfo, + fac1: f64, subgrids: &ArrayView1, orders: &[Order], order_mask: &[bool], @@ -353,7 +353,7 @@ fn ndarray_from_subgrid_orders_slice( for ((ifac1, ix1, ix2), value) in subgrid.indexed_iter() { let Mu2 { ren, fac } = subgrid.mu2_grid()[ifac1]; - if !approx_eq!(f64, xif * xif * fac, info.fac1, ulps = EVOLUTION_TOL_ULPS) { + if !approx_eq!(f64, xif * xif * fac, fac1, ulps = EVOLUTION_TOL_ULPS) { continue; } @@ -413,7 +413,7 @@ pub(crate) fn evolve_slice_with_one( for (subgrids_o, channel1) in subgrids_ol.axis_iter(Axis(1)).zip(grid.channels()) { let (mut x1, array) = ndarray_from_subgrid_orders_slice( - info, + info.fac1, &subgrids_o, grid.orders(), order_mask, @@ -556,7 +556,7 @@ pub(crate) fn evolve_slice_with_two( for (subgrids_o, channel1) in subgrids_oc.axis_iter(Axis(1)).zip(grid.channels()) { let (x1, array) = ndarray_from_subgrid_orders_slice( - info, + info.fac1, &subgrids_o, grid.orders(), order_mask, @@ -644,7 +644,16 @@ pub(crate) fn evolve_slice_with_two2( ) -> Result<(Array3, Vec), GridError> { let gluon_has_pid_zero = gluon_has_pid_zero(grid); - // TODO: assert that infos[0].fac0 == infos[1].fac0 + // TODO: implement matching of different scales for different EKOs + let mut fac1_scales: Vec<_> = infos.iter().map(|info| info.fac1).collect(); + fac1_scales.sort_by(f64::total_cmp); + assert!(fac1_scales.windows(2).all(|scales| approx_eq!( + f64, + scales[0], + scales[1], + ulps = EVOLUTION_TOL_ULPS + ))); + let fac1 = fac1_scales[0]; // TODO: generalize by iterating up to `n` let (pid_indices, pids01): (Vec<_>, Vec<_>) = izip!(0..2, operators, infos) @@ -688,8 +697,7 @@ pub(crate) fn evolve_slice_with_two2( for (subgrids_o, channel1) in subgrids_oc.axis_iter(Axis(1)).zip(grid.channels()) { let (x1, array) = ndarray_from_subgrid_orders_slice( - &infos[0], - // TODO: generalize this function to also accept `info[1]` + fac1, &subgrids_o, grid.orders(), order_mask, From e8ecba7cfa5642e85e8a4d0cd5e6f46490266ba2 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 15:48:18 +0200 Subject: [PATCH 32/38] Add Python bind for `Grid::evolve_with_slice_iter2` --- pineappl_py/src/grid.rs | 54 ++++++++++++++++++++++++++++++ pineappl_py/tests/test_fk_table.py | 19 +++++++++++ 2 files changed, 73 insertions(+) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 74f9524a..02166c71 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -703,6 +703,60 @@ impl PyGrid { .unwrap()) } + /// TODO + /// + /// Parameters + /// ---------- + /// slices : TODO + /// order_mask : TODO + /// + /// Returns + /// ------- + /// TODO + pub fn evolve_with_slice_iter2<'py>( + &self, + slices_a: &Bound<'py, PyIterator>, + slices_b: &Bound<'py, PyIterator>, + order_mask: PyReadonlyArray1, + xi: (f64, f64), + ren1: Vec, + alphas: Vec, + ) -> PyResult { + Ok(self + .grid + .evolve_with_slice_iter2( + slices_a.into_iter().map(|slice| { + let (info, op) = slice + .unwrap() + .extract::<(PyOperatorSliceInfo, PyReadonlyArray4)>() + .unwrap(); + Ok::<_, std::io::Error>(( + info.info, + // TODO: avoid copying + CowArray::from(op.as_array().to_owned()), + )) + }), + slices_b.into_iter().map(|slice| { + let (info, op) = slice + .unwrap() + .extract::<(PyOperatorSliceInfo, PyReadonlyArray4)>() + .unwrap(); + Ok::<_, std::io::Error>(( + info.info, + // TODO: avoid copying + CowArray::from(op.as_array().to_owned()), + )) + }), + // TODO: make `order_mask` a `Vec` + &order_mask.to_vec().unwrap(), + xi, + &AlphasTable { ren1, alphas }, + ) + .map(|fk_table| PyFkTable { fk_table }) + // TODO: avoid unwrap and convert `Result` into `PyResult` + .unwrap()) + } + /// Load grid from file. /// /// **Usage:** `pineko`, FKTable generation diff --git a/pineappl_py/tests/test_fk_table.py b/pineappl_py/tests/test_fk_table.py index e1fa93aa..4f9455e2 100644 --- a/pineappl_py/tests/test_fk_table.py +++ b/pineappl_py/tests/test_fk_table.py @@ -54,3 +54,22 @@ def test_convolve_with_one(self): assert False except: assert True + + # TODO: write a better test + try: + g.evolve_with_slice_iter2( + iter( + [(info, np.ndarray([0, 0, 0, 0])), (info, np.ndarray([0, 0, 0, 0]))] + ), + iter( + [(info, np.ndarray([0, 0, 0, 0])), (info, np.ndarray([0, 0, 0, 0]))] + ), + np.array([], dtype=bool), + (1.0, 1.0), + [], + [], + ) + + assert False + except: + assert True From a4395e21f211e4d2d9fe9b758232e073af23df26 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 12 Jul 2024 16:25:39 +0200 Subject: [PATCH 33/38] Fix clippy warning --- pineappl_cli/src/evolve.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index 739cc3dc..a873823e 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -579,11 +579,10 @@ impl Subcommand for Opts { let fk_table = evolve_grid( &grid, - &if let Some(ekob) = &self.ekob { - vec![self.eko.as_path(), ekob.as_path()] - } else { - vec![self.eko.as_path()] - }, + &self.ekob.as_ref().map_or_else( + || vec![self.eko.as_path()], + |ekob| vec![self.eko.as_path(), ekob], + ), &conv_funs[cfg.use_alphas_from], &self.orders, self.xir, From ad99bcc88223068ac7e1b3227b188fd1a9c8ae9f Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 18 Jul 2024 10:02:22 +0200 Subject: [PATCH 34/38] Remove Node 20 workaround in CI --- .github/workflows/capi.yaml | 5 ----- .github/workflows/msrv.yml | 6 ------ .github/workflows/release.yml | 3 --- .github/workflows/rust.yml | 3 --- 4 files changed, 17 deletions(-) diff --git a/.github/workflows/capi.yaml b/.github/workflows/capi.yaml index 17750e98..90f3d021 100644 --- a/.github/workflows/capi.yaml +++ b/.github/workflows/capi.yaml @@ -6,11 +6,6 @@ on: - pycli - bump-pyo3-version -env: - # our GLIBC version is too old to support Node 20: - # https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ - ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true - jobs: capi: runs-on: ubuntu-latest diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index 1fd6cf1f..e36bd402 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -6,12 +6,6 @@ on: - pycli - bump-pyo3-version -env: - CARGO_TERM_COLOR: always - # our GLIBC version is too old to support Node 20: - # https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ - ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true - jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4fff4b4b..b105f138 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,9 +9,6 @@ on: env: # this is make the `gh` binary work GH_TOKEN: ${{ github.token }} - # our GLIBC version is too old to support Node 20: - # https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ - ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: # create a release on github diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 57d5769c..f416ed0c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -12,9 +12,6 @@ defaults: env: CARGO_TERM_COLOR: always - # our GLIBC version is too old to support Node 20: - # https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ - ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: build: From 3361048ef39d475971d1755143ace32ffeae344e Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 18 Jul 2024 10:03:33 +0200 Subject: [PATCH 35/38] Add back accidentally removed environment variable in CI --- .github/workflows/msrv.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index e36bd402..6a56e06f 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -6,6 +6,9 @@ on: - pycli - bump-pyo3-version +env: + CARGO_TERM_COLOR: always + jobs: build: runs-on: ubuntu-latest From bb6453c426734a766ec0a9759fc820e2e847f5e5 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 18 Jul 2024 10:04:54 +0200 Subject: [PATCH 36/38] Clarify wording of error message --- pineappl_cli/src/evolve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl_cli/src/evolve.rs b/pineappl_cli/src/evolve.rs index a873823e..5b084ea5 100644 --- a/pineappl_cli/src/evolve.rs +++ b/pineappl_cli/src/evolve.rs @@ -478,7 +478,7 @@ fn evolve_grid( #[allow(deprecated)] Ok(grid.evolve(operator.view(), &op_info, &order_mask)?) } else { - bail!("`--use-old-evolve` can only be used with a specific EKO format") + bail!("`--use-old-evolve` can only be used with the old EKO format (`V0`)") } } else { match eko_slices.as_mut_slice() { From 744c4175d945b02188d0327d0a11858ef024b0d2 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 18 Jul 2024 10:05:58 +0200 Subject: [PATCH 37/38] Add changelog entry --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34c7909d..7f8c753a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- added new method `Grid::evolve_with_slice_iter2` which is able to perform + evolutions with two different EKOs + ### Fixed - fixed CI to build CAPI and CLI From c1ba7abb02bdb6ff83a854e7be772004866fe665 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Thu, 18 Jul 2024 10:23:50 +0200 Subject: [PATCH 38/38] remove Grid::evolve2 method and its python wrapper --- pineappl/src/grid.rs | 56 ---------------------- pineappl_py/pineappl/grid.py | 71 ---------------------------- pineappl_py/src/grid.rs | 92 ------------------------------------ 3 files changed, 219 deletions(-) diff --git a/pineappl/src/grid.rs b/pineappl/src/grid.rs index 665a2bc3..86e744b9 100644 --- a/pineappl/src/grid.rs +++ b/pineappl/src/grid.rs @@ -1386,62 +1386,6 @@ impl Grid { ) } - /// Do not use this method, it is scheduled to be removed before this branch is merged. - #[deprecated(since = "0.8.0", note = "use evolve_slice_with_two2 instead")] - pub fn evolve2( - &self, - operator_a: ArrayView5, - operator_b: ArrayView5, - info_a: &OperatorInfo, - info_b: &OperatorInfo, - order_mask: &[bool], - ) -> Result { - self.evolve_with_slice_iter2( - info_a - .fac1 - .iter() - .zip(operator_a.axis_iter(Axis(0))) - .map(|(&fac1, op)| { - Ok::<_, GridError>(( - OperatorSliceInfo { - fac0: info_a.fac0, - pids0: info_a.pids0.clone(), - x0: info_a.x0.clone(), - fac1, - pids1: info_a.pids1.clone(), - x1: info_a.x1.clone(), - pid_basis: info_a.pid_basis, - }, - CowArray::from(op), - )) - }), - info_b - .fac1 - .iter() - .zip(operator_b.axis_iter(Axis(0))) - .map(|(&fac1, op)| { - Ok::<_, GridError>(( - OperatorSliceInfo { - fac0: info_b.fac0, - pids0: info_b.pids0.clone(), - x0: info_b.x0.clone(), - fac1, - pids1: info_b.pids1.clone(), - x1: info_b.x1.clone(), - pid_basis: info_b.pid_basis, - }, - CowArray::from(op), - )) - }), - order_mask, - (info_a.xir, info_a.xif), - &AlphasTable { - ren1: info_a.ren1.clone(), - alphas: info_a.alphas.clone(), - }, - ) - } - // TODO: // - try to find a better solution than to require that E must be convertible into // anyhow::Error diff --git a/pineappl_py/pineappl/grid.py b/pineappl_py/pineappl/grid.py index 8d646dbb..2f962d94 100644 --- a/pineappl_py/pineappl/grid.py +++ b/pineappl_py/pineappl/grid.py @@ -357,77 +357,6 @@ def evolve( ) ) - def evolve2( - self, - operators_a, - mur2_grid, - alphas_values, - operators_b=None, - 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_a : dict - EKO Output - mur2_grid : list[float] - renormalization scales - alphas_values : list[float] - alpha_s values associated to the renormalization scales - operator_b: Optional[dict] - an optional EKO Output - 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_a = np.array( - [op["operators"] for op in operators_a["Q2grid"].values()] - ) - if operators_b is not None: - operator_grid_b = np.array( - [op["operators"] for op in operators_b["Q2grid"].values()] - ) - else: - operator_grid_b = operator_grid_a - - q2grid = list(operators_a["Q2grid"].keys()) - return FkTable( - self.raw.evolve2( - np.array(operator_grid_a), - np.array(operator_grid_b), - operators_a["q2_ref"], - np.array(operators_a["inputpids"], dtype=np.int32), - np.array(operators_a["inputgrid"]), - np.array(q2grid, dtype=np.float64), - np.array(operators_a["targetpids"], dtype=np.int32), - np.array(operators_a["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): """Load an existing grid from file. diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 02166c71..f89c22da 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -552,98 +552,6 @@ impl PyGrid { } } - /// Convolute with grid with an evolution operator. - /// - /// Parameters - /// ---------- - /// operator : numpy.ndarray(int, rank=5) - /// evolution tensor - /// fac0 : float - /// reference scale - /// pids0 : numpy.ndarray(int) - /// sorting of the particles in the tensor for final FkTable - /// x0 : numpy.ndarray(float) - /// final FKTable interpolation grid - /// fac1 : numpy.ndarray(float) - /// list of factorization scales - /// 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 - /// ------- - /// PyFkTable : - /// produced FK table - pub fn evolve2( - &self, - operator_a: PyReadonlyArray5, - operator_b: 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_a = 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, - pid_basis: lumi_id_types.parse().unwrap(), - }; - - let op_info_b = 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, - pid_basis: lumi_id_types.parse().unwrap(), - }; - - let evolved_grid = self - .grid - .evolve2( - operator_a.as_array(), - operator_b.as_array(), - &op_info_a, - &op_info_b, - order_mask.as_slice().unwrap(), - ) - .expect("Nothing returned from evolution."); - PyFkTable { - fk_table: evolved_grid, - } - } - /// Convolute with grid with an evolution operator. /// /// Parameters