use ndarray::{Array1, Array2};
use rayon::prelude::*;
use super::gridpdf::{ForcePositive, GridArray, GridPDF};
use super::metadata::MetaData;
use super::parser::{LhapdfSet, NeopdfSet};
use super::subgrid::{RangeParameters, SubGrid};
trait PdfSet: Send + Sync {
fn num_members(&self) -> usize;
fn member(&self, idx: usize) -> (MetaData, GridArray);
}
impl PdfSet for LhapdfSet {
fn num_members(&self) -> usize {
self.info.num_members as usize
}
fn member(&self, idx: usize) -> (MetaData, GridArray) {
self.member(idx)
}
}
impl PdfSet for NeopdfSet {
fn num_members(&self) -> usize {
self.info.num_members as usize
}
fn member(&self, idx: usize) -> (MetaData, GridArray) {
self.member(idx)
}
}
fn pdfset_loader<T: PdfSet>(set: T, member: usize) -> PDF {
let (info, knot_array) = set.member(member);
PDF {
grid_pdf: GridPDF::new(info, knot_array),
}
}
fn pdfsets_seq_loader<T: PdfSet + Send + Sync>(set: T) -> Vec<PDF> {
(0..set.num_members())
.map(|idx| {
let (info, knot_array) = set.member(idx);
PDF {
grid_pdf: GridPDF::new(info, knot_array),
}
})
.collect()
}
fn pdfsets_par_loader<T: PdfSet + Send + Sync>(set: T) -> Vec<PDF> {
(0..set.num_members())
.into_par_iter()
.map(|idx| {
let (info, knot_array) = set.member(idx);
PDF {
grid_pdf: GridPDF::new(info, knot_array),
}
})
.collect()
}
pub struct PDF {
grid_pdf: GridPDF,
}
impl PDF {
pub fn load(pdf_name: &str, member: usize) -> Self {
if pdf_name.ends_with(".neopdf.lz4") {
pdfset_loader(NeopdfSet::new(pdf_name), member)
} else {
pdfset_loader(LhapdfSet::new(pdf_name), member)
}
}
pub fn load_pdfs(pdf_name: &str) -> Vec<PDF> {
if pdf_name.ends_with(".neopdf.lz4") {
pdfsets_par_loader(NeopdfSet::new(pdf_name))
} else {
pdfsets_par_loader(LhapdfSet::new(pdf_name))
}
}
pub fn load_pdfs_seq(pdf_name: &str) -> Vec<PDF> {
if pdf_name.ends_with(".neopdf.lz4") {
pdfsets_seq_loader(NeopdfSet::new(pdf_name))
} else {
pdfsets_seq_loader(LhapdfSet::new(pdf_name))
}
}
pub fn load_pdfs_lazy(
pdf_name: &str,
) -> impl Iterator<Item = Result<PDF, Box<dyn std::error::Error>>> {
assert!(
pdf_name.ends_with(".neopdf.lz4"),
"Lazy loading is only supported for .neopdf.lz4 files"
);
let iter_lazy = NeopdfSet::new(pdf_name).into_lazy_iterators();
iter_lazy.map(|grid_array_with_metadata_result| {
grid_array_with_metadata_result.map(|grid_array_with_metadata| {
let info = (*grid_array_with_metadata.metadata).clone();
let knot_array = grid_array_with_metadata.grid;
PDF {
grid_pdf: GridPDF::new(info, knot_array),
}
})
})
}
pub fn set_force_positive(&mut self, option: ForcePositive) {
self.grid_pdf.set_force_positive(option);
}
pub fn set_force_positive_members(pdfs: &mut [PDF], option: ForcePositive) {
for pdf in pdfs {
pdf.set_force_positive(option.clone());
}
}
pub fn is_force_positive(&self) -> &ForcePositive {
self.grid_pdf
.force_positive
.as_ref()
.unwrap_or(&ForcePositive::NoClipping)
}
pub fn xfxq2(&self, pid: i32, points: &[f64]) -> f64 {
self.grid_pdf.xfxq2(pid, points).unwrap()
}
pub fn xfxq2s(&self, pids: Vec<i32>, slice_points: &[&[f64]]) -> Array2<f64> {
self.grid_pdf.xfxq2s(pids, slice_points)
}
pub fn xfxq2_cheby_batch(&self, pid: i32, points: &[&[f64]]) -> Vec<f64> {
self.grid_pdf.xfxq2_cheby_batch(pid, points).unwrap()
}
pub fn alphas_q2(&self, q2: f64) -> f64 {
self.grid_pdf.alphas_q2(q2)
}
pub fn metadata(&self) -> &MetaData {
self.grid_pdf.metadata()
}
pub fn num_subgrids(&self) -> usize {
self.grid_pdf.knot_array.subgrids.len()
}
pub fn subgrid(&self, index: usize) -> &SubGrid {
&self.grid_pdf.knot_array.subgrids[index]
}
pub fn subgrids(&self) -> &Vec<SubGrid> {
&self.grid_pdf.knot_array.subgrids
}
pub fn pids(&self) -> &Array1<i32> {
&self.grid_pdf.knot_array.pids
}
pub fn param_ranges(&self) -> RangeParameters {
self.grid_pdf.param_ranges()
}
#[allow(clippy::too_many_arguments)]
pub fn xf_from_index(
&self,
i_nucleons: usize,
i_alphas: usize,
i_kt: usize,
ix: usize,
iq2: usize,
id: i32,
subgrid_id: usize,
) -> f64 {
self.grid_pdf
.knot_array
.xf_from_index(i_nucleons, i_alphas, i_kt, ix, iq2, id, subgrid_id)
}
}