-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathPineAPPL.hpp
More file actions
352 lines (300 loc) · 11 KB
/
PineAPPL.hpp
File metadata and controls
352 lines (300 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/**
* @brief Object oriented interface to PineAPPL using only v1 features.
*/
#ifndef PineAPPL_HPP_
#define PineAPPL_HPP_
#include <LHAPDF/LHAPDF.h>
#include <pineappl_capi.h>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#include <memory>
/** @brief Object oriented interface to PineAPPL.*/
namespace PineAPPL {
// TODO: Add checks within various functions/calls
// TODO: Implement `grid_convolve`
/** @brief Entry in sub-channel function. A sub-channel consists of a vector of
* tuple. Each tuple contains two elements. The first elements store the list of
* PIDs as a vector while the second represent the weighting factor. Note that
* the number of PIDs must correspond to the number of convolutions involved.*/
struct SubChannelEntry {
/** @brief First parton id. */
std::vector<std::pair<std::vector<int>, double>> entry;
};
/** @brief Entry in channels function. */
struct ChannelsEntry {
/** @brief First parton id. */
std::vector<SubChannelEntry> channels_entry;
};
/** @brief Channels function. */
struct Channels {
/** @brief Underlying raw object. */
pineappl_channels *raw;
/** @brief Constructor. */
Channels(const std::size_t convolutions) : raw(pineappl_channels_new(convolutions)) {}
Channels(const Channels &) = delete;
Channels(Channels &&) = delete;
Channels &operator=(const Channels &) = delete;
Channels &operator=(Channels &&) = delete;
/** @brief Destructor. */
~Channels() { pineappl_channels_delete(this->raw); }
/** @brief Number of elements. */
std::size_t count() const { return pineappl_channels_count(this->raw); }
/**
* @brief Add a channel function.
* @param c channel function
*/
void add(const ChannelsEntry &c) const {
const std::size_t combinations = c.channels_entry.size();
if (combinations == 0) return;
std::vector<std::int32_t> pids;
std::vector<double> weights;
for (const SubChannelEntry &s : c.channels_entry) {
for (const std::pair<std::vector<int>, double> &m : s.entry) {
for (const int &pid : m.first) {
pids.push_back(pid);
}
weights.push_back(m.second);
}
}
pineappl_channels_add(this->raw, combinations, pids.data(), weights.data());
}
/**
* @brief Returns the number of combinations of the channels function
* `channels` for the specified entry.
* @param entry position in channels
*/
std::size_t combinations(const std::size_t entry) const {
return pineappl_channels_combinations(this->raw, entry);
}
};
/** @brief Extension of `Order` to accommodate for v1 representation. */
struct Order {
/** @brief Exponent of the strong coupling. */
std::uint8_t alphas;
/** @brief Exponent of the electromagnetic coupling. */
std::uint8_t alpha;
/** @brief Exponent of the logarithm of the scale factor of the
* renomalization scale. */
std::uint8_t logxir;
/** @brief Exponent of the logarithm of the scale factor of the
* factorization scale. */
std::uint8_t logxif;
/** @brief Exponent of the logarithm of the scale factor of the
* fragmentation scale. */
std::uint8_t logxia;
};
/** @brief Object containing the values of the scale factors. */
struct MuScales {
/** @brief renormalization scale factor. */
const double xir;
/** @brief factorization scale factor. */
const double xif;
/** @brief fragmentation scale factor. */
const double xia;
};
/** @brief Base Grid struct that contains the common data in v0 and v1. */
struct Grid {
/** @brief Underlying raw object. */
pineappl_grid *raw;
/** @brief Constructor. */
Grid(pineappl_grid *grid) : raw(grid) {}
/** @brief Deleted copy/move semantics. */
Grid() = delete;
Grid(const Grid &) = delete;
Grid(Grid &&) = delete;
Grid &operator=(const Grid &) = delete;
Grid &operator=(Grid &&) = delete;
public:
/** @brief Destructor. */
virtual ~Grid() { pineappl_grid_delete(this->raw); }
/**
* @brief Constructor.
* @param orders orders
* @param channels channels
* @param pid_basis pid_basis
* @param pids pids
* @param convolutions_types convolution_types
* @param interp interp
* @param bin_limits bin_limits
* @param mu_scales indexes representing the scales
*/
Grid(std::vector<Order> &orders,
const Channels &channels,
pineappl_pid_basis pid_basis,
std::vector<pineappl_conv> &convolutions,
std::vector<pineappl_kinematics> &kinematics,
std::vector<pineappl_interp> &interp,
std::vector<double> &bin_limits,
std::vector<pineappl_scale_func_form> &mu_scales)
: Grid(nullptr) {
const std::size_t n_orders = orders.size();
const std::size_t n_bins = bin_limits.size() - 1;
const std::size_t n_convs = convolutions.size();
// Various checks for the input arguments
assert(n_orders >= 1 && "Orders cannot be empty.");
assert(n_convs == kinematics.size() - 1 &&
"Mismatch in the number of convolutions and the kinematics.");
assert(kinematics.size() == interp.size() &&
"Mismatch in the number of kinematics and the corresponding "
"interpolations.");
// Cast the Orders
std::vector<std::uint8_t> raw_orders;
for (const Order &order : orders) {
raw_orders.push_back(order.alphas);
raw_orders.push_back(order.alpha);
raw_orders.push_back(order.logxir);
raw_orders.push_back(order.logxif);
raw_orders.push_back(order.logxia);
}
this->raw = pineappl_grid_new2(
n_bins, bin_limits.data(), n_orders, raw_orders.data(), channels.raw,
pid_basis, convolutions.data(), interp.size(),
interp.data(), kinematics.data(), mu_scales.data());
}
/**
* @brief Fill grid for the given parameters.
* @param order perturbative order
* @param observable value of the observable
* @param channel index of the channel
* @param ntuples tuples containing the kinematics {q2, x1, ...}
* @param weight value of the weighting factor
*/
void fill(const std::size_t order, const double observable,
const std::size_t channel, std::vector<double> &ntuples,
const double weight) const {
pineappl_grid_fill2(this->raw, order, observable, channel, ntuples.data(),
weight);
}
/**
* @brief Number of orders.
* @return number of orders
*/
std::size_t order_count() const {
return pineappl_grid_order_count(this->raw);
}
/**
* @brief Number of bins.
* @return number of bins
*/
std::size_t bin_count() const { return pineappl_grid_bin_count(this->raw); }
/**
* @brief Write grid to file.
* @param filename file name
*/
void write(const std::string &filename) const {
pineappl_grid_write(this->raw, filename.c_str());
}
/**
* @brief Set a metadata entry.
* @param key key
* @param value value
*/
void set_metadata(const std::string &key, const std::string &value) const {
pineappl_grid_set_metadata(this->raw, key.c_str(), value.c_str());
}
/**
* @brief Get a metadata entry.
* @param key key
* @return value
*/
std::string get_metadata(const std::string &key) const {
auto *value = pineappl_grid_metadata(this->raw, key.c_str());
std::string res(value != nullptr ? value : "");
// delete the allocated object
pineappl_string_delete(value);
return res;
}
/**
* @brief Scale grid with a number.
* This multiplies all subgrids with the given number.
* @param s factor
*/
void scale(const double s) const { pineappl_grid_scale(this->raw, s); }
/**
* @brief Optimizes the grid representation for space efficiency.
*/
void optimize() const { pineappl_grid_optimize(this->raw); }
/**
* @brief Perform the convolution of a Grid with the PDF(s).
*/
std::vector<double> convolve(std::vector<LHAPDF::PDF *> lhapdfs,
const size_t alphas_pdf_index,
const std::vector<bool> &order_mask = {},
const std::vector<bool> &channels_mask = {},
const std::vector<std::size_t> &bin_indices = {},
const std::vector<MuScales> &mu_scales = {
{1.0, 1.0, 1.0}}) {
// Define callables to compute the PDFs and alphas(Q2)
auto xfx = [](std::int32_t id, double x, double q2, void *pdf) {
return static_cast<LHAPDF::PDF *>(pdf)->xfxQ2(id, x, q2);
};
auto alphas = [](double q2, void *pdf) {
return static_cast<LHAPDF::PDF *>(pdf)->alphasQ2(q2);
};
// Select the PDF objec to compute the alphas(Q2) from
LHAPDF::PDF *alphas_pdf = lhapdfs[alphas_pdf_index];
void **pdfs_state = reinterpret_cast<void **>(lhapdfs.data());
// cast order_mask
std::unique_ptr<bool[]> raw_order_mask;
if (!order_mask.empty()) {
raw_order_mask = std::unique_ptr<bool[]>(new bool[order_mask.size()]);
std::copy(order_mask.begin(), order_mask.end(), &raw_order_mask[0]);
}
// cast channels mask
std::unique_ptr<bool[]> raw_channels_mask;
if (!channels_mask.empty()) {
raw_channels_mask =
std::unique_ptr<bool[]>(new bool[channels_mask.size()]);
std::copy(channels_mask.begin(), channels_mask.end(),
&raw_channels_mask[0]);
}
// cast bin indices mask
std::unique_ptr<std::size_t[]> raw_bin_indices;
if (!bin_indices.empty()) {
raw_bin_indices =
std::unique_ptr<std::size_t[]>(new std::size_t[bin_indices.size()]);
std::copy(bin_indices.begin(), bin_indices.end(), &raw_bin_indices[0]);
}
// Linearize the scales
std::vector<double> raw_mu_scales;
raw_mu_scales.reserve(mu_scales.size() * 3);
for (const auto &scale_tuple : mu_scales) {
raw_mu_scales.push_back(scale_tuple.xir);
raw_mu_scales.push_back(scale_tuple.xif);
raw_mu_scales.push_back(scale_tuple.xia);
}
std::vector<double> results(this->bin_count());
pineappl_grid_convolve(this->raw, xfx, alphas, pdfs_state, alphas_pdf,
raw_order_mask.get(), raw_channels_mask.get(),
raw_bin_indices.get(), mu_scales.size(),
raw_mu_scales.data(), results.data());
return results;
}
/**
* @brief Fix one of the convolutions in the Grid and return a new Grid with
* lower dimension.
*
* @param conv_idx index of the convolution to fix
* @param pdf the PDF set to use for the convolution
* @param xi the scale factor (xif or xia)
* @return a new grid with one less convolution
*/
std::unique_ptr<Grid> fix_convolution(std::size_t conv_idx, LHAPDF::PDF *pdf,
double xi) const {
auto xfx = [](std::int32_t id, double x, double q2, void *pdf_ptr) {
return static_cast<LHAPDF::PDF *>(pdf_ptr)->xfxQ2(id, x, q2);
};
pineappl_grid *new_raw_grid =
pineappl_grid_fix_convolution(this->raw, conv_idx, xfx, pdf, xi);
if (new_raw_grid == nullptr) {
return nullptr;
}
return std::unique_ptr<Grid>(new Grid(new_raw_grid));
}
};
} // namespace PineAPPL
#endif // PineAPPL_HPP_