00001
00002
00003 #include "Rivet/Projections/Thrust.hh"
00004 #include "Rivet/RivetCLHEP.hh"
00005
00006 using namespace CLHEP;
00007
00008 namespace Rivet {
00009
00010
00011 void Thrust::calcT(const vector<Vector3>& p, double& t, Vector3& taxis) const {
00012 t = 0.0;
00013 Vector3 tv, ptot;
00014 vector<Vector3> cpm(4);
00015 const size_t psize = p.size();
00016 for (size_t k = 1; k < psize; ++k) {
00017 for (size_t j = 0; j < k; ++j) {
00018 tv = p[j].cross(p[k]);
00019 ptot = Vector3();
00020 for (size_t l = 0; l < psize; ++l) {
00021 if (l != j && l != k) {
00022 if (p[l].dot(tv) > 0.0) {
00023 ptot += p[l];
00024 } else {
00025 ptot -= p[l];
00026 }
00027 }
00028 }
00029 cpm[0] = ptot - p[j] - p[k];
00030 cpm[1] = ptot - p[j] + p[k];
00031 cpm[2] = ptot + p[j] - p[k];
00032 cpm[3] = ptot + p[j] + p[k];
00033 for (size_t i = 0; i < 4; ++i) {
00034 double tval = cpm[i].mag2();
00035 if (tval > t) {
00036 t = tval;
00037 taxis = cpm[i];
00038 }
00039 }
00040 }
00041 }
00042 }
00043
00044
00045
00046 void Thrust::calcM(const vector<Vector3>& p, double& m, Vector3& maxis) const {
00047 double mval;
00048 m = 0.0;
00049 Vector3 tv, ptot;
00050 vector<Vector3> cpm;
00051 for (unsigned int j = 0; j < p.size(); ++j) {
00052 tv = p[j];
00053 ptot = Vector3();
00054 for (unsigned int l = 0; l < p.size(); ++l) {
00055 if (l != j) {
00056 if (p[l].dot(tv) > 0.0) {
00057 ptot += p[l];
00058 } else {
00059 ptot -= p[l];
00060 }
00061 }
00062 }
00063 cpm.clear();
00064 cpm.push_back(ptot - p[j]);
00065 cpm.push_back(ptot + p[j]);
00066 for (vector<Vector3>::iterator it = cpm.begin(); it != cpm.end(); ++it) {
00067 mval = it->mag2();
00068 if (mval > m) {
00069 m = mval;
00070 maxis = *it;
00071 }
00072 }
00073 }
00074 }
00075
00076
00077
00078 void Thrust::calcThrust(const FinalState& fs) {
00079
00080
00081
00082
00083 vector<Vector3> threeMomenta;
00084 double momentumSum(0.0);
00085 for (ParticleVector::const_iterator p = fs.particles().begin(); p != fs.particles().end(); ++p) {
00086 Vector3 p3 = p->getMomentum().vect();
00087 threeMomenta.push_back(p3);
00088 momentumSum += threeMomenta.back().mag();
00089 }
00090
00091
00092 _thrusts.clear();
00093 _thrustAxes.clear();
00094
00095
00096
00097
00098 if (threeMomenta.size() < 2) {
00099 for (int i = 0; i < 3; ++i) {
00100 _thrusts.push_back(-1);
00101 _thrustAxes.push_back(Vector3());
00102 }
00103 return;
00104 }
00105
00106
00107
00108 if (threeMomenta.size() == 2) {
00109 Vector3 axis;
00110 _thrusts.push_back(1.0);
00111 _thrusts.push_back(0.0);
00112 _thrusts.push_back(0.0);
00113 axis = threeMomenta[0].unit();
00114 if (axis.z() < 0) axis = -axis;
00115 _thrustAxes.push_back(axis);
00116 _thrustAxes.push_back(axis.orthogonal());
00117 _thrustAxes.push_back( _thrustAxes[0].cross(_thrustAxes[1]) );
00118 return;
00119 }
00120
00121
00122
00123 if (threeMomenta.size() == 3) {
00124 Vector3 axis;
00125
00126
00127 if (threeMomenta[0].mag2() < threeMomenta[1].mag2()) std::swap(threeMomenta[0], threeMomenta[1]);
00128 if (threeMomenta[0].mag2() < threeMomenta[2].mag2()) std::swap(threeMomenta[0], threeMomenta[2]);
00129 if (threeMomenta[1].mag2() < threeMomenta[2].mag2()) std::swap(threeMomenta[1], threeMomenta[2]);
00130
00131 axis = threeMomenta[0].unit();
00132 if (axis.z() < 0) axis = -axis;
00133 _thrusts.push_back(2.0 * threeMomenta[0].mag() / momentumSum);
00134 _thrustAxes.push_back(axis);
00135
00136 axis = ( threeMomenta[1] - (axis.dot(threeMomenta[1])) * axis ).unit();
00137 if (axis.x() < 0) axis = -axis;
00138 _thrusts.push_back( (fabs(threeMomenta[1].dot(axis)) +
00139 fabs(threeMomenta[2].dot(axis))) / momentumSum);
00140 _thrustAxes.push_back(axis);
00141
00142 _thrusts.push_back(0.0);
00143 _thrustAxes.push_back( _thrustAxes[0].cross(_thrustAxes[1]) );
00144 return;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 Vector3 axis; double val;
00158
00159
00160 calcT(threeMomenta, val, axis);
00161 _thrusts.push_back(sqrt(val) / momentumSum);
00162 if (axis.z() < 0) axis = -axis;
00163 _thrustAxes.push_back(axis.unit());
00164
00165
00166 threeMomenta.clear();
00167 for (ParticleVector::const_iterator p = fs.particles().begin(); p != fs.particles().end(); ++p) {
00168
00169 Vector3 v = p->getMomentum().vect();
00170 Vector3 vpar = v.dot(axis.unit()) * axis.unit();
00171 threeMomenta.push_back(v - vpar);
00172 }
00173 calcM(threeMomenta, val, axis);
00174 _thrusts.push_back(sqrt(val) / momentumSum);
00175 if (axis.x() < 0) axis = -axis;
00176 _thrustAxes.push_back(axis.unit());
00177
00178
00179 if (_thrustAxes[0].dot(_thrustAxes[1]) < 1e-10) {
00180 axis = _thrustAxes[0].cross(_thrustAxes[1]);
00181 _thrustAxes.push_back(axis);
00182 val = 0.0;
00183 for (ParticleVector::const_iterator p = fs.particles().begin(); p != fs.particles().end(); ++p) {
00184 val += fabs(axis * p->getMomentum().vect());
00185 }
00186 _thrusts.push_back(val / momentumSum);
00187 } else {
00188 _thrusts.push_back(-1.0);
00189 _thrustAxes.push_back(Vector3());
00190 }
00191
00192 }
00193
00194
00195 void Thrust::project(const Event& e) {
00196 const FinalState& fs = e.applyProjection(*_fsproj);
00197 calcThrust(fs);
00198 }
00199
00200
00201 }