13static double finite_or_nan(
double x) {
14 return std::isfinite(x) ? x : std::numeric_limits<double>::quiet_NaN();
17static double safe_div(
double num,
double den,
const char* name) {
18 if (!std::isfinite(num) || !std::isfinite(den) || std::abs(den) < 1e-30) {
19 LOG_WARN(name,
"non-finite/singular ratio: num =", num,
"den =", den);
20 return std::numeric_limits<double>::quiet_NaN();
38 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)) * mu_f / (3 *
PI);
47 for (
size_t i = 0; i < 6; i++) {
54 for (
size_t i = 0; i < 8; i++) {
69 for (
const auto& [coef, val] : b_wilsons) {
72 for (
const auto& [coef, val] : bq_wilsons) {
76 for (
const auto& [coef, val] : bp_wilsons) {
82 const int B_id = cfg.
charge == Charge::B_0 ? 511 : 521;
83 const int V_id = cfg.
charge == Charge::B_0 ? 313 : 323;
107 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_B, 3)));
108 cache.
q2_min = 4 * std::pow(cache.
m_l, 2);
114 if (requested_threads == 0u) {
115 requested_threads = std::thread::hardware_concurrency();
117 if (requested_threads == 0u) {
118 requested_threads = 1u;
122 const size_t nworkers = std::min<size_t>(requested_threads, npts);
124 if (nworkers <= 1u) {
125 auto lam_T_perp_p = [
this] (
double q2,
bool bar) {
132 auto lam_T_perp_m = [
this] (
double q2,
bool bar) {
139 auto lam_T_par_m = [
this] (
double q2,
bool bar) {
147 const double x_max = cache.
q2_high;
148 const double step = (x_max - x_min) /
static_cast<double>(npts - 1);
150 std::vector<std::shared_ptr<BVQCDfCalculator>> qcdf_locals;
151 qcdf_locals.reserve(nworkers);
152 for (
size_t w = 0; w < nworkers; ++w) {
153 auto ff_local = std::make_shared<BVFFCalculator>(cache.
ff_calculator);
154 qcdf_locals.emplace_back(std::make_shared<BVQCDfCalculator>(
166 std::vector<std::thread> workers;
167 workers.reserve(nworkers);
169 std::exception_ptr first_exception =
nullptr;
170 std::mutex exception_mutex;
172 auto worker = [&] (
size_t worker_id,
size_t begin,
size_t end) {
175 for (
size_t i = begin; i < end; ++i) {
176 const double q2 = x_min + step *
static_cast<double>(i);
188 std::lock_guard<std::mutex> lock(exception_mutex);
189 if (!first_exception) {
190 first_exception = std::current_exception();
195 const size_t chunk = (npts + nworkers - 1) / nworkers;
196 for (
size_t w = 0; w < nworkers; ++w) {
197 const size_t begin = w * chunk;
198 const size_t end = std::min(npts, begin + chunk);
202 workers.emplace_back(worker, w, begin, end);
205 for (
auto& th : workers) {
209 if (first_exception) {
210 std::rethrow_exception(first_exception);
219 cache.
tp_nf = 4. * std::pow(m_D0, 2);
225 for (
size_t i = 0; i < 3; i++) {
237 for (
size_t i = 0; i < 2; i++) {
249 for (
size_t i = 0; i < 3; i++) {
262 bool changed = cfg.
gen != gen || cfg.
charge != charge;
301 const double x = 1.0 - 4.0 * cache.
m_l * cache.
m_l / q2;
302 return std::sqrt(std::max(0.0, x));
306 const double mB2 = cache.
m_B * cache.
m_B;
307 const double mK2 = cache.
m_Ks * cache.
m_Ks;
313 - 2.0 * (mB2 * mK2 + (mB2 + mK2) * q2);
315 return std::max(0.0, lam);
320 const double b =
beta_l(q2);
321 const double lam =
lambda(q2);
323 return N0 * std::sqrt(std::max(0.0, q2 * b * std::sqrt(lam)));
333 delta_A = 16.0 *
PI2 *
RT2 *
N(q2, bar) * std::pow(cache.
m_B, 3) * (h_p - h_m) / q2;
335 size_t id = size_t (0.5 * (1 + sign));
347 return -32.0 *
PI2 *
N(q2, bar) * std::pow(cache.
m_B, 3) * H_perp / q2;
375 delta_A = 16.0 *
PI2 *
RT2 *
N(q2, bar) * std::pow(cache.
m_B, 3) * (h_p + h_m) / q2;
377 size_t id = 2 + size_t (0.5 * (1 + sign));
389 return 32.0 *
PI2 *
N(q2, bar) * std::pow(cache.
m_B, 3) * H_par / q2;
405 if (bar) w = std::conj(w);
408 size_t id = size_t (0.5 * (1 + sign));
424 return (
N(q2, bar) * std::sqrt(2 *
lambda(q2)) * (F + 2. * m_b_local *
F_T / q2) + delta_A) * had_err_factor;
435 if (bar) w = std::conj(w);
438 size_t id = 2 + size_t (0.5 * (1 + sign));
454 return (-
N(q2, bar) * std::sqrt(2.) * (cache.
m_B * cache.
m_B - cache.
m_Ks * cache.
m_Ks) * (F + 2. * m_b_local *
F_T / q2) + delta_A) * had_err_factor;
458 double mB2 = cache.
m_B * cache.
m_B;
459 double mK2 = cache.
m_Ks * cache.
m_Ks;
467 if (bar) w = std::conj(w);
473 size_t id = 4 + size_t (0.5 * (1 + sign));
489 return (-
N(q2, bar) / (2. * cache.
m_Ks * std::sqrt(q2)) * (F + 2. * m_b_local *
F_T) + delta_A) * had_err_factor;
512 if (bar)
CQ1 = std::conj(
CQ1);
543 delta_A_PC = 32.0 *
PI2 *
N(q2, bar) * std::pow(cache.
m_B, 3) * h_0 / std::sqrt(q2);
545 size_t id = 4 + size_t (0.5 * (1 + sign));
549 const double mB2 = cache.
m_B * cache.
m_B;
550 const double mB3 = cache.
m_B * mB2;
551 const double mK2 = cache.
m_Ks * cache.
m_Ks;
552 const double f =
lambda(q2) / ((mB2 - mK2) * mB2);
560 * mB2 / (std::sqrt(q2) * cache.
m_Ks)
561 * ((2 * (mB2 + 3 * mK2 - q2) * cache.
ff_calculator.
E(q2) / mB3 -
f) * Tperp_m
564 return delta_A_QCDf * guesstimate_err + delta_A_PC;
572 return 32.0 *
PI2 *
N(q2, bar) * std::pow(cache.
m_B, 2) * (cache.
m_B + cache.
m_Ks) * H_0 / q2;
595 double s_hat = q2 / std::pow(cache.
m_b_PS, 2);
607 double s_hat = q2 / std::pow(cache.
m_b_PS, 2);
616 + std::pow(cache.
m_c_mu_b, 2) / q2 * C_mc;
623 if (bar)
C10 = std::conj(
C10);
632 if (bar)
C10 = std::conj(
C10);
640 if (bar)
C10 = std::conj(
C10);
656 if (bar)
CQ1 = std::conj(
CQ1);
668 return t * val_low + (1 - t) * val_high;
692 return (2. + std::pow(
beta_l(q2), 2)) / 4. * (
693 std::pow(std::abs(
A_perp(q2, -1, bar)), 2)
694 + std::pow(std::abs(
A_perp(q2, 1, bar)), 2)
695 + std::pow(std::abs(
A_par(q2, -1, bar)), 2)
696 + std::pow(std::abs(
A_par(q2, 1, bar)), 2)
697 ) + std::pow(2. * cache.
m_l, 2) / q2 * std::real(
699 +
A_par(q2, -1, bar) * std::conj(
A_par(q2, 1, bar))
704 return std::pow(std::abs(
A_0(q2, -1, bar)), 2) + std::pow(std::abs(
A_0(q2, 1, bar)), 2)
705 + std::pow(2 * cache.
m_l, 2) / q2 * (
706 std::pow(std::abs(
A_t(q2, bar)), 2)
707 + 2. * std::real(
A_0(q2, -1, bar) * std::conj(
A_0(q2, 1, bar)))
709 + std::pow(
beta_l(q2) * std::abs(
A_S(q2, bar)), 2);
713 return std::pow(
beta_l(q2), 2) / 4. * (
714 std::pow(std::abs(
A_perp(q2, -1, bar)), 2)
715 + std::pow(std::abs(
A_perp(q2, 1, bar)), 2)
716 + std::pow(std::abs(
A_par(q2, -1, bar)), 2)
717 + std::pow(std::abs(
A_par(q2, 1, bar)), 2)
722 return -std::pow(
beta_l(q2), 2) * (
723 std::pow(std::abs(
A_0(q2, -1, bar)), 2)
724 + std::pow(std::abs(
A_0(q2, 1, bar)), 2)
729 return std::pow(
beta_l(q2), 2) / 2. * (
730 std::pow(std::abs(
A_perp(q2, -1, bar)), 2)
731 + std::pow(std::abs(
A_perp(q2, 1, bar)), 2)
732 - std::pow(std::abs(
A_par(q2, -1, bar)), 2)
733 - std::pow(std::abs(
A_par(q2, 1, bar)), 2)
738 return std::pow(
beta_l(q2), 2) / std::sqrt(2.) * (
739 std::real(
A_0(q2, -1, bar) * std::conj(
A_par(q2, -1, bar)))
740 + std::real(
A_0(q2, 1, bar) * std::conj(
A_par(q2, 1, bar)))
745 return beta_l(q2) * std::sqrt(2.) * (
746 std::real(
A_0(q2, -1, bar) * std::conj(
A_perp(q2, -1, bar)))
747 - std::real(
A_0(q2, 1, bar) * std::conj(
A_perp(q2, 1, bar)))
748 - cache.
m_l / std::sqrt(q2) * std::real((
A_par(q2, -1, bar) +
A_par(q2, 1, bar)) * std::conj(
A_S(q2, bar)))
753 return 2. *
beta_l(q2) * (
754 std::real(
A_par(q2, -1, bar) * std::conj(
A_perp(q2, -1, bar)))
755 - std::real(
A_par(q2, 1, bar) * std::conj(
A_perp(q2, 1, bar)))
760 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))));
764 return beta_l(q2) * std::sqrt(2.) * (
765 std::imag(
A_0(q2, -1, bar) * std::conj(
A_par(q2, -1, bar)))
766 - std::imag(
A_0(q2, 1, bar) * std::conj(
A_par(q2, 1, bar)))
767 + cache.
m_l / std::sqrt(q2) * std::imag((
A_perp(q2, -1, bar) +
A_perp(q2, 1, bar)) * std::conj(
A_S(q2, bar)))
772 return std::pow(
beta_l(q2), 2) / std::sqrt(2.) * (
773 std::imag(
A_0(q2, -1, bar) * std::conj(
A_perp(q2, -1, bar)))
774 + std::imag(
A_0(q2, 1, bar) * std::conj(
A_perp(q2, 1, bar)))
779 return std::pow(
beta_l(q2), 2) * (
780 std::imag(
A_perp(q2, -1, bar) * std::conj(
A_par(q2, -1, bar)))
781 + std::imag(
A_perp(q2, 1, bar) * std::conj(
A_par(q2, 1, bar)))
787 static constexpr std::array<double, 24> GL24_X {{
788 -0.99518721999702131, -0.97472855597130947, -0.93827455200273280, -0.88641552700440107,
789 -0.82000198597390295, -0.74012419157855436, -0.64809365193697555, -0.54542147138883956,
790 -0.43379350762604513, -0.31504267969616340, -0.19111886747361631, -0.06405689286260563,
791 0.06405689286260563, 0.19111886747361631, 0.31504267969616340, 0.43379350762604513,
792 0.54542147138883956, 0.64809365193697555, 0.74012419157855436, 0.82000198597390295,
793 0.88641552700440107, 0.93827455200273280, 0.97472855597130947, 0.99518721999702131
795 static constexpr std::array<double, 24> GL24_W {{
796 0.01234122979998869, 0.02853138862893356, 0.04427743881741941, 0.05929858491543636,
797 0.07334648141108016, 0.08619016153195321, 0.09761865210411393, 0.10744427011596556,
798 0.11550566805372552, 0.12167047292780329, 0.12583745634682825, 0.12793819534675202,
799 0.12793819534675202, 0.12583745634682825, 0.12167047292780329, 0.11550566805372552,
800 0.10744427011596556, 0.09761865210411393, 0.08619016153195321, 0.07334648141108016,
801 0.05929858491543636, 0.04427743881741941, 0.02853138862893356, 0.01234122979998869
818 auto clear_and_reserve = [&] (std::array<std::vector<double>, 15>& dest,
size_t nbins) {
819 for (
auto& v : dest) {
825 auto eval_amplitudes = [&] (
double q2,
bool bar) -> AmpSet {
826 const double beta =
beta_l(q2);
842 auto eval_integrands = [&] (
double q2,
bool bar) -> std::array<double, 15> {
843 const AmpSet a = eval_amplitudes(q2, bar);
844 const double sqrt2 = std::sqrt(2.0);
845 const double ml = cache.
m_l;
846 const double ml_over_sqrt_q2 = ml / a.sqrt_q2;
847 const double four_ml2_over_q2 = 4.0 * ml * ml / q2;
849 const double norm_Aperp_L = std::norm(a.A_perp_L);
850 const double norm_Aperp_R = std::norm(a.A_perp_R);
851 const double norm_Apar_L = std::norm(a.A_par_L);
852 const double norm_Apar_R = std::norm(a.A_par_R);
853 const double norm_A0_L = std::norm(a.A_0_L);
854 const double norm_A0_R = std::norm(a.A_0_R);
855 const double norm_At = std::norm(a.A_t);
856 const double norm_AS = std::norm(a.A_S);
858 const complex_t Apar_sum = a.A_par_L + a.A_par_R;
859 const complex_t A0_sum = a.A_0_L + a.A_0_R;
860 const complex_t Aperp_sum = a.A_perp_L + a.A_perp_R;
863 (2.0 + a.beta2) / 4.0 * (norm_Aperp_L + norm_Aperp_R + norm_Apar_L + norm_Apar_R)
864 + four_ml2_over_q2 * std::real(a.A_perp_L * std::conj(a.A_perp_R)
865 + a.A_par_L * std::conj(a.A_par_R));
868 norm_A0_L + norm_A0_R
869 + four_ml2_over_q2 * (norm_At + 2.0 * std::real(a.A_0_L * std::conj(a.A_0_R)))
872 const double j2s = a.beta2 / 4.0 * (norm_Aperp_L + norm_Aperp_R + norm_Apar_L + norm_Apar_R);
873 const double j2c = -a.beta2 * (norm_A0_L + norm_A0_R);
875 const double j3 = a.beta2 / 2.0 * (norm_Aperp_L + norm_Aperp_R - norm_Apar_L - norm_Apar_R);
877 const double j4 = a.beta2 / sqrt2 * (
878 std::real(a.A_0_L * std::conj(a.A_par_L))
879 + std::real(a.A_0_R * std::conj(a.A_par_R))
882 const double j5 = a.beta * sqrt2 * (
883 std::real(a.A_0_L * std::conj(a.A_perp_L))
884 - std::real(a.A_0_R * std::conj(a.A_perp_R))
885 - ml_over_sqrt_q2 * std::real(Apar_sum * std::conj(a.A_S))
888 const double j6s = 2.0 * a.beta * (
889 std::real(a.A_par_L * std::conj(a.A_perp_L))
890 - std::real(a.A_par_R * std::conj(a.A_perp_R))
893 const double j6c = 4.0 * a.beta * ml_over_sqrt_q2 * std::real(A0_sum * std::conj(a.A_S));
895 const double j7 = a.beta * sqrt2 * (
896 std::imag(a.A_0_L * std::conj(a.A_par_L))
897 - std::imag(a.A_0_R * std::conj(a.A_par_R))
898 + ml_over_sqrt_q2 * std::imag(Aperp_sum * std::conj(a.A_S))
901 const double j8 = a.beta2 / sqrt2 * (
902 std::imag(a.A_0_L * std::conj(a.A_perp_L))
903 + std::imag(a.A_0_R * std::conj(a.A_perp_R))
906 const double j9 = a.beta2 * (
907 std::imag(a.A_perp_L * std::conj(a.A_par_L))
908 + std::imag(a.A_perp_R * std::conj(a.A_par_R))
930 auto integrate_bin = [&] (
double q2_l,
double q2_u,
bool bar) -> std::array<double, 15> {
931 std::array<double, 15> acc {};
932 const double center = 0.5 * (q2_l + q2_u);
933 const double half_width = 0.5 * (q2_u - q2_l);
935 for (
size_t i = 0; i < GL24_X.size(); ++i) {
936 const double q2 = center + half_width * GL24_X[i];
937 const auto vals = eval_integrands(q2, bar);
938 for (
size_t k = 0; k < acc.size(); ++k) {
939 acc[k] += GL24_W[i] * vals[k];
943 for (
double& v : acc) {
950 const auto&
bins = this->
bins.value();
951 const size_t nbins =
bins.size();
956 auto fill_binned = [&] (std::array<std::vector<double>, 15>& dest,
bool bar) {
957 for (
const auto& [q2_l, q2_u] :
bins) {
958 const auto integ = integrate_bin(q2_l, q2_u, bar);
959 for (
size_t k = 0; k < dest.size(); ++k) {
960 dest[k].emplace_back(integ[k]);
972 std::vector<ObservableValue> out;
973 const auto&
bins = this->
bins.value();
974 const double br_factor = br ? cache.
life_B : 1.0;
976 for (
size_t i = 0; i <
bins.size(); i++) {
977 const auto& [q2_l, q2_u] =
bins[i];
978 const double width = q2_u - q2_l;
980 if (!std::isfinite(width) || width <= 0.0) {
981 LOG_WARN(
"BKstarll dBR/dq2: invalid bin width", q2_l, q2_u);
983 std::numeric_limits<double>::quiet_NaN(),
988 const double gamma_integrated_sum =
997 const double res = 0.5 * gamma_integrated_sum * br_factor / width;
1009 std::vector<ObservableValue> out;
1010 double sign = cpv ? -1 : 1;
1011 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1021 auto f = [
this] (
double q2) {
1022 return 2 * (
J6s(q2,
true) +
J6s(q2,
false)) +
J6c(q2,
true) +
J6c(q2,
false);
1027 if (!found_bracket) {
1028 LOG_WARN(
"Forwards-Backwards asymmetry in B > K*ll doesn't cross 0.");
1036 std::vector<ObservableValue> out;
1037 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1040 double res = (dG - dGbar) / (dG + dGbar);
1047 std::vector<ObservableValue> out;
1049 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1056 const double res = safe_div(num, den,
"BKstarll F_L");
1065 std::vector<ObservableValue> out;
1066 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1074 auto num_f = [
this] (
double q2) {
1075 double AperpApar = std::real(
A_par(q2, 1,
false) * std::conj(
A_perp(q2, 1,
false)) +
A_par(q2, -1,
false) * std::conj(
A_perp(q2, -1,
false)));
1076 double AperpApar_bar = std::real(
A_par(q2, 1,
true) * std::conj(
A_perp(q2, 1,
true)) +
A_par(q2, -1,
true) * std::conj(
A_perp(q2, -1,
true)));
1077 return std::pow(
beta_l(q2), 2) * std::real(AperpApar + AperpApar_bar);
1080 std::vector<ObservableValue> out;
1081 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1083 double num =
integrate(num_f, this->
bins.value()[i].first, this->bins.value()[i].second, 1e-2);
1084 double res = -0.5 * num / J2scpa;
1091 std::vector<ObservableValue> out;
1093 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1097 const double res = safe_div(num, den,
"BKstarll A_T_2");
1106 std::vector<ObservableValue> out;
1107 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1113 double res = std::sqrt((4 * J4cp * J4cp + J7cp * J7cp) / std::abs(-2 * J2ccp * (2 * J2scp + J3cp)));
1120 std::vector<ObservableValue> out;
1121 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1126 double res = std::sqrt((J5cp * J5cp + 4 * J8cp * J8cp) / (J7cp * J7cp + 4 * J4cp * J4cp));
1133 auto num_f = [
this] (
double q2) {
1136 return std::abs(AperpApar + AperpApar_bar);
1139 auto den_f = [
this] (
double q2) {
1140 double Aperp2Apar2 = (std::pow(std::abs(
A_perp(q2, -1,
false)), 2) + std::pow(std::abs(
A_perp(q2, 1,
false)), 2) + std::pow(std::abs(
A_par(q2, -1,
false)), 2) + std::pow(std::abs(
A_par(q2, 1,
false)), 2));
1141 double Aperp2Apar2bar = (std::pow(std::abs(
A_perp(q2, -1,
true)), 2) + std::pow(std::abs(
A_perp(q2, 1,
true)), 2) + std::pow(std::abs(
A_par(q2, -1,
true)), 2) + std::pow(std::abs(
A_par(q2, 1,
true)), 2));
1142 return Aperp2Apar2 + Aperp2Apar2bar;
1145 std::vector<ObservableValue> out;
1146 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1147 double num =
integrate(num_f, this->
bins.value()[i].first, this->bins.value()[i].second, 1e-2);
1148 double den =
integrate(den_f, this->
bins.value()[i].first, this->bins.value()[i].second, 1e-2);
1149 double res = num / den;
1156 std::vector<ObservableValue> out;
1158 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1162 const double res = safe_div(num, den,
"BKstarll A_T_Re");
1171 std::vector<ObservableValue> out;
1172 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1175 double res = 0.25 * J6scpa / J2scp;
1182 std::vector<ObservableValue> out;
1183 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1191 std::vector<ObservableValue> out;
1192 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1195 double res = -0.5 * (2 * J2scp + J2ccp) / J2scp;
1202 std::vector<ObservableValue> out;
1203 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1208 double res =
RT2 * J4cp / std::sqrt(std::abs(J2ccp * (J2scp - J3cp)));
1215 std::vector<ObservableValue> out;
1216 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1221 double res = J5cp / std::sqrt(std::abs(2 * J2ccp * (2 * J2scp + J3cp)));
1228 std::vector<ObservableValue> out;
1229 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1233 double res = 0.5 * J6cp / std::sqrt(std::abs(4 * J2scp * J2scp - J3cp * J3cp));
1240 std::vector<ObservableValue> out;
1241 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1244 double res = 0.125 * J6scp / J2scp;
1251 std::vector<ObservableValue> out;
1252 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1255 double res = -0.25 * J9cp / J2scp;
1262 std::vector<ObservableValue> out;
1263 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1268 double res = -J7cp / std::sqrt(std::abs(2 * J2ccp * (2 * J2scp - J3cp)));
1275 std::vector<ObservableValue> out;
1276 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1281 double res = -
RT2 * J8cp / std::sqrt(std::abs(J2ccp * (2 * J2scp - J3cp)));
1288 if (!(i == 4 || i == 5 || i == 6 || i == 8))
LOG_ERROR(
"Value Error",
"P'_i(B > K*ll) is not defined for i =", i);
1290 std::map<size_t, double> factors = {{4, 1.0}, {5, 0.5}, {6, -0.5}, {8, -1.0}};
1291 std::map<size_t, size_t> J_idx = {{4, 4}, {5, 5}, {6, 10}, {8, 12}};
1292 double sign = cpv ? -1 : 1;
1294 std::vector<ObservableValue> out;
1295 for (
size_t j = 0; j < this->
bins.value().size(); j++) {
1299 double res = factors[i] * Jicp / std::sqrt(std::abs(J2ccp * J2scp));
1306 if (i > 10)
LOG_ERROR(
"Value Error",
"S_i(B > K*ll) is not defined for i =", i);
1309 std::map<size_t, size_t> J_idx = {{0, 14}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 7}, {7, 10}, {8, 12}, {9, 13}, {10, 9}};
1310 double sign = cpv ? -1 : 1;
1311 double global_sign = i == 10 || i == 2 && cpv ? -1 : 1;
1313 std::vector<ObservableValue> out;
1314 for (
size_t j = 0; j < this->
bins.value().size(); j++) {
1322 if (i < 1 || i > 3)
LOG_ERROR(
"Value Error",
"P_i_CPV(B > K*ll) is not defined for i =", i);
1324 std::map<size_t, double> factors = {{1, 0.5}, {2, 0.125}, {3, -0.25}};
1325 std::map<size_t, size_t> J_idx = {{1, 3}, {2, 7}, {3, 13}};
1327 std::vector<ObservableValue> out;
1328 for (
size_t j = 0; j < this->
bins.value().size(); j++) {
1331 double res = factors[i] * Jicpv / J2scp;
1339 fs.open(
"B_Ksll_FF.csv");
1340 fs <<
"q2,A0,A1,A12,V,T1,T2,T23\n";
1342 auto write_line = [&] (
double q2) {
1354 double q2_min = 4 * std::pow(0.1057, 2);
1355 double q2_max = 19.2542;
1357 double dq2 = (q2_max - q2_min) / n;
1359 for (
size_t i = 0; i <= n; i++) {
1367 fs.open(
"B_Ksll_T.csv");
1368 fs <<
"q2,T_perp_p_re,T_perp_p_im,T_perp_m_re,T_perp_m_im,T_par_p_re,T_par_p_im,T_par_m_re,T_par_m_im\n";
1370 auto write_line = [&] (
double q2) {
1380 double q2 = cache.
q2_min;
1381 for (
size_t i = 0; i <= n; i++) {
1389 fs.open(
"B_Ksll_J.csv");
1390 fs <<
"q2,J1s,J1c,J2s,J2c,J3,J4,J5,J6s,J6c,J7,J8,J9,J1sbar,J1cbar,J2sbar,J2cbar,J3bar,J4bar,J5bar,J6sbar,J6cbar,J7bar,J8bar,J9bar\n";
1392 auto write_line = [&] (
double q2) {
1394 <<
"," <<
J1s(q2,
false)
1395 <<
"," <<
J1c(q2,
false)
1396 <<
"," <<
J2s(q2,
false)
1397 <<
"," <<
J2c(q2,
false)
1398 <<
"," <<
J3(q2,
false)
1399 <<
"," <<
J4(q2,
false)
1400 <<
"," <<
J5(q2,
false)
1401 <<
"," <<
J6s(q2,
false)
1402 <<
"," <<
J6c(q2,
false)
1403 <<
"," <<
J7(q2,
false)
1404 <<
"," <<
J8(q2,
false)
1405 <<
"," <<
J9(q2,
false)
1406 <<
"," <<
J1s(q2,
true)
1407 <<
"," <<
J1c(q2,
true)
1408 <<
"," <<
J2s(q2,
true)
1409 <<
"," <<
J2c(q2,
true)
1410 <<
"," <<
J3(q2,
true)
1411 <<
"," <<
J4(q2,
true)
1412 <<
"," <<
J5(q2,
true)
1413 <<
"," <<
J6s(q2,
true)
1414 <<
"," <<
J6c(q2,
true)
1415 <<
"," <<
J7(q2,
true)
1416 <<
"," <<
J8(q2,
true)
1417 <<
"," <<
J9(q2,
true)
1423 double q2 = cache.
q2_min;
1425 for (
size_t i = 0; i <= n; i++) {
1435 std::vector<ObservableValue> out;
1436 std::vector<double> Gamma_mu;
1437 std::vector<double> Gamma_e;
1441 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1447 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1451 for (
size_t i = 0; i < this->
bins.value().size(); i++) {
1454 Gamma_mu[i] / Gamma_e[i] - 1.0,
1455 this->
bins.value()[i]
2545 if (!enum_obs.has_value()) {
2549 switch (enum_obs.value()) {
2563 unsigned int available_threads = std::thread::hardware_concurrency();
2565 if (available_threads == 0) {
2566 available_threads = 1;
2569 if (n_threads == 0) {
2570 this->cfg.
n_threads = available_threads;
2574 if (n_threads > available_threads) {
2576 "Requested", n_threads,
2577 "threads, but only", available_threads,
2578 "are available. Using", available_threads,
2582 this->cfg.
n_threads = available_threads;
2586 this->cfg.
n_threads = std::max<size_t>(1, n_threads);
@ A_T_RE_CPV_B__KSTAR_MU_MU
@ A_FL_B0__KSTAR0_TAU_TAU
@ A_T_1_B0__KSTAR0_TAU_TAU
@ H_T_1_B0__KSTAR0_TAU_TAU
@ P_PRIME_8_CPV_B__KSTAR_MU_MU
@ P_2_CPV_B0__KSTAR0_TAU_TAU
@ Q0_A_FB_B__KSTAR_TAU_TAU
@ P_PRIME_8_CPV_B__KSTAR_E_E
@ Q0_A_FB_B0__KSTAR0_TAU_TAU
@ P_PRIME_8_B__KSTAR_MU_MU
@ A_2S_B0__KSTAR0_TAU_TAU
@ P_PRIME_4_CPV_B0__KSTAR0_MU_MU
@ P_1_CPV_B0__KSTAR0_TAU_TAU
@ P_PRIME_4_CPV_B0__KSTAR0_TAU_TAU
@ A_CP_B0__KSTAR0_TAU_TAU
@ DGAMMA_DQ2_B0__KSTAR0_E_E
@ S_2S_B0__KSTAR0_TAU_TAU
@ P_2_CPV_B0__KSTAR0_MU_MU
@ DBR_DQ2_B0__KSTAR0_MU_MU
@ P_PRIME_4_CPV_B__KSTAR_TAU_TAU
@ A_T_RE_B__KSTAR_TAU_TAU
@ A_T_3_B0__KSTAR0_TAU_TAU
@ A_FB_CPV_B0__KSTAR0_TAU_TAU
@ P_PRIME_5_B0__KSTAR0_E_E
@ DGAMMA_DQ2_B__KSTAR_MU_MU
@ P_PRIME_4_CPV_B0__KSTAR0_E_E
@ P_PRIME_8_CPV_B0__KSTAR0_TAU_TAU
@ DGAMMA_DQ2_B__KSTAR_E_E
@ A_T_RE_B0__KSTAR0_TAU_TAU
@ S_6C_B0__KSTAR0_TAU_TAU
@ A_FB_CPV_B0__KSTAR0_E_E
@ P_PRIME_6_CPV_B0__KSTAR0_E_E
@ Q0_A_FB_B0__KSTAR0_MU_MU
@ ALPHA_K_B0__KSTAR0_MU_MU
@ DBR_DQ2_B0__KSTAR0_TAU_TAU
@ ALPHA_K_B__KSTAR_TAU_TAU
@ A_T_RE_B0__KSTAR0_MU_MU
@ A_T_RE_CPV_B__KSTAR_E_E
@ P_PRIME_8_CPV_B0__KSTAR0_MU_MU
@ A_T_RE_CPV_B0__KSTAR0_E_E
@ P_PRIME_8_B0__KSTAR0_TAU_TAU
@ A_T_RE_CPV_B0__KSTAR0_TAU_TAU
@ P_PRIME_6_CPV_B0__KSTAR0_TAU_TAU
@ P_PRIME_5_CPV_B__KSTAR_E_E
@ P_2_CPV_B__KSTAR_TAU_TAU
@ P_PRIME_8_B0__KSTAR0_MU_MU
@ A_T_2_B0__KSTAR0_TAU_TAU
@ DBR_DQ2_B__KSTAR_TAU_TAU
@ S_1C_B0__KSTAR0_TAU_TAU
@ A_FB_CPV_B__KSTAR_TAU_TAU
@ A_6C_B0__KSTAR0_TAU_TAU
@ P_PRIME_4_B0__KSTAR0_E_E
@ P_1_CPV_B__KSTAR_TAU_TAU
@ A_1C_B0__KSTAR0_TAU_TAU
@ P_PRIME_5_B0__KSTAR0_TAU_TAU
@ P_PRIME_4_CPV_B__KSTAR_MU_MU
@ H_T_3_B0__KSTAR0_TAU_TAU
@ P_PRIME_6_CPV_B0__KSTAR0_MU_MU
@ P_PRIME_5_B0__KSTAR0_MU_MU
@ DGAMMA_DQ2_B__KSTAR_TAU_TAU
@ P_PRIME_5_CPV_B0__KSTAR0_E_E
@ A_T_5_B0__KSTAR0_TAU_TAU
@ A_6S_B0__KSTAR0_TAU_TAU
@ P_PRIME_5_B__KSTAR_TAU_TAU
@ P_PRIME_4_B0__KSTAR0_TAU_TAU
@ P_PRIME_5_CPV_B0__KSTAR0_TAU_TAU
@ A_FB_B0__KSTAR0_TAU_TAU
@ P_PRIME_4_B__KSTAR_TAU_TAU
@ P_PRIME_8_CPV_B0__KSTAR0_E_E
@ DGAMMA_DQ2_B0__KSTAR0_MU_MU
@ S_2C_B0__KSTAR0_TAU_TAU
@ P_3_CPV_B__KSTAR_TAU_TAU
@ P_1_CPV_B0__KSTAR0_MU_MU
@ P_PRIME_8_B__KSTAR_TAU_TAU
@ P_PRIME_8_CPV_B__KSTAR_TAU_TAU
@ P_PRIME_6_B__KSTAR_MU_MU
@ P_PRIME_8_B0__KSTAR0_E_E
@ H_T_2_B0__KSTAR0_TAU_TAU
@ A_T_RE_CPV_B0__KSTAR0_MU_MU
@ P_PRIME_6_B0__KSTAR0_E_E
@ P_PRIME_4_B__KSTAR_MU_MU
@ A_T_RE_CPV_B__KSTAR_TAU_TAU
@ P_PRIME_5_CPV_B__KSTAR_TAU_TAU
@ P_PRIME_4_B0__KSTAR0_MU_MU
@ A_IM_B0__KSTAR0_TAU_TAU
@ P_PRIME_6_B__KSTAR_TAU_TAU
@ ALPHA_K_B0__KSTAR0_TAU_TAU
@ A_FB_CPV_B0__KSTAR0_MU_MU
@ P_PRIME_5_CPV_B__KSTAR_MU_MU
@ A_FB_CPV_B__KSTAR_MU_MU
@ P_PRIME_6_B0__KSTAR0_TAU_TAU
@ P_PRIME_6_CPV_B__KSTAR_E_E
@ A_T_4_B0__KSTAR0_TAU_TAU
@ P_PRIME_6_CPV_B__KSTAR_TAU_TAU
@ P_3_CPV_B0__KSTAR0_TAU_TAU
@ DGAMMA_DQ2_B0__KSTAR0_TAU_TAU
@ P_PRIME_6_B0__KSTAR0_MU_MU
@ P_PRIME_4_CPV_B__KSTAR_E_E
@ P_PRIME_6_CPV_B__KSTAR_MU_MU
@ P_3_CPV_B0__KSTAR0_MU_MU
@ P_PRIME_5_CPV_B0__KSTAR0_MU_MU
@ P_PRIME_5_B__KSTAR_MU_MU
#define LOG_ERROR(type,...)
Macro for logging error messages and terminating the application.
#define LOG_WARN(...)
Macro for logging warning messages.
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].
std::complex< double > complex_t
Convenience alias for std::complex<double>.
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].
complex_t delta_A_0_K(double q2, bool bar)
complex_t A_S(double q2, bool bar)
std::vector< ObservableValue > P_3_binned(Observables id)
std::vector< ObservableValue > S_i_binned(size_t i, bool cpv, Observables id)
double J2s(double q2, bool bar)
complex_t A_perp_low(double q2, double sign, bool bar)
double J2c(double q2, bool bar)
std::vector< ObservableValue > P_6_binned(Observables id)
complex_t A_t_high(double q2, bool bar)
std::vector< ObservableValue > H_T_2_binned(Observables id)
complex_t delta_A_perp_QCDf(double q2, double sign, bool bar)
complex_t T_par_m_cached(double q2, bool bar)
complex_t delta_A_0_QCDf(double q2, double sign, bool bar)
complex_t delta_A_0(double q2, double sign, bool bar)
std::vector< ObservableValue > Rm1_BKstar(Observables id, BKstarllConfig::B_Charge charge)
complex_t delta_A_par_vD(double q2, bool bar)
std::vector< ObservableValue > H_T_3_binned(Observables id)
double J7(double q2, bool bar)
void set_lepton_gen_and_charge(BKstarllConfig::Lepton gen, BKstarllConfig::B_Charge charge)
double J3(double q2, bool bar)
double J1c(double q2, bool bar)
complex_t A_perp(double q2, double sign, bool bar)
std::vector< ObservableValue > A_T_2_binned(Observables id)
std::vector< ObservableValue > P_8_binned(Observables id)
std::vector< ObservableValue > P_i_CPV_binned(size_t i, Observables id)
complex_t A_0(double q2, double sign, bool bar)
complex_t N(double q2, bool bar)
std::vector< ObservableValue > A_T_Re_CPV_binned(Observables id)
complex_t delta_A_perp(double q2, double sign, bool bar)
complex_t A_0_low(double q2, double sign, bool bar)
std::vector< ObservableValue > A_T_3_binned(Observables id)
std::vector< ObservableValue > A_T_1_binned(Observables id)
complex_t delta_A_perp_vD(double q2, bool bar)
std::vector< ObservableValue > compute_observable(Observables obs) override
Compute an observable given a public observable enum.
std::vector< ObservableValue > A_T_4_binned(Observables id)
std::vector< ObservableValue > alpha_K_binned(Observables id)
complex_t A_perp_high(double q2, double sign, bool bar)
std::vector< ObservableValue > dBR_dq2_binned(bool bar, Observables id, bool br=true)
complex_t delta_A_par(double q2, double sign, bool bar)
double J6s(double q2, bool bar)
std::vector< ObservableValue > A_CP_binned(Observables id)
std::vector< ObservableValue > Pp_i_binned(size_t i, bool cpv, Observables id)
std::vector< ObservableValue > A_Im_binned(Observables id)
complex_t A_par_high(double q2, double sign, bool bar)
bool is_observable_binned(ObservableId obs) const override
Return whether one observable of this decay requires q² bins.
complex_t delta_A_0_vD(double q2, bool bar)
void compute_binned_J_i()
double dG_dq2_avg_bin(size_t bin)
std::vector< ObservableValue > H_T_1_binned(Observables id)
std::vector< ObservableValue > F_L_binned(Observables id)
complex_t C7_eff(double q2, bool bar)
double J8(double q2, bool bar)
complex_t A_par(double q2, double sign, bool bar)
complex_t delta_A_par_K(double q2, bool bar)
double J5(double q2, bool bar)
complex_t A_S_low(double q2, bool bar)
std::vector< ObservableValue > A_T_Re_binned(Observables id)
void set_n_threads(size_t n_threads) override
Set the number of worker threads used by decays that support parallel cache filling.
complex_t T_perp_p_cached(double q2, bool bar)
std::vector< ObservableValue > F_T_binned(Observables id)
double J4(double q2, bool bar)
complex_t A_0_high(double q2, double sign, bool bar)
complex_t T_perp_m_cached(double q2, bool bar)
double J9(double q2, bool bar)
std::vector< ObservableValue > A_T_5_binned(Observables id)
complex_t A_S_high(double q2, bool bar)
complex_t delta_A_par_QCDf(double q2, double sign, bool bar)
void load_cfg_dependent_params()
ObservableValue q0(Observables id)
double J6c(double q2, bool bar)
complex_t A_t(double q2, bool bar)
complex_t delta_A_perp_K(double q2, bool bar)
complex_t C9_eff(double q2, bool bar)
std::vector< ObservableValue > A_FB_binned(Observables id, bool cpv)
complex_t interpolate(double q2, complex_t val_low, complex_t val_high)
std::vector< ObservableValue > P_2_binned(Observables id)
complex_t A_par_low(double q2, double sign, bool bar)
complex_t A_t_low(double q2, bool bar)
double J1s(double q2, bool bar)
void load_params() override
Load and cache parameters needed by this decay.
double get(BV_FF a, double q2) override
complex_t z(double t, double t_p, double t_0)
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)
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).
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 std::complex< double > I
double integrate(RealValuedFunction f, double l, double u, double prec)
Performs numerical integration of a real-valued function of a real variable.
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)
bool find_bracket(const RealValuedFunction &f, double x_min, double x_max, double &a, double &b, int n_samples)
double brent_root(const RealValuedFunction &f, double a, double b, double xtol, double ftol, int max_it)
std::enable_if_t< not std::numeric_limits< T >::is_integer, bool > fpeq(T, T, std::size_t n=10)
Compares two floating point numbers with a given precision.
double f(double x)
Wilson special function f depending on x.
Configuration for evaluating the strong coupling constant .
std::array< complex_t, 8 > phi_k_high
std::array< double, 3 > r2_M
std::array< scalar_t, LOOKUP_SIZE > T_perp_p_lookup
std::array< double, 3 > DeltaC9_M_qbar
std::array< double, 3 > r1_M
BVFFCalculator ff_calculator
std::array< complex_t, 6 > b_k_low
std::array< complex_t, 6 > theta_k_low
std::array< std::vector< double >, 15 > J_i_binned
std::array< scalar_t, LOOKUP_SIZE > T_par_m_lookup
std::array< complex_t, 3 > h_0_fit
std::array< complex_t, 3 > h_p_fit
std::array< scalar_t, LOOKUP_SIZE > T_par_m_bar_lookup
std::array< complex_t, 8 > a_k_high
std::array< complex_t, 3 > alpha_par
std::map< WCoef, complex_t > C
std::array< scalar_t, LOOKUP_SIZE > T_perp_m_lookup
std::array< complex_t, 2 > alpha_0
BVQCDfCalculator qcdf_calculator
std::array< scalar_t, LOOKUP_SIZE > T_perp_p_bar_lookup
std::array< complex_t, 6 > phi_k_low
std::array< complex_t, 6 > a_k_low
std::array< complex_t, 3 > h_m_fit
std::array< complex_t, 3 > alpha_perp
static constexpr size_t LOOKUP_SIZE
std::array< std::vector< double >, 15 > J_i_bar_binned
std::array< scalar_t, LOOKUP_SIZE > T_perp_m_bar_lookup
Power_Corrections_Impl power_corr_impl
Configuration for computing a particle mass at a given scale.
Container for a computed observable value, optionally binned.
Composite identifier for a single parameter.
QCDOrder order
Perturbative QCD order used for the evolution and matching of Wilson coefficients....