Thrust.cc
Go to the documentation of this file.00001
00002 #include "Rivet/Rivet.hh"
00003 #include "Rivet/Projections/Thrust.hh"
00004 #include "Rivet/Tools/Logging.hh"
00005
00006
00007 namespace Rivet {
00008
00009
00010 void Thrust::calc(const FinalState& fs) {
00011 calc(fs.particles());
00012 }
00013
00014 void Thrust::calc(const vector<Particle>& fsparticles) {
00015 vector<Vector3> threeMomenta;
00016 threeMomenta.reserve(fsparticles.size());
00017 foreach (const Particle& p, fsparticles) {
00018 const Vector3 p3 = p.momentum().vector3();
00019 threeMomenta.push_back(p3);
00020 }
00021 _calcThrust(threeMomenta);
00022 }
00023
00024 void Thrust::calc(const vector<FourMomentum>& fsmomenta) {
00025 vector<Vector3> threeMomenta;
00026 threeMomenta.reserve(fsmomenta.size());
00027 foreach (const FourMomentum& v, fsmomenta) {
00028 threeMomenta.push_back(v.vector3());
00029 }
00030 _calcThrust(threeMomenta);
00031 }
00032
00033 void Thrust::calc(const vector<Vector3>& fsmomenta) {
00034 _calcThrust(fsmomenta);
00035 }
00036
00037
00038
00039
00040
00041
00042 inline bool mod2Cmp(const Vector3& a, const Vector3& b) {
00043 return a.mod2() > b.mod2();
00044 }
00045
00046
00047
00048 void _calcT(const vector<Vector3>& momenta, double& t, Vector3& taxis) {
00049
00050
00051
00052
00053 vector<Vector3> p = momenta;
00054 assert(p.size() >= 3);
00055 unsigned int n = 3;
00056 if (p.size() == 3) n = 3;
00057 vector<Vector3> tvec;
00058 vector<double> tval;
00059 std::sort(p.begin(), p.end(), mod2Cmp);
00060 for (int i = 0 ; i < intpow(2, n-1); ++i) {
00061
00062 Vector3 foo(0,0,0);
00063 int sign = i;
00064 for (unsigned int k = 0 ; k < n ; ++k) {
00065 (sign % 2) == 1 ? foo += p[k] : foo -= p[k];
00066 sign /= 2;
00067 }
00068 foo=foo.unit();
00069
00070
00071 double diff=999.;
00072 while (diff>1e-5) {
00073 Vector3 foobar(0,0,0);
00074 for (unsigned int k=0 ; k<p.size() ; k++)
00075 foo.dot(p[k])>0 ? foobar+=p[k] : foobar-=p[k];
00076 diff=(foo-foobar.unit()).mod();
00077 foo=foobar.unit();
00078 }
00079
00080
00081 t=0.;
00082 for (unsigned int k=0 ; k<p.size() ; k++)
00083 t+=fabs(foo.dot(p[k]));
00084
00085
00086 tval.push_back(t);
00087 tvec.push_back(foo);
00088 }
00089
00090
00091 t=0.;
00092 for (unsigned int i=0 ; i<tvec.size() ; i++)
00093 if (tval[i]>t){
00094 t=tval[i];
00095 taxis=tvec[i];
00096 }
00097 }
00098
00099
00100
00101
00102 void Thrust::_calcThrust(const vector<Vector3>& fsmomenta) {
00103
00104 double momentumSum(0.0);
00105 foreach (const Vector3& p3, fsmomenta) {
00106 momentumSum += mod(p3);
00107 }
00108 MSG_DEBUG("Number of particles = " << fsmomenta.size());
00109
00110
00111
00112 _thrusts.clear();
00113 _thrustAxes.clear();
00114
00115
00116
00117 if (fsmomenta.size() < 2) {
00118 for (int i = 0; i < 3; ++i) {
00119 _thrusts.push_back(-1);
00120 _thrustAxes.push_back(Vector3(0,0,0));
00121 }
00122 return;
00123 }
00124
00125
00126
00127 if (fsmomenta.size() == 2) {
00128 Vector3 axis(0,0,0);
00129 _thrusts.push_back(1.0);
00130 _thrusts.push_back(0.0);
00131 _thrusts.push_back(0.0);
00132 axis = fsmomenta[0].unit();
00133 if (axis.z() < 0) axis = -axis;
00134 _thrustAxes.push_back(axis);
00135
00136
00137 if (axis.z() < 0.75)
00138 _thrustAxes.push_back( (axis.cross(Vector3(0,0,1))).unit() );
00139 else
00140 _thrustAxes.push_back( (axis.cross(Vector3(0,1,0))).unit() );
00141 _thrustAxes.push_back( _thrustAxes[0].cross(_thrustAxes[1]) );
00142 return;
00143 }
00144
00145
00146
00147
00148 Vector3 axis(0,0,0);
00149 double val = 0.;
00150
00151
00152 _calcT(fsmomenta, val, axis);
00153 MSG_DEBUG("Mom sum = " << momentumSum);
00154 _thrusts.push_back(val / momentumSum);
00155
00156 if (axis.z() < 0) axis = -axis;
00157 axis = axis.unit();
00158 MSG_DEBUG("Axis = " << axis);
00159 _thrustAxes.push_back(axis);
00160
00161
00162 vector<Vector3> threeMomenta;
00163 foreach (const Vector3& v, fsmomenta) {
00164
00165 const Vector3 vpar = dot(v, axis.unit()) * axis.unit();
00166 threeMomenta.push_back(v - vpar);
00167 }
00168 _calcT(threeMomenta, val, axis);
00169 _thrusts.push_back(val / momentumSum);
00170 if (axis.x() < 0) axis = -axis;
00171 axis = axis.unit();
00172 _thrustAxes.push_back(axis);
00173
00174
00175 if (_thrustAxes[0].dot(_thrustAxes[1]) < 1e-10) {
00176 axis = _thrustAxes[0].cross(_thrustAxes[1]);
00177 _thrustAxes.push_back(axis);
00178 val = 0.0;
00179 foreach (const Vector3& v, fsmomenta) {
00180 val += fabs(dot(axis, v));
00181 }
00182 _thrusts.push_back(val / momentumSum);
00183 } else {
00184 _thrusts.push_back(-1.0);
00185 _thrustAxes.push_back(Vector3(0,0,0));
00186 }
00187
00188 }
00189
00190
00191
00192 }