Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
SMParamSetter.cpp
Go to the documentation of this file.
1#include "SMParamSetter.h"
2
3#include <algorithm>
4#include <array>
5#include <stdexcept>
6#include <utility>
7
8namespace {
9
10double sqr(double x) { return x * x; }
11double fourth(double x) { const double x2 = x * x; return x2 * x2; }
12
13bool containsAny(const std::string& text, std::initializer_list<const char*> needles) {
14 return std::any_of(needles.begin(), needles.end(), [&](const char* needle) {
15 return text.find(needle) != std::string::npos;
16 });
17}
18
19bool isScalarQ1LikeTemplate(const std::string& path) {
20 return containsAny(path, {"_CQ1", "_CPQ1"});
21}
22
23bool isScalarQ2LikeTemplate(const std::string& path) {
24 return containsAny(path, {"_CQ2", "_CPQ2"});
25}
26
27} // namespace
28
29SMParamSetter::SMParamSetter(const std::string& model,
30 std::set<std::string> special_blocks,
31 std::shared_ptr<IMartyParameterProxy<std::string, LhaID>> sm_proxy,
32 std::shared_ptr<IMartyParameterProxy<std::string, LhaID>> bsm_proxy,
33 std::string cinematic_template)
34 : special_blocks(std::move(special_blocks)),
35 sm_proxy(std::move(sm_proxy)),
36 bsm_proxy(std::move(bsm_proxy)),
37 cinematic_template(std::move(cinematic_template))
38{
39 if (model == "SM") {
40 this->model_type = Model::SM;
41 } else if (model == "THDM") {
42 this->model_type = Model::THDM;
43 } else if (model == "MSSM" || model == "NMSSM") {
44 this->model_type = Model::SUSY;
45 } else {
46 this->model_type = Model::MARTY;
47 }
48
49 if (!this->cinematic_template.empty()) {
50 const auto process = CinematicExtractor().extract_process(this->cinematic_template);
51 if (!process.empty()) {
52 this->cinematic_process = process;
53 }
54 }
55}
56
57std::unordered_map<std::string, double> SMParamSetter::setParam(const std::string& name, const InterpretedParam& interpretedParam) {
58
59 std::unordered_map<std::string, double> params {};
60
61 LOG_DEBUG("setting parameter", name, interpretedParam.block, interpretedParam.code);
62 std::set<std::string> special = this->special_blocks;
63 if (special.find(interpretedParam.block) != special.end()) {
64 params[name] = calculateValue(interpretedParam);
65 } else if (interpretedParam.block == "MASS" && (interpretedParam.code == LhaID(5) || interpretedParam.code == LhaID(6))) {
66 if (interpretedParam.code == LhaID(5)) {
67 params[name] = (*sm_proxy)("MASS_EW_SCALE", LhaID(5, 1));
68 } else {
69 params[name] = (*sm_proxy)("MASS_EW_SCALE", 6);
70 }
71 } else if (interpretedParam.block == "GAUGE" && interpretedParam.code == LhaID(4)) {
72 params[name] = calculateValue(interpretedParam);
73 } else {
74 if (interpretedParam.is_bsm) {
75 if (interpretedParam.is_complex) {
76 params[name+ "_rel"] = (*bsm_proxy)(interpretedParam.block, interpretedParam.code).real();
77 params[name + "_img"] = (*bsm_proxy)(interpretedParam.block, interpretedParam.code).imag();
78 } else {
79 params[name] = (*bsm_proxy)(interpretedParam.block, interpretedParam.code);
80 }
81 } else {
82 if (interpretedParam.is_complex) {
83 params[name+ "_rel"] = (*sm_proxy)(interpretedParam.block, interpretedParam.code).real();
84 params[name + "_img"] = (*sm_proxy)(interpretedParam.block, interpretedParam.code).imag();
85 } else {
86 params[name] = (*sm_proxy)(interpretedParam.block, interpretedParam.code);
87 }
88 }
89 }
90 return params;
91}
92
93scalar_t SMParamSetter::calculateValue(const InterpretedParam& interpretedParam) {
94 if (interpretedParam.block == "KIN") {
95 return calculateKinematicInvariant(interpretedParam.code);
96 }
97 if (interpretedParam.block == "WEIN") {
98 return asin(sqrt((*sm_proxy)("SMINPUTS", LhaID(7, 1))));
99 }
100 if (interpretedParam.block == "Finite") {
101 // MARTY leaves a finite local term in the scalar/pseudoscalar 4-fermion
102 // matching. SuperIso's CQ basis corresponds to different finite
103 // prescriptions for scalar and pseudoscalar lepton bilinears. Apply the
104 // prescription per generated Wilson coefficient instead of using a
105 // single global value: Q1-like coefficients use Finite=0, Q2-like
106 // coefficients use Finite=4. Other generated libraries keep MARTY's
107 // historical default value Finite=1.
108 if (isScalarQ1LikeTemplate(cinematic_template)) {
109 return 0.0;
110 }
111 if (isScalarQ2LikeTemplate(cinematic_template)) {
112 return 4.0;
113 }
114 return 1.0;
115 }
116 if (interpretedParam.block == "REGPROP") {
117 // Default MARTY regulator for generated Wilson libraries.
118 //
119 // C9/CP9 are special only in the numeric wrapper: their BSM photon
120 // component is exported as a separate *_A function and evaluated with
121 // reg_prop = 1, while the non-photon part keeps this small regulator.
122 // Keeping the parameter-file default small makes the policy local to
123 // the coefficient writer and lets the same mechanism be reused for
124 // future split coefficients.
125 return 1e-6;
126 }
127 if (interpretedParam.block == "BETA") {
128 return atan((*bsm_proxy)("MINPAR", 3));
129 }
130 if(interpretedParam.block == "GAUGE") {
131 if (interpretedParam.code == LhaID(4)) {
132 return std::sqrt((*sm_proxy)("SMINPUTS", 2) * std::sqrt(2))
133 * (*sm_proxy)("SMINPUTS", 4)
134 * std::sin(2 * asin(sqrt((*sm_proxy)("SMINPUTS", LhaID(7, 1)))));
135 }
136 }
137 return 1.0;
138}
139
140scalar_t SMParamSetter::calculateKinematicInvariant(const LhaID& code) const {
141 if (!cinematic_process.has_value()) {
142 return legacyKinematicInvariant(code);
143 }
144
145 const auto masses = extractMassesForCurrentProcess();
146
147 if (cinematic_process->incoming_count() == 1 && cinematic_process->outgoing_count() == 3) {
148 return calculateOneToThreeInvariant(code, masses);
149 }
150
151 if (cinematic_process->incoming_count() == 1 && cinematic_process->outgoing_count() == 2) {
152 return calculateOneToTwoInvariant(code, masses);
153 }
154
155 LOG_WARN("SMParamSetter", "Unsupported MARTY kinematics. Falling back to legacy KIN rule.",
156 cinematic_process->incoming_count(), "incoming and", cinematic_process->outgoing_count(), "outgoing particles.");
157 return legacyKinematicInvariant(code);
158}
159
160scalar_t SMParamSetter::calculateOneToThreeInvariant(const LhaID& code, const std::vector<scalar_t>& masses) const {
161 if (masses.size() != 4) {
162 return legacyKinematicInvariant(code);
163 }
164
165 const double m1 = masses[0];
166 const double m2 = masses[1];
167 const double m3 = masses[2];
168 const double m4 = masses[3];
169 const double denom = m1 - m2;
170 const double denom2 = sqr(denom);
171
172 if (std::abs(denom) < 1e-15) {
173 LOG_WARN("SMParamSetter", "Singular 1->3 KIN denominator m1-m2. Falling back to legacy KIN rule.");
174 return legacyKinematicInvariant(code);
175 }
176
177 if (code == LhaID(12)) {
178 return m1 * m2;
179 }
180 if (code == LhaID(13)) {
181 return m1 * (sqr(m1) - 2*m1*m2 + sqr(m2) + sqr(m3) - sqr(m4)) / (2 * denom);
182 }
183 if (code == LhaID(14)) {
184 return m1 * (sqr(m1) - 2*m1*m2 + sqr(m2) - sqr(m3) + sqr(m4)) / (2 * denom);
185 }
186 if (code == LhaID(23)) {
187 return m2 * (sqr(m1) - 2*m1*m2 + sqr(m2) + sqr(m3) - sqr(m4)) / (2 * denom);
188 }
189 if (code == LhaID(24)) {
190 return m2 * (sqr(m1) - 2*m1*m2 + sqr(m2) - sqr(m3) + sqr(m4)) / (2 * denom);
191 }
192 if (code == LhaID(34)) {
193 return (
194 sqr(m1)*sqr(m3) + sqr(m1)*sqr(m4)
195 - 2*m1*m2*sqr(m3) - 2*m1*m2*sqr(m4)
196 + sqr(m2)*sqr(m3) + sqr(m2)*sqr(m4)
197 - fourth(m3) + 2*sqr(m3)*sqr(m4) - fourth(m4)
198 ) / (2 * denom2);
199 }
200
201 return legacyKinematicInvariant(code);
202}
203
204scalar_t SMParamSetter::calculateOneToTwoInvariant(const LhaID& code, const std::vector<scalar_t>& masses) const {
205 if (masses.size() != 3) {
206 return legacyKinematicInvariant(code);
207 }
208
209 const double m1 = masses[0];
210 const double m2 = masses[1];
211 const double m3 = masses[2];
212
213 if (std::abs(m1) < 1e-15) {
214 LOG_WARN("SMParamSetter", "Singular 1->2 KIN denominator m1. Falling back to legacy KIN rule.");
215 return legacyKinematicInvariant(code);
216 }
217
218 const double delta23 = sqr(m2) - sqr(m3);
219 const double root12_arg = fourth(m1) + 2*sqr(m1)*sqr(m2) - 2*sqr(m1)*sqr(m3) + sqr(delta23);
220 const double root13_arg = fourth(m1) - 2*sqr(m1)*sqr(m2) + 2*sqr(m1)*sqr(m3) + sqr(delta23);
221
222 const double root12 = std::sqrt(std::max(0.0, root12_arg));
223 const double root13 = std::sqrt(std::max(0.0, root13_arg));
224
225 if (code == LhaID(12)) {
226 return root12 / 2.0;
227 }
228 if (code == LhaID(13)) {
229 return root13 / 2.0;
230 }
231 if (code == LhaID(23)) {
232 return sqr(m1)/4.0 - sqr(m2)/2.0 - sqr(m3)/2.0
233 + sqr(delta23)/(4.0*sqr(m1))
234 + root13*root12/(4.0*sqr(m1));
235 }
236
237 return legacyKinematicInvariant(code);
238}
239
240scalar_t SMParamSetter::legacyKinematicInvariant(const LhaID& code) const {
241 if (code == LhaID(34)) {
242 return -pow((*sm_proxy)("MASS", 13), 2.);
243 }
244 return (pow((*sm_proxy)("MASS_EW_SCALE", LhaID(5, 1)) ,2.) + std::pow((*sm_proxy)("MASS", 3), 2.))/2.;
245}
246
247std::vector<scalar_t> SMParamSetter::extractMassesForCurrentProcess() const {
248 std::vector<scalar_t> masses;
249 if (!cinematic_process.has_value()) {
250 return masses;
251 }
252
253 const auto particles = cinematic_process->ordered_particles();
254 masses.reserve(particles.size());
255
256 for (const auto& particle : particles) {
257 masses.push_back(massValueForParticle(particle));
258 }
259 return masses;
260}
261
262scalar_t SMParamSetter::massValueForParticle(const std::string& particle_name) const {
263 const auto p = CinematicExtractor::normalize_particle_name(particle_name);
264
265 if (p == "a" || p == "g" || p == "ve" || p == "vmu" || p == "vtau") {
266 return 0.0;
267 }
268
269 if (p == "b") {
270 return (*sm_proxy)("MASS_EW_SCALE", LhaID(5, 1));
271 }
272 if (p == "t") {
273 return (*sm_proxy)("MASS_EW_SCALE", 6);
274 }
275
276 if (p == "d") return (*sm_proxy)("MASS", 1);
277 if (p == "u") return (*sm_proxy)("MASS", 2);
278 if (p == "s") return (*sm_proxy)("MASS", 3);
279 if (p == "c") return (*sm_proxy)("MASS", 4);
280
281 if (p == "e") return (*sm_proxy)("MASS", 11);
282 if (p == "mu") return (*sm_proxy)("MASS", 13);
283 if (p == "tau") return (*sm_proxy)("MASS", 15);
284
285 if (p == "z") return (*sm_proxy)("MASS", 23);
286 if (p == "w" || p == "w+" || p == "w-") return (*sm_proxy)("MASS", 24);
287 if (p == "h") return (*sm_proxy)("MASS", 25);
288
289 LOG_WARN("SMParamSetter", "Unknown particle mass for MARTY kinematics:", particle_name,
290 ". Treating it as massless. Add it to SMParamSetter::massValueForParticle if needed.");
291 return 0.0;
292}
#define LOG_DEBUG(...)
Macro for logging debug messages.
Definition Logger.h:45
#define LOG_WARN(...)
Macro for logging warning messages.
Definition Logger.h:40
Extracts process kinematics from MARTY templates.
static std::string normalize_particle_name(std::string particle_name)
Normalizes common MARTY particle names for dictionary lookup.
CinematicProcess extract_process(const std::string &filename) const
Extracts the first MARTY process from a template file.
Interface for accessing parameter values from different backends.
SMParamSetter(const std::string &model, std::set< std::string > special_blocks, std::shared_ptr< IMartyParameterProxy< std::string, LhaID > > sm_proxy, std::shared_ptr< IMartyParameterProxy< std::string, LhaID > > bsm_proxy=nullptr, std::string cinematic_template="")
Constructs a parameter setter for a given model.
std::unordered_map< std::string, double > setParam(const std::string &name, const InterpretedParam &interpretedParam)
Hash specialization for SymbolId<Tag>.
Definition BlockName.h:353
double imag(const scalar_t &z)
Definition scalar.cpp:87
scalar_t pow(const scalar_t &base, const scalar_t &exp)
Definition scalar.cpp:75
double real(const scalar_t &z)
Definition scalar.cpp:83
Identifies a single interpreted parameter from an LHA block.
std::string block
Name of the LHA block (e.g. "SMINPUTS", "MASS", "B_Dlnu", ...).
bool is_bsm
True if this parameter belongs to the BSM part of the model.
LhaID code
LHA index (or multi-index) identifying the entry inside the block.
bool is_complex
True if the parameter is interpreted as complex-valued.
Represents an identifier of a LHA element, possibly containing several sub-ids.
Definition LhaID.h:56