41 #include "TLorentzRotation.h"
44 #include "conversionUtils.hpp"
45 #include "factorial.hpp"
50 using namespace boost;
54 bool isobarAmplitude::_debug =
false;
57 isobarAmplitude::isobarAmplitude()
59 _useReflectivityBasis(true),
60 _boseSymmetrize (true),
61 _isospinSymmetrize (true),
62 _doSpaceInversion (false),
68 : _useReflectivityBasis(true),
69 _boseSymmetrize (true),
70 _isospinSymmetrize (true),
71 _doSpaceInversion (false),
86 printErr <<
"null pointer to decay topology. aborting." << endl;
89 if (not decay->checkTopology()) {
90 printErr <<
"decay does not have the correct topology. aborting." << endl;
93 if (not decay->checkConsistency()) {
94 printErr <<
"decay is not consistent. aborting." << endl;
106 vector<unsigned int> identityPermMap;
107 for (
unsigned int i = 0;
i <
_decay->nmbFsParticles() ; ++
i)
108 identityPermMap.push_back(
i);
112 printErr <<
"Could not initialize amplitude symetrization maps." << endl;
125 if (nmbSymTerms < 1) {
126 printErr <<
"array of symmetrization terms is empty. make sure isobarAmplitude::init() "
127 <<
"was called. cannot calculate amplitude. returning 0." << endl;
131 complex<double> amp = 0;
132 for (
unsigned int i = 0;
i < nmbSymTerms; ++
i)
140 const TLorentzVector& XLv)
142 TLorentzVector beam = beamLv;
143 TLorentzVector X = XLv;
144 const TVector3 yGjAxis = beam.Vect().Cross(X.Vect());
147 rot1.RotateZ(piHalf - yGjAxis.Phi());
148 rot1.RotateX(yGjAxis.Theta() - piHalf);
152 TLorentzRotation boost;
153 boost.Boost(-X.BoostVector());
157 rot2.RotateY(-signum(beam.X()) * beam.Theta());
160 gjTransform.Transform(boost);
161 gjTransform.Transform(rot2);
170 printDebug <<
"space inverting final state momenta." << endl;
172 const TLorentzVector& beamLv =
_decay->productionVertex()->referenceLzVec();
173 const TLorentzVector& XLv =
_decay->XParticle()->lzVec();
174 const TLorentzRotation gjTrans =
gjTransform(beamLv, XLv);
175 _decay->transformFsParticles(gjTrans);
177 for (
unsigned int i = 0;
i <
_decay->nmbFsParticles(); ++
i) {
179 const TLorentzVector& fsPartLv = part->lzVec();
180 part->setLzVec(TLorentzVector(-fsPartLv.Vect(), fsPartLv.E()));
183 _decay->transformFsParticles(gjTrans.Inverse());
191 printDebug <<
"reflecting final state momenta through production plane." << endl;
193 const TLorentzVector& beamLv =
_decay->productionVertex()->referenceLzVec();
194 const TLorentzVector& XLv =
_decay->XParticle()->lzVec();
195 const TLorentzRotation gjTrans =
gjTransform(beamLv, XLv);
196 _decay->transformFsParticles(gjTrans);
198 for (
unsigned int i = 0;
i <
_decay->nmbFsParticles(); ++
i) {
200 const TLorentzVector& fsPartLv = part->lzVec();
201 part->setLzVec(TLorentzVector(fsPartLv.X(), -fsPartLv.Y(), fsPartLv.Z(), fsPartLv.E()));
204 _decay->transformFsParticles(gjTrans.Inverse());
218 const bool topVertex)
const
221 const particlePtr& daughter1 = vertex->daughter1();
222 const particlePtr& daughter2 = vertex->daughter2();
223 complex<double> ampSum = 0;
224 for (
int lambda1 = -daughter1->J(); lambda1 <= +daughter1->J(); lambda1 += 2) {
226 daughter1->setSpinProj(lambda1);
229 complex<double> daughter1Amp = 0;
230 if (daughter1Vertex) {
231 daughter1Amp = twoBodyDecayAmplitudeSum(daughter1Vertex,
false);
234 for (
int lambda2 = -daughter2->J(); lambda2 <= +daughter2->J(); lambda2 += 2) {
236 daughter2->setSpinProj(lambda2);
239 complex<double> daughter2Amp = 0;
240 if (daughter2Vertex) {
241 daughter2Amp = twoBodyDecayAmplitudeSum(daughter2Vertex,
false);
244 complex<double> parentAmp = twoBodyDecayAmplitude(vertex, topVertex);
245 complex<double> amp = parentAmp * daughter1Amp * daughter2Amp;
247 printDebug <<
"amplitude term for : "
248 << parent->name() <<
" [lambda = " << spinQn(parent->spinProj()) <<
"] -> "
249 << daughter1->name() <<
" [lambda = " << spinQn(lambda1 ) <<
"] + "
250 << daughter2->name() <<
" [lambda = " << spinQn(lambda2 ) <<
"] = "
251 <<
"parent amp. = " << maxPrecisionDouble(parentAmp)
252 <<
" * daughter_1 amp = " << maxPrecisionDouble(daughter1Amp)
253 <<
" * daughter_2 amp = " << maxPrecisionDouble(daughter2Amp) <<
" = "
254 << maxPrecisionDouble(amp) << endl;
259 printDebug <<
"decay amplitude for " << *vertex <<
" = " << maxPrecisionDouble(ampSum) << endl;
268 if (not
_decay->revertMomenta(fsPartPermMap)) {
269 printErr <<
"problems reverting momenta in decay topology. cannot calculate amplitude. "
270 <<
"returning 0." << endl;
284 vector<symTermMap> isoSymTermMaps;
285 vector<symTermMap> boseSymTermMaps;
286 unsigned int nmbIsoSymTerms = 0;
287 unsigned int nmbBoseSymTerms = 0;
290 isoSymTermMaps =
_decay->getIsospinSymmetrization();
291 nmbIsoSymTerms = isoSymTermMaps.size();
292 if (nmbIsoSymTerms < 1) {
293 printErr <<
"array of isospin-symmetrization terms is empty. "
294 <<
"cannot isospin-symmetrize amplitude." << endl;
297 if (nmbIsoSymTerms == 1) {
298 printInfo <<
"no isospin symmetrization needed for this amplitude." << endl;
299 isoSymTermMaps[0].factor = 1;
302 bool isoPermMapsOkay =
true;
303 for (
unsigned int i = 0;
i < nmbIsoSymTerms; ++
i)
304 if (isoSymTermMaps[
i].fsPartPermMap.size() !=
_decay->nmbFsParticles()) {
305 printErr <<
"final-state permutation map for isospin symmetrization has wrong size = "
306 << isoSymTermMaps[
i].fsPartPermMap.size() <<
" expected "
307 <<
_decay->nmbFsParticles() <<
" . cannot isospin-symmetrize amplitude." << endl;
308 isoPermMapsOkay =
false;
310 if (not isoPermMapsOkay)
312 printInfo <<
"Found " << nmbIsoSymTerms <<
" isospin symmetrization terms." << endl;
316 boseSymTermMaps =
_decay->getBoseSymmetrization();
317 nmbBoseSymTerms = boseSymTermMaps.size();
318 if (nmbBoseSymTerms < 1) {
319 printErr <<
"array of Bose-symmetrization terms is empty. "
320 <<
"cannot Bose-symmetrize amplitude." << endl;
323 if (nmbBoseSymTerms == 1) {
324 printInfo <<
"no Bose symmetrization needed for this amplitude." << endl;
326 printInfo <<
"Found " << nmbBoseSymTerms <<
" Bose symmetrization terms." << endl;
329 if(nmbIsoSymTerms + nmbBoseSymTerms > 0) {
332 for(
unsigned int iso_i = 0; iso_i < nmbIsoSymTerms; ++iso_i) {
333 complex<double> isoFactor = isoSymTermMaps[iso_i].factor;
334 vector<unsigned int> isoSymTermMap = isoSymTermMaps[iso_i].fsPartPermMap;
335 for(
unsigned int bose_i = 0; bose_i < nmbBoseSymTerms; ++bose_i) {
336 complex<double> boseFactor = boseSymTermMaps[bose_i].factor;
337 vector<unsigned int> boseSymTermMap = boseSymTermMaps[bose_i].fsPartPermMap;
338 vector<unsigned int> newSymTermMap(isoSymTermMap.size(), 0);
339 assert(isoSymTermMap.size() == boseSymTermMap.size());
340 for(
unsigned int i = 0;
i < boseSymTermMap.size(); ++
i) {
341 newSymTermMap[
i] = boseSymTermMap[isoSymTermMap[
i]];
343 complex<double> newFactor = isoFactor * boseFactor;
349 printDebug <<
"Found the folloing symmetrization parametrization:" << endl;
350 cout <<
"isospin terms: " << endl;
351 for(
unsigned int i = 0;
i < nmbIsoSymTerms; ++
i) {
352 vector<unsigned int> map = isoSymTermMaps[
i].fsPartPermMap;
353 cout << isoSymTermMaps[
i].factor <<
": [" << map[0];
354 for(
unsigned int j = 1; j < map.size(); ++j) {
355 cout <<
", " << map[j];
359 cout <<
"Bose terms: " << endl;
360 for(
unsigned int i = 0;
i < nmbBoseSymTerms; ++
i) {
361 vector<unsigned int> map = boseSymTermMaps[
i].fsPartPermMap;
362 cout << boseSymTermMaps[
i].factor <<
": [" << map[0];
363 for(
unsigned int j = 1; j < map.size(); ++j) {
364 cout <<
", " << map[j];
368 cout <<
"combined terms: " << endl;
372 for(
unsigned int j = 1; j < map.size(); ++j) {
373 cout <<
", " << map[j];
387 out <<
name() <<
": " << endl
389 <<
" Bose symmetrization .............. " << enDisabled(
_boseSymmetrize ) << endl
391 <<
" space inversion of FS momenta .... " << enDisabled(
_doSpaceInversion ) << endl
392 <<
" reflection through prod. plane ... " << enDisabled(
_doReflection ) << endl;