File indexing completed on 2025-01-18 09:57:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #ifndef __FASTJET_CONTRIB_EEHELPERS_HH__
0023 #define __FASTJET_CONTRIB_EEHELPERS_HH__
0024
0025 #include "fastjet/PseudoJet.hh"
0026 #include <array>
0027 #include <limits>
0028
0029 FASTJET_BEGIN_NAMESPACE
0030
0031 namespace contrib{
0032 namespace lund_plane {
0033
0034
0035
0036
0037
0038 inline PseudoJet cross_product(const PseudoJet & p1, const PseudoJet & p2, bool lightlike=false) {
0039 double px = p1.py() * p2.pz() - p2.py() * p1.pz();
0040 double py = p1.pz() * p2.px() - p2.pz() * p1.px();
0041 double pz = p1.px() * p2.py() - p2.px() * p1.py();
0042
0043 double E;
0044 if (lightlike) {
0045 E = sqrt(px*px + py*py + pz*pz);
0046 } else {
0047 E = 0.0;
0048 }
0049 return PseudoJet(px, py, pz, E);
0050 }
0051
0052
0053 inline const double map_to_pi(const double &phi) {
0054 if (phi < -M_PI) return phi + 2 * M_PI;
0055 else if (phi > M_PI) return phi - 2 * M_PI;
0056 else return phi;
0057 }
0058
0059 inline double dot_product_3d(const PseudoJet & a, const PseudoJet & b) {
0060 return a.px()*b.px() + a.py()*b.py() + a.pz()*b.pz();
0061 }
0062
0063
0064 inline double one_minus_costheta(const PseudoJet & p1, const PseudoJet & p2) {
0065
0066 if (p1.m2() == 0 && p2.m2() == 0) {
0067
0068
0069 return dot_product(p1,p2) / (p1.E() * p2.E());
0070 } else {
0071 double p1mod = p1.modp();
0072 double p2mod = p2.modp();
0073 double p1p2mod = p1mod*p2mod;
0074 double dot = dot_product_3d(p1,p2);
0075
0076 if (dot > (1-std::numeric_limits<double>::epsilon()) * p1p2mod) {
0077 PseudoJet cross_result = cross_product(p1, p2, false);
0078
0079
0080
0081 return -cross_result.m2()/(p1p2mod * (p1p2mod+dot));
0082 }
0083
0084 return 1.0 - dot/p1p2mod;
0085
0086 }
0087 }
0088
0089
0090
0091 inline double signed_angle_between_planes(const PseudoJet& n1,
0092 const PseudoJet& n2, const PseudoJet& n) {
0093
0094
0095 assert(fabs(n1.modp()-1) < sqrt(std::numeric_limits<double>::epsilon()) && fabs(n2.modp()-1) < sqrt(std::numeric_limits<double>::epsilon()));
0096
0097 double omcost = one_minus_costheta(n1,n2);
0098 double theta;
0099
0100
0101 if(fabs(omcost-2) < sqrt(std::numeric_limits<double>::epsilon())) {
0102 theta = M_PI;
0103 } else if (omcost > sqrt(std::numeric_limits<double>::epsilon())) {
0104 double cos_theta = 1.0 - omcost;
0105 theta = acos(cos_theta);
0106 } else {
0107
0108 theta = sqrt(2. * omcost);
0109 }
0110
0111 PseudoJet cp = cross_product(n1,n2);
0112 double sign = dot_product_3d(cp,n);
0113
0114 if (sign > 0) return theta;
0115 else return -theta;
0116 }
0117
0118 class Matrix3 {
0119 public:
0120
0121 Matrix3() : matrix_({{{{0,0,0}}, {{0,0,0}}, {{0,0,0}}}}) {}
0122
0123
0124 Matrix3(double unit) : matrix_({{{{unit,0,0}}, {{0,unit,0}}, {{0,0,unit}}}}) {}
0125
0126
0127 Matrix3(const std::array<std::array<double,3>,3> & mat) : matrix_(mat) {}
0128
0129
0130 inline double operator()(int i, int j) const {
0131 return matrix_[i][j];
0132 }
0133
0134
0135
0136 static Matrix3 azimuthal_rotation(double phi) {
0137 double cos_phi = cos(phi);
0138 double sin_phi = sin(phi);
0139 Matrix3 phi_rot( {{ {{cos_phi, sin_phi, 0}},
0140 {{-sin_phi, cos_phi, 0}},
0141 {{0,0,1}}}});
0142 return phi_rot;
0143 }
0144
0145
0146
0147 static Matrix3 polar_rotation(double theta) {
0148 double cos_theta = cos(theta);
0149 double sin_theta = sin(theta);
0150 Matrix3 theta_rot( {{ {{cos_theta, 0, sin_theta}},
0151 {{0,1,0}},
0152 {{-sin_theta, 0, cos_theta}}}});
0153 return theta_rot;
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163 template<class T>
0164 static Matrix3 from_direction(const T & p, bool skip_pre_rotation = false) {
0165 double pt = p.pt();
0166 double modp = p.modp();
0167 double cos_theta = p.pz() / modp;
0168 double sin_theta = pt / modp;
0169 double cos_phi, sin_phi;
0170 if (pt > 0.0) {
0171 cos_phi = p.px()/pt;
0172 sin_phi = p.py()/pt;
0173 } else {
0174 cos_phi = 1.0;
0175 sin_phi = 0.0;
0176 }
0177
0178 Matrix3 phi_rot({{ {{ cos_phi,-sin_phi, 0 }},
0179 {{ sin_phi, cos_phi, 0 }},
0180 {{ 0, 0, 1 }} }});
0181 Matrix3 theta_rot( {{ {{ cos_theta, 0, sin_theta }},
0182 {{ 0, 1, 0 }},
0183 {{-sin_theta, 0, cos_theta }} }});
0184
0185
0186
0187
0188 if (skip_pre_rotation) {
0189 return phi_rot * theta_rot;
0190 } else {
0191 return phi_rot * (theta_rot * phi_rot.transpose());
0192 }
0193 }
0194
0195 template<class T>
0196 static Matrix3 from_direction_no_pre_rotn(const T & p) {
0197 return from_direction(p,true);
0198 }
0199
0200
0201
0202
0203 Matrix3 transpose() const {
0204
0205
0206
0207 Matrix3 result = *this;
0208 std::swap(result.matrix_[0][1],result.matrix_[1][0]);
0209 std::swap(result.matrix_[0][2],result.matrix_[2][0]);
0210 std::swap(result.matrix_[1][2],result.matrix_[2][1]);
0211 return result;
0212 }
0213
0214
0215 Matrix3 operator*(const Matrix3 & other) const {
0216 Matrix3 result;
0217
0218 for (int i = 0; i < 3; i++) {
0219 for (int j = 0; j < 3; j++) {
0220 for (int k = 0; k < 3; k++) {
0221 result.matrix_[i][j] += this->matrix_[i][k] * other.matrix_[k][j];
0222 }
0223 }
0224 }
0225 return result;
0226 }
0227
0228 friend std::ostream & operator<<(std::ostream & ostr, const Matrix3 & mat);
0229 private:
0230 std::array<std::array<double,3>,3> matrix_;
0231 };
0232
0233 inline std::ostream & operator<<(std::ostream & ostr, const Matrix3 & mat) {
0234 ostr << mat.matrix_[0][0] << " " << mat.matrix_[0][1] << " " << mat.matrix_[0][2] << std::endl;
0235 ostr << mat.matrix_[1][0] << " " << mat.matrix_[1][1] << " " << mat.matrix_[1][2] << std::endl;
0236 ostr << mat.matrix_[2][0] << " " << mat.matrix_[2][1] << " " << mat.matrix_[2][2] << std::endl;
0237 return ostr;
0238 }
0239
0240
0241
0242 inline PseudoJet operator*(const Matrix3 & mat, const PseudoJet & p) {
0243
0244 std::array<double,3> res3{{0,0,0}};
0245 for (unsigned i = 0; i < 3; i++) {
0246 for (unsigned j = 0; j < 3; j++) {
0247 res3[i] += mat(i,j) * p[j];
0248 }
0249 }
0250
0251
0252
0253 PseudoJet result(p);
0254
0255 result.reset_momentum(res3[0], res3[1], res3[2], p[3]);
0256 return result;
0257 }
0258
0259 }
0260 }
0261
0262 FASTJET_END_NAMESPACE
0263
0264 #endif
0265