File indexing completed on 2025-10-16 08:19:02
0001 #include "AfterburnerAlgo.h"
0002
0003 #include <algorithm>
0004 #include <cmath>
0005 #include <iostream>
0006 #include <cstdlib> // for exit
0007 #include <array>
0008
0009 #include <CLHEP/Random/RandomEngine.h>
0010
0011 AfterburnerAlgo::AfterburnerAlgo( flowAfterburnerAlgorithm algorithm)
0012 : m_algorithm(algorithm)
0013 {
0014 for (unsigned int i = 0; i < 6; ++i)
0015 {
0016 m_vn[i] = 0.0;
0017 m_vn_scalefactors[i] = 1.0;
0018 }
0019 }
0020
0021 void AfterburnerAlgo::set_single_scale_N( const unsigned int n, const float scale )
0022 {
0023 if (n < 1 || n > 6)
0024 {
0025 std::cerr << "AfterburnerAlgo::set_single_scale_N: n must be between 1 and 6, got " << n << std::endl;
0026 return;
0027 }
0028 m_vn_scalefactors[n - 1] = scale;
0029 }
0030
0031 void AfterburnerAlgo::set_scale_all( const float scale )
0032 {
0033 for (float & m_vn_scalefactor : m_vn_scalefactors)
0034 {
0035 m_vn_scalefactor = scale;
0036 }
0037 }
0038
0039 float AfterburnerAlgo::get_vn(unsigned int n) const
0040 {
0041 if (n < 1 || n > 6)
0042 {
0043 std::cerr << "AfterburnerAlgo::get_vn: n must be between 1 and 6, got " << n << std::endl;
0044 return 0.0;
0045 }
0046 return m_vn[n - 1];
0047 }
0048
0049 float AfterburnerAlgo::calc_v2(double b, double eta, double pt)
0050 {
0051
0052 float a1 = 0.4397 * exp(-(b - 4.526) * (b - 4.526) / 72.0) + 0.636;
0053 float a2 = 1.916 / (b + 2) + 0.1;
0054 float a3 = 4.79 * 0.0001 * (b - 0.621) * (b - 10.172) * (b - 23) + 1.2;
0055 float a4 = 0.135 * exp(-0.5 * (b - 10.855) * (b - 10.855) / 4.607 / 4.607) + 0.0120;
0056
0057 float temp1 = pow(pt, a1) / (1 + exp((pt - 3.0) / a3));
0058 float temp2 = pow(pt + 0.1, -a2) / (1 + exp(-(pt - 4.5) / a3));
0059 float temp3 = 0.01 / (1 + exp(-(pt - 4.5) / a3));
0060
0061
0062
0063
0064 float val = (a4 * (temp1 + temp2) + temp3) * exp(-0.5 * eta * eta / 3.43 / 3.43);
0065 return val;
0066 }
0067
0068 void AfterburnerAlgo::calc_flow(double eta, double pt, CLHEP::HepRandomEngine* engine)
0069 {
0070
0071 float v1 = 0;
0072 float v2 = 0;
0073 float v3 = 0;
0074 float v4 = 0;
0075 float v5 = 0;
0076 float v6 = 0;
0077 if ( m_algorithm == custom_algorithm )
0078 {
0079 v1 = 0.0000;
0080 v2 = 0.0500;
0081 v3 = 0.0280;
0082 v4 = 0.0130;
0083 v5 = 0.0045;
0084 v6 = 0.0015;
0085 }
0086 else if (m_algorithm == minbias_algorithm)
0087 {
0088 v1 = 0;
0089 v2 = AfterburnerAlgo::calc_v2(m_impact_parameter, eta, pt);
0090 float v2_sqrt = std::sqrt(v2);
0091
0092 float fb = (
0093 0.97
0094 + (1.06 * exp(-0.5 * m_impact_parameter * m_impact_parameter / 3.2 / 3.2))
0095 ) * v2_sqrt;
0096 float gb = (
0097 1.096
0098 + (1.36 * exp(-0.5 * m_impact_parameter * m_impact_parameter / 3.0 / 3.0))
0099 ) * v2_sqrt;
0100
0101 v3 = pow( fb , 3);
0102 v4 = pow( gb, 4);
0103 v5 = pow( gb, 5);
0104 v6 = pow( gb, 6);
0105 }
0106 else if (m_algorithm == minbias_v2_algorithm)
0107 {
0108 v1 = 0;
0109 v2 = AfterburnerAlgo::calc_v2(m_impact_parameter, eta, pt);
0110 v3 = 0;
0111 v4 = 0;
0112 v5 = 0;
0113 v6 = 0;
0114 }
0115
0116 if ( _do_fluctuations )
0117 {
0118 flucatate(engine, v1, v2, v3, v4, v5, v6);
0119 }
0120
0121 m_vn[0] = v1 * m_vn_scalefactors[0];
0122 m_vn[1] = v2 * m_vn_scalefactors[1];
0123 m_vn[2] = v3 * m_vn_scalefactors[2];
0124 m_vn[3] = v4 * m_vn_scalefactors[3];
0125 m_vn[4] = v5 * m_vn_scalefactors[4];
0126 m_vn[5] = v6 * m_vn_scalefactors[5];
0127
0128
0129
0130
0131 return;
0132 }
0133
0134 void AfterburnerAlgo::flucatate(CLHEP::HepRandomEngine* engine, float &v1, float &v2, float &v3, float &v4, float &v5, float &v6) const
0135 {
0136
0137
0138 const std::array<float, 8> coeffs = {
0139 -7.00411e-09, 4.24567e-07,
0140 -9.87748e-06, 0.000112689,
0141 -0.000694686, 0.002413930,
0142 -0.00324709, 0.0107906};
0143 float sigma = 0.0;
0144 for (float coeff : coeffs)
0145 {
0146 sigma = sigma * m_impact_parameter + coeff;
0147 }
0148 sigma = std::max<double>(sigma, 0.0);
0149 const float fb = (
0150 0.97
0151 + (1.06 * exp(-0.5 * m_impact_parameter * m_impact_parameter / 3.2 / 3.2))
0152 ) * std::sqrt(v2);
0153 const float gb = (
0154 1.096
0155 + (1.36 * exp(-0.5 * m_impact_parameter * m_impact_parameter / 3.0 / 3.0))
0156 ) * std::sqrt(v2);
0157
0158 const float s1 = 0;
0159 const float s2 = sigma;
0160 const float s3 = 1.5*std::pow(fb,3) * std::sqrt(v2) * sigma;
0161 const float s4 = 2.0*std::pow(gb,4) * v2 * sigma;
0162 const float s5 = 2.5*std::pow(gb,5) * std::sqrt(v2*v2*v2) * sigma;
0163 const float s6 = 3.0*std::pow(gb,6) * v2*v2 * sigma;
0164
0165
0166 float u;
0167 float v;
0168 float s;
0169 do
0170 {
0171 u = 2.0*engine->flat() - 1.0;
0172 v = 2.0*engine->flat() - 1.0;
0173 s = u*u + v*v;
0174 } while (s >= 1.0 || s == 0.0);
0175
0176 const float mul = std::sqrt(-2.0*std::log(s)/s);
0177 const float z0 = u*mul;
0178 const float z1 = v*mul;
0179
0180
0181 if ( v1 != 0.0 )
0182 {
0183 float _v1 = std::hypot(v1 + s1*z0, s1*z1);
0184 v1 = std::clamp(_v1, 0.0F, 1.0F);
0185 }
0186 if ( v2 != 0.0 )
0187 {
0188 float _v2 = std::hypot(v2 + s2*z0, s2*z1);
0189 v2 = std::clamp(_v2, 0.0F, 1.0F);
0190 }
0191 if ( v3 != 0.0 )
0192 {
0193 float _v3 = std::hypot(v3 + s3*z0, s3*z1);
0194 v3 = std::clamp(_v3, 0.0F, 1.0F);
0195 }
0196 if ( v4 != 0.0 )
0197 {
0198 float _v4 = std::hypot(v4 + s4*z0, s4*z1);
0199 v4 = std::clamp(_v4, 0.0F, 1.0F);
0200 }
0201 if ( v5 != 0.0 )
0202 {
0203 float _v5 = std::hypot(v5 + s5*z0, s5*z1);
0204 v5 = std::clamp(_v5, 0.0F, 1.0F);
0205 }
0206 if ( v6 != 0.0 )
0207 {
0208 float _v6 = std::hypot(v6 + s6*z0, s6*z1);
0209 v6 = std::clamp(_v6, 0.0F, 1.0F);
0210 }
0211
0212
0213
0214 return;
0215
0216 }
0217
0218
0219 std::string AfterburnerAlgo::getAlgoName(flowAfterburnerAlgorithm algo)
0220 {
0221 switch (algo)
0222 {
0223 case minbias_algorithm:
0224 return "MINBIAS";
0225 case minbias_v2_algorithm:
0226 return "MINBIAS_V2_ONLY";
0227 case custom_algorithm:
0228 return "CUSTOM";
0229 default:
0230 std::cerr << "AfterburnerAlgo::getAlgoName: Unknown algorithm type, returning MINBIAS" << std::endl;
0231 return "MINBIAS";
0232 }
0233 }
0234
0235 AfterburnerAlgo::flowAfterburnerAlgorithm AfterburnerAlgo::getAlgoFromName(const std::string &name)
0236 {
0237 if (name == "MINBIAS")
0238 {
0239 return minbias_algorithm;
0240 }
0241 if (name == "MINBIAS_V2_ONLY")
0242 {
0243 return minbias_v2_algorithm;
0244 }
0245 if (name == "CUSTOM")
0246 {
0247 return custom_algorithm;
0248 }
0249
0250 std::cerr << "AfterburnerAlgo::getAlgoFromName: Unknown algorithm name: " << name << std::endl;
0251 return minbias_algorithm;
0252 }
0253
0254 void AfterburnerAlgo::print(std::ostream &os) const
0255 {
0256 os << "AfterburnerAlgo parameters:" << std::endl;
0257 os << "Algorithm: " << getAlgoName(m_algorithm) << std::endl;
0258 os << "Scale factors: ";
0259 for (const auto &scale : m_vn_scalefactors)
0260 {
0261 os << scale << " ";
0262 }
0263 os << std::endl;
0264 os << "Flow fluctuations enabled: " << (_do_fluctuations ? "Yes" : "No") << std::endl;
0265
0266 return;
0267 }