From 0a3d1b64353116a879caf0f7024a33ffb1c8b67a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 26 Sep 2024 11:55:02 +0200 Subject: [PATCH 01/30] Add preliminary code for fastNLO exporter --- pineappl_cli/src/export.rs | 49 +++++++++++++++++++++++++++++++++++++- pineappl_fastnlo/build.rs | 2 +- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/pineappl_cli/src/export.rs b/pineappl_cli/src/export.rs index e4ee819d..30c96d8e 100644 --- a/pineappl_cli/src/export.rs +++ b/pineappl_cli/src/export.rs @@ -12,6 +12,9 @@ use std::process::ExitCode; #[cfg(feature = "applgrid")] mod applgrid; +#[cfg(feature = "fastnlo")] +mod fastnlo; + #[cfg(feature = "applgrid")] fn convert_into_applgrid( output: &Path, @@ -42,6 +45,36 @@ fn convert_into_applgrid( )) } +#[cfg(feature = "fastnlo")] +fn convert_into_fastnlo( + output: &Path, + grid: &Grid, + conv_funs: &mut [Pdf], + _: usize, + discard_non_matching_scales: bool, +) -> Result<(&'static str, Vec, usize, Vec)> { + // TODO: check also scale-varied results + + let (mut fastnlo, order_mask) = + fastnlo::convert_into_fastnlo(grid, output, discard_non_matching_scales)?; + let results = fastnlo::convolve_fastnlo(fastnlo.pin_mut(), conv_funs); + + Ok(("fastNLO", results, 1, order_mask)) +} + +#[cfg(not(feature = "fastnlo"))] +fn convert_into_fastnlo( + _: &Path, + _: &Grid, + _: &mut [Pdf], + _: usize, + _: bool, +) -> Result<(&'static str, Vec, usize, Vec)> { + Err(anyhow!( + "you need to install `pineappl` with feature `fastnlo`" + )) +} + fn convert_into_grid( output: &Path, grid: &Grid, @@ -58,13 +91,27 @@ fn convert_into_grid( scales, discard_non_matching_scales, ); + } else if extension == "tab" + || (extension == "gz" + && output + .with_extension("") + .extension() + .map_or(false, |ext| ext == "tab")) + { + return convert_into_fastnlo( + output, + grid, + conv_funs, + scales, + discard_non_matching_scales, + ); } } Err(anyhow!("could not detect file format")) } -/// Converts PineAPPL grids to APPLgrid files. +/// Converts PineAPPL grids to APPLgrid or fastNLO files. #[derive(Parser)] pub struct Opts { /// Path to the input grid. diff --git a/pineappl_fastnlo/build.rs b/pineappl_fastnlo/build.rs index 0eadd2b8..461854b8 100644 --- a/pineappl_fastnlo/build.rs +++ b/pineappl_fastnlo/build.rs @@ -65,7 +65,7 @@ fn main() { .file("src/fastnlo.cpp") .include(fnlo_include_path.trim()) .includes(lhapdf_include_paths) - .std("c++11") // apparently not supported by MSVC, but fastNLO probably can't be compiled on Windows + .std("c++17") // apparently not supported by MSVC, but fastNLO probably can't be compiled on Windows .compile("fnlo-bridge"); println!("cargo:rerun-if-changed=src/lib.rs"); From 0cf99c1dc4f6af7fba4d52215b350c7fd64b7926 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 26 Sep 2024 12:46:02 +0200 Subject: [PATCH 02/30] Add missing file --- pineappl_cli/src/export/fastnlo.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 pineappl_cli/src/export/fastnlo.rs diff --git a/pineappl_cli/src/export/fastnlo.rs b/pineappl_cli/src/export/fastnlo.rs new file mode 100644 index 00000000..3cd67aa8 --- /dev/null +++ b/pineappl_cli/src/export/fastnlo.rs @@ -0,0 +1,22 @@ +use anyhow::Result; +use cxx::UniquePtr; +use lhapdf::Pdf; +use pineappl::grid::Grid; +use pineappl_fastnlo::ffi::fastNLOLHAPDF; +use std::path::Path; +use std::pin::Pin; + +pub fn convert_into_fastnlo( + _grid: &Grid, + _output: &Path, + _discard_non_matching_scales: bool, +) -> Result<(UniquePtr, Vec)> { + todo!() +} + +pub fn convolve_fastnlo(_grid: Pin<&mut fastNLOLHAPDF>, conv_funs: &mut [Pdf]) -> Vec { + // TODO: add support for convolving an APPLgrid with two functions + assert_eq!(conv_funs.len(), 1); + + todo!() +} From 30cd1b7a1e1c8dff6d3acf4e3a6e5db1a1bf7279 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 26 Sep 2024 13:12:04 +0200 Subject: [PATCH 03/30] Fix tests --- pineappl_cli/src/export.rs | 2 +- pineappl_cli/tests/export.rs | 2 +- pineappl_cli/tests/main.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pineappl_cli/src/export.rs b/pineappl_cli/src/export.rs index 30c96d8e..e0f8ff21 100644 --- a/pineappl_cli/src/export.rs +++ b/pineappl_cli/src/export.rs @@ -111,7 +111,7 @@ fn convert_into_grid( Err(anyhow!("could not detect file format")) } -/// Converts PineAPPL grids to APPLgrid or fastNLO files. +/// Converts PineAPPL grids to APPLgrid/fastNLO files. #[derive(Parser)] pub struct Opts { /// Path to the input grid. diff --git a/pineappl_cli/tests/export.rs b/pineappl_cli/tests/export.rs index 47fe293a..1fa6e8f1 100644 --- a/pineappl_cli/tests/export.rs +++ b/pineappl_cli/tests/export.rs @@ -3,7 +3,7 @@ use assert_cmd::Command; #[cfg(feature = "applgrid")] use assert_fs::NamedTempFile; -const HELP_STR: &str = "Converts PineAPPL grids to APPLgrid files +const HELP_STR: &str = "Converts PineAPPL grids to APPLgrid/fastNLO files Usage: pineappl export [OPTIONS] diff --git a/pineappl_cli/tests/main.rs b/pineappl_cli/tests/main.rs index 0ba04dce..24bb2fd5 100644 --- a/pineappl_cli/tests/main.rs +++ b/pineappl_cli/tests/main.rs @@ -10,7 +10,7 @@ Commands: convolve Convolutes a PineAPPL grid with a PDF set diff Compares the numerical content of two grids with each other evolve Evolve a grid with an evolution kernel operator to an FK table - export Converts PineAPPL grids to APPLgrid files + export Converts PineAPPL grids to APPLgrid/fastNLO files help Display a manpage for selected subcommands import Converts APPLgrid/fastNLO/FastKernel files to PineAPPL grids merge Merges one or more PineAPPL grids together From 7d2389f814042e93e7cd166e6a5ee40c2a08e375 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 14 Oct 2024 10:45:45 +0200 Subject: [PATCH 04/30] Add code to initialize an new fastNLO table --- pineappl_cli/Cargo.toml | 2 +- pineappl_cli/src/export/fastnlo.rs | 97 +++++++++++++++++- pineappl_fastnlo/build.rs | 2 +- pineappl_fastnlo/src/fastnlo.cpp | 151 +++++++++++++++++++++++++++++ pineappl_fastnlo/src/fastnlo.hpp | 13 +++ pineappl_fastnlo/src/lib.rs | 18 ++++ 6 files changed, 278 insertions(+), 5 deletions(-) diff --git a/pineappl_cli/Cargo.toml b/pineappl_cli/Cargo.toml index 3c569e5f..cda2f2d6 100644 --- a/pineappl_cli/Cargo.toml +++ b/pineappl_cli/Cargo.toml @@ -54,6 +54,6 @@ rustc-args = [ "--cfg feature=\"docs-only\"" ] [features] applgrid = ["dep:cxx", "dep:pineappl_applgrid"] evolve = ["dep:base64", "dep:either", "dep:tar", "dep:lz4_flex", "dep:ndarray-npy", "dep:serde", "dep:serde_yaml"] -fastnlo = ["dep:pineappl_fastnlo"] +fastnlo = ["dep:cxx", "dep:pineappl_fastnlo"] fktable = ["dep:flate2", "dep:tar"] static = ["lhapdf/static", "pineappl/static", "pineappl_applgrid?/static", "pineappl_fastnlo?/static"] diff --git a/pineappl_cli/src/export/fastnlo.rs b/pineappl_cli/src/export/fastnlo.rs index 3cd67aa8..2ef1a538 100644 --- a/pineappl_cli/src/export/fastnlo.rs +++ b/pineappl_cli/src/export/fastnlo.rs @@ -1,16 +1,107 @@ -use anyhow::Result; +use anyhow::{bail, Result}; use cxx::UniquePtr; +use float_cmp::assert_approx_eq; use lhapdf::Pdf; +use pineappl::boc::Order; use pineappl::grid::Grid; -use pineappl_fastnlo::ffi::fastNLOLHAPDF; +use pineappl_fastnlo::ffi::{self, fastNLOLHAPDF}; use std::path::Path; use std::pin::Pin; pub fn convert_into_fastnlo( - _grid: &Grid, + grid: &Grid, _output: &Path, _discard_non_matching_scales: bool, ) -> Result<(UniquePtr, Vec)> { + let bin_info = grid.bin_info(); + let dim = bin_info.dimensions(); + + if dim > 3 { + bail!( + "grid has {} dimensions, but fastNLO only supports up to three-dimensional distributions", + dim + ); + } + + let bin_limits = bin_info.limits(); + let left_bin_limits: Vec> = bin_limits + .iter() + .map(|limits| limits.iter().map(|&(left, _)| left).collect()) + .collect(); + let right_bin_limits: Vec> = bin_limits + .iter() + .map(|limits| limits.iter().map(|&(_, right)| right).collect()) + .collect(); + let normalizations = bin_info.normalizations(); + + let order_mask = Order::create_mask(grid.orders(), 3, 0, false); + let orders_with_mask: Vec<_> = grid + .orders() + .iter() + .cloned() + .zip(order_mask.iter().copied()) + .collect(); + let lo_alphas = orders_with_mask + .iter() + .filter_map(|&(Order { alphas, .. }, keep)| keep.then_some(alphas)) + .min() + // UNWRAP: this will fail for `Grid` with no orders, but this shouldn't happen + .unwrap(); + //let loops = orders_with_mask + // .iter() + // .filter_map(|&(Order { alphas, .. }, keep)| keep.then_some(alphas)) + // .max() + // .unwrap() + // - lo_alphas; + + let convolutions: Vec = grid + .convolutions() + .iter() + .filter_map(|conv| conv.pid()) + .collect(); + + let channels: Vec> = grid + .channels() + .iter() + .map(|channel| { + channel + .entry() + .iter() + .map(|&(a, b, factor)| { + assert_approx_eq!(f64, factor, 1.0, ulps = 4); + ffi::pair_int_int { + first: a, + second: b, + } + }) + .collect() + }) + .collect(); + + //for (fnlo_order, order) in order_mask + // .iter() + // .enumerate() + // .filter_map(|(index, keep)| keep.then_some(index)) + // .enumerate() + //{} + + let _fastnlo = ffi::make_fastnlo_create( + // UNWRAP: negative numbers and overflow should not happen + lo_alphas.try_into().unwrap(), + &left_bin_limits, + &right_bin_limits, + &normalizations, + // TODO: calculate channels for each order separately + // UNWRAP: negative numbers and overflow should not happen + channels.len().try_into().unwrap(), + // UNWRAP: negative numbers and overflow should not happen + channels.len().try_into().unwrap(), + // UNWRAP: negative numbers and overflow should not happen + channels.len().try_into().unwrap(), + &convolutions, + &channels, + ); + todo!() } diff --git a/pineappl_fastnlo/build.rs b/pineappl_fastnlo/build.rs index 461854b8..412ff1e5 100644 --- a/pineappl_fastnlo/build.rs +++ b/pineappl_fastnlo/build.rs @@ -65,7 +65,7 @@ fn main() { .file("src/fastnlo.cpp") .include(fnlo_include_path.trim()) .includes(lhapdf_include_paths) - .std("c++17") // apparently not supported by MSVC, but fastNLO probably can't be compiled on Windows + .std("c++17") .compile("fnlo-bridge"); println!("cargo:rerun-if-changed=src/lib.rs"); diff --git a/pineappl_fastnlo/src/fastnlo.cpp b/pineappl_fastnlo/src/fastnlo.cpp index 7cda9649..1b94d1e4 100644 --- a/pineappl_fastnlo/src/fastnlo.cpp +++ b/pineappl_fastnlo/src/fastnlo.cpp @@ -1,6 +1,7 @@ #include "pineappl_fastnlo/src/fastnlo.hpp" #include +#include #include #include @@ -65,6 +66,156 @@ std::unique_ptr make_fastnlo_lhapdf_with_name_file_set( return std::unique_ptr(new fastNLOLHAPDF(arg0, arg1, PDFSet)); } +std::unique_ptr make_fastnlo_create( + int alphas_lo, + rust::Slice const> left_bin_limits, + rust::Slice const> right_bin_limits, + rust::Slice normalizations, + int lo_channels, + int nlo_channels, + int nnlo_channels, + rust::Slice convolutions, + rust::Slice const> channels +) { + assert(left_bin_limits.size() == right_bin_limits.size()); + auto const bins = left_bin_limits.size(); + assert(bins == normalizations.size()); + assert(bins > 0); + auto const dimensions = left_bin_limits.at(0).size(); + assert(dimensions > 0); + assert(convolutions.size() <= 2); + assert(convolutions.size() >= 1); + + std::vector> bin_limits(dimensions); + + // TODO: check if this is the right ordering + for (std::size_t i = 0; i != dimensions; ++i) { + assert(left_bin_limits.at(i).size() == dimensions); + assert(right_bin_limits.at(i).size() == dimensions); + + //bin_limits.at(i).resize(2 * limits); + + //for (std::size_t j = 0; j != limits; ++j) { + // bin_limits.at(i).at(2 * j + 0) = left_bin_limits.at(j).at(i); + // bin_limits.at(i).at(2 * j + 1) = right_bin_limits.at(j).at(i); + //} + bin_limits.at(i).resize(bins + 1); + bin_limits.at(i).at(0) = left_bin_limits.at(0).front(); + + for (std::size_t j = 0; j != bins; ++j) { + bin_limits.at(i).at(j + 1) = right_bin_limits.at(j).at(i); + } + } + + fastNLO::GeneratorConstants gconst; + // TODO: add PineAPPL's version number + gconst.Name = "PineAPPL-fastNLO interface"; + + fastNLO::ProcessConstants pconst; + pconst.LeadingOrder = alphas_lo; + pconst.NPDF = convolutions.size(); + pconst.NSubProcessesLO = lo_channels; + pconst.NSubProcessesNLO = nlo_channels; + pconst.NSubProcessesNNLO = nnlo_channels; + + if (convolutions.size() == 1) { + pconst.IPDFdef1 = 2; + } else { + pconst.IPDFdef1 = 3; + } + + // TODO: is this the correct value to set the linear combinations ourselves? + pconst.IPDFdef2 = 0; + pconst.IPDFdef3LO = 2; + pconst.IPDFdef3NLO = 0; + pconst.IPDFdef3NNLO = 0; + + if (convolutions.size() == 1) { + // TODO: not yet implemented + assert(false); + } else { + pconst.NPDFDim = 2; + } + + std::vector>> linear_combinations(channels.size()); + for (std::size_t i = 0; i != channels.size(); ++i) { + std::vector> entries(channels.at(i).size()); + for (std::size_t j = 0; j != channels.at(i).size(); ++j) { + auto const first = channels.at(i).at(j).first; + auto const second = channels.at(i).at(j).second; + entries.at(j) = std::make_pair(first, second); + } + linear_combinations.at(i) = entries; + } + pconst.PDFCoeffLO = linear_combinations; + + fastNLO::ScenarioConstants sconst; + sconst.DifferentialDimension = dimensions; + sconst.DimensionIsDifferential = std::vector(dimensions, 0); + sconst.CalculateBinSize = false; + sconst.BinSize = std::vector(normalizations.begin(), normalizations.end()); + + switch (sconst.DifferentialDimension) { + case 1: + sconst.SingleDifferentialBinning = bin_limits.at(0); + break; + + case 2: + sconst.DoubleDifferentialBinning = bin_limits; + break; + + case 3: + sconst.TripleDifferentialBinning = bin_limits; + break; + + default: + // ASSERT: there are no or too many dimensions, which fastNLO doesn't support + assert(false); + } + sconst.FlexibleScaleTable = true; + + if (convolutions.size() == 1) { + sconst.PDF1 = convolutions.at(0); + // TODO: do we leave PDF2 unchanged (set to 'proton') for DIS? + } else { + sconst.PDF1 = convolutions.at(0); + sconst.PDF2 = convolutions.at(1); + } + + sconst.ReadBinningFromSteering = true; + sconst.IgnoreWarmupBinningCheck = true; + sconst.X_NNodeCounting = "NodesPerBin"; + sconst.Mu1_NNodeCounting = "NodesPerBin"; + sconst.Mu2_NNodeCounting = "NodesPerBin"; + + fastNLO::WarmupConstants wconst(sconst); + wconst.Binning = bin_limits; + + // these values are probably irrelevant but must nevertheless given + wconst.Values.resize(bins, std::vector{ + // bin index + 0, + // x-min + 2e-7, + // x-max + 1.0, + // scale1-min + 10.0, + // scale1-max + 100.0, + // scale2-min + 10.0, + // scale2-max + 100.0 + }); + for (std::size_t i = 0; i != wconst.Values.size(); ++i) { + wconst.Values.at(i).at(0) = static_cast (i); + } + // wconst.headerValues = ; + + return std::unique_ptr(new fastNLOCreate(gconst, pconst, sconst, wconst)); +} + rust::Vec GetCrossSection(fastNLOReader& reader, bool lNorm) { return std_vector_to_rust_vec(reader.GetCrossSection(lNorm)); diff --git a/pineappl_fastnlo/src/fastnlo.hpp b/pineappl_fastnlo/src/fastnlo.hpp index 832e8809..ef666be8 100644 --- a/pineappl_fastnlo/src/fastnlo.hpp +++ b/pineappl_fastnlo/src/fastnlo.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,18 @@ std::unique_ptr make_fastnlo_lhapdf_with_name_file_set( int PDFSet ); +std::unique_ptr make_fastnlo_create( + int alphas_lo, + rust::Slice const> left_bin_limits, + rust::Slice const> right_bin_limits, + rust::Slice normalizations, + int lo_channels, + int nlo_channels, + int nnlo_channels, + rust::Slice convolutions, + rust::Slice const> channels +); + rust::Vec CalcPDFLinearCombination( fastNLOPDFLinearCombinations const& lc, fastNLOCoeffAddBase const& base, diff --git a/pineappl_fastnlo/src/lib.rs b/pineappl_fastnlo/src/lib.rs index e72b0d15..bcea7f6c 100644 --- a/pineappl_fastnlo/src/lib.rs +++ b/pineappl_fastnlo/src/lib.rs @@ -134,6 +134,12 @@ pub mod ffi { fn GetPDFPDG(&self, _: i32) -> i32; } + unsafe extern "C++" { + include!("fastnlotk/fastNLOCreate.h"); + + type fastNLOCreate; + } + unsafe extern "C++" { include!("pineappl_fastnlo/src/fastnlo.hpp"); @@ -189,6 +195,18 @@ pub mod ffi { _: &str, _: i32, ) -> UniquePtr; + + fn make_fastnlo_create( + alphas_lo: i32, + left_bin_limits: &[Vec], + right_bin_limits: &[Vec], + normalizations: &[f64], + lo_channels: i32, + nlo_channels: i32, + nnlo_channels: i32, + convolutions: &[i32], + channels: &[Vec], + ) -> UniquePtr; } } From 745bb30c616236efdf402ef79e232bcf92418fc7 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 8 Jan 2025 14:24:40 +0100 Subject: [PATCH 05/30] Fix binning --- pineappl_cli/src/export/fastnlo.rs | 4 +--- pineappl_fastnlo/src/fastnlo.cpp | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/pineappl_cli/src/export/fastnlo.rs b/pineappl_cli/src/export/fastnlo.rs index 2ef1a538..0b7a77d8 100644 --- a/pineappl_cli/src/export/fastnlo.rs +++ b/pineappl_cli/src/export/fastnlo.rs @@ -101,12 +101,10 @@ pub fn convert_into_fastnlo( &convolutions, &channels, ); - - todo!() } pub fn convolve_fastnlo(_grid: Pin<&mut fastNLOLHAPDF>, conv_funs: &mut [Pdf]) -> Vec { - // TODO: add support for convolving an APPLgrid with two functions + // TODO: add support for convolving an fastNLO table with two functions assert_eq!(conv_funs.len(), 1); todo!() diff --git a/pineappl_fastnlo/src/fastnlo.cpp b/pineappl_fastnlo/src/fastnlo.cpp index 1b94d1e4..93865738 100644 --- a/pineappl_fastnlo/src/fastnlo.cpp +++ b/pineappl_fastnlo/src/fastnlo.cpp @@ -189,7 +189,22 @@ std::unique_ptr make_fastnlo_create( sconst.Mu2_NNodeCounting = "NodesPerBin"; fastNLO::WarmupConstants wconst(sconst); - wconst.Binning = bin_limits; + + for (std::size_t bin = 0; bin != bins; ++bin) { + std::vector limits; + + // TODO: the following code assumes one dimension + assert(dimensions == 1); + + // TODO: don't know the meaning of this field + limits.push_back(-1.0); + // left bin limit + limits.push_back(bin_limits.at(0).at(2 * bin + 0)); + // right bin limit + limits.push_back(bin_limits.at(0).at(2 * bin + 1)); + + wconst.Binning.push_back(limits); + } // these values are probably irrelevant but must nevertheless given wconst.Values.resize(bins, std::vector{ From 614faadfdc18e9bcec7f10daad91bd9710f01e9b Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 11:03:11 +0100 Subject: [PATCH 06/30] Fix compilation errors --- pineappl_cli/src/export/fastnlo.rs | 33 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/pineappl_cli/src/export/fastnlo.rs b/pineappl_cli/src/export/fastnlo.rs index 0b7a77d8..13495e7f 100644 --- a/pineappl_cli/src/export/fastnlo.rs +++ b/pineappl_cli/src/export/fastnlo.rs @@ -13,8 +13,8 @@ pub fn convert_into_fastnlo( _output: &Path, _discard_non_matching_scales: bool, ) -> Result<(UniquePtr, Vec)> { - let bin_info = grid.bin_info(); - let dim = bin_info.dimensions(); + let bwfl = grid.bwfl(); + let dim = bwfl.dimensions(); if dim > 3 { bail!( @@ -23,16 +23,16 @@ pub fn convert_into_fastnlo( ); } - let bin_limits = bin_info.limits(); - let left_bin_limits: Vec> = bin_limits + let bins = bwfl.bins(); + let left_bin_limits: Vec> = bins .iter() - .map(|limits| limits.iter().map(|&(left, _)| left).collect()) + .map(|bin| bin.limits().iter().map(|&(l, _)| l).collect()) .collect(); - let right_bin_limits: Vec> = bin_limits + let right_bin_limits: Vec> = bins .iter() - .map(|limits| limits.iter().map(|&(_, right)| right).collect()) + .map(|bin| bin.limits().iter().map(|&(_, r)| r).collect()) .collect(); - let normalizations = bin_info.normalizations(); + let normalizations = bwfl.normalizations(); let order_mask = Order::create_mask(grid.orders(), 3, 0, false); let orders_with_mask: Vec<_> = grid @@ -54,11 +54,10 @@ pub fn convert_into_fastnlo( // .unwrap() // - lo_alphas; - let convolutions: Vec = grid - .convolutions() - .iter() - .filter_map(|conv| conv.pid()) - .collect(); + let convolutions: Vec = grid.convolutions().iter().map(|conv| conv.pid()).collect(); + + // TODO: lift this restriction + assert_eq!(grid.convolutions().len(), 2); let channels: Vec> = grid .channels() @@ -67,11 +66,11 @@ pub fn convert_into_fastnlo( channel .entry() .iter() - .map(|&(a, b, factor)| { + .map(|&(ref pids, factor)| { assert_approx_eq!(f64, factor, 1.0, ulps = 4); ffi::pair_int_int { - first: a, - second: b, + first: pids[0], + second: pids[1], } }) .collect() @@ -101,6 +100,8 @@ pub fn convert_into_fastnlo( &convolutions, &channels, ); + + todo!() } pub fn convolve_fastnlo(_grid: Pin<&mut fastNLOLHAPDF>, conv_funs: &mut [Pdf]) -> Vec { From 17d6f751fcd4c9a92b08a47085c94f82f8cbba7c Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 11:23:03 +0100 Subject: [PATCH 07/30] Create container fastNLO version v2.6-3067 --- .github/workflows/container.yml | 1 + maintainer/pineappl-ci/Containerfile | 3 ++- maintainer/pineappl-ci/script.sh | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 5fc727b7..c5dfe749 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -36,6 +36,7 @@ jobs: uses: redhat-actions/buildah-build@v2 with: image: pineappl-ci + tags: fastnlo-3067 containerfiles: maintainer/pineappl-ci/Containerfile context: maintainer/pineappl-ci/ oci: true diff --git a/maintainer/pineappl-ci/Containerfile b/maintainer/pineappl-ci/Containerfile index e1d8fea8..a990f6a7 100644 --- a/maintainer/pineappl-ci/Containerfile +++ b/maintainer/pineappl-ci/Containerfile @@ -4,7 +4,8 @@ FROM debian:11-slim ARG APPLGRID_V=1.6.36 ARG CARGOC_V=0.10.3 -ARG FASTNLO_V=2.5.0-2826 +ARG FASTNLO_T=3067 +ARG FASTNLO_V=2.6 ARG LHAPDF_V=6.5.4 ARG ZLIB_V=1.3.1 diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index 93b0b26b..3b32bd68 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -85,8 +85,9 @@ cp src/*.h "${APPL_IGRID_DIR}" cd .. # install fastNLO -curl "https://fastnlo.hepforge.org/code/v25/fastnlo_toolkit-${FASTNLO_V}.tar.gz" | tar xzf - -cd "fastnlo_toolkit-${FASTNLO_V}" +# curl "https://fastnlo.hepforge.org/code/v25/fastnlo_toolkit-${FASTNLO_V}.tar.gz" | tar xzf - +git clone --depth 1 --branch "${FASTNLO_T}" https://gitlab.etp.kit.edu/qcd-public/fastNLO.git +cd "fastNLO/v${FASTNLO_V}" ./configure --prefix=/usr/local/ make -j V=1 make install From 53bed5a99ca5e4515ee28c145b19e0fe969fc0f6 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 11:36:21 +0100 Subject: [PATCH 08/30] Resort packages in ascending order --- .github/workflows/container.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index c5dfe749..f35cf735 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -18,16 +18,7 @@ jobs: df -h # 100 largest packages, in ascending order dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -n 100 - sudo apt-get remove -y google-cloud-cli - sudo apt-get remove -y azure-cli - sudo apt-get remove -y microsoft-edge-stable - sudo apt-get remove -y '^dotnet-.*' - sudo apt-get remove -y '^temurin-.*-jdk' - sudo apt-get remove -y google-chrome-stable - sudo apt-get remove -y '^llvm-.*-dev' - sudo apt-get remove -y firefox - sudo apt-get remove -y powershell - sudo apt-get remove -y mono-devel + sudo apt-get remove -y microsoft-edge-stable azure-cli google-cloud-cli google-chrome-stable '^temurin-.*-jdk' '^llvm-.*-dev' firefox powershell sudo apt-get autoremove -y sudo apt-get clean # disk space after removing packages From 04a120542444094a6f9b8a6da7e3600f22150137 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 11:37:03 +0100 Subject: [PATCH 09/30] Generate autotools files for fastNLO in container --- maintainer/pineappl-ci/script.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index 3b32bd68..9dc2a651 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -88,6 +88,7 @@ cd .. # curl "https://fastnlo.hepforge.org/code/v25/fastnlo_toolkit-${FASTNLO_V}.tar.gz" | tar xzf - git clone --depth 1 --branch "${FASTNLO_T}" https://gitlab.etp.kit.edu/qcd-public/fastNLO.git cd "fastNLO/v${FASTNLO_V}" +autoreconf -fi ./configure --prefix=/usr/local/ make -j V=1 make install From 30af6804bba599714508db263aa8603b964ca74c Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 11:52:44 +0100 Subject: [PATCH 10/30] Install missing `autoreconf` into container --- maintainer/pineappl-ci/script.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index 9dc2a651..27672cfb 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -3,6 +3,7 @@ set -euo pipefail pkgs=( + automake build-essential curl gfortran From 16d88d2feb2f44c7ad90d174b096b1f808b19303 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 12:06:41 +0100 Subject: [PATCH 11/30] Change into right fastNLO directory --- maintainer/pineappl-ci/script.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index 27672cfb..c6735386 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -88,7 +88,7 @@ cd .. # install fastNLO # curl "https://fastnlo.hepforge.org/code/v25/fastnlo_toolkit-${FASTNLO_V}.tar.gz" | tar xzf - git clone --depth 1 --branch "${FASTNLO_T}" https://gitlab.etp.kit.edu/qcd-public/fastNLO.git -cd "fastNLO/v${FASTNLO_V}" +cd "fastNLO/v${FASTNLO_V}/toolkit" autoreconf -fi ./configure --prefix=/usr/local/ make -j V=1 From e920e8886ecd6f8c7519c1b24b8d934f23991f76 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 12:26:37 +0100 Subject: [PATCH 12/30] Upgrade fastNLO to circumvent higher autotools requirements --- .github/workflows/container.yml | 2 +- maintainer/pineappl-ci/Containerfile | 2 +- maintainer/pineappl-ci/script.sh | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index f35cf735..c9cd2139 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -27,7 +27,7 @@ jobs: uses: redhat-actions/buildah-build@v2 with: image: pineappl-ci - tags: fastnlo-3067 + tags: fastnlo-69d87cf4 containerfiles: maintainer/pineappl-ci/Containerfile context: maintainer/pineappl-ci/ oci: true diff --git a/maintainer/pineappl-ci/Containerfile b/maintainer/pineappl-ci/Containerfile index a990f6a7..fda2a2a2 100644 --- a/maintainer/pineappl-ci/Containerfile +++ b/maintainer/pineappl-ci/Containerfile @@ -4,7 +4,7 @@ FROM debian:11-slim ARG APPLGRID_V=1.6.36 ARG CARGOC_V=0.10.3 -ARG FASTNLO_T=3067 +ARG FASTNLO_R=69d87cf4 ARG FASTNLO_V=2.6 ARG LHAPDF_V=6.5.4 ARG ZLIB_V=1.3.1 diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index c6735386..7c8700e5 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -87,7 +87,8 @@ cd .. # install fastNLO # curl "https://fastnlo.hepforge.org/code/v25/fastnlo_toolkit-${FASTNLO_V}.tar.gz" | tar xzf - -git clone --depth 1 --branch "${FASTNLO_T}" https://gitlab.etp.kit.edu/qcd-public/fastNLO.git +git clone https://gitlab.etp.kit.edu/qcd-public/fastNLO.git +git checkout "${FASTNLO_R}" cd "fastNLO/v${FASTNLO_V}/toolkit" autoreconf -fi ./configure --prefix=/usr/local/ From e613e8be3e81b262c4638bbd4501695df0ebae4b Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 12:39:28 +0100 Subject: [PATCH 13/30] Change into the right directory --- maintainer/pineappl-ci/script.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index 7c8700e5..1cfe89c8 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -88,8 +88,9 @@ cd .. # install fastNLO # curl "https://fastnlo.hepforge.org/code/v25/fastnlo_toolkit-${FASTNLO_V}.tar.gz" | tar xzf - git clone https://gitlab.etp.kit.edu/qcd-public/fastNLO.git +cd fastNLO git checkout "${FASTNLO_R}" -cd "fastNLO/v${FASTNLO_V}/toolkit" +cd "v${FASTNLO_V}/toolkit" autoreconf -fi ./configure --prefix=/usr/local/ make -j V=1 From a912cfcb8fec5a691fa637111c62222ae9e6c64c Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 12:40:49 +0100 Subject: [PATCH 14/30] Disable workflows in this branch --- .github/workflows/capi.yaml | 1 + .github/workflows/msrv.yml | 1 + .github/workflows/python.yml | 1 + .github/workflows/rust.yml | 1 + 4 files changed, 4 insertions(+) diff --git a/.github/workflows/capi.yaml b/.github/workflows/capi.yaml index 0587f3ba..b176681e 100644 --- a/.github/workflows/capi.yaml +++ b/.github/workflows/capi.yaml @@ -5,6 +5,7 @@ on: branches-ignore: - pycli - bump-pyo3-version + - fastnlo-exporter defaults: run: diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index cc8d6815..4abdb4d1 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -5,6 +5,7 @@ on: branches-ignore: - pycli - bump-pyo3-version + - fastnlo-exporter env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 6df4bfc8..45ecc9de 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -4,6 +4,7 @@ on: push: branches-ignore: - pycli + - fastnlo-exporter jobs: test: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0f9e7528..9d12b0f8 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -5,6 +5,7 @@ on: branches-ignore: - pycli - bump-pyo3-version + - fastnlo-exporter defaults: run: From c98fbbd40d802a53cd96dfe79ee3329ec8768956 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 12:55:00 +0100 Subject: [PATCH 15/30] Install `libtool` in container --- maintainer/pineappl-ci/script.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/maintainer/pineappl-ci/script.sh b/maintainer/pineappl-ci/script.sh index 1cfe89c8..c1f6c8ab 100755 --- a/maintainer/pineappl-ci/script.sh +++ b/maintainer/pineappl-ci/script.sh @@ -9,6 +9,7 @@ pkgs=( gfortran git libssl-dev + libtool openssl pkg-config ) From 4137fdaf72ef5c61534dc7114ce429d84a10da6b Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 14:17:40 +0100 Subject: [PATCH 16/30] Add 'latest' tag in hope of fixing container upload --- .github/workflows/container.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index c9cd2139..b8596915 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -27,7 +27,7 @@ jobs: uses: redhat-actions/buildah-build@v2 with: image: pineappl-ci - tags: fastnlo-69d87cf4 + tags: fastnlo-69d87cf4 latest containerfiles: maintainer/pineappl-ci/Containerfile context: maintainer/pineappl-ci/ oci: true From 950976a730eac36acc6dad5da9de1ba9c6247aa2 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 14 Nov 2025 15:05:34 +0100 Subject: [PATCH 17/30] Revert "Disable workflows in this branch" This reverts commit a912cfcb8fec5a691fa637111c62222ae9e6c64c. --- .github/workflows/capi.yaml | 1 - .github/workflows/msrv.yml | 1 - .github/workflows/python.yml | 1 - .github/workflows/rust.yml | 1 - 4 files changed, 4 deletions(-) diff --git a/.github/workflows/capi.yaml b/.github/workflows/capi.yaml index b176681e..0587f3ba 100644 --- a/.github/workflows/capi.yaml +++ b/.github/workflows/capi.yaml @@ -5,7 +5,6 @@ on: branches-ignore: - pycli - bump-pyo3-version - - fastnlo-exporter defaults: run: diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index 4abdb4d1..cc8d6815 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -5,7 +5,6 @@ on: branches-ignore: - pycli - bump-pyo3-version - - fastnlo-exporter env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 45ecc9de..6df4bfc8 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -4,7 +4,6 @@ on: push: branches-ignore: - pycli - - fastnlo-exporter jobs: test: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9d12b0f8..0f9e7528 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -5,7 +5,6 @@ on: branches-ignore: - pycli - bump-pyo3-version - - fastnlo-exporter defaults: run: From 4a8e9d371a2199861a78110bfc882bac1b35e11a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 09:44:37 +0200 Subject: [PATCH 18/30] Revert "Resort packages in ascending order" This reverts commit 53bed5a99ca5e4515ee28c145b19e0fe969fc0f6. --- .github/workflows/container.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index b8596915..53909e83 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -18,7 +18,16 @@ jobs: df -h # 100 largest packages, in ascending order dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -n 100 - sudo apt-get remove -y microsoft-edge-stable azure-cli google-cloud-cli google-chrome-stable '^temurin-.*-jdk' '^llvm-.*-dev' firefox powershell + sudo apt-get remove -y google-cloud-cli + sudo apt-get remove -y azure-cli + sudo apt-get remove -y microsoft-edge-stable + sudo apt-get remove -y '^dotnet-.*' + sudo apt-get remove -y '^temurin-.*-jdk' + sudo apt-get remove -y google-chrome-stable + sudo apt-get remove -y '^llvm-.*-dev' + sudo apt-get remove -y firefox + sudo apt-get remove -y powershell + sudo apt-get remove -y mono-devel sudo apt-get autoremove -y sudo apt-get clean # disk space after removing packages From c5af6c6dd9cffce7944eaafea0757aa57ff9b548 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 09:46:52 +0200 Subject: [PATCH 19/30] Remove container tag --- .github/workflows/container.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 53909e83..3910da51 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -36,7 +36,7 @@ jobs: uses: redhat-actions/buildah-build@v2 with: image: pineappl-ci - tags: fastnlo-69d87cf4 latest + tags: latest containerfiles: maintainer/pineappl-ci/Containerfile context: maintainer/pineappl-ci/ oci: true From 614eb8152a3548a28145c4248f624f7d24e7e85b Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 10:15:01 +0200 Subject: [PATCH 20/30] Add fixes missing from merge --- maintainer/build-container.sh | 2 ++ maintainer/install-cli-dependencies.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/maintainer/build-container.sh b/maintainer/build-container.sh index f2a03f39..a1cf26a7 100755 --- a/maintainer/build-container.sh +++ b/maintainer/build-container.sh @@ -3,11 +3,13 @@ set -euo pipefail pkgs=( + automake build-essential curl gfortran git libssl-dev + libtool openssl pkg-config ) diff --git a/maintainer/install-cli-dependencies.sh b/maintainer/install-cli-dependencies.sh index c9ccab27..d4153543 100755 --- a/maintainer/install-cli-dependencies.sh +++ b/maintainer/install-cli-dependencies.sh @@ -1,7 +1,7 @@ #!/bin/bash APPLGRID_V=1.6.36 -# FASTNLO_V=2.5.0-2826 +FASTNLO_V=2.6 FASTNLO_R=69d87cf4 LHAPDF_V=6.5.4 ZLIB_V=1.3.1 From f3a57ac0cb76acbe94487ba17c528ded24a8347a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 10:15:56 +0200 Subject: [PATCH 21/30] Add clarifying comment --- maintainer/Containerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/maintainer/Containerfile b/maintainer/Containerfile index b9094e64..d8e7fef1 100644 --- a/maintainer/Containerfile +++ b/maintainer/Containerfile @@ -9,6 +9,7 @@ ENV APPL_IGRID_DIR="/usr/local/src/applgrid/src" # the last version is the default Rust version used in the container # as long as we're using `persist-doctests` in the `Rust` workflow we need nightly as default +# see also https://github.com/rust-lang/rust/issues/56925 ARG RUST_V="1.80.1 1.91.1 nightly-2026-03-10" ENV CARGO_HOME="/usr/local/cargo" From 2d2c17f2aed0c6012273b3174bef084cf6905833 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 10:26:26 +0200 Subject: [PATCH 22/30] Run `cargo fmt` --- pineappl_cli/src/export.rs | 8 ++------ pineappl_cli/src/export/fastnlo.rs | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pineappl_cli/src/export.rs b/pineappl_cli/src/export.rs index 4d33c566..8f16eb45 100644 --- a/pineappl_cli/src/export.rs +++ b/pineappl_cli/src/export.rs @@ -1,6 +1,6 @@ use super::helpers::{self, ConvFuns, ConvoluteMode}; use super::{GlobalConfiguration, Subcommand}; -use anyhow::{anyhow, Result}; +use anyhow::{Result, anyhow}; use clap::builder::{PossibleValuesParser, TypedValueParser}; use clap::{Parser, ValueHint}; use lhapdf::Pdf; @@ -240,11 +240,7 @@ impl Subcommand for Opts { // ALLOW: here we really need an exact comparison // TODO: change allow to `expect` if MSRV >= 1.81.0 #[allow(clippy::float_cmp)] - if a == b { - 0.0 - } else { - b / a - 1.0 - } + if a == b { 0.0 } else { b / a - 1.0 } }) .collect(); diff --git a/pineappl_cli/src/export/fastnlo.rs b/pineappl_cli/src/export/fastnlo.rs index 13495e7f..a6bd3df9 100644 --- a/pineappl_cli/src/export/fastnlo.rs +++ b/pineappl_cli/src/export/fastnlo.rs @@ -1,4 +1,4 @@ -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use cxx::UniquePtr; use float_cmp::assert_approx_eq; use lhapdf::Pdf; From 35f9634c4a495c0bc1fbf88dd8cac92832022f9e Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 12:28:01 +0200 Subject: [PATCH 23/30] Make error message more helpful --- pineappl_cli/src/export.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pineappl_cli/src/export.rs b/pineappl_cli/src/export.rs index 8f16eb45..c5c5fa7f 100644 --- a/pineappl_cli/src/export.rs +++ b/pineappl_cli/src/export.rs @@ -108,7 +108,9 @@ fn convert_into_grid( } } - Err(anyhow!("could not detect file format")) + Err(anyhow!( + "file extension must be one of: .appl, .root, .tab or .tab.gz" + )) } /// Converts PineAPPL grids to APPLgrid/fastNLO files. From 8f9e6a1d34435ab83b25e5b063baee62822b5fa9 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 12:28:45 +0200 Subject: [PATCH 24/30] Fix bin-limits related bug --- pineappl_fastnlo/src/fastnlo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl_fastnlo/src/fastnlo.cpp b/pineappl_fastnlo/src/fastnlo.cpp index 93865738..17091c50 100644 --- a/pineappl_fastnlo/src/fastnlo.cpp +++ b/pineappl_fastnlo/src/fastnlo.cpp @@ -199,9 +199,9 @@ std::unique_ptr make_fastnlo_create( // TODO: don't know the meaning of this field limits.push_back(-1.0); // left bin limit - limits.push_back(bin_limits.at(0).at(2 * bin + 0)); + limits.push_back(bin_limits.at(0).at(bin)); // right bin limit - limits.push_back(bin_limits.at(0).at(2 * bin + 1)); + limits.push_back(bin_limits.at(0).at(bin + 1)); wconst.Binning.push_back(limits); } From 87b3ee3912d8c61e11f17d03e4c27da5a46d949c Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 12:31:08 +0200 Subject: [PATCH 25/30] Write out converted grid --- pineappl_cli/src/export/fastnlo.rs | 11 +++++++++-- pineappl_fastnlo/src/fastnlo.cpp | 5 +++++ pineappl_fastnlo/src/fastnlo.hpp | 2 ++ pineappl_fastnlo/src/lib.rs | 2 ++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pineappl_cli/src/export/fastnlo.rs b/pineappl_cli/src/export/fastnlo.rs index a6bd3df9..ca88a199 100644 --- a/pineappl_cli/src/export/fastnlo.rs +++ b/pineappl_cli/src/export/fastnlo.rs @@ -10,7 +10,7 @@ use std::pin::Pin; pub fn convert_into_fastnlo( grid: &Grid, - _output: &Path, + output: &Path, _discard_non_matching_scales: bool, ) -> Result<(UniquePtr, Vec)> { let bwfl = grid.bwfl(); @@ -84,7 +84,7 @@ pub fn convert_into_fastnlo( // .enumerate() //{} - let _fastnlo = ffi::make_fastnlo_create( + let mut fastnlo = ffi::make_fastnlo_create( // UNWRAP: negative numbers and overflow should not happen lo_alphas.try_into().unwrap(), &left_bin_limits, @@ -101,6 +101,13 @@ pub fn convert_into_fastnlo( &channels, ); + let output = output + .to_str() + // TODO: decide what to do in case of an error + .unwrap(); + + ffi::WriteTable(fastnlo.pin_mut(), &output); + todo!() } diff --git a/pineappl_fastnlo/src/fastnlo.cpp b/pineappl_fastnlo/src/fastnlo.cpp index 17091c50..1e222c82 100644 --- a/pineappl_fastnlo/src/fastnlo.cpp +++ b/pineappl_fastnlo/src/fastnlo.cpp @@ -295,6 +295,11 @@ double GetSigmaTilde( return coeffs.GetSigmaTildes().at(mu)->at(obs).at(ix).at(is1).at(is2).at(subproc); } +void WriteTable(fastNLOCreate& table, rust::Str filename) +{ + table.WriteTable(static_cast (filename)); +} + std::size_t GetNx(fastNLOCoeffAddFlex const& coeffs, std::size_t obs) { return coeffs.GetSigmaTildes().at(0)->at(obs).size(); diff --git a/pineappl_fastnlo/src/fastnlo.hpp b/pineappl_fastnlo/src/fastnlo.hpp index ef666be8..f60b36df 100644 --- a/pineappl_fastnlo/src/fastnlo.hpp +++ b/pineappl_fastnlo/src/fastnlo.hpp @@ -74,6 +74,8 @@ double GetSigmaTilde( int ); +void WriteTable(fastNLOCreate& table, rust::Str filename); + std::size_t GetNx(fastNLOCoeffAddFlex const& coeffs, std::size_t); fastNLOCoeffAddBase const& downcast_coeff_add_fix_to_base(fastNLOCoeffAddFix const& coeffs); diff --git a/pineappl_fastnlo/src/lib.rs b/pineappl_fastnlo/src/lib.rs index 3c15cb70..78f208df 100644 --- a/pineappl_fastnlo/src/lib.rs +++ b/pineappl_fastnlo/src/lib.rs @@ -174,6 +174,8 @@ pub mod ffi { _: i32, ) -> f64; + fn WriteTable(_: Pin<&mut fastNLOCreate>, _: &str); + fn downcast_coeff_add_fix_to_base(_: &fastNLOCoeffAddFix) -> &fastNLOCoeffAddBase; fn downcast_coeff_add_flex_to_base(_: &fastNLOCoeffAddFlex) -> &fastNLOCoeffAddBase; fn downcast_lhapdf_to_reader(_: &fastNLOLHAPDF) -> &fastNLOReader; From 8af86eedd58e6e11c371ae43257dd24554bbff7a Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Fri, 3 Apr 2026 12:32:10 +0200 Subject: [PATCH 26/30] Add code to convolve converted grid --- pineappl_cli/src/export.rs | 57 +++++++++++++++++++++++++----- pineappl_cli/src/export/fastnlo.rs | 16 ++------- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/pineappl_cli/src/export.rs b/pineappl_cli/src/export.rs index c5c5fa7f..0cfb8376 100644 --- a/pineappl_cli/src/export.rs +++ b/pineappl_cli/src/export.rs @@ -49,24 +49,61 @@ fn convert_into_applgrid( fn convert_into_fastnlo( output: &Path, grid: &Grid, - conv_funs: &mut [Pdf], - _: usize, + fun_names: &ConvFuns, + scales: usize, discard_non_matching_scales: bool, ) -> Result<(&'static str, Vec, usize, Vec)> { - // TODO: check also scale-varied results + use pineappl_fastnlo::ffi; + + // TODO: other cases NYI + assert_eq!(scales, 1); + + // TODO: convert this into an error? + assert_eq!(fun_names.lhapdf_names.len(), 1); + + // this creates a file, but doesn't give us an object that we can convolve with a function + let order_mask = fastnlo::convert_into_fastnlo(grid, output, discard_non_matching_scales)?; + + // so load this file, giving the right PDF set + let mut file = ffi::make_fastnlo_lhapdf_with_name_file_set( + output.to_str().unwrap(), + &fun_names.lhapdf_names[0], + // UNWRAP: this shouldn't be negative or overflow + fun_names.members[0].unwrap_or(0).try_into().unwrap(), + ); - let (mut fastnlo, order_mask) = - fastnlo::convert_into_fastnlo(grid, output, discard_non_matching_scales)?; - let results = fastnlo::convolve_fastnlo(fastnlo.pin_mut(), conv_funs); + let mut reader = ffi::downcast_lhapdf_to_reader_mut(file.as_mut().unwrap()); - Ok(("fastNLO", results, 1, order_mask)) + // fastNLO does not support a fragmentation scale + let unpermuted_results: Vec<_> = helpers::SCALES_VECTOR_REN_FAC[0..scales] + .iter() + .map(|&(xir, xif, _)| { + if !reader.as_mut().SetScaleFactorsMuRMuF(xir, xif) { + return None; + } + reader.as_mut().CalcCrossSection(); + Some(ffi::GetCrossSection(reader.as_mut(), false)) + }) + .take_while(Option::is_some) + .map(Option::unwrap) + .collect(); + + assert!(matches!(unpermuted_results.len(), 1 | 3 | 7 | 9)); + + let bins = unpermuted_results[0].len(); + + let results: Vec<_> = (0..bins) + .flat_map(|bin| unpermuted_results.iter().map(move |r| r[bin])) + .collect(); + + Ok(("fastNLO", results, scales, order_mask)) } #[cfg(not(feature = "fastnlo"))] fn convert_into_fastnlo( _: &Path, _: &Grid, - _: &mut [Pdf], + _: &ConvFuns, _: usize, _: bool, ) -> Result<(&'static str, Vec, usize, Vec)> { @@ -79,6 +116,7 @@ fn convert_into_grid( output: &Path, grid: &mut Grid, conv_funs: &mut [Pdf], + fun_names: &ConvFuns, scales: usize, discard_non_matching_scales: bool, ) -> Result<(&'static str, Vec, usize, Vec)> { @@ -101,7 +139,7 @@ fn convert_into_grid( return convert_into_fastnlo( output, grid, - conv_funs, + fun_names, scales, discard_non_matching_scales, ); @@ -158,6 +196,7 @@ impl Subcommand for Opts { &self.output, &mut grid, &mut conv_funs, + &self.conv_funs, self.scales, self.discard_non_matching_scales, )?; diff --git a/pineappl_cli/src/export/fastnlo.rs b/pineappl_cli/src/export/fastnlo.rs index ca88a199..08873cb6 100644 --- a/pineappl_cli/src/export/fastnlo.rs +++ b/pineappl_cli/src/export/fastnlo.rs @@ -1,18 +1,15 @@ use anyhow::{Result, bail}; -use cxx::UniquePtr; use float_cmp::assert_approx_eq; -use lhapdf::Pdf; use pineappl::boc::Order; use pineappl::grid::Grid; -use pineappl_fastnlo::ffi::{self, fastNLOLHAPDF}; +use pineappl_fastnlo::ffi; use std::path::Path; -use std::pin::Pin; pub fn convert_into_fastnlo( grid: &Grid, output: &Path, _discard_non_matching_scales: bool, -) -> Result<(UniquePtr, Vec)> { +) -> Result> { let bwfl = grid.bwfl(); let dim = bwfl.dimensions(); @@ -108,12 +105,5 @@ pub fn convert_into_fastnlo( ffi::WriteTable(fastnlo.pin_mut(), &output); - todo!() -} - -pub fn convolve_fastnlo(_grid: Pin<&mut fastNLOLHAPDF>, conv_funs: &mut [Pdf]) -> Vec { - // TODO: add support for convolving an fastNLO table with two functions - assert_eq!(conv_funs.len(), 1); - - todo!() + Ok(order_mask) } From 1b646e5dfb22fd57a05a078f5b220c4b3a6be421 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 6 Apr 2026 15:21:09 +0200 Subject: [PATCH 27/30] Leave `wconst.Binning` empty to avoid failing check --- pineappl_fastnlo/src/fastnlo.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/pineappl_fastnlo/src/fastnlo.cpp b/pineappl_fastnlo/src/fastnlo.cpp index 1e222c82..4c8d43ce 100644 --- a/pineappl_fastnlo/src/fastnlo.cpp +++ b/pineappl_fastnlo/src/fastnlo.cpp @@ -190,21 +190,9 @@ std::unique_ptr make_fastnlo_create( fastNLO::WarmupConstants wconst(sconst); - for (std::size_t bin = 0; bin != bins; ++bin) { - std::vector limits; - - // TODO: the following code assumes one dimension - assert(dimensions == 1); - - // TODO: don't know the meaning of this field - limits.push_back(-1.0); - // left bin limit - limits.push_back(bin_limits.at(0).at(bin)); - // right bin limit - limits.push_back(bin_limits.at(0).at(bin + 1)); - - wconst.Binning.push_back(limits); - } + // leave `wconst.Binning` empty, otherwise it's being checked and I don't know what it's + // supposed to contain + // wconst.Binning.resize(bins, std::vector{}); // these values are probably irrelevant but must nevertheless given wconst.Values.resize(bins, std::vector{ From c0994bb301c6b1025e6df9f55d87cc8d5dc761db Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 6 Apr 2026 15:22:32 +0200 Subject: [PATCH 28/30] Write out table in C++ function --- pineappl_cli/src/export/fastnlo.rs | 13 +++++-------- pineappl_fastnlo/src/fastnlo.cpp | 19 +++++++++++-------- pineappl_fastnlo/src/fastnlo.hpp | 7 +++---- pineappl_fastnlo/src/lib.rs | 11 ++--------- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/pineappl_cli/src/export/fastnlo.rs b/pineappl_cli/src/export/fastnlo.rs index 08873cb6..cb7568e0 100644 --- a/pineappl_cli/src/export/fastnlo.rs +++ b/pineappl_cli/src/export/fastnlo.rs @@ -81,7 +81,7 @@ pub fn convert_into_fastnlo( // .enumerate() //{} - let mut fastnlo = ffi::make_fastnlo_create( + ffi::make_fastnlo_create( // UNWRAP: negative numbers and overflow should not happen lo_alphas.try_into().unwrap(), &left_bin_limits, @@ -96,14 +96,11 @@ pub fn convert_into_fastnlo( channels.len().try_into().unwrap(), &convolutions, &channels, + &output + .to_str() + // TODO: decide what to do in case of an error + .unwrap(), ); - let output = output - .to_str() - // TODO: decide what to do in case of an error - .unwrap(); - - ffi::WriteTable(fastnlo.pin_mut(), &output); - Ok(order_mask) } diff --git a/pineappl_fastnlo/src/fastnlo.cpp b/pineappl_fastnlo/src/fastnlo.cpp index 4c8d43ce..4edc2be3 100644 --- a/pineappl_fastnlo/src/fastnlo.cpp +++ b/pineappl_fastnlo/src/fastnlo.cpp @@ -66,7 +66,7 @@ std::unique_ptr make_fastnlo_lhapdf_with_name_file_set( return std::unique_ptr(new fastNLOLHAPDF(arg0, arg1, PDFSet)); } -std::unique_ptr make_fastnlo_create( +void make_fastnlo_create( int alphas_lo, rust::Slice const> left_bin_limits, rust::Slice const> right_bin_limits, @@ -75,7 +75,8 @@ std::unique_ptr make_fastnlo_create( int nlo_channels, int nnlo_channels, rust::Slice convolutions, - rust::Slice const> channels + rust::Slice const> channels, + rust::Str filename ) { assert(left_bin_limits.size() == right_bin_limits.size()); auto const bins = left_bin_limits.size(); @@ -187,6 +188,12 @@ std::unique_ptr make_fastnlo_create( sconst.X_NNodeCounting = "NodesPerBin"; sconst.Mu1_NNodeCounting = "NodesPerBin"; sconst.Mu2_NNodeCounting = "NodesPerBin"; + sconst.OutputFilename = static_cast (filename); + + // TODO: implement compression. Since fastNLO adds '.gz' to the filename for us, we must always + // omit the suffix + assert( sconst.OutputFilename.substr(sconst.OutputFilename.size() - 3, 3) != ".gz" ); + sconst.OutputCompression = false; fastNLO::WarmupConstants wconst(sconst); @@ -216,7 +223,8 @@ std::unique_ptr make_fastnlo_create( } // wconst.headerValues = ; - return std::unique_ptr(new fastNLOCreate(gconst, pconst, sconst, wconst)); + fastNLOCreate table(gconst, pconst, sconst, wconst); + table.WriteTable(); } rust::Vec GetCrossSection(fastNLOReader& reader, bool lNorm) @@ -283,11 +291,6 @@ double GetSigmaTilde( return coeffs.GetSigmaTildes().at(mu)->at(obs).at(ix).at(is1).at(is2).at(subproc); } -void WriteTable(fastNLOCreate& table, rust::Str filename) -{ - table.WriteTable(static_cast (filename)); -} - std::size_t GetNx(fastNLOCoeffAddFlex const& coeffs, std::size_t obs) { return coeffs.GetSigmaTildes().at(0)->at(obs).size(); diff --git a/pineappl_fastnlo/src/fastnlo.hpp b/pineappl_fastnlo/src/fastnlo.hpp index f60b36df..0f2cc638 100644 --- a/pineappl_fastnlo/src/fastnlo.hpp +++ b/pineappl_fastnlo/src/fastnlo.hpp @@ -22,7 +22,7 @@ std::unique_ptr make_fastnlo_lhapdf_with_name_file_set( int PDFSet ); -std::unique_ptr make_fastnlo_create( +void make_fastnlo_create( int alphas_lo, rust::Slice const> left_bin_limits, rust::Slice const> right_bin_limits, @@ -31,7 +31,8 @@ std::unique_ptr make_fastnlo_create( int nlo_channels, int nnlo_channels, rust::Slice convolutions, - rust::Slice const> channels + rust::Slice const> channels, + rust::Str filename ); rust::Vec CalcPDFLinearCombination( @@ -74,8 +75,6 @@ double GetSigmaTilde( int ); -void WriteTable(fastNLOCreate& table, rust::Str filename); - std::size_t GetNx(fastNLOCoeffAddFlex const& coeffs, std::size_t); fastNLOCoeffAddBase const& downcast_coeff_add_fix_to_base(fastNLOCoeffAddFix const& coeffs); diff --git a/pineappl_fastnlo/src/lib.rs b/pineappl_fastnlo/src/lib.rs index 78f208df..89122e03 100644 --- a/pineappl_fastnlo/src/lib.rs +++ b/pineappl_fastnlo/src/lib.rs @@ -134,12 +134,6 @@ pub mod ffi { fn GetPDFPDG(&self, _: i32) -> i32; } - unsafe extern "C++" { - include!("fastnlotk/fastNLOCreate.h"); - - type fastNLOCreate; - } - unsafe extern "C++" { include!("pineappl_fastnlo/src/fastnlo.hpp"); @@ -174,8 +168,6 @@ pub mod ffi { _: i32, ) -> f64; - fn WriteTable(_: Pin<&mut fastNLOCreate>, _: &str); - fn downcast_coeff_add_fix_to_base(_: &fastNLOCoeffAddFix) -> &fastNLOCoeffAddBase; fn downcast_coeff_add_flex_to_base(_: &fastNLOCoeffAddFlex) -> &fastNLOCoeffAddBase; fn downcast_lhapdf_to_reader(_: &fastNLOLHAPDF) -> &fastNLOReader; @@ -208,7 +200,8 @@ pub mod ffi { nnlo_channels: i32, convolutions: &[i32], channels: &[Vec], - ) -> UniquePtr; + filename: &str, + ); } } From 5162aeee25d34ed2256652e250030e7bc9588785 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 6 Apr 2026 15:22:47 +0200 Subject: [PATCH 29/30] Set number of events to avoid division by zero --- pineappl_fastnlo/src/fastnlo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pineappl_fastnlo/src/fastnlo.cpp b/pineappl_fastnlo/src/fastnlo.cpp index 4edc2be3..42d7a809 100644 --- a/pineappl_fastnlo/src/fastnlo.cpp +++ b/pineappl_fastnlo/src/fastnlo.cpp @@ -224,6 +224,8 @@ void make_fastnlo_create( // wconst.headerValues = ; fastNLOCreate table(gconst, pconst, sconst, wconst); + + table.SetNumberOfEvents(1.0); table.WriteTable(); } From dfa52277947eea522d87bef9ace96d1c088cec11 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Mon, 6 Apr 2026 18:07:16 +0200 Subject: [PATCH 30/30] Avoid potentially unknow parton IDs --- pineappl_fastnlo/src/fastnlo.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pineappl_fastnlo/src/fastnlo.cpp b/pineappl_fastnlo/src/fastnlo.cpp index 42d7a809..73154afd 100644 --- a/pineappl_fastnlo/src/fastnlo.cpp +++ b/pineappl_fastnlo/src/fastnlo.cpp @@ -144,6 +144,11 @@ void make_fastnlo_create( for (std::size_t j = 0; j != channels.at(i).size(); ++j) { auto const first = channels.at(i).at(j).first; auto const second = channels.at(i).at(j).second; + + // TODO: has the gluon id `0`? + assert( first >= -6 && first <= 6 ); + assert( second >= -6 && first <= 6 ); + entries.at(j) = std::make_pair(first, second); } linear_combinations.at(i) = entries;