10double sqr(
double x) {
return x * x; }
11double fourth(
double x) {
const double x2 = x * x;
return x2 * x2; }
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;
19bool isScalarQ1LikeTemplate(
const std::string& path) {
20 return containsAny(path, {
"_CQ1",
"_CPQ1"});
23bool isScalarQ2LikeTemplate(
const std::string& path) {
24 return containsAny(path, {
"_CQ2",
"_CPQ2"});
30 std::set<std::string> special_blocks,
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))
41 }
else if (model ==
"THDM") {
43 }
else if (model ==
"MSSM" || model ==
"NMSSM") {
49 if (!this->cinematic_template.empty()) {
51 if (!process.empty()) {
52 this->cinematic_process = process;
59 std::unordered_map<std::string, double> params {};
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))) {
67 params[name] = (*sm_proxy)(
"MASS_EW_SCALE",
LhaID(5, 1));
69 params[name] = (*sm_proxy)(
"MASS_EW_SCALE", 6);
71 }
else if (interpretedParam.
block ==
"GAUGE" && interpretedParam.
code ==
LhaID(4)) {
72 params[name] = calculateValue(interpretedParam);
74 if (interpretedParam.
is_bsm) {
76 params[name+
"_rel"] = (*bsm_proxy)(interpretedParam.
block, interpretedParam.
code).
real();
77 params[name +
"_img"] = (*bsm_proxy)(interpretedParam.
block, interpretedParam.
code).
imag();
79 params[name] = (*bsm_proxy)(interpretedParam.
block, interpretedParam.
code);
83 params[name+
"_rel"] = (*sm_proxy)(interpretedParam.
block, interpretedParam.
code).
real();
84 params[name +
"_img"] = (*sm_proxy)(interpretedParam.
block, interpretedParam.
code).
imag();
86 params[name] = (*sm_proxy)(interpretedParam.
block, interpretedParam.
code);
94 if (interpretedParam.
block ==
"KIN") {
95 return calculateKinematicInvariant(interpretedParam.
code);
97 if (interpretedParam.
block ==
"WEIN") {
100 if (interpretedParam.
block ==
"Finite") {
108 if (isScalarQ1LikeTemplate(cinematic_template)) {
111 if (isScalarQ2LikeTemplate(cinematic_template)) {
116 if (interpretedParam.
block ==
"REGPROP") {
127 if (interpretedParam.
block ==
"BETA") {
128 return atan((*bsm_proxy)(
"MINPAR", 3));
130 if(interpretedParam.
block ==
"GAUGE") {
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)))));
140scalar_t SMParamSetter::calculateKinematicInvariant(
const LhaID& code)
const {
141 if (!cinematic_process.has_value()) {
142 return legacyKinematicInvariant(code);
145 const auto masses = extractMassesForCurrentProcess();
147 if (cinematic_process->incoming_count() == 1 && cinematic_process->outgoing_count() == 3) {
148 return calculateOneToThreeInvariant(code, masses);
151 if (cinematic_process->incoming_count() == 1 && cinematic_process->outgoing_count() == 2) {
152 return calculateOneToTwoInvariant(code, masses);
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);
160scalar_t SMParamSetter::calculateOneToThreeInvariant(
const LhaID& code,
const std::vector<scalar_t>& masses)
const {
161 if (masses.size() != 4) {
162 return legacyKinematicInvariant(code);
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);
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);
177 if (code ==
LhaID(12)) {
180 if (code ==
LhaID(13)) {
181 return m1 * (sqr(m1) - 2*m1*m2 + sqr(m2) + sqr(m3) - sqr(m4)) / (2 * denom);
183 if (code ==
LhaID(14)) {
184 return m1 * (sqr(m1) - 2*m1*m2 + sqr(m2) - sqr(m3) + sqr(m4)) / (2 * denom);
186 if (code ==
LhaID(23)) {
187 return m2 * (sqr(m1) - 2*m1*m2 + sqr(m2) + sqr(m3) - sqr(m4)) / (2 * denom);
189 if (code ==
LhaID(24)) {
190 return m2 * (sqr(m1) - 2*m1*m2 + sqr(m2) - sqr(m3) + sqr(m4)) / (2 * denom);
192 if (code ==
LhaID(34)) {
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)
201 return legacyKinematicInvariant(code);
204scalar_t SMParamSetter::calculateOneToTwoInvariant(
const LhaID& code,
const std::vector<scalar_t>& masses)
const {
205 if (masses.size() != 3) {
206 return legacyKinematicInvariant(code);
209 const double m1 = masses[0];
210 const double m2 = masses[1];
211 const double m3 = masses[2];
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);
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);
222 const double root12 = std::sqrt(std::max(0.0, root12_arg));
223 const double root13 = std::sqrt(std::max(0.0, root13_arg));
225 if (code ==
LhaID(12)) {
228 if (code ==
LhaID(13)) {
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));
237 return legacyKinematicInvariant(code);
240scalar_t SMParamSetter::legacyKinematicInvariant(
const LhaID& code)
const {
241 if (code ==
LhaID(34)) {
242 return -
pow((*sm_proxy)(
"MASS", 13), 2.);
244 return (
pow((*sm_proxy)(
"MASS_EW_SCALE",
LhaID(5, 1)) ,2.) + std::pow((*sm_proxy)(
"MASS", 3), 2.))/2.;
247std::vector<scalar_t> SMParamSetter::extractMassesForCurrentProcess()
const {
248 std::vector<scalar_t> masses;
249 if (!cinematic_process.has_value()) {
253 const auto particles = cinematic_process->ordered_particles();
254 masses.reserve(particles.size());
256 for (
const auto& particle : particles) {
257 masses.push_back(massValueForParticle(particle));
262scalar_t SMParamSetter::massValueForParticle(
const std::string& particle_name)
const {
265 if (p ==
"a" || p ==
"g" || p ==
"ve" || p ==
"vmu" || p ==
"vtau") {
270 return (*sm_proxy)(
"MASS_EW_SCALE",
LhaID(5, 1));
273 return (*sm_proxy)(
"MASS_EW_SCALE", 6);
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);
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);
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);
289 LOG_WARN(
"SMParamSetter",
"Unknown particle mass for MARTY kinematics:", particle_name,
290 ". Treating it as massless. Add it to SMParamSetter::massValueForParticle if needed.");
#define LOG_DEBUG(...)
Macro for logging debug messages.
#define LOG_WARN(...)
Macro for logging warning messages.
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>.
double imag(const scalar_t &z)
scalar_t pow(const scalar_t &base, const scalar_t &exp)
double real(const scalar_t &z)
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.