Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
BsPhiDecay.cpp
Go to the documentation of this file.
1#include <algorithm>
2#include "wcoef_ids.hpp"
3#include <exception>
4#include <mutex>
5#include <thread>
6#include <vector>
7
8#include "BsPhiDecay.h"
9
12
13 cache.ff_calculator = BVFFCalculator(531, 333, p, cfg.ff_src);
14 cache.mu_b = (*p)(ParamId{ParameterType::WILSON, "B_SCALE", 1}, DataType::VALUE);
15
17 531, 333,
18 cache.mu_b,
19 cache.C,
20 std::make_shared<BVFFCalculator>(cache.ff_calculator),
21 cfg.ff_type,
22 p,
24 );
25
26 cache.alpha_em = (*p)(ParamId{ParameterType::SM, "EW", {1, 2}}, DataType::VALUE);
27 cache.G_F = (*p)(ParamId{ParameterType::SM, "SMINPUTS", 2}, DataType::VALUE);
28 cache.m_s = (*p)(ParamId{ParameterType::SM, "MASS", 3}, DataType::VALUE);
29 cache.alpha_s_mu_b = (*iobs_qcdp)(AlphasConfig(cache.mu_b, MassType::POLE, MassType::POLE));
30 cache.m_c_m_c = (*p)(ParamId{ParameterType::SM, "MASS", 4}, DataType::VALUE);
31 cache.m_b_mu_b = (*iobs_qcdp)(MassConfig(5, cache.mu_b, MassType::MSBAR, MassType::POLE));
32 cache.m_b_m_b = (*p)(ParamId{ParameterType::SM, "SMINPUTS", 5}, DataType::VALUE);
33 cache.m_b_PS = (*p)(ParamId{ParameterType::SM, "QCD", {5, 2}}, DataType::VALUE) - 4 * (*iobs_qcdp)(AlphasConfig((*p)(ParamId{ParameterType::SM, "QCD", {5, 2}}, DataType::VALUE), MassType::POLE, MassType::POLE)) * sqrt(cache.mu_b * (*p)(ParamId{ParameterType::DECAY, "B_phi", 14}, DataType::VALUE)) / (3 * PI);
34 cache.L_b = std::log(cache.mu_b / cache.m_b_PS);
35 cache.m_Bs = (*p)(ParamId{ParameterType::FLAVOR, "FMASS", 531}, DataType::VALUE);
36 cache.m_phi = (*p)(ParamId{ParameterType::FLAVOR, "FMASS", 333}, DataType::VALUE);
37 cache.life_Bs = (*p)(ParamId{ParameterType::FLAVOR, "FLIFE", 531}, DataType::VALUE) / HBAR;
38 cache.lambda_hat_u = std::conj((*p)(ParamId{ParameterType::SM, "VCKM", {0, 1}}, DataType::VALUE)) * (*p)(ParamId{ParameterType::SM, "VCKM", {0, 2}}, DataType::VALUE)
39 / (std::conj((*p)(ParamId{ParameterType::SM, "VCKM", {2, 1}}, DataType::VALUE)) * (*p)(ParamId{ParameterType::SM, "VCKM", {2, 2}}, DataType::VALUE));
40 cache.kappa = 1 - 2. * cache.alpha_s_mu_b / (3. * PI) * std::log(cache.mu_b / cache.m_b_m_b);
41 cache.Delta_M = -6. * cache.L_b - 4. * (1 - sqrt(cache.mu_b * (*p)(ParamId{ParameterType::DECAY, "B_phi", 14}, DataType::VALUE)) / cache.m_b_PS);
42 cache.N_0 = std::conj((*p)(ParamId{ParameterType::SM, "VCKM", {2, 1}}, DataType::VALUE)) * (*p)(ParamId{ParameterType::SM, "VCKM", {2, 2}}, DataType::VALUE) * cache.G_F * cache.alpha_em / (std::sqrt(3072. * std::pow(PI, 5) * std::pow(cache.m_Bs, 3)));
43 cache.q2_max = std::pow(cache.m_Bs - cache.m_phi, 2);
44 cache.q2_low = (*p)(ParamId{ParameterType::DECAY, "B_phi", {15, 1}}, DataType::VALUE);
45 cache.q2_high = (*p)(ParamId{ParameterType::DECAY, "B_phi", {15, 2}}, DataType::VALUE);
46 cache.ys = (*p)(ParamId{ParameterType::DECAY, "B_ll", 1}, DataType::VALUE);
47 // ASK : hardcoded in SI
48
49 cache.phi_s = 0.04;
50 cache.up = 1. + cache.phi_s * I;
51 cache.um = 1. - cache.phi_s * I;
52
53 complex_t eipi4 = std::exp(I * PI / 4.0);
54
55 for (size_t i = 0; i < 6; i++) {
56 cache.A_had_err_low_0[i] = (*p)(ParamId{ParameterType::DECAY, "B_phi", {18, 1, i + 1}}, DataType::VALUE);
57 cache.A_had_err_low_1[i] = (*p)(ParamId{ParameterType::DECAY, "B_phi", {18, 2, i + 1}}, DataType::VALUE);
58 }
59
60 for (size_t i = 0; i < 8; i++) {
61 cache.A_had_err_high[i] = (*p)(ParamId{ParameterType::DECAY, "B_phi", {18, 3, i + 1}}, DataType::VALUE);
62 }
63
65}
66
68 cache.C.clear();
69
70 auto b_wilsons = w_proxy->getAFR(WGroup::B, this->w_config.order);
71 auto bp_wilsons = w_proxy->getAFR(WGroup::BPrime, this->w_config.order);
72 auto bq_wilsons = w_proxy->getAFR(WGroup::BScalar, this->w_config.order);
73
74 for (const auto& [id, val] : b_wilsons) {
75 cache.C[id] = val;
76 }
77 for (const auto& [id, val] : bq_wilsons) {
78 cache.C[id] = val;
79 }
80 for (const auto& [id, val] : bp_wilsons) {
81 cache.C[id] = val;
82 }
83}
84
86 if (cfg.gen != gen) {
87 cfg.gen = gen;
89 }
90}
91
93 cache.m_l = (*p)(
94 ParamId{ParameterType::SM, "MASS", 11 + 2 * (int)cfg.gen},
96 );
97
98 cache.q2_min = 4 * std::pow(cache.m_l, 2);
99 cache.q2_lookup_min = std::max(cache.q2_min, 1e-4);
100
101 auto requested_threads = cfg.n_threads;
102 if (requested_threads == 0u) {
103 requested_threads = std::thread::hardware_concurrency();
104 }
105 if (requested_threads == 0u) {
106 requested_threads = 1u;
107 }
108
109 const size_t npts = BsPhiDecayCache::LOOKUP_SIZE;
110 const size_t nworkers = std::min<size_t>(requested_threads, npts);
111
112 if (nworkers <= 1u) {
113 auto lam_T_perp_p = [this] (double q2, bool bar) {
114 return cache.qcdf_calculator.T_perp_p(q2, bar);
115 };
116
117 fill_cache(lam_T_perp_p, cache.q2_lookup_min, cache.q2_high, cache.T_perp_p_lookup, false);
118 fill_cache(lam_T_perp_p, cache.q2_lookup_min, cache.q2_high, cache.T_perp_p_bar_lookup, true);
119
120 auto lam_T_perp_m = [this] (double q2, bool bar) {
121 return cache.qcdf_calculator.T_perp_m(q2, bar);
122 };
123
124 fill_cache(lam_T_perp_m, cache.q2_lookup_min, cache.q2_high, cache.T_perp_m_lookup, false);
125 fill_cache(lam_T_perp_m, cache.q2_lookup_min, cache.q2_high, cache.T_perp_m_bar_lookup, true);
126
127 auto lam_T_par_m = [this] (double q2, bool bar) {
128 return cache.qcdf_calculator.T_par_m(q2, bar);
129 };
130
131 fill_cache(lam_T_par_m, cache.q2_lookup_min, cache.q2_high, cache.T_par_m_lookup, false);
132 fill_cache(lam_T_par_m, cache.q2_lookup_min, cache.q2_high, cache.T_par_m_bar_lookup, true);
133 } else {
134 const int B_id = 531;
135 const int V_id = 333;
136 const double x_min = cache.q2_lookup_min;
137 const double x_max = cache.q2_high;
138 const double step = (x_max - x_min) / static_cast<double>(npts - 1);
139
140 std::vector<std::shared_ptr<BVQCDfCalculator>> qcdf_locals;
141 qcdf_locals.reserve(nworkers);
142 for (size_t w = 0; w < nworkers; ++w) {
143 auto ff_local = std::make_shared<BVFFCalculator>(cache.ff_calculator);
144 qcdf_locals.emplace_back(std::make_shared<BVQCDfCalculator>(
145 B_id,
146 V_id,
147 cache.mu_b,
148 cache.C,
149 ff_local,
150 cfg.ff_type,
151 p,
153 ));
154 }
155
156 std::vector<std::thread> workers;
157 workers.reserve(nworkers);
158
159 std::exception_ptr first_exception = nullptr;
160 std::mutex exception_mutex;
161
162 auto worker = [&] (size_t worker_id, size_t begin, size_t end) {
163 try {
164 BVQCDfCalculator& qcdf = *qcdf_locals[worker_id];
165 for (size_t i = begin; i < end; ++i) {
166 const double q2 = x_min + step * static_cast<double>(i);
167
168 cache.T_perp_p_lookup[i] = qcdf.T_perp_p(q2, false);
169 cache.T_perp_p_bar_lookup[i] = qcdf.T_perp_p(q2, true);
170
171 cache.T_perp_m_lookup[i] = qcdf.T_perp_m(q2, false);
172 cache.T_perp_m_bar_lookup[i] = qcdf.T_perp_m(q2, true);
173
174 cache.T_par_m_lookup[i] = qcdf.T_par_m(q2, false);
175 cache.T_par_m_bar_lookup[i] = qcdf.T_par_m(q2, true);
176 }
177 } catch (...) {
178 std::lock_guard<std::mutex> lock(exception_mutex);
179 if (!first_exception) {
180 first_exception = std::current_exception();
181 }
182 }
183 };
184
185 const size_t chunk = (npts + nworkers - 1) / nworkers;
186 for (size_t w = 0; w < nworkers; ++w) {
187 const size_t begin = w * chunk;
188 const size_t end = std::min(npts, begin + chunk);
189 if (begin >= end) {
190 break;
191 }
192 workers.emplace_back(worker, w, begin, end);
193 }
194
195 for (auto& th : workers) {
196 th.join();
197 }
198
199 if (first_exception) {
200 std::rethrow_exception(first_exception);
201 }
202 }
203
205}
206
208 const double x = std::max(q2, cache.q2_lookup_min);
209 return lerp(
210 x,
211 bar ? cache.T_perp_p_bar_lookup : cache.T_perp_p_lookup,
212 cache.q2_lookup_min,
213 cache.q2_high
214 );
215}
216
218 const double x = std::max(q2, cache.q2_lookup_min);
219 return lerp(
220 x,
221 bar ? cache.T_perp_m_bar_lookup : cache.T_perp_m_lookup,
222 cache.q2_lookup_min,
223 cache.q2_high
224 );
225}
226
228 const double x = std::max(q2, cache.q2_lookup_min);
229 return lerp(
230 x,
231 bar ? cache.T_par_m_bar_lookup : cache.T_par_m_lookup,
232 cache.q2_lookup_min,
233 cache.q2_high
234 );
235}
236
237double BsPhiDecay::beta_l(double q2) {
238 const double x = 1.0 - 4.0 * cache.m_l * cache.m_l / q2;
239 return std::sqrt(std::max(0.0, x));
240}
241
242double BsPhiDecay::lambda(double q2) {
243 const double mB2 = cache.m_Bs * cache.m_Bs;
244 const double mphi2 = cache.m_phi * cache.m_phi;
245
246 const double lam =
247 mB2 * mB2
248 + mphi2 * mphi2
249 + q2 * q2
250 - 2.0 * (mB2 * mphi2 + (mB2 + mphi2) * q2);
251
252 return std::max(0.0, lam);
253}
254
255complex_t BsPhiDecay::N(double q2, bool bar) {
256 complex_t N0 = bar ? std::conj(cache.N_0) : cache.N_0;
257 return N0 * std::sqrt(q2 * beta_l(q2) * std::sqrt(lambda(q2)));
258}
259
260complex_t BsPhiDecay::delta_A_perp(double q2, double sign, bool bar) {
261 size_t id = size_t (0.5 * (1 + sign));
262 complex_t guesstimate_err = 1.0 + cache.A_had_err_low_0[id] + cache.A_had_err_low_1[id] * q2 / 6.0;
263 double m_b = cache.m_b_PS + cache.alpha_s_mu_b * cache.Delta_M / (3 * PI);
264 return 2 * RT2 * m_b * N(q2, bar) * std::sqrt(lambda(q2)) / q2 * T_perp_p_cached(q2, bar) * guesstimate_err;
265}
266
267complex_t BsPhiDecay::delta_A_par(double q2, double sign, bool bar) {
268 size_t id = 2 + size_t (0.5 * (1 + sign));
269 complex_t guesstimate_err = 1.0 + cache.A_had_err_low_0[id] + cache.A_had_err_low_1[id] * q2 / 6.0;
270 double m_b = cache.m_b_PS + cache.alpha_s_mu_b * cache.Delta_M / (3 * PI);
271 return -4 * RT2 * m_b * N(q2, bar) * (cache.m_Bs * cache.m_Bs - cache.m_phi * cache.m_phi) * cache.ff_calculator.E(q2) / (q2 * cache.m_Bs) * T_perp_m_cached(q2, bar) * guesstimate_err;
272}
273
274complex_t BsPhiDecay::A_perp_low(double q2, double sign, bool bar) {
275 complex_t F, F_T;
276 complex_t delta_A {0.0};
277 complex_t had_err_factor {1.0};
278 double m_b_local;
279
280 if (cfg.ff_type == B_FF_Type::SOFT) {
281 complex_t w = cache.C[WCoef::C9] + cache.C[WCoef::CP9] + sign * (cache.C[WCoef::C10] + cache.C[WCoef::CP10]);
282 if (bar) w = std::conj(w);
283 F = w * cache.ff_calculator.get(BV_FF::V, q2) / (cache.m_Bs + cache.m_phi);
284 F_T = T_perp_p_cached(q2, bar);
285 size_t id = size_t (0.5 * (1 + sign));
286 had_err_factor = 1.0 + cache.A_had_err_low_0[id] + cache.A_had_err_low_1[id] * q2 / 6.0;
287 m_b_local = cache.m_b_PS;
288 } else {
289 F_T = (cache.C[WCoef::C7] + cache.C[WCoef::CP7]) * cache.ff_calculator.get(BV_FF::T1, q2);
290 complex_t w = cache.C[WCoef::C9] + cache.C[WCoef::CP9] + sign * (cache.C[WCoef::C10] + cache.C[WCoef::CP10]);
291 if (bar) {
292 w = std::conj(w);
293 F_T = std::conj(F_T);
294 }
295 w += cache.qcdf_calculator.Y(q2);
296 F = w * cache.ff_calculator.get(BV_FF::V, q2) / (cache.m_Bs + cache.m_phi);
297 delta_A = delta_A_perp(q2, sign, bar);
298 m_b_local = cache.m_b_PS + cache.alpha_s_mu_b * cache.Delta_M / (3 * PI);
299 }
300
301 return (N(q2, bar) * std::sqrt(2 * lambda(q2)) * (F + 2. * m_b_local * F_T / q2) + delta_A) * had_err_factor;
302}
303
304complex_t BsPhiDecay::A_par_low(double q2, double sign, bool bar) {
305 complex_t F, F_T;
306 complex_t delta_A {0.0};
307 complex_t had_err_factor {1.0};
308 double m_b_local;
309
310 if (cfg.ff_type == B_FF_Type::SOFT) {
311 complex_t w = cache.C[WCoef::C9] - cache.C[WCoef::CP9] + sign * (cache.C[WCoef::C10] - cache.C[WCoef::CP10]);
312 if (bar) w = std::conj(w);
313 F = w * 2. * cache.ff_calculator.E(q2) / (cache.m_Bs + cache.m_phi) * cache.ff_calculator.get(BV_FF::XI_PERP, q2) / (cache.m_Bs - cache.m_phi);
314 F_T = 2. * cache.ff_calculator.E(q2) * T_perp_m_cached(q2, bar) / cache.m_Bs;
315 size_t id = 2 + size_t (0.5 * (1 + sign));
316 had_err_factor = 1.0 + cache.A_had_err_low_0[id] + cache.A_had_err_low_1[id] * q2 / 6.0;
317 m_b_local = cache.m_b_PS;
318 } else {
319 F_T = (cache.C[WCoef::C7] - cache.C[WCoef::CP7]) * cache.ff_calculator.get(BV_FF::T2, q2);
320 complex_t w = cache.C[WCoef::C9] - cache.C[WCoef::CP9] + sign * (cache.C[WCoef::C10] - cache.C[WCoef::CP10]);
321 if (bar) {
322 w = std::conj(w);
323 F_T = std::conj(F_T);
324 }
325 w += cache.qcdf_calculator.Y(q2);
326 F = w * cache.ff_calculator.get(BV_FF::A1, q2) / (cache.m_Bs - cache.m_phi);
327 delta_A = delta_A_par(q2, sign, bar);
328 m_b_local = cache.m_b_PS + cache.alpha_s_mu_b * cache.Delta_M / (3 * PI);
329 }
330
331 return (-N(q2, bar) * std::sqrt(2.) * (cache.m_Bs * cache.m_Bs - cache.m_phi * cache.m_phi) * (F + 2. * m_b_local * F_T / q2) + delta_A) * had_err_factor;
332}
333
334complex_t BsPhiDecay::A_0_low(double q2, double sign, bool bar) {
335 double mB2 = cache.m_Bs * cache.m_Bs;
336 double mK2 = cache.m_phi * cache.m_phi;
337 complex_t F, F_T;
338 complex_t delta_A {0.0};
339 complex_t had_err_factor {1.0};
340 double m_b_local;
341
342 if (cfg.ff_type == B_FF_Type::SOFT) {
343 complex_t w = cache.C[WCoef::C9] - cache.C[WCoef::CP9] + sign * (cache.C[WCoef::C10] - cache.C[WCoef::CP10]);
344 if (bar) w = std::conj(w);
345 F = w * ((mB2 - mK2 - q2) * 2. * cache.ff_calculator.E(q2) * cache.ff_calculator.get(BV_FF::XI_PERP, q2) - lambda(q2) * cache.m_Bs / (mB2 - mK2) * (cache.ff_calculator.get(BV_FF::XI_PERP, q2) - cache.ff_calculator.get(BV_FF::XI_PAR, q2)));
346 F_T = 2. * cache.ff_calculator.E(q2) * (mB2 + 3. * mK2 - q2) * T_perp_m_cached(q2, bar) / cache.m_Bs - lambda(q2) * (T_perp_m_cached(q2, bar) + T_par_m_cached(q2, bar)) / (mB2 - mK2);
347 size_t id = 4 + size_t (0.5 * (1 + sign));
348 had_err_factor = 1.0 + cache.A_had_err_low_0[id] + cache.A_had_err_low_1[id] * q2 / 6.0;
349 m_b_local = cache.m_b_PS;
350 } else {
351 F_T = (cache.C[WCoef::C7] - cache.C[WCoef::CP7]) * 8. * cache.m_Bs * mK2 / (cache.m_Bs + cache.m_phi) * cache.ff_calculator.get(BV_FF::T23, q2);
352 complex_t w = cache.C[WCoef::C9] - cache.C[WCoef::CP9] + sign * (cache.C[WCoef::C10] - cache.C[WCoef::CP10]);
353 if (bar) {
354 w = std::conj(w);
355 F_T = std::conj(F_T);
356 }
357 w += cache.qcdf_calculator.Y(q2);
358 F = w * 16. * cache.m_Bs * mK2 * cache.ff_calculator.get(BV_FF::A12, q2);
359 delta_A = delta_A_0(q2, sign, bar);
360 m_b_local = cache.m_b_PS + cache.alpha_s_mu_b * cache.Delta_M / (3 * PI);
361 }
362
363 return (-N(q2, bar) / (2. * cache.m_phi * std::sqrt(q2)) * (F + 2. * m_b_local * F_T) + delta_A) * had_err_factor;
364}
365
366complex_t BsPhiDecay::A_t_low(double q2, bool bar) {
367 complex_t C10 = cache.C[WCoef::C10] - cache.C[WCoef::CP10];
368 complex_t CQ2 = cache.C[WCoefMapper::cq2_for_lepton_index(static_cast<int>(cfg.gen))] - cache.C[WCoefMapper::cpq2_for_lepton_index(static_cast<int>(cfg.gen))];
369 if (bar) {
370 C10 = std::conj(C10);
371 CQ2 = std::conj(CQ2);
372 }
373
374 complex_t F;
375 if (cfg.ff_type == B_FF_Type::SOFT) {
376 F = cache.ff_calculator.E(q2) * cache.ff_calculator.get(BV_FF::XI_PAR, q2) / (cache.m_phi * cache.qcdf_calculator.Delta_par(q2));
377 } else {
378 F = cache.ff_calculator.get(BV_FF::A0, q2);
379 }
380
381 return N(q2, bar) * std::sqrt(lambda(q2) / q2) * ((2. * C10 + q2 / (cache.m_l * (cache.m_b_mu_b + cache.m_s)) * CQ2)) * F;
382}
383
384complex_t BsPhiDecay::A_S_low(double q2, bool bar) {
385 complex_t CQ1 = cache.C[WCoefMapper::cq1_for_lepton_index(static_cast<int>(cfg.gen))] - cache.C[WCoefMapper::cpq1_for_lepton_index(static_cast<int>(cfg.gen))];
386 if (bar) CQ1 = std::conj(CQ1);
387
388 complex_t F;
389 if (cfg.ff_type == B_FF_Type::SOFT) {
390 F = cache.ff_calculator.E(q2) * cache.ff_calculator.get(BV_FF::XI_PAR, q2) / (cache.m_phi * cache.qcdf_calculator.Delta_par(q2));
391 } else {
392 F = cache.ff_calculator.get(BV_FF::A0, q2);
393 }
394
395 return -2. * N(q2, bar) * std::sqrt(lambda(q2)) * CQ1 / (cache.m_b_mu_b + cache.m_s) * F;
396}
397
398complex_t BsPhiDecay::delta_A_0(double q2, double sign, bool bar) {
399 size_t id = 4 + size_t (0.5 * (1 + sign));
400 complex_t guesstimate_err = 1.0 + cache.A_had_err_low_0[id] + cache.A_had_err_low_1[id] * q2 / 6.0;
401
402 double mB2 = cache.m_Bs * cache.m_Bs;
403 double mB3 = cache.m_Bs * mB2;
404 double mK2 = cache.m_phi * cache.m_phi;
405 double f = lambda(q2) / ((mB2 - mK2) * mB2);
406 double m_b = cache.m_b_PS + cache.alpha_s_mu_b * cache.Delta_M / (3 * PI);
407 complex_t delta_A = -N(q2, bar) * m_b * mB2 / (std::sqrt(q2) * cache.m_phi) * (
408 (2 * (mB2 + 3 * mK2 - q2) * cache.ff_calculator.E(q2) / mB3 - f) * T_perp_m_cached(q2, bar)
409 - f * T_par_m_cached(q2, bar)
410 );
411 return delta_A * guesstimate_err;
412}
413
414complex_t BsPhiDecay::C7_eff(double q2, bool bar) {
415 double s_hat = q2 / std::pow(cache.m_b_PS, 2);
416 complex_t A = BV::A_Seidel(s_hat, cache.L_b);
417 return (!bar ? std::conj(cache.C[WCoef::C7]) : cache.C[WCoef::C7]) + cache.alpha_s_mu_b / (4. * PI) * ((cache.C[WCoef::C1]-6.*cache.C[WCoef::C2])*A-cache.C[WCoef::C8]*BV::f_87(s_hat, cache.L_b));
418}
419
420complex_t BsPhiDecay::C9_eff(double q2, bool bar) {
421 complex_t C_h0 = 4./3.*cache.C[WCoef::C1]+cache.C[WCoef::C2]+11./2.*cache.C[WCoef::C3]-2./3.*cache.C[WCoef::C4]+52.*cache.C[WCoef::C5]-32./3.*cache.C[WCoef::C6];
422 complex_t C_hb = -0.5 * (7.*cache.C[WCoef::C3]+4./3.*cache.C[WCoef::C4]+76.*cache.C[WCoef::C5]+64./3.*cache.C[WCoef::C6]);
423 complex_t C_0 = 4./3.*(cache.C[WCoef::C3]+16./3.*cache.C[WCoef::C5]+16./9.*cache.C[WCoef::C6]);
424 complex_t l_u = bar ? std::conj(cache.lambda_hat_u) : cache.lambda_hat_u;
425 complex_t C_mc = 8. * ((4./9.*cache.C[WCoef::C1]+1./3.*cache.C[WCoef::C2])*(1.+l_u)+2.*cache.C[WCoef::C3]+20.*cache.C[WCoef::C5]);
426
427 double s_hat = q2 / std::pow(cache.m_b_PS, 2);
428 complex_t B = BV::B_Seidel(s_hat, cache.L_b);
429 complex_t C = BV::C_Seidel(q2, cache.mu_b);
430
431 return (!bar ? std::conj(cache.C[WCoef::C9]) : cache.C[WCoef::C9])
432 + BV::h(q2, 0., cache.mu_b) * C_h0
433 + BV::h(q2, cache.m_b_PS, cache.mu_b) * C_hb
434 + C_0
435 + cache.alpha_s_mu_b / (4. * PI) * (cache.C[WCoef::C1]*(B + 4. * C) - 3. * cache.C[WCoef::C2] * (2. * B - C) - cache.C[WCoef::C8] * BV::f_89(s_hat))
436 + std::pow(cache.m_c_m_c, 2) / q2 * C_mc;
437}
438
439complex_t BsPhiDecay::A_perp_high(double q2, double sign, bool bar) {
440 complex_t C7 = C7_eff(q2, bar) + (!bar ? std::conj(cache.C[WCoef::CP7]) : cache.C[WCoef::CP7]);
441 complex_t C9 = C9_eff(q2, bar) + (!bar ? std::conj(cache.C[WCoef::CP9]) : cache.C[WCoef::CP9]);
442 complex_t C10 = cache.C[WCoef::C10] + cache.C[WCoef::CP10];
443 if (!bar) C10 = std::conj(C10);
444
445 return N(q2, bar) * (C9 + sign * C10 + 2. * cache.kappa * cache.m_b_m_b * cache.m_Bs / q2 * C7) * cache.ff_calculator.get(BV_FF::F_PERP, q2) * (1. + cache.A_had_err_high[size_t (0.5 * (1 + sign))]);
446}
447
448complex_t BsPhiDecay::A_par_high(double q2, double sign, bool bar) {
449 complex_t C7 = C7_eff(q2, bar) - (!bar ? std::conj(cache.C[WCoef::CP7]) : cache.C[WCoef::CP7]);
450 complex_t C9 = C9_eff(q2, bar) - (!bar ? std::conj(cache.C[WCoef::CP9]) : cache.C[WCoef::CP9]);
451 complex_t C10 = cache.C[WCoef::C10] - cache.C[WCoef::CP10];
452 if (!bar) C10 = std::conj(C10);
453 return -N(q2, bar) * (C9 + sign * C10 + 2. * cache.kappa * cache.m_b_m_b * cache.m_Bs / q2 * C7) * cache.ff_calculator.get(BV_FF::F_PAR, q2) * (1. + cache.A_had_err_high[2 + size_t (0.5 * (1 + sign))]);
454}
455
456complex_t BsPhiDecay::A_0_high(double q2, double sign, bool bar) {
457 complex_t C7 = C7_eff(q2, bar) - (!bar ? std::conj(cache.C[WCoef::CP7]) : cache.C[WCoef::CP7]);
458 complex_t C9 = C9_eff(q2, bar) - (!bar ? std::conj(cache.C[WCoef::CP9]) : cache.C[WCoef::CP9]);
459 complex_t C10 = cache.C[WCoef::C10] - cache.C[WCoef::CP10];
460 if (!bar) C10 = std::conj(C10);
461 return -N(q2, bar) * (C9 + sign * C10 + 2. * cache.kappa * cache.m_b_m_b * cache.m_Bs / q2 * C7) * cache.ff_calculator.get(BV_FF::F_0, q2) * (1. + cache.A_had_err_high[4 + size_t (0.5 * (1 + sign))]);
462}
463
464complex_t BsPhiDecay::A_t_high(double q2, bool bar) {
465 complex_t C10 = cache.C[WCoef::C10] - cache.C[WCoef::CP10];
466 complex_t CQ2 = cache.C[WCoefMapper::cq2_for_lepton_index(static_cast<int>(cfg.gen))] - cache.C[WCoefMapper::cpq2_for_lepton_index(static_cast<int>(cfg.gen))];
467 if (!bar) {
468 C10 = std::conj(C10);
469 CQ2 = std::conj(CQ2);
470 }
471 return N(q2, bar) * sqrt(lambda(q2) / q2) * (2. * C10 + q2 / cache.m_l * CQ2 / (cache.m_b_m_b + cache.m_s)) * cache.ff_calculator.get(BV_FF::A0, q2) * (1. + cache.A_had_err_high[6]);
472}
473
474complex_t BsPhiDecay::A_S_high(double q2, bool bar) {
475 complex_t CQ1 = cache.C[WCoefMapper::cq1_for_lepton_index(static_cast<int>(cfg.gen))] - cache.C[WCoefMapper::cpq1_for_lepton_index(static_cast<int>(cfg.gen))];
476 if (!bar) CQ1 = std::conj(CQ1);
477 return -2. * N(q2, bar) * sqrt(lambda(q2)) * CQ1 / (cache.m_b_m_b + cache.m_s) * cache.ff_calculator.get(BV_FF::A0, q2) * (1. + cache.A_had_err_high[7]);
478}
479
481 if (q2 < cache.q2_low)
482 return val_low;
483
484 if (q2 > cache.q2_high)
485 return val_high;
486
487 double t = (cache.q2_high - q2) / (cache.q2_high - cache.q2_low);
488 return t * val_low + (1 - t) * val_high;
489}
490
491complex_t BsPhiDecay::A_perp(double q2, double sign, bool bar) {
492 return interpolate(q2, A_perp_low(q2, sign, !bar), A_perp_high(q2, sign, !bar));
493}
494
495complex_t BsPhiDecay::A_par(double q2, double sign, bool bar) {
496 return interpolate(q2, A_par_low(q2, sign, !bar), A_par_high(q2, sign, !bar));
497}
498
499complex_t BsPhiDecay::A_0(double q2, double sign, bool bar) {
500 return interpolate(q2, A_0_low(q2, sign, !bar), A_0_high(q2, sign, !bar));
501}
502
503complex_t BsPhiDecay::A_t(double q2, bool bar) {
504 return interpolate(q2, A_t_low(q2, !bar), A_t_high(q2, !bar));
505}
506
507complex_t BsPhiDecay::A_S(double q2, bool bar) {
508 return interpolate(q2, A_S_low(q2, !bar), A_S_high(q2, !bar));
509}
510
511double BsPhiDecay::J1s(double q2, bool bar) {
512 return (2. + std::pow(beta_l(q2), 2)) / 4. * (
513 std::pow(std::abs(A_perp(q2, -1, bar)), 2)
514 + std::pow(std::abs(A_perp(q2, 1, bar)), 2)
515 + std::pow(std::abs(A_par(q2, -1, bar)), 2)
516 + std::pow(std::abs(A_par(q2, 1, bar)), 2)
517 ) + std::pow(2. * cache.m_l, 2) / q2 * std::real(
518 A_perp(q2, -1, bar) * std::conj(A_perp(q2, 1, bar))
519 + A_par(q2, -1, bar) * std::conj(A_par(q2, 1, bar))
520 );
521}
522
523double BsPhiDecay::J1c(double q2, bool bar) {
524 return std::pow(std::abs(A_0(q2, -1, bar)), 2) + std::pow(std::abs(A_0(q2, 1, bar)), 2)
525 + std::pow(2 * cache.m_l, 2) / q2 * (
526 std::pow(std::abs(A_t(q2, bar)), 2)
527 + 2. * std::real(A_0(q2, -1, bar) * std::conj(A_0(q2, 1, bar)))
528 )
529 + std::pow(beta_l(q2) * std::abs(A_S(q2, bar)), 2);
530}
531
532double BsPhiDecay::J2s(double q2, bool bar) {
533 return std::pow(beta_l(q2), 2) / 4. * (
534 std::pow(std::abs(A_perp(q2, -1, bar)), 2)
535 + std::pow(std::abs(A_perp(q2, 1, bar)), 2)
536 + std::pow(std::abs(A_par(q2, -1, bar)), 2)
537 + std::pow(std::abs(A_par(q2, 1, bar)), 2)
538 );
539}
540
541double BsPhiDecay::J2c(double q2, bool bar) {
542 return -std::pow(beta_l(q2), 2) * (
543 std::pow(std::abs(A_0(q2, -1, bar)), 2)
544 + std::pow(std::abs(A_0(q2, 1, bar)), 2)
545 );
546}
547
548double BsPhiDecay::J3(double q2, bool bar) {
549 return std::pow(beta_l(q2), 2) / 2. * (
550 std::pow(std::abs(A_perp(q2, -1, bar)), 2)
551 + std::pow(std::abs(A_perp(q2, 1, bar)), 2)
552 - std::pow(std::abs(A_par(q2, -1, bar)), 2)
553 - std::pow(std::abs(A_par(q2, 1, bar)), 2)
554 );
555}
556
557double BsPhiDecay::J4(double q2, bool bar) {
558 return std::pow(beta_l(q2), 2) / std::sqrt(2.) * (
559 std::real(A_0(q2, -1, bar) * std::conj(A_par(q2, -1, bar)))
560 + std::real(A_0(q2, 1, bar) * std::conj(A_par(q2, 1, bar)))
561 );
562}
563
564double BsPhiDecay::J5(double q2, bool bar) {
565 return beta_l(q2) * std::sqrt(2.) * (
566 std::real(A_0(q2, -1, bar) * std::conj(A_perp(q2, -1, bar)))
567 - std::real(A_0(q2, 1, bar) * std::conj(A_perp(q2, 1, bar)))
568 - cache.m_l / std::sqrt(q2) * std::real((A_par(q2, -1, bar) + A_par(q2, 1, bar)) * std::conj(A_S(q2, bar)))
569 );
570}
571
572double BsPhiDecay::J6s(double q2, bool bar) {
573 return 2. * beta_l(q2) * (
574 std::real(A_par(q2, -1, bar) * std::conj(A_perp(q2, -1, bar)))
575 - std::real(A_par(q2, 1, bar) * std::conj(A_perp(q2, 1, bar)))
576 );
577}
578
579double BsPhiDecay::J6c(double q2, bool bar) {
580 return 4. * beta_l(q2) * cache.m_l / std::sqrt(q2) * (std::real((A_0(q2, -1, bar) + A_0(q2, 1, bar)) * std::conj(A_S(q2, bar))));
581}
582
583double BsPhiDecay::J7(double q2, bool bar) {
584 return beta_l(q2) * std::sqrt(2.) * (
585 std::imag(A_0(q2, -1, bar) * std::conj(A_par(q2, -1, bar)))
586 - std::imag(A_0(q2, 1, bar) * std::conj(A_par(q2, 1, bar)))
587 + cache.m_l / std::sqrt(q2) * std::imag((A_perp(q2, -1, bar) + A_perp(q2, 1, bar)) * std::conj(A_S(q2, bar)))
588 );
589}
590
591double BsPhiDecay::J8(double q2, bool bar) {
592 return std::pow(beta_l(q2), 2) / std::sqrt(2.) * (
593 std::imag(A_0(q2, -1, bar) * std::conj(A_perp(q2, -1, bar)))
594 + std::imag(A_0(q2, 1, bar) * std::conj(A_perp(q2, 1, bar)))
595 );
596}
597
598double BsPhiDecay::J9(double q2, bool bar) {
599 return std::pow(beta_l(q2), 2) * (
600 std::imag(A_perp(q2, -1, bar) * std::conj(A_par(q2, -1, bar)))
601 + std::imag(A_perp(q2, 1, bar) * std::conj(A_par(q2, 1, bar)))
602 );
603}
604
605double BsPhiDecay::h1s(double q2) {
606 complex_t ALperp = A_perp(q2, -1, false);
607 complex_t ARperp = A_perp(q2, 1, false);
608 complex_t ALpar = A_par(q2, -1, false);
609 complex_t ARpar = A_par(q2, 1, false);
610 complex_t ALperp_tilde = -A_perp(q2, -1, true);
611 complex_t ARperp_tilde = -A_perp(q2, 1, true);
612 complex_t ALpar_tilde = A_par(q2, -1, true);
613 complex_t ARpar_tilde = A_par(q2, 1, true);
614 complex_t sh1s_A = cache.up * (ALperp_tilde * std::conj(ALperp) + ALpar_tilde * std::conj(ALpar) + ARperp_tilde * std::conj(ARperp) + ARpar_tilde * std::conj(ARpar));
615 complex_t sh1s_B = cache.up * (ALperp_tilde * std::conj(ARperp) + ALpar_tilde * std::conj(ARpar));
616 complex_t sh1s_C = cache.um * (ALperp * std::conj(ARperp_tilde) + ALpar * std::conj(ARpar_tilde));
617 double x = std::pow(cache.m_l, 2) / q2;
618
619 return (2. + std::pow(beta_l(q2), 2)) / 2. * std::real(sh1s_A) + 4. * x * std::real(sh1s_B + sh1s_C);
620}
621
622double BsPhiDecay::h1c(double q2) {
623 complex_t AL0 = A_0(q2, -1, false);
624 complex_t AR0 = A_0(q2, 1, false);
625 complex_t AL0_tilde = A_0(q2, -1, true);
626 complex_t AR0_tilde = A_0(q2, 1, true);
627 complex_t sh1c_A = cache.up * (AL0_tilde * std::conj(AL0) + AR0_tilde * std::conj(AR0));
628 complex_t sh1c_B = cache.up * A_t(q2, true) * std::conj(A_t(q2, false));
629 complex_t sh1c_C = cache.up * AL0_tilde * std::conj(AR0);
630 complex_t sh1c_D = cache.um * AL0 * std::conj(AR0_tilde);
631 complex_t sh1c_E = cache.up * -A_S(q2, true) * std::conj(A_S(q2, false));
632 double x = std::pow(cache.m_l, 2) / q2;
633
634 return 2. * std::real(sh1c_A) + 8. * x * (std::real(sh1c_B) + std::real(sh1c_C + sh1c_D)) + 2. * std::pow(beta_l(q2), 2) * std::real(sh1c_E);
635}
636
637double BsPhiDecay::h2s(double q2) {
638 complex_t sh1s_A = cache.up * (-A_perp(q2, -1, true) * std::conj(A_perp(q2, -1, false)) + A_par(q2, -1, true) * std::conj(A_par(q2, -1, false)) - A_perp(q2, 1, true) * std::conj(A_perp(q2, 1, false)) + A_par(q2, 1, true) * std::conj(A_par(q2, 1, false)));
639 return std::pow(beta_l(q2), 2) / 2. * std::real(sh1s_A);
640}
641
642double BsPhiDecay::h2c(double q2) {
643 complex_t sh1c_A = cache.up * (A_0(q2, -1, true) * std::conj(A_0(q2, -1, false)) + A_0(q2, 1, true) * std::conj(A_0(q2, 1, false)));
644 return -2. * std::pow(beta_l(q2), 2) * std::real(sh1c_A);
645}
646
647double BsPhiDecay::h3(double q2) {
648 complex_t sh3_A = -cache.up * (A_perp(q2, -1, true) * std::conj(A_perp(q2, -1, false)) + A_par(q2, -1, true) * std::conj(A_par(q2, -1, false)) + A_perp(q2, 1, true) * std::conj(A_perp(q2, 1, false)) + A_par(q2, 1, true) * std::conj(A_par(q2, 1, false)));
649 return std::pow(beta_l(q2), 2) * std::real(sh3_A);
650}
651
652double BsPhiDecay::h4(double q2) {
653 complex_t sh4_A = cache.up * (A_0(q2, -1, true) * std::conj(A_par(q2, -1, false)) + A_0(q2, 1, true) * std::conj(A_par(q2, 1, false)));
654 complex_t sh4_B = cache.um * (A_0(q2, -1, false) * std::conj(A_par(q2, -1, true)) + A_0(q2, 1, false) * std::conj(A_par(q2, 1, true)));
655 return INV_RT2 * std::pow(beta_l(q2), 2) * std::real(sh4_A + sh4_B);
656}
657
658double BsPhiDecay::h5(double q2) {
659 complex_t sh5_A = cache.up * (A_0(q2, -1, true) * std::conj(A_perp(q2, -1, false)) - A_0(q2, 1, true) * std::conj(A_perp(q2, 1, false)));
660 complex_t sh5_B = cache.um * (A_0(q2, -1, false) * std::conj(-A_perp(q2, -1, true)) - A_0(q2, 1, false) * std::conj(A_par(q2, 1, true)));
661 complex_t sh5_C = cache.up * ((A_par(q2, -1, true) + A_par(q2, 1, true)) * std::conj(A_S(q2, false)));
662 complex_t sh5_D = cache.um * ((A_par(q2, -1, false) + A_par(q2, 1, false)) * std::conj(-A_S(q2, true)));
663 return RT2 * beta_l(q2) * (std::real(sh5_A + sh5_B) - cache.m_l / std::sqrt(q2) * std::real(sh5_C + sh5_D));
664}
665
666double BsPhiDecay::h6s(double q2) {
667 complex_t sh6s_A = cache.up * (A_par(q2, -1, true) * std::conj(A_perp(q2, -1, false)) - A_par(q2, 1, true) * std::conj(A_perp(q2, 1, false)));
668 complex_t sh6s_B = cache.um * (A_par(q2, -1, false) * std::conj(-A_perp(q2, -1, true)) - A_par(q2, 1, false) * std::conj(-A_perp(q2, 1, true)));
669 return 2. * beta_l(q2) * std::real(sh6s_A + sh6s_B);
670}
671
672double BsPhiDecay::h6c(double q2) {
673 complex_t sh6c_A = cache.up * ((A_0(q2, -1, true) + A_0(q2, 1, true)) * std::conj(A_S(q2, false)));
674 complex_t sh6c_B = cache.um * ((A_0(q2, -1, false) + A_0(q2, 1, false)) * std::conj(-A_S(q2, true)));
675 return 4. * beta_l(q2) * cache.m_l / std::sqrt(q2) * std::real(sh6c_A + sh6c_B);
676}
677
678double BsPhiDecay::h7(double q2) {
679 complex_t sh7_A = cache.up * (A_0(q2, -1, true) * std::conj(A_par(q2, -1, false)) - A_0(q2, 1, true) * std::conj(A_par(q2, 1, false)));
680 complex_t sh7_B = cache.um * (A_0(q2, -1, false) * std::conj(A_par(q2, -1, true)) - A_0(q2, 1, false) * std::conj(A_par(q2, 1, true)));
681 complex_t sh7_C = cache.up * (-(A_perp(q2, -1, true) + A_perp(q2, 1, true)) * std::conj(A_S(q2, false)));
682 complex_t sh7_D = cache.um * ((A_perp(q2, -1, false) + A_perp(q2, 1, false)) * std::conj(-A_S(q2, true)));
683 return RT2 * beta_l(q2) * (std::imag(sh7_A + sh7_B) + cache.m_l / std::sqrt(q2) * std::imag(sh7_C + sh7_D));
684}
685
686double BsPhiDecay::h8(double q2) {
687 complex_t sh8_A = cache.up * (A_0(q2, -1, true) * std::conj(A_perp(q2, -1, false)) + A_0(q2, 1, true) * std::conj(A_perp(q2, 1, false)));
688 complex_t sh8_B = cache.um * (A_0(q2, -1, false) * std::conj(-A_perp(q2, -1, true)) + A_0(q2, 1, false) * std::conj(-A_perp(q2, 1, true)));
689 return INV_RT2 * std::pow(beta_l(q2), 2) * std::imag(sh8_A + sh8_B);
690}
691
692double BsPhiDecay::h9(double q2) {
693 complex_t sh9_A = cache.up * (A_par(q2, -1, true) * std::conj(A_perp(q2, -1, false)) + A_par(q2, 1, true) * std::conj(A_perp(q2, 1, false)));
694 complex_t sh9_B = cache.um * (A_par(q2, -1, false) * std::conj(-A_perp(q2, -1, true)) + A_par(q2, 1, false) * std::conj(-A_perp(q2, 1, true)));
695 return -std::pow(beta_l(q2), 2) * std::imag(sh9_A + sh9_B);
696}
697
698double BsPhiDecay::s8(double q2) {
699 complex_t sh8_A = cache.up * (A_0(q2, -1, true) * std::conj(A_perp(q2, -1, false)) + A_0(q2, 1, true) * std::conj(A_perp(q2, 1, false)));
700 complex_t sh8_B = cache.um * (A_0(q2, -1, false) * std::conj(-A_perp(q2, -1, true)) + A_0(q2, 1, false) * std::conj(-A_perp(q2, 1, true)));
701 return -1. / sqrt(q2) * std::pow(beta_l(q2), 2) * std::real(sh8_A - sh8_B);
702}
703
704double BsPhiDecay::s9(double q2) {
705 complex_t sh9_A = cache.up * (A_par(q2, -1, true) * std::conj(A_perp(q2, -1, false)) + A_par(q2, 1, true) * std::conj(A_perp(q2, 1, false)));
706 complex_t sh9_B = cache.um * (A_par(q2, -1, false) * std::conj(-A_perp(q2, -1, true)) + A_par(q2, 1, false) * std::conj(-A_perp(q2, 1, true)));
707 return std::pow(beta_l(q2), 2) * std::real(sh9_A - sh9_B);
708}
709
711 static constexpr std::array<double, 24> GL24_X {{
712 -0.99518721999702131, -0.97472855597130947, -0.93827455200273280, -0.88641552700440107,
713 -0.82000198597390295, -0.74012419157855436, -0.64809365193697555, -0.54542147138883956,
714 -0.43379350762604513, -0.31504267969616340, -0.19111886747361631, -0.06405689286260563,
715 0.06405689286260563, 0.19111886747361631, 0.31504267969616340, 0.43379350762604513,
716 0.54542147138883956, 0.64809365193697555, 0.74012419157855436, 0.82000198597390295,
717 0.88641552700440107, 0.93827455200273280, 0.97472855597130947, 0.99518721999702131
718 }};
719 static constexpr std::array<double, 24> GL24_W {{
720 0.01234122979998869, 0.02853138862893356, 0.04427743881741941, 0.05929858491543636,
721 0.07334648141108016, 0.08619016153195321, 0.09761865210411393, 0.10744427011596556,
722 0.11550566805372552, 0.12167047292780329, 0.12583745634682825, 0.12793819534675202,
723 0.12793819534675202, 0.12583745634682825, 0.12167047292780329, 0.11550566805372552,
724 0.10744427011596556, 0.09761865210411393, 0.08619016153195321, 0.07334648141108016,
725 0.05929858491543636, 0.04427743881741941, 0.02853138862893356, 0.01234122979998869
726 }};
727
728 struct AmpSet {
729 complex_t A_perp_L;
730 complex_t A_perp_R;
731 complex_t A_par_L;
732 complex_t A_par_R;
733 complex_t A_0_L;
734 complex_t A_0_R;
735 complex_t A_t;
736 complex_t A_S;
737 double beta;
738 double beta2;
739 double sqrt_q2;
740 };
741
742 struct JSet {
743 double j1s;
744 double j1c;
745 double j2s;
746 double j2c;
747 double j3;
748 double j4;
749 double j5;
750 double j6s;
751 double j6c;
752 double j7;
753 double j8;
754 double j9;
755 };
756
757 auto zero_if_close = [] (double x, double tol) {
758 return std::abs(x) < tol ? 0.0 : x;
759 };
760
761 auto clear_and_reserve = [&] (std::array<std::vector<double>, 15>& dest, size_t nbins) {
762 for (auto& v : dest) {
763 v.clear();
764 v.reserve(nbins);
765 }
766 };
767
768 auto eval_amplitudes = [&] (double q2, bool bar) -> AmpSet {
769 const double beta = beta_l(q2);
770 return {
771 A_perp(q2, -1, bar),
772 A_perp(q2, 1, bar),
773 A_par(q2, -1, bar),
774 A_par(q2, 1, bar),
775 A_0(q2, -1, bar),
776 A_0(q2, 1, bar),
777 A_t(q2, bar),
778 A_S(q2, bar),
779 beta,
780 beta * beta,
781 std::sqrt(q2)
782 };
783 };
784
785 auto eval_J = [&] (const AmpSet& a, double q2) -> JSet {
786 const double sqrt2 = std::sqrt(2.0);
787 const double ml = cache.m_l;
788 const double ml_over_sqrt_q2 = ml / a.sqrt_q2;
789 const double four_ml2_over_q2 = 4.0 * ml * ml / q2;
790
791 const double norm_Aperp_L = std::norm(a.A_perp_L);
792 const double norm_Aperp_R = std::norm(a.A_perp_R);
793 const double norm_Apar_L = std::norm(a.A_par_L);
794 const double norm_Apar_R = std::norm(a.A_par_R);
795 const double norm_A0_L = std::norm(a.A_0_L);
796 const double norm_A0_R = std::norm(a.A_0_R);
797 const double norm_At = std::norm(a.A_t);
798 const double norm_AS = std::norm(a.A_S);
799
800 const complex_t Apar_sum = a.A_par_L + a.A_par_R;
801 const complex_t A0_sum = a.A_0_L + a.A_0_R;
802 const complex_t Aperp_sum = a.A_perp_L + a.A_perp_R;
803
804 JSet j {};
805 j.j1s =
806 (2.0 + a.beta2) / 4.0 * (norm_Aperp_L + norm_Aperp_R + norm_Apar_L + norm_Apar_R)
807 + four_ml2_over_q2 * std::real(a.A_perp_L * std::conj(a.A_perp_R)
808 + a.A_par_L * std::conj(a.A_par_R));
809
810 j.j1c =
811 norm_A0_L + norm_A0_R
812 + four_ml2_over_q2 * (norm_At + 2.0 * std::real(a.A_0_L * std::conj(a.A_0_R)))
813 + a.beta2 * norm_AS;
814
815 j.j2s = a.beta2 / 4.0 * (norm_Aperp_L + norm_Aperp_R + norm_Apar_L + norm_Apar_R);
816 j.j2c = -a.beta2 * (norm_A0_L + norm_A0_R);
817
818 j.j3 = a.beta2 / 2.0 * (norm_Aperp_L + norm_Aperp_R - norm_Apar_L - norm_Apar_R);
819
820 j.j4 = a.beta2 / sqrt2 * (
821 std::real(a.A_0_L * std::conj(a.A_par_L))
822 + std::real(a.A_0_R * std::conj(a.A_par_R))
823 );
824
825 j.j5 = a.beta * sqrt2 * (
826 std::real(a.A_0_L * std::conj(a.A_perp_L))
827 - std::real(a.A_0_R * std::conj(a.A_perp_R))
828 - ml_over_sqrt_q2 * std::real(Apar_sum * std::conj(a.A_S))
829 );
830
831 j.j6s = 2.0 * a.beta * (
832 std::real(a.A_par_L * std::conj(a.A_perp_L))
833 - std::real(a.A_par_R * std::conj(a.A_perp_R))
834 );
835
836 j.j6c = 4.0 * a.beta * ml_over_sqrt_q2 * std::real(A0_sum * std::conj(a.A_S));
837
838 j.j7 = a.beta * sqrt2 * (
839 std::imag(a.A_0_L * std::conj(a.A_par_L))
840 - std::imag(a.A_0_R * std::conj(a.A_par_R))
841 + ml_over_sqrt_q2 * std::imag(Aperp_sum * std::conj(a.A_S))
842 );
843
844 j.j8 = a.beta2 / sqrt2 * (
845 std::imag(a.A_0_L * std::conj(a.A_perp_L))
846 + std::imag(a.A_0_R * std::conj(a.A_perp_R))
847 );
848
849 j.j9 = a.beta2 * (
850 std::imag(a.A_perp_L * std::conj(a.A_par_L))
851 + std::imag(a.A_perp_R * std::conj(a.A_par_R))
852 );
853
854 return j;
855 };
856
857 auto eval_integrands = [&] (double q2) -> std::array<double, 15> {
858 const AmpSet a = eval_amplitudes(q2, false);
859 const AmpSet b = eval_amplitudes(q2, true);
860 const JSet jf = eval_J(a, q2);
861 const JSet jt = eval_J(b, q2);
862
863 const double ml = cache.m_l;
864 const double x = ml * ml / q2;
865 const double beta = a.beta;
866 const double beta2 = a.beta2;
867 const double sqrt_q2 = a.sqrt_q2;
868
869 const complex_t ALperp_tilde = -b.A_perp_L;
870 const complex_t ARperp_tilde = -b.A_perp_R;
871 const complex_t ALpar_tilde = b.A_par_L;
872 const complex_t ARpar_tilde = b.A_par_R;
873 const complex_t AL0_tilde = b.A_0_L;
874 const complex_t AR0_tilde = b.A_0_R;
875 const complex_t At_tilde = b.A_t;
876 const complex_t AS_tilde = -b.A_S;
877
878 const complex_t sh1s_A = cache.up * (ALperp_tilde * std::conj(a.A_perp_L) + ALpar_tilde * std::conj(a.A_par_L)
879 + ARperp_tilde * std::conj(a.A_perp_R) + ARpar_tilde * std::conj(a.A_par_R));
880 const complex_t sh1s_B = cache.up * (ALperp_tilde * std::conj(a.A_perp_R) + ALpar_tilde * std::conj(a.A_par_R));
881 const complex_t sh1s_C = cache.um * (a.A_perp_L * std::conj(ARperp_tilde) + a.A_par_L * std::conj(ARpar_tilde));
882 const double h1s = (2.0 + beta2) / 2.0 * std::real(sh1s_A) + 4.0 * x * std::real(sh1s_B + sh1s_C);
883
884 const complex_t sh1c_A = cache.up * (AL0_tilde * std::conj(a.A_0_L) + AR0_tilde * std::conj(a.A_0_R));
885 const complex_t sh1c_B = cache.up * At_tilde * std::conj(a.A_t);
886 const complex_t sh1c_C = cache.up * AL0_tilde * std::conj(a.A_0_R);
887 const complex_t sh1c_D = cache.um * a.A_0_L * std::conj(AR0_tilde);
888 const complex_t sh1c_E = cache.up * AS_tilde * std::conj(a.A_S);
889 const double h1c = 2.0 * std::real(sh1c_A)
890 + 8.0 * x * (std::real(sh1c_B) + std::real(sh1c_C + sh1c_D))
891 + 2.0 * beta2 * std::real(sh1c_E);
892
893 const complex_t sh2s_A = cache.up * (ALperp_tilde * std::conj(a.A_perp_L) + ALpar_tilde * std::conj(a.A_par_L)
894 + ARperp_tilde * std::conj(a.A_perp_R) + ARpar_tilde * std::conj(a.A_par_R));
895 const double h2s = beta2 / 2.0 * std::real(sh2s_A);
896
897 const complex_t sh2c_A = cache.up * (AL0_tilde * std::conj(a.A_0_L) + AR0_tilde * std::conj(a.A_0_R));
898 const double h2c = -2.0 * beta2 * std::real(sh2c_A);
899
900 const complex_t sh3_A = -cache.up * (b.A_perp_L * std::conj(a.A_perp_L) + b.A_par_L * std::conj(a.A_par_L)
901 + b.A_perp_R * std::conj(a.A_perp_R) + b.A_par_R * std::conj(a.A_par_R));
902 const double h3 = beta2 * std::real(sh3_A);
903
904 const complex_t sh4_A = cache.up * (b.A_0_L * std::conj(a.A_par_L) + b.A_0_R * std::conj(a.A_par_R));
905 const complex_t sh4_B = cache.um * (a.A_0_L * std::conj(b.A_par_L) + a.A_0_R * std::conj(b.A_par_R));
906 const double h4 = INV_RT2 * beta2 * std::real(sh4_A + sh4_B);
907
908 const complex_t sh5_A = cache.up * (b.A_0_L * std::conj(a.A_perp_L) - b.A_0_R * std::conj(a.A_perp_R));
909 const complex_t sh5_B = cache.um * (a.A_0_L * std::conj(-b.A_perp_L) - a.A_0_R * std::conj(b.A_par_R));
910 const complex_t sh5_C = cache.up * ((b.A_par_L + b.A_par_R) * std::conj(a.A_S));
911 const complex_t sh5_D = cache.um * ((a.A_par_L + a.A_par_R) * std::conj(-b.A_S));
912 const double h5 = RT2 * beta * (std::real(sh5_A + sh5_B) - ml / sqrt_q2 * std::real(sh5_C + sh5_D));
913
914 const complex_t sh6s_A = cache.up * (b.A_par_L * std::conj(a.A_perp_L) - b.A_par_R * std::conj(a.A_perp_R));
915 const complex_t sh6s_B = cache.um * (a.A_par_L * std::conj(-b.A_perp_L) - a.A_par_R * std::conj(-b.A_perp_R));
916 const double h6s = 2.0 * beta * std::real(sh6s_A + sh6s_B);
917
918 const complex_t sh6c_A = cache.up * ((b.A_0_L + b.A_0_R) * std::conj(a.A_S));
919 const complex_t sh6c_B = cache.um * ((a.A_0_L + a.A_0_R) * std::conj(-b.A_S));
920 const double h6c = 4.0 * beta * ml / sqrt_q2 * std::real(sh6c_A + sh6c_B);
921
922 const complex_t sh7_A = cache.up * (b.A_0_L * std::conj(a.A_par_L) - b.A_0_R * std::conj(a.A_par_R));
923 const complex_t sh7_B = cache.um * (a.A_0_L * std::conj(b.A_par_L) - a.A_0_R * std::conj(b.A_par_R));
924 const complex_t sh7_C = cache.up * (-(b.A_perp_L + b.A_perp_R) * std::conj(a.A_S));
925 const complex_t sh7_D = cache.um * ((a.A_perp_L + a.A_perp_R) * std::conj(-b.A_S));
926 const double h7 = RT2 * beta * (std::imag(sh7_A + sh7_B) + ml / sqrt_q2 * std::imag(sh7_C + sh7_D));
927
928 const complex_t sh8_A = cache.up * (b.A_0_L * std::conj(a.A_perp_L) + b.A_0_R * std::conj(a.A_perp_R));
929 const complex_t sh8_B = cache.um * (a.A_0_L * std::conj(-b.A_perp_L) + a.A_0_R * std::conj(-b.A_perp_R));
930 const double h8 = INV_RT2 * beta2 * std::imag(sh8_A + sh8_B);
931
932 const complex_t sh9_A = cache.up * (b.A_par_L * std::conj(a.A_perp_L) + b.A_par_R * std::conj(a.A_perp_R));
933 const complex_t sh9_B = cache.um * (a.A_par_L * std::conj(-b.A_perp_L) + a.A_par_R * std::conj(-b.A_perp_R));
934 const double h9 = -beta2 * std::imag(sh9_A + sh9_B);
935
936 const double s8v = -beta2 / sqrt_q2 * std::real(sh8_A - sh8_B);
937 const double s9v = beta2 * std::real(sh9_A - sh9_B);
938
939 const double val6 = zero_if_close(jf.j5 - jt.j5 - cache.ys * h5, 1e-30);
940 const double val7 = zero_if_close(jf.j6s - jt.j6s - cache.ys * h6s, 1e-30);
941 const double val9 = zero_if_close(jf.j6c - jt.j6c - cache.ys * h6c, 1e-30);
942 const double val11 = zero_if_close(jf.j8 - jt.j8 - cache.ys * h8, 1e-30);
943 const double val12 = zero_if_close(jf.j9 - jt.j9 - cache.ys * h9, 1e-30);
944
945 return {{
946 2.0 * (jf.j1s - cache.ys * h1s / 2.0) + jf.j1c - cache.ys * h1c / 2.0
947 - (2.0 * (jf.j2s - cache.ys * h2s / 2.0) + jf.j2c - cache.ys * h2c / 2.0) / 3.0,
948 2.0 * (jt.j1s - cache.ys * h1s / 2.0) + jt.j1c - cache.ys * h1c / 2.0
949 - (2.0 * (jt.j2s - cache.ys * h2s / 2.0) + jt.j2c - cache.ys * h2c / 2.0) / 3.0,
950 jt.j2s + jf.j2s - cache.ys * h2s,
951 jt.j2c + jf.j2c - cache.ys * h2c,
952 jt.j3 + jf.j3 - cache.ys * h3,
953 jt.j4 + jf.j4 - cache.ys * h4,
954 val6,
955 val7,
956 beta * val7,
957 val9,
958 jt.j7 + jf.j7 - cache.ys * h7,
959 val11,
960 val12,
961 s8v,
962 s9v
963 }};
964 };
965
966 auto integrate_bin = [&] (double q2_l, double q2_u) -> std::array<double, 15> {
967 std::array<double, 15> acc {};
968 const double center = 0.5 * (q2_l + q2_u);
969 const double half_width = 0.5 * (q2_u - q2_l);
970
971 for (size_t i = 0; i < GL24_X.size(); ++i) {
972 const double q2 = center + half_width * GL24_X[i];
973 const auto vals = eval_integrands(q2);
974 for (size_t k = 0; k < acc.size(); ++k) {
975 acc[k] += GL24_W[i] * vals[k];
976 }
977 }
978
979 for (double& v : acc) {
980 v *= half_width;
981 }
982
983 return acc;
984 };
985
986 const double endpoint_eps = 1e-5;
987 const double low_q2_eps = 1e-7;
988
989 const auto& bins = this->bins.value();
990 const size_t nbins = bins.size();
991 clear_and_reserve(cache.f_J_i_binned, nbins);
992 cache.bin_widths.clear();
993 cache.bin_widths.reserve(nbins);
994
995 for (const auto& [q2_l_raw, q2_u_raw] : bins) {
996 const double q2_l = std::max(q2_l_raw, cache.q2_min + low_q2_eps);
997 const double q2_u = std::min(q2_u_raw, cache.q2_max - endpoint_eps);
998
999 if (!(q2_l < q2_u)) {
1000 LOG_WARN(
1001 "Skipping invalid BsPhi bin [",
1002 q2_l_raw,
1003 ",",
1004 q2_u_raw,
1005 "] clipped to [",
1006 q2_l,
1007 ",",
1008 q2_u,
1009 "]"
1010 );
1011
1012 for (auto& v : cache.f_J_i_binned) {
1013 v.emplace_back(std::numeric_limits<double>::quiet_NaN());
1014 }
1015 cache.bin_widths.emplace_back(std::numeric_limits<double>::quiet_NaN());
1016 continue;
1017 }
1018
1019 const double width = q2_u - q2_l;
1020 const auto integ = integrate_bin(q2_l, q2_u);
1021
1022 cache.bin_widths.emplace_back(width);
1023
1024 for (size_t k = 0; k < cache.f_J_i_binned.size(); ++k) {
1025 cache.f_J_i_binned[k].emplace_back(integ[k]);
1026 }
1027 }
1028}
1029
1030std::vector<ObservableValue> BsPhiDecay::dBR_dq2_binned(bool bar, Observables id, bool br) {
1031 std::vector<ObservableValue> out;
1032 size_t idx = bar ? 1 : 0;
1033 const auto& bins = this->bins.value();
1034 const double br_factor = br ? cache.life_Bs : 1.0;
1035
1036 for (size_t i = 0; i < bins.size(); i++) {
1037 const double requested_width = bins[i].second - bins[i].first;
1038 const double width =
1039 (i < cache.bin_widths.size() && std::isfinite(cache.bin_widths[i]) && cache.bin_widths[i] > 0.0)
1040 ? cache.bin_widths[i]
1041 : requested_width;
1042
1043 const double integrated_rate =
1044 0.75 * cache.f_J_i_binned[idx][i] / (1.0 - cache.ys * cache.ys);
1045
1046 const double res =
1047 (std::isfinite(width) && width > 0.0)
1048 ? integrated_rate * br_factor / width
1049 : std::numeric_limits<double>::quiet_NaN();
1050
1051 out.emplace_back(ObservableMapper::to_id(id), res, bins[i]);
1052 }
1053
1054 return out;
1055}
1056
1057double BsPhiDecay::dG_dq2_avg_bin(size_t bin) {
1058 return 0.75 * (cache.f_J_i_binned[0][bin] + cache.f_J_i_binned[1][bin]);
1059}
1060
1061static double safe_ratio(double num, double den, const char* name) {
1062 if (!std::isfinite(num) || !std::isfinite(den) || std::abs(den) < 1e-30) {
1063 LOG_WARN(
1064 "Non-finite or singular denominator in",
1065 name,
1066 ": num =",
1067 num,
1068 "den =",
1069 den
1070 );
1071 return std::numeric_limits<double>::quiet_NaN();
1072 }
1073
1074 return num / den;
1075}
1076
1077std::vector<ObservableValue> BsPhiDecay::F_L(Observables id) {
1078 std::vector<ObservableValue> out;
1079
1080 for (size_t i = 0; i < this->bins.value().size(); i++) {
1081 const double res = safe_ratio(
1082 -cache.f_J_i_binned[3][i],
1083 dG_dq2_avg_bin(i),
1084 "BsPhi F_L"
1085 );
1086
1087 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1088 }
1089
1090 return out;
1091}
1092
1093std::vector<ObservableValue> BsPhiDecay::A_T_2(Observables id) {
1094 std::vector<ObservableValue> out;
1095
1096 for (size_t i = 0; i < this->bins.value().size(); i++) {
1097 const double res = safe_ratio(
1098 0.5 * cache.f_J_i_binned[4][i],
1099 cache.f_J_i_binned[2][i],
1100 "BsPhi A_T_2"
1101 );
1102
1103 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1104 }
1105
1106 return out;
1107}
1108
1109std::vector<ObservableValue> BsPhiDecay::A_T_Re_CPV(Observables id) {
1110 std::vector<ObservableValue> out;
1111 for (size_t i = 0; i < this->bins.value().size(); i++) {
1112 double res = 0.25 * cache.f_J_i_binned[8][i] / cache.f_J_i_binned[2][i];
1113 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1114 }
1115 return out;
1116}
1117
1118std::vector<ObservableValue> BsPhiDecay::A_T_Im_CPV(Observables id) {
1119 std::vector<ObservableValue> out;
1120 for (size_t i = 0; i < this->bins.value().size(); i++) {
1121 double res = 0.5 * cache.f_J_i_binned[12][i] / cache.f_J_i_binned[2][i];
1122 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1123 }
1124 return out;
1125}
1126
1127std::vector<ObservableValue> BsPhiDecay::Pp_4(Observables id) {
1128 std::vector<ObservableValue> out;
1129 for (size_t i = 0; i < this->bins.value().size(); i++) {
1130 double res = cache.f_J_i_binned[5][i] / std::sqrt(std::abs(cache.f_J_i_binned[2][i] * cache.f_J_i_binned[3][i]));
1131 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1132 }
1133 return out;
1134}
1135
1136std::vector<ObservableValue> BsPhiDecay::Pp_6(Observables id) {
1137 std::vector<ObservableValue> out;
1138 for (size_t i = 0; i < this->bins.value().size(); i++) {
1139 double res = -0.5 * cache.f_J_i_binned[10][i] / std::sqrt(std::abs(cache.f_J_i_binned[2][i] * cache.f_J_i_binned[3][i]));
1140 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1141 }
1142 return out;
1143}
1144
1145std::vector<ObservableValue> BsPhiDecay::S_i(int i, Observables id) {
1146 if (!(i == 2 || i == 3 || i == 4 || i == 7)) LOG_ERROR("Value Error", "S_i(Bs > phi ll) is not defined for i =", i);
1147
1148 std::map<size_t, size_t> J_idx = {{2, 2}, {3, 4}, {4, 5}, {7, 10}};
1149
1150 std::vector<ObservableValue> out;
1151 for (size_t j = 0; j < this->bins.value().size(); j++) {
1152 double res = cache.f_J_i_binned[J_idx[i]][j] / dG_dq2_avg_bin(j);
1153 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[j]);
1154 }
1155 return out;
1156}
1157
1158std::vector<ObservableValue> BsPhiDecay::A_i(int i, Observables id) {
1159 if (!(i == 5 || i == 6 || i == 8 || i == 9)) LOG_ERROR("Value Error", "A_i(Bs > phi ll) is not defined for i =", i);
1160
1161 std::map<size_t, size_t> J_idx = {{5, 6}, {6, 9}, {8, 11}, {9, 12}};
1162 double sign = i == 6 ? -1 : 1;
1163
1164 std::vector<ObservableValue> out;
1165 for (size_t j = 0; j < this->bins.value().size(); j++) {
1166 double res = sign * cache.f_J_i_binned[J_idx[i]][j] / dG_dq2_avg_bin(j);
1167 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[j]);
1168 }
1169 return out;
1170}
1171
1172std::vector<ObservableValue> BsPhiDecay::A_FB_CPV(Observables id) {
1173 std::vector<ObservableValue> out;
1174 for (size_t i = 0; i < this->bins.value().size(); i++) {
1175 double res = -0.375 * (2 * cache.f_J_i_binned[7][i] + cache.f_J_i_binned[9][i]) / dG_dq2_avg_bin(i);
1176 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1177 }
1178 return out;
1179}
1180
1181std::vector<ObservableValue> BsPhiDecay::P_2_CPV(Observables id) {
1182 std::vector<ObservableValue> out;
1183 for (size_t i = 0; i < this->bins.value().size(); i++) {
1184 double res = 0.125 * cache.f_J_i_binned[7][i] / cache.f_J_i_binned[2][i];
1185 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1186 }
1187 return out;
1188}
1189
1190std::vector<ObservableValue> BsPhiDecay::P_3_CPV(Observables id) {
1191 std::vector<ObservableValue> out;
1192 for (size_t i = 0; i < this->bins.value().size(); i++) {
1193 double res = -0.25 * cache.f_J_i_binned[12][i] / cache.f_J_i_binned[2][i];
1194 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1195 }
1196 return out;
1197}
1198
1199std::vector<ObservableValue> BsPhiDecay::Pp_5_CPV(Observables id) {
1200 std::vector<ObservableValue> out;
1201 for (size_t i = 0; i < this->bins.value().size(); i++) {
1202 double res = 0.5 * cache.f_J_i_binned[6][i] / std::sqrt(std::abs(cache.f_J_i_binned[2][i] * cache.f_J_i_binned[3][i]));
1203 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1204 }
1205 return out;
1206}
1207
1208std::vector<ObservableValue> BsPhiDecay::Pp_8_CPV(Observables id) {
1209 std::vector<ObservableValue> out;
1210 for (size_t i = 0; i < this->bins.value().size(); i++) {
1211 double res = -cache.f_J_i_binned[11][i] / std::sqrt(std::abs(cache.f_J_i_binned[2][i] * cache.f_J_i_binned[3][i]));
1212 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1213 }
1214 return out;
1215}
1216
1217std::vector<ObservableValue> BsPhiDecay::Q_8_m(Observables id) {
1218 std::vector<ObservableValue> out;
1219 for (size_t i = 0; i < this->bins.value().size(); i++) {
1220 double res = cache.f_J_i_binned[13][i] / std::sqrt(std::abs(2 * cache.f_J_i_binned[3][i] * (cache.f_J_i_binned[2][i] - cache.f_J_i_binned[4][i])));
1221 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1222 }
1223 return out;
1224}
1225
1226std::vector<ObservableValue> BsPhiDecay::Q_8_p(Observables id) {
1227 std::vector<ObservableValue> out;
1228 for (size_t i = 0; i < this->bins.value().size(); i++) {
1229 double res = cache.f_J_i_binned[13][i] / std::sqrt(std::abs(2 * cache.f_J_i_binned[3][i] * (cache.f_J_i_binned[2][i] + cache.f_J_i_binned[4][i])));
1230 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1231 }
1232 return out;
1233}
1234
1235std::vector<ObservableValue> BsPhiDecay::Q_9(Observables id) {
1236 std::vector<ObservableValue> out;
1237 for (size_t i = 0; i < this->bins.value().size(); i++) {
1238 double res = 0.5 * cache.f_J_i_binned[14][i] / cache.f_J_i_binned[2][i];
1239 out.emplace_back(ObservableMapper::to_id(id), res, this->bins.value()[i]);
1240 }
1241 return out;
1242}
1243
1244std::vector<ObservableValue> BsPhiDecay::Rm1_BsPhi(Observables id) {
1245 std::vector<ObservableValue> out;
1246 std::vector<double> Gamma_mu;
1247 std::vector<double> Gamma_e;
1248
1250
1251 for (size_t i = 0; i < this->bins.value().size(); i++)
1252 Gamma_mu.emplace_back(dG_dq2_avg_bin(i));
1253
1255
1256 for (size_t i = 0; i < this->bins.value().size(); i++)
1257 Gamma_e.emplace_back(dG_dq2_avg_bin(i));
1258
1259 for (size_t i = 0; i < this->bins.value().size(); i++)
1260 out.emplace_back(ObservableMapper::to_id(id), Gamma_mu[i] / Gamma_e[i] - 1, this->bins.value()[i]);
1261
1262 return out;
1263}
1264
1265std::vector<ObservableValue> BsPhiDecay::compute_observable(Observables obs) {
1266 switch (obs) {
1269 return dBR_dq2_binned(false, obs, false);
1272 return dBR_dq2_binned(false, obs);
1275 return F_L(obs);
1278 return A_T_2(obs);
1281 return A_T_Re_CPV(obs);
1284 return A_T_Im_CPV(obs);
1287 return Pp_4(obs);
1290 return Pp_6(obs);
1293 return S_i(2, obs);
1296 return S_i(3, obs);
1299 return S_i(4, obs);
1302 return S_i(7, obs);
1305 return A_i(5, obs);
1308 return A_i(6, obs);
1311 return A_i(8, obs);
1314 return A_i(9, obs);
1317 return A_FB_CPV(obs);
1320 return P_2_CPV(obs);
1323 return P_3_CPV(obs);
1326 return Pp_5_CPV(obs);
1329 return Pp_8_CPV(obs);
1332 return Q_8_m(obs);
1335 return Q_8_p(obs);
1338 return Q_9(obs);
1341 return dBR_dq2_binned(false, obs, false);
1344 return dBR_dq2_binned(false, obs);
1347 return F_L(obs);
1350 return A_T_2(obs);
1353 return A_T_Re_CPV(obs);
1356 return A_T_Im_CPV(obs);
1359 return Pp_4(obs);
1362 return Pp_6(obs);
1365 return S_i(2, obs);
1368 return S_i(3, obs);
1371 return S_i(4, obs);
1374 return S_i(7, obs);
1377 return A_i(5, obs);
1380 return A_i(6, obs);
1383 return A_i(8, obs);
1386 return A_i(9, obs);
1389 return A_FB_CPV(obs);
1392 return P_2_CPV(obs);
1395 return P_3_CPV(obs);
1398 return Pp_5_CPV(obs);
1401 return Pp_8_CPV(obs);
1404 return Q_8_m(obs);
1407 return Q_8_p(obs);
1410 return Q_9(obs);
1413 return dBR_dq2_binned(false, obs, false);
1416 return dBR_dq2_binned(false, obs);
1419 return F_L(obs);
1422 return A_T_2(obs);
1425 return A_T_Re_CPV(obs);
1428 return A_T_Im_CPV(obs);
1431 return Pp_4(obs);
1434 return Pp_6(obs);
1437 return S_i(2, obs);
1440 return S_i(3, obs);
1443 return S_i(4, obs);
1446 return S_i(7, obs);
1449 return A_i(5, obs);
1452 return A_i(6, obs);
1455 return A_i(8, obs);
1458 return A_i(9, obs);
1461 return A_FB_CPV(obs);
1464 return P_2_CPV(obs);
1467 return P_3_CPV(obs);
1470 return Pp_5_CPV(obs);
1473 return Pp_8_CPV(obs);
1476 return Q_8_m(obs);
1479 return Q_8_p(obs);
1482 return Q_9(obs);
1484 return Rm1_BsPhi(obs);
1485 default:
1486 LOG_ERROR("IndexError", "Observable", ObservableMapper::str(obs), "doesn't belong to the decay", DecayMapper::str(this->id));
1487 }
1488}
1489
1490std::vector<ObservableValue> BsPhiDecay::compute_observable(ObservableId obs) {
1491 return compute_observable(ObservableMapper::enum_of(obs).value());
1492}
1493
1494void BsPhiDecay::set_n_threads(size_t n_threads) {
1495 unsigned int available_threads = std::thread::hardware_concurrency();
1496
1497 if (available_threads == 0) {
1498 available_threads = 1;
1499 }
1500
1501 if (n_threads == 0) {
1502 this->cfg.n_threads = available_threads;
1503 return;
1504 }
1505
1506 if (n_threads > available_threads) {
1507 LOG_WARN(
1508 "Requested", n_threads,
1509 "threads, but only", available_threads,
1510 "are available. Using", available_threads,
1511 "threads instead."
1512 );
1513
1514 this->cfg.n_threads = available_threads;
1515 return;
1516 }
1517
1518 this->cfg.n_threads = std::max<size_t>(1, n_threads);
1519}
Observables
Definition GeneralEnum.h:4
@ P_PRIME_8_CPV_BS_PHI_MU_MU
@ P_PRIME_8_CPV_BS_PHI_E_E
@ A_T_RE_CPV_BS_PHI_MU_MU
@ A_T_2_BS_PHI_TAU_TAU
@ P_PRIME_5_CPV_BS_PHI_TAU_TAU
@ A_T_IM_CPV_BS_PHI_MU_MU
@ DGAMMA_DQ2_BS__PHI_TAU_TAU
@ P_3_CPV_BS_PHI_TAU_TAU
@ P_PRIME_6_BS_PHI_MU_MU
@ P_PRIME_5_CPV_BS_PHI_E_E
@ P_PRIME_6_BS_PHI_TAU_TAU
@ A_FB_CPV_BS__PHI_MU_MU
@ A_FB_CPV_BS__PHI_E_E
@ P_PRIME_5_CPV_BS_PHI_MU_MU
@ DGAMMA_DQ2_BS__PHI_E_E
@ P_PRIME_8_CPV_BS_PHI_TAU_TAU
@ DBR_DQ2_BS__PHI_TAU_TAU
@ P_2_CPV_BS_PHI_MU_MU
@ P_PRIME_4_BS_PHI_E_E
@ P_PRIME_4_BS_PHI_MU_MU
@ A_FB_CPV_BS__PHI_TAU_TAU
@ DBR_DQ2_BS__PHI_MU_MU
@ P_PRIME_6_BS_PHI_E_E
@ A_T_IM_CPV_BS_PHI_TAU_TAU
@ A_T_RE_CPV_BS_PHI_E_E
@ P_3_CPV_BS_PHI_MU_MU
@ DGAMMA_DQ2_BS__PHI_MU_MU
@ P_PRIME_4_BS_PHI_TAU_TAU
@ A_T_IM_CPV_BS_PHI_E_E
@ A_T_RE_CPV_BS_PHI_TAU_TAU
@ P_2_CPV_BS_PHI_TAU_TAU
#define LOG_ERROR(type,...)
Macro for logging error messages and terminating the application.
Definition Logger.h:41
#define LOG_WARN(...)
Macro for logging warning messages.
Definition Logger.h:40
void fill_cache(Func &&f, double a, double b, std::array< T, cache_size > &cache, Args &&... args)
Fills a lookup cache for a function on a finite interval [a, b].
Definition Utils.h:241
std::complex< double > complex_t
Convenience alias for std::complex<double>.
Definition Utils.h:35
T lerp(U x, const std::array< T, cache_size > &lookup, double a=0.0, double b=1.0)
Linearly interpolates a cached function on [a, b].
Definition Utils.h:276
double get(BV_FF a, double q2) override
double E(double q2)
complex_t T_par_m(double q2, bool bar)
complex_t T_perp_m(double q2, bool bar)
complex_t T_perp_p(double q2, bool bar)
complex_t Delta_par(double q2)
complex_t Y(double q2)
complex_t interpolate(double q2, complex_t val_low, complex_t val_high)
complex_t A_par_low(double q2, double sign, bool bar)
std::vector< ObservableValue > Pp_4(Observables id)
void compute_binned_J_i()
complex_t A_t_low(double q2, bool bar)
double J8(double q2, bool bar)
double h1s(double q2)
double h5(double q2)
complex_t A_S_low(double q2, bool bar)
std::vector< ObservableValue > F_L(Observables id)
complex_t A_0_low(double q2, double sign, bool bar)
double lambda(double q2)
std::vector< ObservableValue > Pp_5_CPV(Observables id)
complex_t delta_A_0(double q2, double sign, bool bar)
complex_t T_par_m_cached(double q2, bool bar)
complex_t A_t(double q2, bool bar)
std::vector< ObservableValue > A_T_Re_CPV(Observables id)
std::vector< ObservableValue > A_T_Im_CPV(Observables id)
double h2c(double q2)
double beta_l(double q2)
complex_t A_S_high(double q2, bool bar)
std::vector< ObservableValue > compute_observable(Observables obs) override
Compute an observable given a public observable enum.
complex_t T_perp_m_cached(double q2, bool bar)
void load_params() override
Load and cache parameters needed by this decay.
std::vector< ObservableValue > Q_8_m(Observables id)
std::vector< ObservableValue > A_T_2(Observables id)
std::vector< ObservableValue > Q_9(Observables id)
double J6c(double q2, bool bar)
double h1c(double q2)
std::vector< ObservableValue > S_i(int i, Observables id)
std::vector< ObservableValue > P_2_CPV(Observables id)
complex_t A_0_high(double q2, double sign, bool bar)
std::vector< ObservableValue > A_FB_CPV(Observables id)
double J6s(double q2, bool bar)
void load_cfg_dep_params()
double dG_dq2_avg_bin(size_t bin)
double h2s(double q2)
double J1c(double q2, bool bar)
double J4(double q2, bool bar)
complex_t delta_A_perp(double q2, double sign, bool bar)
void fill_wilson_cache()
double h9(double q2)
std::vector< ObservableValue > Pp_6(Observables id)
double J2c(double q2, bool bar)
complex_t A_perp(double q2, double sign, bool bar)
void set_n_threads(size_t n_threads) override
Set the number of worker threads used by decays that support parallel cache filling.
std::vector< ObservableValue > dBR_dq2_binned(bool bar, Observables id, bool br=true)
complex_t A_S(double q2, bool bar)
complex_t A_perp_high(double q2, double sign, bool bar)
double h7(double q2)
complex_t delta_A_par(double q2, double sign, bool bar)
complex_t A_par(double q2, double sign, bool bar)
double h3(double q2)
double J1s(double q2, bool bar)
std::vector< ObservableValue > Pp_8_CPV(Observables id)
complex_t C9_eff(double q2, bool bar)
double J7(double q2, bool bar)
void set_cfg_flags(BsPhiConfig::Lepton gen)
complex_t A_perp_low(double q2, double sign, bool bar)
complex_t A_par_high(double q2, double sign, bool bar)
complex_t C7_eff(double q2, bool bar)
double s8(double q2)
double J3(double q2, bool bar)
complex_t A_t_high(double q2, bool bar)
complex_t T_perp_p_cached(double q2, bool bar)
double h6s(double q2)
double h4(double q2)
double J5(double q2, bool bar)
double s9(double q2)
std::vector< ObservableValue > Rm1_BsPhi(Observables id)
complex_t A_0(double q2, double sign, bool bar)
std::vector< ObservableValue > P_3_CPV(Observables id)
double J9(double q2, bool bar)
complex_t N(double q2, bool bar)
double J2s(double q2, bool bar)
std::vector< ObservableValue > Q_8_p(Observables id)
std::vector< ObservableValue > A_i(int i, Observables id)
double h8(double q2)
double h6c(double q2)
Definition BWilson.h:149
Definition BWilson.h:99
Definition BWilson.h:133
DecayId id
Unique decay identifier.
WilsonBuildConfig w_config
Wilson build configuration used when enabling this decay (scales, order, groups).
std::optional< std::vector< std::pair< double, double > > > bins
Optional q^2 bins.
std::shared_ptr< IObsParameterProxy< ParamId, DataType, std::string, LhaID > > p
Parameter proxy for SM-like quantities used by the decay (may be SM/BSM depending on wiring).
std::shared_ptr< IObsWilsonProxy > w_proxy
Wilson proxy used at compute-time to query coefficients (matching/run).
Definition DecayParent.h:99
std::shared_ptr< IObsQCDProxy > iobs_qcdp
QCD proxy (alpha_s, running masses, constants...).
static std::optional< Observables > enum_of(const IdOf< ObservableTag > &id)
Attempts to recover the enum value associated with an identifier.
static IdOf< ObservableTag > to_id(Observables e)
Converts an enum value to an IdOf<Tag>.
static std::string str(const IdOf< ObservableTag > &id)
Returns the string representation of an identifier.
static WCoef cpq1_for_lepton_index(int lepton_index)
static WCoef cq1_for_lepton_index(int lepton_index)
static WCoef cq2_for_lepton_index(int lepton_index)
static WCoef cpq2_for_lepton_index(int lepton_index)
constexpr double PI
Definition constants.h:7
constexpr double HBAR
Definition constants.h:23
constexpr std::complex< double > I
Definition constants.h:20
constexpr double INV_RT2
Definition constants.h:16
constexpr double RT2
Definition constants.h:15
complex_t h(double s, double m_q, double mu_b)
complex_t B_Seidel(double s_hat, double L_b)
complex_t C_Seidel(double s, double mu_b)
complex_t f_87(double s_hat, double L_b)
complex_t A_Seidel(double s_hat, double L_b)
complex_t f_89(double s_hat)
double f(double x)
Wilson special function f depending on x.
Configuration for evaluating the strong coupling constant .
Definition Configs.h:206
B_FF_Type ff_type
Definition BsPhiDecay.h:18
Lepton gen
Definition BsPhiDecay.h:19
size_t n_threads
Definition BsPhiDecay.h:21
BV_FF_Src ff_src
Definition BsPhiDecay.h:17
complex_t up
Definition BsPhiDecay.h:42
std::array< scalar_t, LOOKUP_SIZE > T_par_m_lookup
Definition BsPhiDecay.h:55
std::array< std::vector< double >, 15 > f_J_i_binned
Definition BsPhiDecay.h:60
std::array< scalar_t, LOOKUP_SIZE > T_perp_p_lookup
Definition BsPhiDecay.h:53
complex_t N_0
Definition BsPhiDecay.h:38
complex_t lambda_hat_u
Definition BsPhiDecay.h:35
std::array< scalar_t, LOOKUP_SIZE > T_perp_p_bar_lookup
Definition BsPhiDecay.h:56
BVQCDfCalculator qcdf_calculator
Definition BsPhiDecay.h:27
std::array< scalar_t, LOOKUP_SIZE > T_perp_m_bar_lookup
Definition BsPhiDecay.h:57
std::vector< double > bin_widths
Definition BsPhiDecay.h:61
std::array< complex_t, 6 > A_had_err_low_1
Definition BsPhiDecay.h:48
std::map< WCoef, complex_t > C
Definition BsPhiDecay.h:25
double alpha_s_mu_b
Definition BsPhiDecay.h:32
double q2_lookup_min
Definition BsPhiDecay.h:44
complex_t um
Definition BsPhiDecay.h:42
std::array< complex_t, 8 > A_had_err_high
Definition BsPhiDecay.h:49
std::array< scalar_t, LOOKUP_SIZE > T_perp_m_lookup
Definition BsPhiDecay.h:54
std::array< scalar_t, LOOKUP_SIZE > T_par_m_bar_lookup
Definition BsPhiDecay.h:58
std::array< complex_t, 6 > A_had_err_low_0
Definition BsPhiDecay.h:47
static constexpr size_t LOOKUP_SIZE
Definition BsPhiDecay.h:52
BVFFCalculator ff_calculator
Definition BsPhiDecay.h:26
Configuration for computing a particle mass at a given scale.
Definition Configs.h:242
Composite identifier for a single parameter.
Definition ParamID.h:57
QCDOrder order
Perturbative QCD order used for the evolution and matching of Wilson coefficients....
Definition Configs.h:54