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