diff --git a/Hadronization/ColourReconnector.cc b/Hadronization/ColourReconnector.cc --- a/Hadronization/ColourReconnector.cc +++ b/Hadronization/ColourReconnector.cc @@ -1,3797 +1,3797 @@ // -*- C++ -*- // // ColourReconnector.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ColourReconnector class. // #include "ColourReconnector.h" #include "Cluster.h" #include <ThePEG/Utilities/DescribeClass.h> #include <ThePEG/Repository/UseRandom.h> #include <ThePEG/PDT/StandardMatchers.h> #include <ThePEG/Persistency/PersistentOStream.h> #include <ThePEG/Persistency/PersistentIStream.h> #include <ThePEG/Interface/Switch.h> #include <ThePEG/Interface/Reference.h> #include <ThePEG/Interface/Parameter.h> #include "Herwig/MatrixElement/Matchbox/CVolver/ColourFlows.h" #include "Herwig/Utilities/Maths.h" #include "Herwig/Utilities/expm-1.h" #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/io.hpp> using namespace Herwig; using CluVecIt = ColourReconnector::CluVecIt; using Constants::pi; using Constants::twopi; DescribeClass<ColourReconnector,Interfaced> describeColourReconnector("Herwig::ColourReconnector","Herwig.so"); IBPtr ColourReconnector::clone() const { return new_ptr(*this); } IBPtr ColourReconnector::fullclone() const { return new_ptr(*this); } void ColourReconnector::rearrange(ClusterVector & clusters) { if (_clreco == 0) return; // need at least two clusters if (clusters.size() < 2) return; if (0) { CVolver::ColourFlow c1({0,1,2}); CVolver::ColourFlow c2({1,0,2}); for (const auto & p : c1.permutation()) { std::cout << "c1 = " << p<< std::endl; } for (const auto & p : c2.permutation()) { std::cout << "c2 = " << p<< std::endl; } std::cout << "<c2|c1> = " << c2.scalarProduct(c1) << std::endl; std::cout << "<c1|c2> = " << c1.scalarProduct(c2) << std::endl; std::set<CVolver::ColourFlow> setCF = CVolver::ColourFlow::allFlows(4); for (const auto & perm : setCF) { for (const auto & p : perm.permutation()) std::cout << p << " "; std::cout << std::endl; } for (const auto & perm1 : setCF) { for (const auto & perm2 : setCF) { std::cout << perm1.scalarProduct(perm2) << " "; } std::cout << std::endl; } std::cout << "Correct matrix?:" << std::endl; for (const auto & perm1 : setCF) { for (auto perm2 : setCF) { std::cout << perm1.scalarProduct(perm2.conjugate()) << " "; } std::cout << std::endl; } CVolver::ColourFlow c4({1,2,0}); std::cout << "<c4|c4> = " << c4.scalarProduct(c4) << std::endl; // std::cout << "s(c1,c2) = Nc^" << c1.scalarProduct(c2)<< std::endl; } // std::cout << "size before = "<< clusters.size() << std::endl; for (unsigned int i = 0; i < _crIterations; i++) { // do the colour reconnection switch (_algorithm) { case 0: _doRecoPlain(clusters); break; case 1: // TODO Non-dynamic _doRecoStatistical(clusters); break; case 2: _doRecoBaryonic(clusters); break; case 3: // TODO Non-dynamic _doRecoBaryonicMesonic(clusters); break; case 4: _doRecoBaryonicDiquarkCluster(clusters); break; default: assert(false); } } // std::cout << "size after = "<< clusters.size() << std::endl; } namespace { inline int hasDiquark(const ClusterPtr & cit) { int res = 0; for (unsigned int i = 0; i<(cit)->numComponents(); i++) { if (DiquarkMatcher::Check(*((cit)->particle(i)->dataPtr()))) { res++; } } return res; } double calculateRapidityRF(const Lorentz5Momentum & q1, const Lorentz5Momentum & p2) { //calculate rapidity wrt the direction of q1 //angle between the particles in the RF of cluster of q1 // calculate the z component of p2 w.r.t the direction of q1 if(q1.rho2()==ZERO) return 0.; const Energy pz = p2.vect() * q1.vect().unit(); if ( pz == ZERO ) return 0.; // Transverse momentum of p2 w.r.t the direction of q1 const Energy pt = sqrt(p2.vect().mag2() - sqr(pz)); // Transverse mass pf p2 w.r.t to the direction of q1 const Energy mtrans = sqrt(p2.mass()*p2.mass() + (pt*pt)); // Correct formula const double y2 = log((p2.t() + abs(pz))/mtrans); return ( pz < ZERO ) ? -y2 : y2; } } Energy2 ColourReconnector::_clusterMassSum(const PVector & q, const PVector & aq) const { const size_t nclusters = q.size(); assert (aq.size() == nclusters); Energy2 sum = ZERO; for (size_t i = 0; i < nclusters; i++) sum += ( q[i]->momentum() + aq[i]->momentum() ).m2(); return sum; } double ColourReconnector::_displacement(tcPPtr p, tcPPtr q) const { double deltaRap = (p->rapidity() - q->rapidity()); double deltaPhi = fabs(p->momentum().phi() - q->momentum().phi()); // keep deltaPhi's below Pi due to periodicity if (deltaPhi > M_PI) deltaPhi-=M_PI; return sqrt(deltaRap * deltaRap + deltaPhi * deltaPhi); } /** * Computes circular Mean of three angles alpha, beta, gamma * */ static double circularMean(double alpha, double beta, double gamma) { double xMean=(cos(alpha)+cos(beta)+cos(gamma))/3.0; double yMean=(sin(alpha)+sin(beta)+sin(gamma))/3.0; // to make the function fail-save if (xMean==0 && yMean==0) return M_PI; return atan2(yMean,xMean); } namespace { // ColourFlow for 3 colour flows for baryon state // ordered permutations by one transposition // sign of permutations # of difference // |1> = |123> + 0 // |2> = |132> - 1 // |3> = |213> - 1 // |4> = |231> + 2 // |5> = |312> + 2 // |6> = |321> - 1 int signPermutationState(int i); int signPermutationState(int i) { if (i==0 || i==3 || i==4) return 1; else if (i==1 || i==2 || i==5) return -1; else assert(false); } // ColourFlow scalar product matrix for 3 // colour flows in the following basis // |1> = |123> + 0 // |2> = |132> - 1 // |3> = |213> - 1 // |4> = |231> + 2 // |5> = |312> + 2 // |6> = |321> - 1 unsigned int scalarProducts(int i, int j); unsigned int scalarProducts(int i, int j) { // Verified for i,j < 3! and 3 colour flows if (i>j) return scalarProducts(j,i); // TODO need to restore Nc dependence unsigned int Nc=3; if (i==j) return Nc*Nc*Nc; switch(i) { case 0: { if (j==1 || j==2 || j==5) return Nc*Nc; else if (j==3 || j==4) return Nc; else return Nc*Nc*Nc; break; } case 1: { if (j==0 || j==3 || j==4) return Nc*Nc; else if (j==2 || j==5) return Nc; else return Nc*Nc*Nc; break; } case 2: { if (j==0 || j==3 || j==4) return Nc*Nc; else if (j==1 || j==5) return Nc; else return Nc*Nc*Nc; break; } case 3: { if (j==1 || j==2 || j==5) return Nc*Nc; else if (j==0 || j==4) return Nc; else return Nc*Nc*Nc; break; } case 4: { if (j==1 || j==2 || j==5) return Nc*Nc; else if (j==0 || j==3) return Nc; else return Nc*Nc*Nc; break; } case 5: { if (j==0 || j==3 || j==4) return Nc*Nc; else if (j==1 || j==2) return Nc; else return Nc*Nc*Nc; break; } default: assert(false); } return Nc; } } std::unordered_map<int,double> ColourReconnector::_reconnectionAmplitudesCF2 (const ClusterPtr & c1, const ClusterPtr & c2) const{ // Verified according to convention of analytics/matrices2_BCR.nb and not // according to https://arxiv.org/abs/1808.06770 // The same convention as in https://arxiv.org/abs/1808.06770 can be obtained by // the mapping 1->1;2->4;3->2;4->3 (here->paper) Lorentz5Momentum p1 = c1->colParticle()->momentum(); Lorentz5Momentum p2 = c1->antiColParticle()->momentum(); Lorentz5Momentum p3 = c2->colParticle()->momentum(); Lorentz5Momentum p4 = c2->antiColParticle()->momentum(); Energy mLightestConstMass = 1000*GeV; for (const auto & id : _hadronSpectrum->lightHadronizingQuarks() ) { if (getParticleData(id)->constituentMass()<mLightestConstMass) mLightestConstMass = getParticleData(id)->constituentMass(); } double M12 = (p1 + p2).m2()/sqr(2*mLightestConstMass*_dynamicCRscale); double M24 = (p2 + p4).m2()/sqr(2*mLightestConstMass*_dynamicCRscale); double M13 = (p1 + p3).m2()/sqr(2*mLightestConstMass*_dynamicCRscale); double M23 = (p2 + p3).m2()/sqr(2*mLightestConstMass*_dynamicCRscale); double M14 = (p1 + p4).m2()/sqr(2*mLightestConstMass*_dynamicCRscale); double M34 = (p3 + p4).m2()/sqr(2*mLightestConstMass*_dynamicCRscale); if ( M12 < 1.0 || M24 < 1.0 || M13 < 1.0 || M23 < 1.0 || M14 < 1.0 || M34 < 1.0 ) { throw Exception() << "DynamicCR scale "<< _dynamicCRscale << " too high in ColourReconnector" << " must be less than 1" << " invariant masses:\n" << "M12 = " << sqrt(M12*sqr(2*mLightestConstMass*_dynamicCRscale))/GeV << "\n" << "M24 = " << sqrt(M24*sqr(2*mLightestConstMass*_dynamicCRscale))/GeV << "\n" << "M13 = " << sqrt(M13*sqr(2*mLightestConstMass*_dynamicCRscale))/GeV << "\n" << "M23 = " << sqrt(M23*sqr(2*mLightestConstMass*_dynamicCRscale))/GeV << "\n" << "M14 = " << sqrt(M14*sqr(2*mLightestConstMass*_dynamicCRscale))/GeV << "\n" << "M34 = " << sqrt(M34*sqr(2*mLightestConstMass*_dynamicCRscale))/GeV << "\n" << Exception::eventerror; } double alphaQCD=_dynamicCRalphaS; // TODO missing factor of two due to sum_i!=j // can be fixed by twopi->pi double logSqrOmega12=alphaQCD*pow(log(M12),2)/(2.0*twopi); double logSqrOmega24=alphaQCD*pow(log(M24),2)/(2.0*twopi); double logSqrOmega13=alphaQCD*pow(log(M13),2)/(2.0*twopi); double logSqrOmega23=alphaQCD*pow(log(M23),2)/(2.0*twopi); double logSqrOmega14=alphaQCD*pow(log(M14),2)/(2.0*twopi); double logSqrOmega34=alphaQCD*pow(log(M34),2)/(2.0*twopi); // TODO need to restore Nc dependence double Nc=3.0; double U11,U21; // relevant matrix elements switch (_dynamicCR) { case 1: { double a = (logSqrOmega34 + logSqrOmega12)/2.0; double b = (logSqrOmega14 + logSqrOmega23)/2.0; double c = (logSqrOmega13 + logSqrOmega24)/2.0; // TODO need to restore Nc dependence double sqrtDelta=sqrt(9*a*a-4*c*(a+b)-14*a*b+9*b*b+4*c*c); U11=sqrtDelta/tanh(sqrtDelta/2.0)+3*(b-a); U21=2*(c-b); break; } case 2: { // not Exponentiated soft anomalous dimension // i.e. eq (5.2) Omega matrix in https://arxiv.org/pdf/1808.06770 // TODO need to restore Nc dependence U11=-Nc*0.5*(logSqrOmega34+logSqrOmega12); U21= 0.5*(logSqrOmega13+logSqrOmega24-(logSqrOmega14+logSqrOmega23)); break; } default: assert(false); } // TODO need to restore Nc dependence double TransAmpNoCR = Nc*(Nc * U11 + U21); double TransAmpMesonicCR = Nc*(U11 + Nc * U21); std::unordered_map<int,double> amplitudes; // No Colour Reconnection amplitude amplitudes[123] = TransAmpNoCR; // Mesonic Colour Reconnection amplitude amplitudes[213] = TransAmpMesonicCR; return amplitudes; } std::tuple<double,double,double> ColourReconnector::_dynamicRecoProbabilitiesCF2(const ClusterPtr & c1, const ClusterPtr & c2, bool diquarkCR) const{ std::unordered_map<int,double> amplitudes = _reconnectionAmplitudesCF2 (c1, c2); double pNoCR; double pMesonicCR; double pDiquarkCR = 0.0; double TransAmpNoCR = sqr(amplitudes[123]); double TransAmpMesonicCR = _becomesColour8Cluster(c1,c2) ? 0.0:sqr(amplitudes[213]); double sum = TransAmpNoCR + TransAmpMesonicCR; double PhaseSpace=0.0; if (diquarkCR && _canMakeDiquarkCluster(c1,c2,PhaseSpace) && !hasDiquark(c1) && !hasDiquark(c2)) { // TODO need to restore Nc dependence double ND = 2.0/sqrt(3.0); // sqrt(2*(Nc-1.0)/Nc); double TransAmpDiquarkCR = sqr((amplitudes[123]-amplitudes[213])/ND); sum += _phaseSpaceDiquarkFission ? PhaseSpace*TransAmpDiquarkCR:TransAmpDiquarkCR; pDiquarkCR = TransAmpDiquarkCR/sum; if (_phaseSpaceDiquarkFission) pDiquarkCR*=PhaseSpace; assert( pDiquarkCR<=1.0 && pDiquarkCR>=0.0); } pNoCR = TransAmpNoCR/sum; pMesonicCR = TransAmpMesonicCR/sum; assert( pNoCR<=1.0 && pNoCR>=0.0); assert( pMesonicCR<=1.0 && pMesonicCR>=0.0); if (_debug) { Lorentz5Momentum p1col = (c1)->colParticle()->momentum(); Lorentz5Momentum p1acol = (c1)->antiColParticle()->momentum(); Lorentz5Momentum p2col = (c2)->colParticle()->momentum(); Lorentz5Momentum p2acol = (c2)->antiColParticle()->momentum(); const Boost boostv1=-c1->momentum().boostVector(); const Boost boostv2=-c2->momentum().boostVector(); p1col .boost(boostv1); p1acol.boost(boostv1); p2col .boost(boostv1); p2acol.boost(boostv1); double rap1c= calculateRapidityRF(p1acol,p2col); double rap1a= calculateRapidityRF(p1acol,p2acol); double pT1c = p2col.vect() .perp(p1acol.vect())/GeV; double pT1a = p2acol.vect().perp(p1acol.vect())/GeV; p1col .boost(-boostv1); p1acol.boost(-boostv1); p2col .boost(-boostv1); p2acol.boost(-boostv1); p1col .boost(boostv2); p1acol.boost(boostv2); p2col .boost(boostv2); p2acol.boost(boostv2); double rap2c= calculateRapidityRF(p2acol,p1col); double rap2a= calculateRapidityRF(p2acol,p1acol); double pT2c = p1col.vect() .perp(p1acol.vect())/GeV; double pT2a = p1acol.vect().perp(p1acol.vect())/GeV; // calculate the rapidity of the other constituents of the clusters // w.r.t axis of p1anticol.vect.unit // const double rapq = calculateRapidityRF(p1anticol,p2col); ofstream out("WriteOut/kinematicRecoProbability.dat", std::ios::app); out << pNoCR << "\t" << pMesonicCR << "\t" << pDiquarkCR << "\t"; out << rap1c << "\t" << rap1a << "\t" << pT1c << "\t" << pT1a << "\t"; out << rap2c << "\t" << rap2a << "\t" << pT2c << "\t" << pT2a << "\n"; out.close(); } return {pNoCR, pMesonicCR, pDiquarkCR}; } int ColourReconnector::_stateToPermutation(const int i) const { switch (i) { case 0: // Baryonic CR return 0; // Mesonic CR's case 1: return 123; case 2: return 132; case 3: return 213; case 4: return 231; case 5: return 312; case 6: return 321; default: assert(false); } } Selector<int> ColourReconnector::_selector(const ClusterVector & clusters, bool diquarkCR) const { switch (clusters.size()) { case 2: return getProbabilities2CF(clusters[0], clusters[1], diquarkCR); break; case 3: { if (_dynamicCR) { return _selectorCF3(clusters, diquarkCR); // return _selectorCF3(clusters, false); } else { Selector<int> CRoptions; double sum=_preco+_precoBaryonic; const int NpossibilitiesMCR = 6; int state; for (int i = 0; i < NpossibilitiesMCR; i++) { state = _stateToPermutation(i+1); if (_isColour8Forbidden(state,clusters)) continue; CRoptions.insert(_preco, state); } CRoptions.insert(_precoBaryonic, 0); if (diquarkCR) { const int N=3; bool first=false; // Here i is the index of the quark and j of the antiquark // which will be connected to each other (other partons will be // forming the diquark cluster if kinematically viable) double PhaseSpace; for (int i = 1; i <= N; i++) { for (int j = 1; j <= N; j++) { state = -(10*i+j); if (_isColour8Forbidden(state,clusters)) continue; if (_canMakeDiquarkCluster( clusters[i%3]->colParticle(), clusters[(i+1)%3]->colParticle(), clusters[j%3]->antiColParticle(), clusters[(j+1)%3]->antiColParticle(),PhaseSpace)){ CRoptions.insert(_precoDiquark*PhaseSpace, state); if (first){ sum+=_precoDiquark*PhaseSpace; first=false; } } } } } // no CR probability CRoptions.insert((1-sum) > 0 ? (1-sum):0, _stateToPermutation(1)); return CRoptions; } } default: assert(false); } } namespace { int orientation(const ClusterPtr & c1,const ClusterPtr & c2){ Lorentz5Momentum cl1 = c1->momentum(); const Boost boostv(-cl1.boostVector()); // boost constituents of cl into RF of cl // Lorentz5Momentum p1col = (*cl)->colParticle()->momentum(); Lorentz5Momentum p1anticol = c1->antiColParticle()->momentum(); // p1col.boost(boostv); p1anticol.boost(boostv); // boost constituents of cit into RF of cl Lorentz5Momentum p2col = c2->colParticle()->momentum(); Lorentz5Momentum p2anticol = c2->antiColParticle()->momentum(); p2col.boost(boostv); p2anticol.boost(boostv); // calculate the rapidity of the other constituents of the clusters // w.r.t axis of p1anticol.vect.unit const double rapq = calculateRapidityRF(p1anticol,p2col); const double rapqbar = calculateRapidityRF(p1anticol,p2anticol); if (rapq>0.0 && rapqbar<0.0 ) { // Mesonic Type return 1; } else if (rapq<0.0 && rapqbar>0.0 ) { // diquark Type return -1; } else { return 0; } } } bool ColourReconnector::_isColour8Forbidden(int state, const ClusterVector & clusters) const{ if (state>0){ int c1 = ((state/100) % 4) -1; int c2 = ((state-(c1+1)*100)/10 % 4) -1; int c3 = ((state-(c1+1)*100-(c2+1)*10) % 4) -1; assert(c1>=0 && c1<3); assert(c2>=0 && c2<3); assert(c3>=0 && c3<3); assert(c1!=c2 && c1!=c3 && c2 !=c3); assert(state==(c1+1)*100+(c2+1)*10+(c3+1)); if (c1!=0 && _isColour8(clusters[0]->colParticle(),clusters[c1]->antiColParticle())) return true; if (c2!=1 && _isColour8(clusters[1]->colParticle(),clusters[c2]->antiColParticle())) return true; if (c3!=2 && _isColour8(clusters[2]->colParticle(),clusters[c3]->antiColParticle())) return true; // int config1 = (0==c1) ? 1:orientation(clusters[0],clusters[c1]); // int config2 = (1==c2) ? 1:orientation(clusters[1],clusters[c2]); // int config3 = (2==c3) ? 1:orientation(clusters[2],clusters[c3]); // if (!(config1>0 && config2>0 && config3>0)) // return true; // if (!(config1<0 || config2<0 || config3<0)) // return true; // if (!(config1>=0 && config2>=0 && config3>=0)) // return true; } else if (state<0){ int i = -state/10 -1; int j = -state - 10*(i+1) - 1; assert(-state==((i+1)*10+(j+1))); if (_isColour8(clusters[i]->colParticle(),clusters[j]->antiColParticle())) return true; int config=orientation(clusters[i],clusters[j]); if (!(config>0)) return true; } return false; } Selector<int> ColourReconnector::_selectorCF3(const ClusterVector & clusters, bool diquarkCR) const { std::unordered_map<int, double> amplitudes = _reconnectionAmplitudesSGE(clusters); double sum2 = 0; double sumBaryon = 0; double NB=2.0/sqrt(3.0); Selector<int> CRoptions; double amp2; const int NpossibilitiesMCR = 6; int state; for (int i = 0; i < NpossibilitiesMCR; i++) { state=_stateToPermutation(i+1); sumBaryon += amplitudes[state]*signPermutationState(i)/NB; if (_isColour8Forbidden(state,clusters)) continue; amp2 = sqr(amplitudes[state]); sum2 += amp2; CRoptions.insert(amp2, state); } sum2+=sumBaryon*sumBaryon; if (diquarkCR) { // TODO need to restore Nc dependence double ND=2.0/sqrt(3.0); // sqrt(2*(Nc-1.0)/Nc) const int N=3; // TODO need to restore Nc dependence double NDiqFACT=1.0; // sqrt(2*(Nc-1.0)/Nc) double PhaseSpace; int perm1; int perm2; // Here i is the index of the quark and j of the antiquark // which will be connected to each other (other partons will be // forming the diquark cluster if kinematically viable) for (int i = 1; i <= N; i++) { for (int j = 1; j <= N; j++) { // TODO add here a check if we can make Diquarkclsuter // std::cout << "i = "<<i-1 <<" j = "<<j-1 << std::endl; // std::cout << "c1= "<<i%3 <<" a1= "<<j%3 << std::endl; // std::cout << "c2= "<<(i+1)%3 <<" a2= "<<(j+1)%3 << std::endl; assert(i%3!=(i-1)); assert((i+1)%3!=(i-1)); assert(j%3!=(j-1)); assert((j+1)%3!=(j-1)); if (_canMakeDiquarkCluster( clusters[i%3]->colParticle(), clusters[(i+1)%3]->colParticle(), clusters[j%3]->antiColParticle(), clusters[(j+1)%3]->antiColParticle() ,PhaseSpace)) { state = -(10*i+j); if (_isColour8Forbidden(state,clusters)) continue; switch (i) { case 1: { perm1 = 100*j + 10*(((j+1)%3)+1) + (((j)%3)+1); perm2 = 100*j + 10*(((j)%3)+1) + (((j+1)%3)+1); amp2 = sqr((amplitudes[perm1] - amplitudes[perm2])/ND); amp2*=NDiqFACT; sum2 += amp2; if (amp2==0 || amplitudes[perm2]==0 || amplitudes[perm1]==0 ){ std::cout << "amp23 = "<< amp2 << std::endl; std::cout << "perm13 = "<< perm1 << std::endl; std::cout << "perm23 = "<< perm2 << std::endl; } assert((((j)%3)+1)!=j); assert((((j+1)%3)+1)!=j); CRoptions.insert(PhaseSpace*amp2*_diquarkEnhancementFactor, state); break; } case 2: { perm1 = 100*(((j)%3)+1) + 10*j + (((j+1)%3)+1); perm2 = 100*(((j+1)%3)+1) + 10*j + (((j)%3)+1); amp2 = sqr((amplitudes[perm1] - amplitudes[perm2])/ND); amp2*=NDiqFACT; sum2 += amp2; if (amp2==0 || amplitudes[perm2]==0 || amplitudes[perm1]==0 ){ std::cout << "amp22 = "<< amp2 << std::endl; std::cout << "perm12 = "<< perm1 << std::endl; std::cout << "perm22 = "<< perm2 << std::endl; } assert((((j)%3)+1)!=j); assert((((j+1)%3)+1)!=j); CRoptions.insert(PhaseSpace*amp2*_diquarkEnhancementFactor, state); break; } case 3: { perm1 = 100*(((j+1)%3)+1) + 10*(((j)%3)+1) + j; perm2 = 100*(((j)%3)+1) + 10*(((j+1)%3)+1) + j; amp2 = sqr((amplitudes[perm1] - amplitudes[perm2])/ND); amp2*=NDiqFACT; sum2 += amp2; if (amp2==0 || amplitudes[perm2]==0 || amplitudes[perm1]==0 ){ std::cout << "amp21 = "<< amp2 << std::endl; std::cout << "perm11 = "<< perm1 << std::endl; std::cout << "perm21 = "<< perm2 << std::endl; } assert((((j)%3)+1)!=j); assert((((j+1)%3)+1)!=j); CRoptions.insert(PhaseSpace*amp2*_diquarkEnhancementFactor, state); break; } default: assert(false); } // std::cout << CRoptions << std::endl; } } } } // double BaryonRate = sumBaryon*sumBaryon/sum2; // std::cout << "BaryonRate "<<BaryonRate <<"\n"; // std::cout << "NoRecoRate "<<sqr(amplitudes[_stateToPermutation(1)])/sum2 <<"\n"; // std::cout << "MeRecoRate "<<1-BaryonRate-sqr(amplitudes[_stateToPermutation(1)])/sum2 <<"\n"; CRoptions.insert(sumBaryon*sumBaryon*_baryonEnhancementFactor, _stateToPermutation(0)); //TODO insert diquarks return CRoptions; } // TODO HERE add context to the nonTrivialInitialState -> |D> or similar std::unordered_map<int, double> ColourReconnector::_reconnectionAmplitudesSGE(const ClusterVector & clusters, int nonTrivialInitialState) const { int size=clusters.size(); assert(clusters.size()<4); switch(size){ case 2: { const std::unordered_map<int, double> & amplitudes = _reconnectionAmplitudesCF2(clusters[0],clusters[1]); return amplitudes; } case 3: { std::unordered_map<int, double> amplitudes; if (clusters[0]->numComponents()!=2 || clusters[1]->numComponents()!=2 || clusters[2]->numComponents()!=2 || hasDiquark(clusters[0]) || hasDiquark(clusters[1]) || hasDiquark(clusters[2]) ) { std::cout << "reject config. should reject before somehow\n"; return amplitudes; } const int N=6; // 2*Nclu; double omIJ[N][N]; double alphaQCD=_dynamicCRalphaS; Lorentz5Momentum mom_i, mom_j; // Assumption in notebook analytics/matrices2_BCR.nb // Ordering of omIJ and scalarProds is according to {clu1_col, clu1_anti, clu2_col, clu2_anti,...} Energy mLightestConstMass = 1000*GeV; for (auto id : _hadronSpectrum->lightHadronizingQuarks() ) { if (getParticleData(id)->constituentMass()<mLightestConstMass) mLightestConstMass = getParticleData(id)->constituentMass(); } for (int i = 0; i < N; i++) { if ((i+1)%2==1) mom_i=clusters[i/2]->colParticle()->momentum(); else mom_i=clusters[(i-1)/2]->antiColParticle()->momentum(); for (int j = i+1; j < N; j++) { if ((j+1)%2==1) mom_j=clusters[j/2]->colParticle()->momentum(); else mom_j=clusters[(j-1)/2]->antiColParticle()->momentum(); double rho = (mom_i+mom_j).m2()/sqr(2*mLightestConstMass*_dynamicCRscale); if (rho < 1.0) { throw Exception() << "DynamicCR scale "<< _dynamicCRscale << " too high in ColourReconnector" << " must be less than 1" << " Found parton invariant mass combinations with invariant mass ratio "<< (mom_i+mom_j).m2()/sqr((mom_i.m()+mom_j.m())) << Exception::eventerror; } // TODO missing factor of two due to sum_i!=j // can be fixed by twopi->pi omIJ[i][j]=alphaQCD*pow(log(rho),2)/(2.0*twopi); } } boost::numeric::ublas::matrix<double> * Uevolve = new boost::numeric::ublas::matrix<double>(N,N); boost::numeric::ublas::matrix<double> Omega(N,N); // TODO need to restore Nc dependence int Nc = 3; // Verified Omega Matrix with analytics/matrices2_BCR.nb Omega(0,0) = - 0.5 * Nc * (omIJ[0][1]+omIJ[2][3]+omIJ[4][5]); Omega(1,0) = 0.5 * (omIJ[2][4]-omIJ[3][4]-omIJ[2][5]+omIJ[3][5]); Omega(2,0) = 0.5 * (omIJ[0][2]-omIJ[1][2]-omIJ[0][3]+omIJ[1][3]); Omega(3,0) = 0.0; Omega(4,0) = 0.0; Omega(5,0) = 0.5 * (omIJ[0][4]-omIJ[1][4]-omIJ[0][5]+omIJ[1][5]); Omega(0,1) = - 0.5 * (omIJ[2][3]-omIJ[2][4]-omIJ[3][5]+omIJ[4][5]); Omega(1,1) = - 0.5 * Nc * (omIJ[0][1]+omIJ[3][4]+omIJ[2][5]); Omega(2,1) = 0.0; Omega(3,1) = - 0.5 * (omIJ[0][3]-omIJ[1][3]-omIJ[0][4]+omIJ[1][4]); Omega(4,1) = 0.5 * (omIJ[0][2]-omIJ[1][2]-omIJ[0][5]+omIJ[1][5]); Omega(5,1) = 0.0; Omega(0,2) = - 0.5 * (omIJ[0][1]-omIJ[0][2]-omIJ[1][3]+omIJ[2][3]); Omega(1,2) = 0.0; Omega(2,2) = - 0.5 * Nc * (omIJ[1][2]+omIJ[0][3]+omIJ[4][5]); Omega(3,2) = - 0.5 * (omIJ[1][4]-omIJ[2][4]-omIJ[1][5]+omIJ[2][5]); Omega(4,2) = 0.5 * (omIJ[0][4]-omIJ[3][4]-omIJ[0][5]+omIJ[3][5]); Omega(5,2) = 0.0; Omega(0,3) = 0.0; Omega(1,3) = - 0.5 * (omIJ[0][1]-omIJ[1][3]-omIJ[0][4]+omIJ[3][4]); Omega(2,3) = - 0.5 * (omIJ[1][2]-omIJ[2][4]-omIJ[1][5]+omIJ[4][5]); Omega(3,3) = - 0.5 * Nc * (omIJ[0][3]+omIJ[1][4]+omIJ[2][5]); Omega(4,3) = 0.0; Omega(5,3) = 0.5 * (omIJ[0][2]-omIJ[2][3]-omIJ[0][5]+omIJ[3][5]); Omega(0,4) = 0.0; Omega(1,4) = - 0.5 * (omIJ[0][1]-omIJ[0][2]-omIJ[1][5]+omIJ[2][5]); Omega(2,4) = - 0.5 * (omIJ[0][3]-omIJ[0][4]-omIJ[3][5]+omIJ[4][5]); Omega(3,4) = 0.0; Omega(4,4) = - 0.5 * Nc * (omIJ[1][2]+omIJ[3][4]+omIJ[0][5]); Omega(5,4) = 0.5 * (omIJ[1][3]-omIJ[2][3]-omIJ[1][4]+omIJ[2][4]); Omega(0,5) = - 0.5 * (omIJ[0][1]-omIJ[0][4]-omIJ[1][5]+omIJ[4][5]); Omega(1,5) = 0.0; Omega(2,5) = 0.0; Omega(3,5) = 0.5 * (omIJ[0][2]-omIJ[0][3]-omIJ[2][5]+omIJ[3][5]); Omega(4,5) = - 0.5 * (omIJ[1][2]-omIJ[1][3]-omIJ[2][4]+omIJ[3][4]); Omega(5,5) = - 0.5 * Nc * (omIJ[2][3]+omIJ[1][4]+omIJ[0][5]); switch (_dynamicCR) { case 1: // Exponentiated *Uevolve=expm_pad(Omega); break; case 2: // NotExponentiated *Uevolve=Omega; break; default: assert(false); } // std::cout << *Uevolve << std::endl; // std::vector<double> Transition1toJ; // |<J|U|1>|^2 double amp1toJ; for (int J = 0; J < N; J++) { // amp1toJ is here for each J transition amplitude 1->J amp1toJ=0; for (int i = 0; i < N; i++) { // amp1toJ corresponds to the Uevolve operator applied to the |1> state // and projected by fixed <J| // The resulting amp1toJ is <J|U|1> // Should be correct this way // TODO : Generalize here to general starting states i.e. |1> -> |initial> amp1toJ+=(*Uevolve)(i,0)*scalarProducts(i,J); } if (std::isnan(amp1toJ) || std::isinf(amp1toJ)){ throw Exception() << "nan or inf transition probability in ColourReconnector::_reconnectionAmplitudesSGE" << Exception::runerror; } amplitudes[_stateToPermutation(J+1)] = amp1toJ; } delete Uevolve; return amplitudes; break; } default: { throw Exception() << "Found cluster set of "<<size<<" in ColourReconnector::_reconnectionAmplitudesSGE (can only handle 2 or 3 colour Flows)" << Exception::runerror; } } std::unordered_map<int, double> amplitudes; return amplitudes; } double ColourReconnector::_displacementBaryonic(tcPPtr q1, tcPPtr q2, tcPPtr q3) const { if (_junctionMBCR) { /** * Junction-like option i.e. displacement * from "junction centre" (mean rapidity/phi) */ double rap1=q1->rapidity(); double rap2=q2->rapidity(); double rap3=q3->rapidity(); double phi1=q1->momentum().phi(); double phi2=q2->momentum().phi(); double phi3=q3->momentum().phi(); double meanRap=(rap1 + rap2 + rap3)/3.0; // Use circularMean for defining a sensible mean of an angle double meanPhi=circularMean(phi1,phi2,phi3); double deltaPhi1=fabs(phi1-meanPhi); double deltaPhi2=fabs(phi2-meanPhi); double deltaPhi3=fabs(phi3-meanPhi); // keep deltaPhi's below Pi due to periodicity if (deltaPhi1>M_PI) deltaPhi1-=M_PI; if (deltaPhi2>M_PI) deltaPhi2-=M_PI; if (deltaPhi3>M_PI) deltaPhi3-=M_PI; double delR; delR = sqrt( (rap1-meanRap)*(rap1-meanRap) + deltaPhi1*deltaPhi1 ); delR += sqrt( (rap2-meanRap)*(rap2-meanRap) + deltaPhi2*deltaPhi2 ); delR += sqrt( (rap3-meanRap)*(rap3-meanRap) + deltaPhi3*deltaPhi3 ); return delR; } else { /* just summing up all possible 2 quark displacements */ return _displacement(q1, q2) + _displacement(q1, q3) + _displacement(q2, q3); } } bool ColourReconnector::_containsColour8(const ClusterVector & cv, const vector<size_t> & P) const { assert (P.size() == cv.size()); for (size_t i = 0; i < cv.size(); i++) { tcPPtr p = cv[i]->colParticle(); tcPPtr q = cv[P[i]]->antiColParticle(); if (_isColour8(p, q)) return true; } return false; } void ColourReconnector::_doRecoStatistical(ClusterVector & cv) const { const size_t nclusters = cv.size(); // initially, enumerate (anti)quarks as given in the cluster vector ParticleVector q, aq; for (size_t i = 0; i < nclusters; i++) { q.push_back( cv[i]->colParticle() ); aq.push_back( cv[i]->antiColParticle() ); } // annealing scheme Energy2 t, delta; Energy2 lambda = _clusterMassSum(q,aq); const unsigned _ntries = _triesPerStepFactor * nclusters; // find appropriate starting temperature by measuring the largest lambda // difference in some dry-run random rearrangements { vector<Energy2> typical; for (int i = 0; i < 10; i++) { const pair <int,int> toswap = _shuffle(q,aq,5); ParticleVector newaq = aq; swap (newaq[toswap.first], newaq[toswap.second]); Energy2 newlambda = _clusterMassSum(q,newaq); typical.push_back( abs(newlambda - lambda) ); } t = _initTemp * Math::median(typical); } // anneal in up to _annealingSteps temperature steps for (unsigned step = 0; step < _annealingSteps; step++) { // For this temperature step, try to reconnect _ntries times. Stop the // algorithm if no successful reconnection happens. unsigned nSuccess = 0; for (unsigned it = 0; it < _ntries; it++) { // make a random rearrangement const unsigned maxtries = 10; const pair <int,int> toswap = _shuffle(q,aq,maxtries); const int i = toswap.first; const int j = toswap.second; // stop here if we cannot find any allowed reconfiguration if (i == -1) break; // create a new antiquark vector with the two partons swapped ParticleVector newaq = aq; swap (newaq[i], newaq[j]); // Check if lambda would decrease. If yes, accept the reconnection. If no, // accept it only with a probability given by the current Boltzmann // factor. In the latter case we set p = 0 if the temperature is close to // 0, to avoid division by 0. Energy2 newlambda = _clusterMassSum(q,newaq); delta = newlambda - lambda; double prob = 1.0; if (delta > ZERO) prob = ( abs(t) < 1e-8*MeV2 ) ? 0.0 : exp(-delta/t); if (UseRandom::rnd() < prob) { lambda = newlambda; swap (newaq, aq); nSuccess++; } } if (nSuccess == 0) break; // reduce temperature t *= _annealingFactor; } // construct the new cluster vector ClusterVector newclusters; for (size_t i = 0; i < nclusters; i++) { ClusterPtr cl = new_ptr( Cluster( q[i], aq[i] ) ); newclusters.push_back(cl); } swap(newclusters,cv); return; } Selector <int> ColourReconnector::getProbabilities2CF(const ClusterPtr & c1, const ClusterPtr & c2, bool diquarkCR) const{ Selector <int> res; if (_dynamicCR) { double pNoCR; double pMCR; double pDCR; std::tie(pNoCR, pMCR, pDCR) = _dynamicRecoProbabilitiesCF2(c1, c2, diquarkCR); int orient= orientation(c1,c2); // std::cout <<"orient = "<<orient<<"\t" << pMCR << "\t"<<pDCR << "\t" << pNoCR<< "\n"; // Mesonic CR if ( orient>0 && !( _isColour8(c1->colParticle(), c2->antiColParticle()) || _isColour8(c2->colParticle(), c1->antiColParticle()) ) ) { res.insert(pMCR, 213); } if ( orient<0 && diquarkCR && pDCR>0.0 ) { // Diquark CR res.insert(pDCR*_diquarkEnhancementFactor, -213); } // No CR res.insert(pNoCR, 123); } else { double wMCR = _preco; double sum = 0.0; // Mesonic CR if ( !( _isColour8(c1->colParticle(), c2->antiColParticle()) || _isColour8(c2->colParticle(), c1->antiColParticle()) ) ) { res.insert(wMCR, 213); sum+=wMCR; } double PhaseSpace; if (diquarkCR && _canMakeDiquarkCluster(c1,c2,PhaseSpace)) { double wDCR = _precoDiquark*PhaseSpace; // Diquark CR res.insert(wDCR, -213); sum+=wDCR; } // No CR res.insert((1.0-sum)>0 ? (1.0-sum):0.0, 123); } return res; } void ColourReconnector::_doRecoPlain(ClusterVector & cv) const { ClusterVector newcv = cv; ClusterVector deleted; deleted.reserve(cv.size()); // try to avoid systematic errors by randomising the reconnection order long (*p_irnd)(long) = UseRandom::irnd; random_shuffle( newcv.begin(), newcv.end(), p_irnd ); // iterate over all clusters for (CluVecIt cit = newcv.begin(); cit != newcv.end(); cit++) { // find the cluster which, if reconnected with *cit, would result in the // smallest sum of cluster masses // skip the diquark clusters to be deleted later 2->1 cluster if (find(deleted.begin(), deleted.end(), *cit) != deleted.end()) continue; // skip diquark clusters if ((*cit)->numComponents()>2 || (_diquarkCR && hasDiquark(*cit))) continue; // NB this method returns *cit if no reconnection partner can be found CluVecIt candidate = _dynamicCR ? _findRecoPartnerPlainDynamic(cit, newcv, deleted, _diquarkCR>0):_findRecoPartnerPlain(cit, newcv, deleted); // skip this cluster if no possible reshuffling partner can be found if (candidate == cit) continue; // accept the reconnection with probability PrecoProb. ClusterVector cluvec = {*cit, *candidate}; // const Selector <int> & sel = getProbabilities2CF(*cit, *candidate, _diquarkCR>0); const Selector <int> & sel = _selector(cluvec, _diquarkCR>0); enum Selection2ColourFlows { NoReconnection = 123, MesonicReconnection = 213, DiquarkReconnection = -213, }; switch (sel.select(UseRandom::rnd())) { case MesonicReconnection: { // Mesonic Colour Reconnection pair <ClusterPtr,ClusterPtr> reconnected = _reconnect(*cit, *candidate); // Replace the clusters in the ClusterVector. The order of the // colour-triplet partons in the cluster vector is retained here. // replace *cit by reconnected.first *cit = reconnected.first; // replace candidate by reconnected.second *candidate = reconnected.second; break; } case DiquarkReconnection: { ClusterPtr DiqCluster; if (_makeDiquarkCluster(*cit, *candidate, DiqCluster)){ deleted.push_back(*candidate); // Note that these must be the cit,candidate and not cluvec *cit = DiqCluster; } break; } case NoReconnection: // No colour Reconnection break; default: assert(false); } } if (deleted.size()==0) { swap(cv, newcv); } else { // create a new vector of clusters except for the ones which are "deleted" during // Diquark reconnection ClusterVector clustervector; for (const auto & cluster : newcv) if (find(deleted.begin(), deleted.end(), cluster) == deleted.end()) clustervector.push_back(cluster); swap(cv, clustervector); } } void ColourReconnector::_doRecoBaryonicDiquarkCluster(ClusterVector & cv) const { /*START REVIEW*/ ClusterVector newcv = cv; ClusterVector deleted; deleted.reserve(cv.size()); // try to avoid systematic errors by randomising the reconnection order long (*p_irnd)(long) = UseRandom::irnd; random_shuffle(newcv.begin(), newcv.end(), p_irnd); Selector <int> sel; ClusterVector cluvec; int selection; // iterate over all clusters for (CluVecIt cit = newcv.begin(); cit != newcv.end(); ++cit) { //avoid clusters already containing diuarks if (hasDiquark(*cit)) continue; //skip the cluster to be deleted later 3->2 cluster if (find(deleted.begin(), deleted.end(), *cit) != deleted.end()) continue; // Skip all found baryonic and Tetra clusters, this biases the // algorithm but implementing something like re-reconnection // is ongoing work if ((*cit)->numComponents()>=3) continue; // Find a candidate suitable for reconnection CluVecIt candidate1, candidate2; unsigned typeOfReconnection = 0; // TODO fix the function below yields Cluster in final state _findPartnerBaryonicDiquarkCluster(cit, newcv, // _findPartnerBaryonicDiquarkClusterTEST(cit, newcv, typeOfReconnection, deleted, candidate1, candidate2); switch (typeOfReconnection) { case 0: // No CR found continue; case 3: case 1: // Mesonic or Diquark CR with 2 Colour Flows cluvec={*cit,*candidate1}; break; case 2: // Baryonic CR with 3 Colour Flows cluvec={*cit,*candidate1,*candidate2}; break; default: assert(false); } if (candidate2!=cit) { cluvec={*cit,*candidate1,*candidate2}; } else if (candidate1!=cit) { cluvec={*cit,*candidate1}; } else { std::cout << "no CR" << std::endl; continue; } if (_dynamicCR) { sel = _selector(cluvec, _diquarkCR>0); if (typeOfReconnection!=0 && sel.empty()){ throw Exception() << "No Selection availible" << "ColourReconnector::_doRecoBaryonicDiquarkCluster()" << Exception::runerror; } selection = sel.select(UseRandom::rnd()); sel.clear(); assert(sel.empty()); } else { switch (typeOfReconnection) { case 0: // No CR std::cout << "Should never execute!!!" << std::endl; selection = 123; break; case 1: // Mesonic CR with 2 Colour Flows if (UseRandom::rnd() < _preco) selection = 213; else selection = 123; break; case 2: // Baryonic CR with 3 Colour Flows if (UseRandom::rnd() < _precoBaryonic) selection = 0; else selection = 123; break; case 3: // Diquark CR with 2 Colour Flows if (UseRandom::rnd() < _precoDiquark) selection = -1000; else selection = 123; break; default: assert(false); } } if (selection == 0){ // Baryonic CR (only one option for 3 colourflows) deleted.push_back(*candidate2); // Function that does the reconnection from 3 -> 2 clusters ClusterPtr b1, b2; _makeBaryonicClusters(*cit,*candidate1,*candidate2, b1, b2); // Note that these must be the cit,candidate1 and not cluvec *cit = b1; *candidate1 = b2; } else if (selection > 0) { // Mesonic CR int c1 = ((selection/100) % 4) -1; int c2 = ((selection-(c1+1)*100)/10 % 4) -1; int c3 = ((selection-(c1+1)*100-(c2+1)*10) % 4) -1; if ( c1==0 && c2==1 && c3==2){ // noCR continue; } assert(c1>=0 && c1<3); assert(c2>=0 && c2<3); assert(c3>=0 && c3<3); assert(c1!=c2 && c1!=c3 && c2 !=c3); // if last cluster is untouched we do only reconnect the first two clusters if (c3==2) { const auto & reconnected = _reconnect(*cit,*candidate1); // Note that these must be the cit, candidate1 and not cluvec *cit = reconnected.first; *candidate1 = reconnected.second; } else { // Form clusters (0,c1) (1,c2) (2,c3) const int infoMCR[3] = {c1, c2, c3}; const auto & reconnected = _reconnect3Mto3M(*cit,*candidate1,*candidate2, infoMCR); // Note that these must be the cit,candidateX and not cluvec *cit = std::get<0>(reconnected); *candidate1 = std::get<1>(reconnected); *candidate2 = std::get<2>(reconnected); } } else if (selection < 0) { //TODO DiquarkCR // We will delete the candidate1 mesonic clusters // need to check with 2CF solution // to form a diquark cluster if (cluvec.size()==3 && -selection<999) { const auto & reconnected = _reconnect3MtoMD(cluvec, -selection); *cit = std::get<0>(reconnected); *candidate1 = std::get<1>(reconnected); deleted.push_back(*candidate2); // *candidate2 = std::get<2>(reconnected); } - else if (cluvec.size()==2){ + else if (cluvec.size()==2 || -selection>999){ ClusterPtr DiqCluster; if (_makeDiquarkCluster(*cit, *candidate1, DiqCluster)){ deleted.push_back(*candidate1); // Note that these must be the cit,candidate and not cluvec *cit = DiqCluster; } } else { assert(false); } } else { std::cout << "\nError in selection = "<<selection<<"\n" << std::endl; assert(false); } } ClusterVector addedcv; // bool splitSomeDiquarkCluster=true; bool splitSomeDiquarkCluster=false; if (splitSomeDiquarkCluster) { for (CluVecIt cit = newcv.begin(); cit != newcv.end(); ++cit){ if (!*cit || hasDiquark(*cit)) continue; if (find(deleted.begin(), deleted.end(), *cit) != deleted.end()) continue; if ((*cit)->numComponents()==4 && UseRandom::rnd()>0.33){ const auto & res=_splitDiquarkCluster(*cit, UseRandom::rnd()>0.5); *cit = res.first; addedcv.push_back(res.second); } } } // create a new vector of clusters except for the ones which are "deleted" during // baryonic reconnection ClusterVector clustervector; // add new clusters for (const auto & c : addedcv) clustervector.push_back(c); // delete deleted clusters for (const auto & cluster : newcv) if (find(deleted.begin(), deleted.end(), cluster) == deleted.end()) clustervector.push_back(cluster); swap(cv, clustervector); } // Implementation of the baryonic reconnection algorithm void ColourReconnector::_doRecoBaryonic(ClusterVector & cv) const { ClusterVector newcv = cv; ClusterVector deleted; deleted.reserve(cv.size()); // try to avoid systematic errors by randomising the reconnection order long (*p_irnd)(long) = UseRandom::irnd; random_shuffle(newcv.begin(), newcv.end(), p_irnd); double ProbabilityMesonic = _preco; double ProbabilityBaryonic = _precoBaryonic; ClusterVector cluvec; cluvec.reserve(3); // iterate over all clusters for (CluVecIt cit = newcv.begin(); cit != newcv.end(); ++cit) { //avoid clusters already containing diuarks if (hasDiquark(*cit)) continue; //skip the cluster to be deleted later 3->2 cluster if (find(deleted.begin(), deleted.end(), *cit) != deleted.end()) continue; // Skip all found baryonic clusters, this biases the algorithm but implementing // something like re-reconnection is ongoing work if ((*cit)->numComponents()>=3) continue; // Find a candidate suitable for reconnection CluVecIt baryonic1, baryonic2; bool isBaryonicCandidate = false; CluVecIt candidate = _findPartnerBaryonic(cit, newcv, isBaryonicCandidate, deleted, baryonic1, baryonic2); // skip this cluster if no possible reconnection partner can be found if ( !isBaryonicCandidate && *candidate==*cit) continue; if (_dynamicCR) { cluvec.clear(); if (isBaryonicCandidate) { cluvec={*cit,*baryonic1,*baryonic2}; } else{ cluvec={*cit,*candidate}; } const Selector <int> & sel = _selector(cluvec, _diquarkCR>0); int selection = sel.select(UseRandom::rnd()); // std::cout << "selector print = " << sel <<"\n"; // sel.clear(); // assert(sel.empty()); // 3 aligned meson case // Normal 2->2 Colour reconnection if (selection == 0){ // Baryonic CR only one option deleted.push_back(*baryonic2); // Function that does the reconnection from 3 -> 2 clusters ClusterPtr b1, b2; _makeBaryonicClusters(*cit,*baryonic1,*baryonic2, b1, b2); *cit = b1; *baryonic1 = b2; } else if (selection > 0) { //TODO Mesonic CR if (isBaryonicCandidate) { int c1 = ((selection/100) % 4) -1; int c2 = ((selection-(c1+1)*100)/10 % 4) -1; int c3 = ((selection-(c1+1)*100-(c2+1)*10) % 4) -1; if ( c1==0 && c2==1 && c3==2){ // noCR continue; } assert(c1>=0 && c1<3); assert(c2>=0 && c2<3); assert(c3>=0 && c3<3); assert(c1!=c2 && c1!=c3 && c2 !=c3); if (c3==2 ) { const auto & reconnected = _reconnect(*cit,*baryonic1); *cit = reconnected.first; *baryonic1 = reconnected.second; } else { // Form clusters (0,c1) (1,c2) (2,c3) const int infoMCR[3] = {c1, c2, c3}; const auto & reconnected = _reconnect3Mto3M(*cit,*baryonic1,*baryonic2, infoMCR); *cit = std::get<0>(reconnected); *baryonic1 = std::get<1>(reconnected); *baryonic2 = std::get<2>(reconnected); } } else { const auto & reconnected = _reconnect(*cit,*candidate); *cit = reconnected.first; *candidate = reconnected.second; } } else if (selection < 0) { //TODO DiquarkCR // We will delete the candidate1 mesonic clusters // need to check with 2CF solution // to form a diquark cluster if (cluvec.size()==3) { const auto & reconnected = _reconnect3MtoMD(cluvec, -selection); *cit = std::get<0>(reconnected); *baryonic1 = std::get<1>(reconnected); deleted.push_back(*baryonic2); } else if (cluvec.size()==2) { ClusterPtr DiqCluster; if (_makeDiquarkCluster(*cit, *candidate, DiqCluster)){ deleted.push_back(*candidate); // Note that these must be the cit,candidate and not cluvec *cit = DiqCluster; } } } else { std::cout << "\nError in selection = "<<selection<<"\n" << std::endl; assert(false); } } else { // 3 aligned meson case if ( isBaryonicCandidate && UseRandom::rnd() < ProbabilityBaryonic ) { deleted.push_back(*baryonic2); // Function that does the reconnection from 3 -> 2 clusters ClusterPtr b1, b2; _makeBaryonicClusters(*cit, *baryonic1, *baryonic2, b1, b2); *cit = b1; *baryonic1 = b2; // Baryonic2 is easily skipped in the next loop } // Normal 2->2 Colour reconnection if (!isBaryonicCandidate && UseRandom::rnd() < ProbabilityMesonic) { const auto & reconnected = _reconnect(*cit, *candidate); *cit = reconnected.first; *candidate = reconnected.second; } } } // create a new vector of clusters except for the ones which are "deleted" during // baryonic reconnection ClusterVector clustervector; for (const auto & cluster : newcv) if (find(deleted.begin(), deleted.end(), cluster) == deleted.end()) clustervector.push_back(cluster); swap(cv, clustervector); } bool ColourReconnector::_clustersFarApart( const std::vector<CluVecIt> & clu ) const { int Ncl=clu.size(); assert(Ncl<=3); if (Ncl==1) { return false; } else if (Ncl==2) { // veto if Clusters further apart than _maxDistance if (_localCR && ((*clu[0])->vertex().vect()-(*clu[1])->vertex().vect()).mag() > _maxDistance) return true; // veto if Clusters have negative spacetime difference if (_causalCR && ((*clu[0])->vertex()-(*clu[1])->vertex()).m() < ZERO) return true; } else if (Ncl==3) { // veto if Clusters further apart than _maxDistance if (_localCR && ((*clu[0])->vertex().vect()-(*clu[1])->vertex().vect()).mag() > _maxDistance) return true; if (_localCR && ((*clu[1])->vertex().vect()-(*clu[2])->vertex().vect()).mag() > _maxDistance) return true; if (_localCR && ((*clu[0])->vertex().vect()-(*clu[2])->vertex().vect()).mag() > _maxDistance) return true; // veto if Clusters have negative spacetime difference if (_causalCR && ((*clu[0])->vertex()-(*clu[1])->vertex()).m() < ZERO) return true; if (_causalCR && ((*clu[1])->vertex()-(*clu[2])->vertex()).m() < ZERO) return true; if (_causalCR && ((*clu[0])->vertex()-(*clu[2])->vertex()).m() < ZERO) return true; } return false; } void ColourReconnector::_doReco2BeamClusters(ClusterVector & cv) const { // try other option tPPtr p1Di=(cv[0])->colParticle(); tPPtr p2Di=(cv[1])->colParticle(); tPPtr p1Q=(cv[0])->antiColParticle(); tPPtr p2Q=(cv[1])->antiColParticle(); double min_dist=_displacement(p1Di,p1Q)+_displacement(p2Di,p2Q); if ((_displacement(p1Di,p2Q)+_displacement(p1Di,p2Q))<min_dist) { _reconnect(cv[0],cv[1]); } return; } void ColourReconnector::_doRecoBaryonicMesonic(ClusterVector & cv) const { if (cv.size() < 3) { /* * if the option _cr2BeamClusters!=0 is chosen then we try to * colour reconnect the special case of 2 beam clusters with * probability 1.0 if there is a better _displacement * */ if( _cr2BeamClusters && cv.size()==2 ) _doReco2BeamClusters(cv); return; } ClusterVector newcv = cv; newcv.reserve(2*cv.size()); ClusterVector deleted; deleted.reserve(cv.size()); // counters for numbers of mesons and baryons selected unsigned num_meson = 0; unsigned num_baryon = 0; // vector of selected clusters std::vector<CluVecIt> sel; unsigned number_of_tries = _stepFactor*cv.size()*cv.size(); if (number_of_tries<1) number_of_tries=1; long (*p_irnd)(long) = UseRandom::irnd; for (unsigned reconnections_tries = 0; reconnections_tries < number_of_tries; reconnections_tries++) { num_meson = 0; num_baryon = 0; // flag if we are able to find a suitable combinations of clusters bool _found = false; // Shuffle list of clusters to avoid systematic bias in cluster selection random_shuffle(newcv.begin(), newcv.end(), p_irnd); // loop over clustervector to find CR candidates for (CluVecIt cit = newcv.begin(); cit != newcv.end(); ++cit) { // skip the clusters to be deleted later from 3->2 cluster CR if (find(deleted.begin(), deleted.end(), *cit) != deleted.end()) continue; // avoid clusters already containing diuarks if (hasDiquark(*cit)) continue; // add to selection sel.push_back(cit); if (_clustersFarApart(sel)) { // reject far appart CR // TODO: after discussion maybe to be omitted sel.pop_back(); continue; } bool isMeson=((*cit)->numComponents() == 2); if ( isMeson && (num_meson ==0|| num_meson==1) && num_baryon ==0) { num_meson++; /** * now we habe either 1 or 2 mesonic clusters and have to continue */ continue; } else if ( isMeson && (num_baryon == 1 || num_meson ==2)) { num_meson++; _found = true; /** * we have either 3 mesonic or 1 mesonic and 1 baryonic cluster * and try to colour reconnect */ break; } else if (num_baryon ==0 && num_meson==0) { num_baryon++; /** * now we have 1 baryonic cluster and have to continue */ continue; } else if (num_meson == 2) { /** * we already have 2 mesonic clusters and dont want a baryonic one * since this is an invalid selection */ // remove previously added cluster sel.pop_back(); continue; } else { num_baryon++; _found = true; /** * now we have either 2 baryonic clusters or 1 mesonic and 1 baryonic cluster * and try to colour reconnect */ break; } } // added for more efficent rejection if some reco probabilities are 0 if ( _found ) { // reject MBtoMB candidates if _precoMB_MB=0 if ( _precoMB_MB == 0 && (num_baryon == 1 && num_meson == 1) ) { _found=false; } // reject BbarBto3M candidates if _precoBbarB_3M=0 if ( _precoBbarB_3M== 0 && num_baryon == 2 ) { bool isBbarBto3Mcandidate=( (*sel[0])->particle(0)->hasColour() && (*sel[1])->particle(0)->hasColour(true) ) || ( (*sel[0])->particle(0)->hasColour(true) && (*sel[1])->particle(0)->hasColour() ); if ( isBbarBto3Mcandidate) _found=false; } // reject 2Bto2B candidates if _preco2B_2B=0 if ( _preco2B_2B == 0 && num_baryon == 2 ) { bool is2Bto2Bcandidate=( (*sel[0])->particle(0)->hasColour() && (*sel[1])->particle(0)->hasColour() ) || ( (*sel[0])->particle(0)->hasColour(true) && (*sel[1])->particle(0)->hasColour(true) ); if ( is2Bto2Bcandidate ) _found=false; } } // were we able to find a combination? if (_found==false) { // clear the selection if we did not find a valid set of clusters sel.erase(sel.begin(), sel.end()); continue; } assert(sel.size()<4); assert(sel.size()>1); string kind_of_reco = ""; int reco_info[3]; // find best CR option for the selection _findbestreconnectionoption(sel, num_baryon, kind_of_reco, reco_info); if (kind_of_reco == "") { // no reconnection was found sel.erase(sel.begin(), sel.end()); continue; } else if (kind_of_reco == "3Mto3M" && UseRandom::rnd() < _preco3M_3M) { // 3Mto3M colour reconnection const auto & reconnected = _reconnect3Mto3M(*sel[0], *sel[1], *sel[2], reco_info); (*sel[0]) = std::get<0>(reconnected); (*sel[1]) = std::get<1>(reconnected); (*sel[2]) = std::get<2>(reconnected); } else if (kind_of_reco=="2Bto3M" && UseRandom::rnd() < _precoBbarB_3M) { // antibaryonic and baryonic to 3 mesonic reconnecion const auto & reconnected = _reconnectBbarBto3M(*sel[0], *sel[1], reco_info[0], reco_info[1], reco_info[2]); (*sel[0]) = std::get<0>(reconnected); (*sel[1]) = std::get<1>(reconnected); newcv.push_back(std::get<2>(reconnected)); } else if (kind_of_reco=="3Mto2B" && UseRandom::rnd() < _preco3M_BBbar) { // 3 mesonic to antibaryonic and baryonic reconnection ClusterPtr b1, b2; _makeBaryonicClusters(*sel[0], *sel[1], *sel[2], b1, b2); (*sel[0]) = b1; (*sel[1]) = b2; deleted.push_back(*sel[2]); } else if (kind_of_reco=="2Bto2B" && UseRandom::rnd() < _preco2B_2B) { // 2 (anti)baryonic to 2 (anti)baryonic reconnection const auto & reconnected = _reconnect2Bto2B(*sel[0], *sel[1], reco_info[0], reco_info[1]); (*sel[0]) = reconnected.first; (*sel[1]) = reconnected.second; } else if (kind_of_reco=="MBtoMB" && UseRandom::rnd() < _precoMB_MB) { // (anti)baryonic and mesonic to (anti)baryonic and mesonic reconnection const auto & reconnected = _reconnectMBtoMB(*sel[0], *sel[1], reco_info[0]); (*sel[0]) = reconnected.first; (*sel[1]) = reconnected.second; } // erase the sel-vector sel.erase(sel.begin(), sel.end()); } // write to clustervector new CR'd clusters and deleting // all deleted clusters ClusterVector clustervector; for (const auto & cluster : newcv) if (find(deleted.begin(), deleted.end(), cluster) == deleted.end()) clustervector.push_back(cluster); swap(cv, clustervector); } void ColourReconnector::_findbestreconnectionoption(std::vector<CluVecIt> & cls, const unsigned & baryonic, string & kind_of_reco, int (&reco_info)[3]) const { double min_displacement; if (baryonic==0) { // case with 3 mesonic clusters assert(cls.size()==3); // calculate the initial displacement sum min_displacement = _mesonToBaryonFactor * _displacement((*cls[0])->particle(0), (*cls[0])->particle(1)); min_displacement += _mesonToBaryonFactor * _displacement((*cls[1])->particle(0), (*cls[1])->particle(1)); min_displacement += _mesonToBaryonFactor * _displacement((*cls[2])->particle(0), (*cls[2])->particle(1)); // find best CR reco_info and kind_of_reco _3MtoXreconnectionfinder(cls, reco_info[0], reco_info[1], reco_info[2], min_displacement, kind_of_reco); /** * kind_of_reco either "3Mto3M" or "3Mto2B" (or "" if no better configuration is found) * case 3Mto3M: the coloured particle of the i-th cluster forms a new cluster with the * antiparticle of the reco_info[i]-th cluster * case 3MtoBbarB: all 3 (anti)coloured particle form a new (anti)baryonic cluster */ } else if (baryonic == 1) { // case 1 baryonic and 1 mesonic cluster assert(cls.size()==2); // make mesonic cluster always the cls[0] if ((*cls[0])->numComponents() == 3) { ClusterPtr zw = *cls[0]; *cls[0] = *cls[1]; *cls[1] = zw; } // calculate the initial displacement sum min_displacement = _mesonToBaryonFactor *_displacement((*cls[0])->particle(0), (*cls[0])->particle(1)); min_displacement += _displacementBaryonic((*cls[1])->particle(0), (*cls[1])->particle(1), (*cls[1])->particle(2)); // find best CR reco_info and kind_of_reco _BMtoBMreconnectionfinder(*cls[0], *cls[1], reco_info[0], min_displacement, kind_of_reco); /** * reco_info[0] is the index of the (anti)quarks of the baryonic cluster cls[1], which should * be swapped with the (anti)quarks of the mesonic cluster cls[0] */ } else { assert(baryonic==2); assert(cls.size()==2); // calculate the initial displacement sum min_displacement = _displacementBaryonic((*cls[0])->particle(0), (*cls[0])->particle(1), (*cls[0])->particle(2)); min_displacement += _displacementBaryonic((*cls[1])->particle(0), (*cls[1])->particle(1), (*cls[1])->particle(2)); // case 2 (anti)baryonic clusters to 2 other (anti)baryonic clusters if ( ( (*cls[0])->particle(0)->hasColour() && (*cls[1])->particle(0)->hasColour() ) || ( (*cls[0])->particle(0)->hasColour(true) && (*cls[1])->particle(0)->hasColour(true) ) ) { // find best CR reco_info and kind_of_reco _2Bto2BreconnectionFinder(*cls[0], *cls[1], reco_info[0], reco_info[1], min_displacement, kind_of_reco); /** * swap the reco_info[0]-th particle of the first cluster in the vector with the * reco_info[1]-th particle of the second cluster */ } else { // case 1 baryonic and 1 antibaryonic cluster to 3 mesonic clusters // find best CR reco_info and kind_of_reco _BbarBto3MreconnectionFinder(*cls[0], *cls[1], reco_info[0], reco_info[1], reco_info[2], min_displacement, kind_of_reco); /** * the i-th particle of the first cluster form a new mesonic cluster with the * reco_info[i]-th particle of the second cluster */ } } return; } void ColourReconnector::_findPartnerBaryonicDiquarkCluster( const CluVecIt & cl, ClusterVector & cv, unsigned & typeOfReconnection, const ClusterVector& deleted, CluVecIt &candidate1, CluVecIt &candidate2 ) const { typeOfReconnection=0; // no Reconnection found using Constants::pi; using Constants::twopi; candidate1=cl; candidate2=cl; bool candIsOctet1 = false; bool candIsOctet2 = false; bool candIsQQ1 = false; bool candIsQQ2 = false; bool foundCR = false; double maxrap1 = 0.0; double maxrap2 = 0.0; double minrap1 = 0.0; double minrap2 = 0.0; double maxsum1 = 0.0; double maxsum2 = 0.0; double NegativeRapidtyThreshold = 0.0; double PositiveRapidtyThreshold = 0.0; // boost into RF of cl Lorentz5Momentum cl1 = (*cl)->momentum(); // TODO Boost not covariant!! ERROR const Boost boostv(-cl1.boostVector()); // cl1.boost(boostv); // boost constituents of cl into RF of cl // Lorentz5Momentum p1col = (*cl)->colParticle()->momentum(); Lorentz5Momentum p1anticol = (*cl)->antiColParticle()->momentum(); // TODO Boost not covariant!! ERROR // p1col.boost(boostv); p1anticol.boost(boostv); for (CluVecIt cit=cv.begin(); cit != cv.end(); ++cit) { //avoid looping over clusters containing diquarks if ( (*cit)->numComponents()>=3 ) continue; //skip the cluster to be deleted later 3->2 cluster if ( find(deleted.begin(), deleted.end(), *cit) != deleted.end() ) continue; if ( hasDiquark(*cit) ) continue; if ( (*cl)->isBeamCluster() && (*cit)->isBeamCluster() ) continue; if ( cit==cl ) continue; // veto if Clusters further apart than _maxDistance if (_localCR && ((**cl).vertex().vect()-(**cit).vertex().vect()).mag() > _maxDistance) continue; // veto if Clusters have negative spacetime difference if (_causalCR && ((**cl).vertex()-(**cit).vertex()).m() < ZERO) continue; bool octetNormalCR = (_isColour8( (*cl)->colParticle(), (*cit)->antiColParticle() ) || _isColour8( (*cit)->colParticle(), (*cl)->antiColParticle() ) ); // boost constituents of cit into RF of cl Lorentz5Momentum p2col = (*cit)->colParticle()->momentum(); Lorentz5Momentum p2anticol = (*cit)->antiColParticle()->momentum(); p2col.boost(boostv); p2anticol.boost(boostv); // calculate the rapidity of the other constituents of the clusters // w.r.t axis of p1anticol.vect.unit const double rapq = calculateRapidityRF(p1anticol,p2col); const double rapqbar = calculateRapidityRF(p1anticol,p2anticol); // std::cout << "\nPRE\n" // << "\t octet = " << octetNormalCR << "\n" // << "\t rapq = " << rapq << "\n" // << "\t rapqbar = " << rapqbar << "\n"; // configuration for Mesonic CR if ( rapq > 0.0 && rapqbar < 0.0 && rapq > PositiveRapidtyThreshold && rapqbar < NegativeRapidtyThreshold) { //sum of rapidities of quarks const double sumQQbar = abs(rapq) + abs(rapqbar); if ( sumQQbar > maxsum2 ) { if ( sumQQbar > maxsum1 ) { double factor = candIsQQ1 ? _mesonToBaryonFactor:1.0; maxsum2 = (factor*maxsum1) > sumQQbar ? sumQQbar:(factor*maxsum1); candidate2 = candidate1; candIsQQ2 = candIsQQ1; candIsOctet2 = candIsOctet1; maxrap2 = maxrap1; minrap2 = minrap1; maxsum1 = sumQQbar; candidate1 = cit; candIsQQ1 = false; candIsOctet1 = octetNormalCR; maxrap1 = rapq; minrap1 = rapqbar; } else { maxsum2 = sumQQbar; candidate2 = cit; candIsQQ2 = false; candIsOctet2 = octetNormalCR; maxrap2 = rapq; minrap2 = rapqbar; } // choose the less stringent threshold for further iterations PositiveRapidtyThreshold = maxrap1 > maxrap2 ? maxrap2:maxrap1; NegativeRapidtyThreshold = minrap1 < minrap2 ? minrap2:minrap1; foundCR=true; } } assert(PositiveRapidtyThreshold<=maxrap1); assert(PositiveRapidtyThreshold<=maxrap2); assert(NegativeRapidtyThreshold>=minrap1); assert(NegativeRapidtyThreshold>=minrap2); assert(maxsum1>=maxsum2); if ( rapq < 0.0 && rapqbar > 0.0 && rapqbar > PositiveRapidtyThreshold/_mesonToBaryonFactor && rapq < NegativeRapidtyThreshold/_mesonToBaryonFactor ) { //sum of rapidities of quarks const double sumQQ = abs(rapq) + abs(rapqbar); if ( sumQQ > maxsum2/_mesonToBaryonFactor ) { if ( sumQQ > maxsum1 ) { double factor = candIsQQ1 ? _mesonToBaryonFactor:1.0; maxsum2 = (factor*maxsum1) > sumQQ ? sumQQ:(factor*maxsum1); candidate2 = candidate1; candIsQQ2 = candIsQQ1; candIsOctet2 = candIsOctet1; maxrap2 = maxrap1; minrap2 = minrap1; maxsum1 = sumQQ; candidate1 = cit; candIsQQ1 = true; candIsOctet1 = octetNormalCR; maxrap1 = rapqbar; minrap1 = rapq; } else { maxsum2 = (_mesonToBaryonFactor*maxsum1) > sumQQ ? sumQQ:(_mesonToBaryonFactor*maxsum1); candidate2 = cit; candIsQQ2 = true; candIsOctet2 = octetNormalCR; maxrap2 = rapqbar; minrap2 = rapq; } // choose the less stringent threshold for further iterations PositiveRapidtyThreshold = maxrap1 > maxrap2 ? maxrap2:maxrap1; NegativeRapidtyThreshold = minrap1 < minrap2 ? minrap2:minrap1; foundCR=true; } } assert(PositiveRapidtyThreshold<=maxrap1); assert(PositiveRapidtyThreshold<=maxrap2); assert(NegativeRapidtyThreshold>=minrap1); assert(NegativeRapidtyThreshold>=minrap2); assert(maxsum1>=maxsum2); } // determine the type if (!candIsQQ1) { // Mesonic CR if (candIsOctet1) { if (!candIsQQ2 && !candIsOctet2) { // TODO Here is the problem if (candidate2!=cl){ swap(candidate2,candidate1); typeOfReconnection = 1; } else typeOfReconnection = 0; // typeOfReconnection = 0; } else typeOfReconnection = 0; } else typeOfReconnection = 1; } else if (candIsQQ1) { if (candIsQQ2) // Baryonic CR typeOfReconnection = 2; else // Diquark CR typeOfReconnection = 3; } if (!foundCR) typeOfReconnection = 0; // veto reconnection if cannot make a Diquark Cluster bool failDCR=false; if (typeOfReconnection == 3) { if (_diquarkCR && !_canMakeDiquarkCluster(*cl, *candidate1)) { /* TODO Here is the problem if (!candIsQQ2 && !candIsOctet2 && candidate2!=cl) { // if second nearest is candidate for Mesonic CR // allow MCR candidate1=candidate2; typeOfReconnection=1; } else if ( _canMakeDiquarkCluster(*cl, *candidate2) && candidate2!=cl) { // if second nearest is allowed for DCR // allow DCR candidate1=candidate2; typeOfReconnection=3; } else { */ // No CR typeOfReconnection = 0; failDCR=true; // } } } if (_debug) { std::ofstream outTypes("WriteOut/TypesOfDCR.dat", std::ios::app); outTypes << (failDCR ? 4:typeOfReconnection) << "\n"; outTypes.close(); switch (typeOfReconnection) { // Mesonic CR case 1: { std::ofstream outMCR("WriteOut/MCR.dat", std::ios::app); outMCR << minrap1 << "\t" << maxrap1 << "\t" << minrap2 << "\t" << maxrap2 << "\t" <<"\n"; outMCR.close(); break; } // Baryonic CR case 2: { std::ofstream outBCR("WriteOut/BCR.dat", std::ios::app); outBCR << minrap1 << "\t" << maxrap1 << "\t" << minrap2 << "\t" << maxrap2 << "\t" <<"\n"; outBCR.close(); break; } // Diquark CR case 3: { std::ofstream outDCR("WriteOut/DCR.dat", std::ios::app); outDCR << minrap1 << "\t" << maxrap1 << "\t" << minrap2 << "\t" << maxrap2 << "\t" <<"\n"; outDCR.close(); break; } // No CR found case 0: { std::ofstream outNoCR("WriteOut/NoCR.dat", std::ios::app); outNoCR<< minrap1 << "\t" << maxrap1 << "\t" << minrap2 << "\t" << maxrap2 << "\t" <<"\n"; outNoCR.close(); break; } default: assert(false); } } } namespace { struct ClusterInfo{ double rapSumMin; bool isQQ; bool isOctetWithOriginal; CluVecIt cluIt; } ; bool compare_Clusters(ClusterInfo c1, ClusterInfo c2){ return c1.rapSumMin>c2.rapSumMin; } } void ColourReconnector::_findPartnerBaryonicDiquarkClusterTEST( const CluVecIt & cl, ClusterVector & cv, unsigned & typeOfReconnection, const ClusterVector& deleted, CluVecIt &candidate1, CluVecIt &candidate2 ) const { typeOfReconnection=0; // no Reconnection found using Constants::pi; using Constants::twopi; candidate1=cl; candidate2=cl; // boost into RF of cl Lorentz5Momentum cl1 = (*cl)->momentum(); const Boost boostv(-cl1.boostVector()); Lorentz5Momentum p1anticol = (*cl)->antiColParticle()->momentum(); // direction p1anticol.boost(boostv); std::vector<ClusterInfo> cluVec; cluVec.reserve(cv.size()); for (CluVecIt cit=cv.begin(); cit != cv.end(); ++cit) { //avoid looping over clusters containing diquarks if ( (*cit)->numComponents()>=3 ) continue; //skip the cluster to be deleted later 3->2 cluster if ( find(deleted.begin(), deleted.end(), *cit) != deleted.end() ) continue; if ( hasDiquark(*cit) ) continue; if ( (*cl)->isBeamCluster() && (*cit)->isBeamCluster() ) continue; if ( cit==cl ) continue; // veto if Clusters further apart than _maxDistance if (_localCR && ((**cl).vertex().vect()-(**cit).vertex().vect()).mag() > _maxDistance) continue; // veto if Clusters have negative spacetime difference if (_causalCR && ((**cl).vertex()-(**cit).vertex()).m() < ZERO) continue; bool octetNormalCR = (_isColour8( (*cl)->colParticle(), (*cit)->antiColParticle() ) || _isColour8( (*cit)->colParticle(), (*cl)->antiColParticle() ) ); // boost constituents of cit into RF of cl Lorentz5Momentum p2col = (*cit)->colParticle()->momentum(); Lorentz5Momentum p2anticol = (*cit)->antiColParticle()->momentum(); p2col.boost(boostv); p2anticol.boost(boostv); // calculate the rapidity of the other constituents of the clusters // w.r.t axis of p1anticol.vect.unit const double rapq = calculateRapidityRF(p1anticol,p2col); const double rapqbar = calculateRapidityRF(p1anticol,p2anticol); // std::cout << "\nPRE\n" // << "\t octet = " << octetNormalCR << "\n" // << "\t rapq = " << rapq << "\n" // << "\t rapqbar = " << rapqbar << "\n"; const double sumAbsRap = abs(rapq) + abs(rapqbar); // configuration for Mesonic CR if ( rapq > 0.0 && rapqbar < 0.0 ) { //sum of rapidities of quarks ClusterInfo cluMesInfo; cluMesInfo.rapSumMin=sumAbsRap; cluMesInfo.isQQ=false; cluMesInfo.isOctetWithOriginal=octetNormalCR; cluMesInfo.cluIt=cit; cluVec.push_back(cluMesInfo); } else if ( rapq < 0.0 && rapqbar > 0.0 ) { //sum of rapidities of quarks ClusterInfo cluMesInfo; cluMesInfo.rapSumMin=sumAbsRap; cluMesInfo.isQQ=false; cluMesInfo.isOctetWithOriginal=octetNormalCR; cluMesInfo.cluIt=cit; cluVec.push_back(cluMesInfo); } } std::sort(cluVec.begin(), cluVec.end(), compare_Clusters); switch (cluVec.size()) { case 0: typeOfReconnection=0; return; case 1: { if (cluVec[0].isQQ) { // diquark CR if possible if (_canMakeDiquarkCluster(*cl, *(cluVec[0].cluIt))) { typeOfReconnection=3; candidate1=cluVec[0].cluIt; return; } else { typeOfReconnection=0; return; } } else { // Mesonic CR if not Octet if (cluVec[0].isOctetWithOriginal){ typeOfReconnection=0; return; } else { candidate1=cluVec[0].cluIt; typeOfReconnection=1; return; } } break; } } bool candidate1isQQ=false; // bool candidate2isQQ=false; typeOfReconnection=0; for (const auto & c : cluVec) { if (candidate1!=cl && candidate2!=cl) break; if (c.isQQ) { // diquark CR if possible if (_canMakeDiquarkCluster(*cl, *(c.cluIt))) { if (candidate1==cl){ candidate1=c.cluIt; candidate1isQQ=true; typeOfReconnection=3; } else { candidate2=c.cluIt; // candidate2isQQ=true; typeOfReconnection=2; } } } else { // Mesonic CR if not Octet if (c.isOctetWithOriginal) { continue; } else { if (candidate1==cl){ candidate1=c.cluIt; candidate1isQQ=false; typeOfReconnection=1; } else { candidate2=c.cluIt; // candidate2isQQ=false; if (candidate1isQQ) typeOfReconnection=3; else typeOfReconnection=1; break; } } } } return; } CluVecIt ColourReconnector::_findPartnerBaryonic( const CluVecIt & cl, ClusterVector & cv, bool & baryonicCand, const ClusterVector& deleted, CluVecIt &baryonic1, CluVecIt &baryonic2 ) const { using Constants::pi; using Constants::twopi; // Returns a candidate for possible reconnection CluVecIt candidate = cl; bool bcand = false; double maxrap = 0.0; double minrap = 0.0; double maxrapNormal = 0.0; double minrapNormal = 0.0; double maxsumnormal = 0.0; double maxsum = 0.0; double secondsum = 0.0; // boost into RF of cl Lorentz5Momentum cl1 = (*cl)->momentum(); const Boost boostv(-cl1.boostVector()); // cl1.boost(boostv); // boost constituents of cl into RF of cl // Lorentz5Momentum p1col = (*cl)->colParticle()->momentum(); Lorentz5Momentum p1anticol = (*cl)->antiColParticle()->momentum(); // p1col.boost(boostv); p1anticol.boost(boostv); for (CluVecIt cit=cv.begin(); cit != cv.end(); ++cit) { //avoid looping over clusters containing diquarks if ( hasDiquark(*cit) ) continue; if ( (*cit)->numComponents()>=3 ) continue; if ( cit==cl ) continue; //skip the cluster to be deleted later 3->2 cluster if ( find(deleted.begin(), deleted.end(), *cit) != deleted.end() ) continue; if ( (*cl)->isBeamCluster() && (*cit)->isBeamCluster() ) continue; // veto if Clusters further apart than _maxDistance if (_localCR && ((**cl).vertex().vect()-(**cit).vertex().vect()).mag() > _maxDistance) continue; // veto if Clusters have negative spacetime difference if (_causalCR && ((**cl).vertex()-(**cit).vertex()).m() < ZERO) continue; const bool Colour8 = _isColour8( (*cl)->colParticle(), (*cit)->antiColParticle() ) || _isColour8( (*cit)->colParticle(), (*cl)->antiColParticle() ) ; // boost constituents of cit into RF of cl Lorentz5Momentum p2col = (*cit)->colParticle()->momentum(); Lorentz5Momentum p2anticol = (*cit)->antiColParticle()->momentum(); p2col.boost(boostv); p2anticol.boost(boostv); // calculate the rapidity of the other constituents of the clusters // w.r.t axis of p1anticol.vect.unit const double rapq = calculateRapidityRF(p1anticol,p2col); const double rapqbar = calculateRapidityRF(p1anticol,p2anticol); // configuration for normal CR if ( !Colour8 && rapq > 0.0 && rapqbar < 0.0 && rapq > maxrap && rapqbar < minrap ) { maxrap = rapq; minrap = rapqbar; //sum of rapidities of quarks const double normalsum = abs(rapq) + abs(rapqbar); if ( normalsum > maxsumnormal ) { maxsumnormal = normalsum; maxrapNormal = rapq; minrapNormal = rapqbar; bcand = false; candidate = cit; } } if ( rapq < 0.0 && rapqbar >0.0 && rapqbar > maxrapNormal && rapq < minrapNormal ) { maxrap = rapqbar; minrap = rapq; const double sumrap = abs(rapqbar) + abs(rapq); // first candidate gets here. If second baryonic candidate has higher Ysum than the first // one, the second candidate becomes the first one and the first the second. if (sumrap > maxsum) { if (maxsum != 0) { baryonic2 = baryonic1; baryonic1 = cit; bcand = true; } else { baryonic1 = cit; } maxsum = sumrap; } else { if (sumrap > secondsum && sumrap != maxsum) { secondsum = sumrap; bcand = true; baryonic2 = cit; } } } } if (bcand == true) { baryonicCand = true; } if (_debug) { std::ofstream outTypes("WriteOut/TypesOfBCR.dat", std::ios::app); outTypes << (baryonicCand ? 2:(candidate==cl ? 0:1)) << "\n"; outTypes.close(); } return candidate; } CluVecIt ColourReconnector::_findRecoPartnerPlainDynamic(const CluVecIt & cl, ClusterVector & cv, const ClusterVector & deleted, bool diquarkCR) const { CluVecIt candidate = cl; double pNoRecoMin=1.0; double pNoReco,preco,precoDiquark; // boost into RF of cl Lorentz5Momentum cl1 = (*cl)->momentum(); const Boost boostv(-cl1.boostVector()); // boost constituents of cl into RF of cl Lorentz5Momentum p1anticol = (*cl)->antiColParticle()->momentum(); p1anticol.boost(boostv); for (CluVecIt cit=cv.begin(); cit != cv.end(); ++cit) { // Skip deleted clusters if (find(deleted.begin(), deleted.end(), *cit) != deleted.end()) continue; // skip diquark clusters if ((*cit)->numComponents()>2 || (_diquarkCR && hasDiquark(*cit))) continue; // don't even look at original cluster if (cit==cl) continue; // don't allow colour octet clusters bool Colour8 = ( _isColour8( (*cl)->colParticle(), (*cit)->antiColParticle() ) || _isColour8( (*cit)->colParticle(), (*cl)->antiColParticle() ) ); // stop it putting beam remnants together if ((*cl)->isBeamCluster() && (*cit)->isBeamCluster()) continue; // veto if Clusters further apart than _maxDistance if (_localCR && ((**cl).vertex().vect()-(**cit).vertex().vect()).mag() > _maxDistance) continue; // veto if Clusters have negative spacetime difference if (_causalCR && ((**cl).vertex()-(**cit).vertex()).m() < ZERO) continue; // boost constituents of cit into RF of cl Lorentz5Momentum p2col = (*cit)->colParticle()->momentum(); Lorentz5Momentum p2anticol = (*cit)->antiColParticle()->momentum(); p2col.boost(boostv); p2anticol.boost(boostv); // calculate the rapidity of the other constituents of the clusters // w.r.t axis of p1anticol.vect.unit const double rapq = calculateRapidityRF(p1anticol,p2col); const double rapqbar = calculateRapidityRF(p1anticol,p2anticol); // configuration for normal CR if ( !Colour8 && rapq > 0.0 && rapqbar < 0.0) { } // configuration for diquark CR else if ( _diquarkCR && rapq < 0.0 && rapqbar > 0.0) { } else continue; // Get dynamic CR probabilities and try to minimize the non-reco probability std::tie( pNoReco, preco, precoDiquark) = _dynamicRecoProbabilitiesCF2(*cl,*cit,diquarkCR); if (pNoReco<pNoRecoMin) { candidate = cit; pNoRecoMin=pNoReco; } } if (_debug) { ofstream out("WriteOut/pNoReco.dat", std::ios::app); out << pNoRecoMin << "\t" << cv.size() << "\n"; out.close(); } return candidate; } CluVecIt ColourReconnector::_findRecoPartnerPlain(const CluVecIt & cl, ClusterVector & cv, const ClusterVector & deleted) const { CluVecIt candidate = cl; Energy minMass = 1*TeV; for (CluVecIt cit=cv.begin(); cit != cv.end(); ++cit) { // Skip deleted clusters if (find(deleted.begin(), deleted.end(), *cit) != deleted.end()) continue; // skip diquark clusters if ((*cit)->numComponents()>2 || (_diquarkCR && hasDiquark(*cit))) continue; // don't even look at original cluster if (cit==cl) continue; // don't allow colour octet clusters if ( _isColour8( (*cl)->colParticle(), (*cit)->antiColParticle() ) || _isColour8( (*cit)->colParticle(), (*cl)->antiColParticle() ) ) { continue; } // stop it putting beam remnants together if ((*cl)->isBeamCluster() && (*cit)->isBeamCluster()) continue; // veto if Clusters further apart than _maxDistance if (_localCR && ((**cl).vertex().vect()-(**cit).vertex().vect()).mag() > _maxDistance) continue; // veto if Clusters have negative spacetime difference if (_causalCR && ((**cl).vertex()-(**cit).vertex()).m() < ZERO) continue; // momenta of the old clusters Lorentz5Momentum p1 = (*cl)->colParticle()->momentum() + (*cl)->antiColParticle()->momentum(); Lorentz5Momentum p2 = (*cit)->colParticle()->momentum() + (*cit)->antiColParticle()->momentum(); // momenta of the new clusters Lorentz5Momentum p3 = (*cl)->colParticle()->momentum() + (*cit)->antiColParticle()->momentum(); Lorentz5Momentum p4 = (*cit)->colParticle()->momentum() + (*cl)->antiColParticle()->momentum(); Energy oldMass = abs( p1.m() ) + abs( p2.m() ); Energy newMass = abs( p3.m() ) + abs( p4.m() ); if ( newMass < oldMass && newMass < minMass ) { minMass = newMass; candidate = cit; } } return candidate; } // forms two baryonic clusters from three clusters void ColourReconnector::_makeBaryonicClusters( ClusterPtr &c1, ClusterPtr &c2, ClusterPtr &c3, ClusterPtr &newcluster1, ClusterPtr &newcluster2) const { //make sure they all have 2 components assert(c1->numComponents()==2); assert(c2->numComponents()==2); assert(c3->numComponents()==2); //abandon children c1->colParticle()->abandonChild(c1); c1->antiColParticle()->abandonChild(c1); c2->colParticle()->abandonChild(c2); c2->antiColParticle()->abandonChild(c2); c3->colParticle()->abandonChild(c3); c3->antiColParticle()->abandonChild(c3); newcluster1 = new_ptr(Cluster(c1->colParticle(),c2->colParticle(), c3->colParticle())); c1->colParticle()->addChild(newcluster1); c2->colParticle()->addChild(newcluster1); c3->colParticle()->addChild(newcluster1); newcluster1->setVertex(LorentzPoint()); newcluster2 = new_ptr(Cluster(c1->antiColParticle(), c2->antiColParticle(), c3->antiColParticle())); c1->antiColParticle()->addChild(newcluster2); c2->antiColParticle()->addChild(newcluster2); c3->antiColParticle()->addChild(newcluster2); newcluster2->setVertex(LorentzPoint()); } bool ColourReconnector::_canMakeDiquarkCluster(tcPPtr pCol1, tcPPtr pCol2,tcPPtr pAntiCol1, tcPPtr pAntiCol2) const{ double a; return _canMakeDiquarkCluster( pCol1, pCol2, pAntiCol1, pAntiCol2,a); } bool ColourReconnector::_canMakeDiquarkCluster(tcPPtr pCol1, tcPPtr pCol2,tcPPtr pAntiCol1, tcPPtr pAntiCol2, double & PhaseSpace) const{ tcPDPtr dataDiquark = _hadronSpectrum->makeDiquark(pCol1->dataPtr(), pCol2->dataPtr()); tcPDPtr dataDiquarkBar = _hadronSpectrum->makeDiquark(pAntiCol1->dataPtr(), pAntiCol2->dataPtr()); if (!dataDiquark){ throw Exception() << "Could not make a diquark from" << pCol1->dataPtr()->PDGName() << " and " << pCol2->dataPtr()->PDGName() << " in ColourReconnector::_canMakeDiquarkCluster()" << Exception::eventerror; } if (!dataDiquarkBar){ throw Exception() << "Could not make an anti-diquark from" << pAntiCol1->dataPtr()->PDGName() << " and " << pAntiCol2->dataPtr()->PDGName() << " in ColourReconnector::_canMakeDiquarkCluster()" << Exception::eventerror; } Energy minMass=_hadronSpectrum->massLightestHadronPair(dataDiquark,dataDiquarkBar); Lorentz5Momentum Ptot=pCol1->momentum() + pCol2->momentum() + pAntiCol1->momentum() + pAntiCol2->momentum(); Energy Mass=Ptot.m(); if ( Mass<=minMass ) { return false; } if (_phaseSpaceDiquarkFission){ // Tried to add a factor suppressing to low mass Diquark Clusters double factor; switch (_phaseSpaceDiquarkFission) { case 1: { const auto & BaryonPair=_hadronSpectrum->lightestHadronPair(dataDiquark,dataDiquarkBar); if (Mass-(BaryonPair.first->mass()+BaryonPair.second->mass())<=ZERO) return false; factor = 2.0*Kinematics::pstarTwoBodyDecay(Mass,BaryonPair.first->mass(),BaryonPair.second->mass())/Mass; break; } case 2: { if (Mass-(dataDiquark->constituentMass()+dataDiquarkBar->constituentMass())<ZERO) return false; factor = 2.0*Kinematics::pstarTwoBodyDecay(Mass,dataDiquark->constituentMass(),dataDiquarkBar->constituentMass())/Mass; break; } default: assert(false); } assert(factor>=0.0); assert(factor<=1.0); PhaseSpace = factor; } else { PhaseSpace = 1.0; } return true; } bool ColourReconnector::_canMakeDiquarkCluster(const ClusterPtr &c1, const ClusterPtr &c2) const { double a; return _canMakeDiquarkCluster(c1,c2,a); } // forms a four-quark cluster bool ColourReconnector::_canMakeDiquarkCluster(const ClusterPtr &c1, const ClusterPtr &c2, double & PhaseSpace) const { //make sure they all have 2 components assert(c1->numComponents()==2); assert(c2->numComponents()==2); return _canMakeDiquarkCluster(c1->colParticle(),c2->colParticle(),c1->antiColParticle(),c2->antiColParticle(),PhaseSpace); } bool ColourReconnector::_makeDiquarkCluster( ClusterPtr &c1, ClusterPtr &c2, ClusterPtr &newcluster) const{ // std::cout << "MakeDiq" << std::endl; if (!_canMakeDiquarkCluster(c1,c2)){ std::cout << "Should never execute! check this earlier" << std::endl; return false; } //abandon children c1->colParticle()->abandonChild(c1); c1->antiColParticle()->abandonChild(c1); c2->colParticle()->abandonChild(c2); c2->antiColParticle()->abandonChild(c2); // Note: the convention that c1->newcluster.particle(0,2) and c2->newcluster.particle(1,3) // TODO probably need to use particleB to access it newcluster = new_ptr(Cluster(c1->colParticle(),c2->colParticle(), c1->antiColParticle(), c2->antiColParticle())); c1->colParticle()->addChild(newcluster); c2->colParticle()->addChild(newcluster); c1->antiColParticle()->addChild(newcluster); c2->antiColParticle()->addChild(newcluster); newcluster->setVertex(LorentzPoint()); return true; } pair <ClusterPtr,ClusterPtr> ColourReconnector::_splitDiquarkCluster( ClusterPtr &diquarkCluster, bool colourReconnect) const{ // Works just fine! // std::cout << "MakeDiq" << std::endl; // if (!_canMakeDiquarkCluster(c1,c2)){ // std::cout << "Should never execute! check this earlier" << std::endl; // return false; // } ClusterPtr newcluster1,newcluster2; //abandon children diquarkCluster->particleB(0)->abandonChild(diquarkCluster); diquarkCluster->particleB(1)->abandonChild(diquarkCluster); diquarkCluster->particleB(2)->abandonChild(diquarkCluster); diquarkCluster->particleB(3)->abandonChild(diquarkCluster); // Note: the convention that c1->newcluster.particle(0,2) and c2->newcluster.particle(1,3) // TODO probably need to use particleB to access it // Here we decide if we want to colour reconnect the original clusters (0,2) and (1,3) to // the clusters (0,3) and (1,2) if (colourReconnect) { // colour reconnect newcluster1 = new_ptr(Cluster(diquarkCluster->particleB(0), diquarkCluster->particleB(3))); newcluster2 = new_ptr(Cluster(diquarkCluster->particleB(1), diquarkCluster->particleB(2))); diquarkCluster->particleB(0)->addChild(newcluster1); diquarkCluster->particleB(1)->addChild(newcluster2); diquarkCluster->particleB(2)->addChild(newcluster2); diquarkCluster->particleB(3)->addChild(newcluster1); } else { // keep original colour connection newcluster1 = new_ptr(Cluster(diquarkCluster->particleB(0), diquarkCluster->particleB(2))); newcluster2 = new_ptr(Cluster(diquarkCluster->particleB(1), diquarkCluster->particleB(3))); diquarkCluster->particleB(0)->addChild(newcluster1); diquarkCluster->particleB(1)->addChild(newcluster2); diquarkCluster->particleB(2)->addChild(newcluster1); diquarkCluster->particleB(3)->addChild(newcluster2); } newcluster1->setVertex(LorentzPoint()); newcluster2->setVertex(LorentzPoint()); return pair <ClusterPtr, ClusterPtr> (newcluster1, newcluster2); } pair <ClusterPtr,ClusterPtr> ColourReconnector::_reconnect2Bto2B(ClusterPtr &c1, ClusterPtr &c2, const int s1, const int s2) const { // form the first new cluster // separate the quarks from their original cluster c1->particleB((s1+1)%3)->abandonChild(c1); c1->particleB((s1+2)%3)->abandonChild(c1); c2->particleB(s2)->abandonChild(c2); // now the new cluster ClusterPtr newCluster1 = new_ptr(Cluster(c1->particleB((s1+1)%3), c1->particleB((s1+2)%3), c2->particleB(s2))); c1->particleB((s1+1)%3)->addChild(newCluster1); c1->particleB((s1+2)%3)->addChild(newCluster1); c2->particleB(s2)->addChild(newCluster1); // set new vertex newCluster1->setVertex(LorentzPoint()); // set beam remnants for new cluster if (c1->isBeamRemnant((s1+1)%3)) newCluster1->setBeamRemnant(0, true); if (c1->isBeamRemnant((s1+2)%3)) newCluster1->setBeamRemnant(1, true); if (c2->isBeamRemnant(s2)) newCluster1->setBeamRemnant(2, true); // for the second cluster same procedure c2->particleB((s2+1)%3)->abandonChild(c2); c2->particleB((s2+2)%3)->abandonChild(c2); c1->particleB(s1)->abandonChild(c1); ClusterPtr newCluster2 = new_ptr(Cluster(c2->particleB((s2+1)%3), c2->particleB((s2+2)%3), c1->particleB(s1))); c2->particleB((s2+1)%3)->addChild(newCluster2); c2->particleB((s2+2)%3)->addChild(newCluster2); c1->particleB(s1)->addChild(newCluster2); newCluster2->setVertex(LorentzPoint()); if (c2->isBeamRemnant((s2+1)%3)) newCluster2->setBeamRemnant(0, true); if (c2->isBeamRemnant((s2+2)%3)) newCluster2->setBeamRemnant(1, true); if (c1->isBeamRemnant(s1)) newCluster2->setBeamRemnant(2, true); return pair <ClusterPtr, ClusterPtr> (newCluster1, newCluster2); } std::tuple <ClusterPtr, ClusterPtr, ClusterPtr> ColourReconnector::_reconnectBbarBto3M(ClusterPtr & c1, ClusterPtr & c2, const int s0, const int s1, const int s2) const { // make sure they all have 3 components assert(c1->numComponents()==3); assert(c2->numComponents()==3); // first Cluster c1->particleB(0)->abandonChild(c1); c2->particleB(s0)->abandonChild(c2); ClusterPtr newCluster1 = new_ptr(Cluster(c1->particleB(0), c2->particleB(s0))); c1->particleB(0)->addChild(newCluster1); c2->particleB(s0)->addChild(newCluster1); // set new vertex newCluster1->setVertex(0.5*(c1->particleB(0)->vertex() + c2->particleB(s0)->vertex())); // set beam remnants for new cluster if (c1->isBeamRemnant(0)) newCluster1->setBeamRemnant(0, true); if (c2->isBeamRemnant(s0)) newCluster1->setBeamRemnant(1, true); // same for second cluster c1->particleB(1)->abandonChild(c1); c2->particleB(s1)->abandonChild(c2); ClusterPtr newCluster2 = new_ptr(Cluster(c1->particleB(1), c2->particleB(s1))); c1->particleB(1)->addChild(newCluster2); c2->particleB(s1)->addChild(newCluster2); newCluster2->setVertex(0.5*(c1->particleB(1)->vertex() + c2->particleB(s1)->vertex())); if (c1->isBeamRemnant(1)) newCluster2->setBeamRemnant(0, true); if (c2->isBeamRemnant(s1)) newCluster2->setBeamRemnant(1, true); // same for third cluster c1->particleB(2)->abandonChild(c1); c2->particleB(s2)->abandonChild(c2); ClusterPtr newCluster3 = new_ptr(Cluster(c1->particleB(2), c2->particleB(s2))); c1->particleB(2)->addChild(newCluster3); c2->particleB(s2)->addChild(newCluster3); newCluster3->setVertex(0.5*(c1->particleB(2)->vertex() + c2->particleB(s2)->vertex())); if (c1->isBeamRemnant(2)) newCluster3->setBeamRemnant(0, true); if (c2->isBeamRemnant(s2)) newCluster3->setBeamRemnant(1, true); return std::tuple <ClusterPtr, ClusterPtr, ClusterPtr> (newCluster1, newCluster2, newCluster3); } pair <ClusterPtr,ClusterPtr> ColourReconnector::_reconnect(ClusterPtr &c1, ClusterPtr &c2) const { // if (_isColour8(c1->colParticle(), c2->antiColParticle()) // || _isColour8(c2->colParticle(), c1->antiColParticle())) { // std::cout << "reconnect _isColour8" << std::endl; // } if (_becomesColour8Cluster(c1,c2)){ std::cout << "Should never execute! _isColour8 in reconnect check this earlier" << std::endl; } // choose the other possibility to form two clusters from the given // constituents assert(c1->numComponents()==2); assert(c2->numComponents()==2); int c1_col(-1),c1_anti(-1),c2_col(-1),c2_anti(-1); for(unsigned int ix=0; ix<2; ++ix) { if (c1->particle(ix)->hasColour(false)) c1_col = ix; else if(c1->particle(ix)->hasColour(true )) c1_anti = ix; if (c2->particle(ix)->hasColour(false)) c2_col = ix; else if(c2->particle(ix)->hasColour(true )) c2_anti = ix; } assert(c1_col>=0&&c2_col>=0&&c1_anti>=0&&c2_anti>=0); c1->colParticle()->abandonChild(c1); c2->antiColParticle()->abandonChild(c2); ClusterPtr newCluster1 = new_ptr( Cluster( c1->colParticle(), c2->antiColParticle() ) ); c1->colParticle()->addChild(newCluster1); c2->antiColParticle()->addChild(newCluster1); /* * TODO: Questionable setting of the vertex * */ newCluster1->setVertex(0.5*(c1->colParticle()->vertex() + c2->antiColParticle()->vertex())); if(c1->isBeamRemnant(c1_col )) newCluster1->setBeamRemnant(0,true); if(c2->isBeamRemnant(c2_anti)) newCluster1->setBeamRemnant(1,true); c1->antiColParticle()->abandonChild(c1); c2->colParticle()->abandonChild(c2); ClusterPtr newCluster2 = new_ptr( Cluster( c2->colParticle(), c1->antiColParticle() ) ); c1->antiColParticle()->addChild(newCluster2); c2->colParticle()->addChild(newCluster2); /* * TODO: Questionable setting of the vertex * */ newCluster2->setVertex(0.5*(c2->colParticle()->vertex() + c1->antiColParticle()->vertex())); if(c2->isBeamRemnant(c2_col )) newCluster2->setBeamRemnant(0,true); if(c1->isBeamRemnant(c1_anti)) newCluster2->setBeamRemnant(1,true); return pair <ClusterPtr,ClusterPtr> (newCluster1, newCluster2); } std::tuple <ClusterPtr, ClusterPtr> ColourReconnector::_reconnect3MtoMD(ClusterVector & cluvec, const int topology) const { // std::cout << "MakeDiq3MtoMD" << std::endl; assert(cluvec.size()==3); assert(topology>0 && topology<=33); int colIndexMCR = (topology/10)-1; int antiColIndexMCR = (topology-(colIndexMCR+1)*10)-1; assert(colIndexMCR<3 && colIndexMCR>=0); assert(antiColIndexMCR<3 && antiColIndexMCR>=0); // std::cout << "topo = "<< topology <<"\t==\t" << colIndexMCR+1<<antiColIndexMCR+1 << std::endl; /* if (colIndexMCR==antiColIndexMCR) { ClusterPtr DiquarkClu; assert((colIndexMCR+1)%3!=(colIndexMCR+2)%3); assert((colIndexMCR+1)%3!=colIndexMCR); assert((colIndexMCR+2)%3!=colIndexMCR); if (!_makeDiquarkCluster(cluvec[(colIndexMCR+1)%3], cluvec[(colIndexMCR+2)%3], DiquarkClu)){ std::cout << "could not make diquark cluster of index " << (colIndexMCR+1)%3 <<", " <<(colIndexMCR+2)%3<<"\nColIdx "<<colIndexMCR << std::endl; assert(false); // return std::tuple <ClusterPtr, ClusterPtr, ClusterPtr> (cluvec[0],cluvec[1],cluvec[2]); } // return (original untouched mesonic cluster, Diquark cluster, to be deleted cluster) std::cout << "simple DCR" << std::endl; // TODO check that the ordering is still maintained return std::tuple <ClusterPtr, ClusterPtr> (cluvec[colIndexMCR], DiquarkClu); } */ ClusterPtr cMCR1 = cluvec[colIndexMCR]; ClusterPtr cMCR2 = cluvec[antiColIndexMCR]; if (_isColour8(cMCR1->colParticle(),cMCR2->antiColParticle())){ std::cout << "Should never execute! _isColour8 in _reconnect3MtoMD check this earlier" << std::endl; } // std::cout << "Never " << std::endl; // ClusterVector cluvec = cluvec; ClusterVector newclusters; int colIdx[3]={-1,-1,-1}; int anticolIdx[3]={-1,-1,-1}; for (int i = 0; i < 3; i++) { assert(cluvec[i]->numComponents()==2); for (unsigned ip= 0; ip < 2; ip++){ if (cluvec[i]->particle(ip)->hasColour(false)) colIdx[i] = ip; if (cluvec[i]->particle(ip)->hasColour(true)) anticolIdx[i] = ip; } assert(colIdx[i]>=0); assert(anticolIdx[i]>=0); // abbandon all children cluvec[i]->colParticle()->abandonChild(cluvec[i]); cluvec[i]->antiColParticle()->abandonChild(cluvec[i]); } // make the MCR cluster with indices colIndexMCR,antiColIndexMCR // form new mesonic cluster ClusterPtr newClusterMCR = new_ptr(Cluster(cluvec[colIndexMCR]->colParticle(), cluvec[antiColIndexMCR]->antiColParticle())); newClusterMCR->colParticle()->addChild(newClusterMCR); newClusterMCR->antiColParticle()->addChild(newClusterMCR); // set new vertex newClusterMCR->setVertex(0.5*(newClusterMCR->colParticle()->vertex() + newClusterMCR->antiColParticle()->vertex())); // set beam remnants for new cluster if (cluvec[colIndexMCR]->isBeamRemnant(colIdx[colIndexMCR])) newClusterMCR->setBeamRemnant(0, true); if (cluvec[antiColIndexMCR]->isBeamRemnant(anticolIdx[antiColIndexMCR])) newClusterMCR->setBeamRemnant(1, true); // make the DCR cluster with remaining indices int indexDCRcol1 = (colIndexMCR+1)%3; int indexDCRcol2 = (colIndexMCR+2)%3; int indexDCRacol1 = (antiColIndexMCR+1)%3; int indexDCRacol2 = (antiColIndexMCR+2)%3; assert(indexDCRcol1!=indexDCRcol2); assert(indexDCRcol1!=colIndexMCR); assert(indexDCRcol2!=colIndexMCR); assert(indexDCRacol1!=indexDCRacol2); assert(indexDCRacol1!=antiColIndexMCR); assert(indexDCRacol2!=antiColIndexMCR); ClusterPtr newClusterDCR = new_ptr(Cluster( cluvec[indexDCRcol1]->colParticle(), cluvec[indexDCRcol2]->colParticle(), cluvec[indexDCRacol1]->antiColParticle(), cluvec[indexDCRacol2]->antiColParticle() )); cluvec[indexDCRcol1]->colParticle()->addChild(newClusterDCR); cluvec[indexDCRcol2]->colParticle()->addChild(newClusterDCR); cluvec[indexDCRacol1]->antiColParticle()->addChild(newClusterDCR); cluvec[indexDCRacol2]->antiColParticle()->addChild(newClusterDCR); // set new vertex newClusterDCR->setVertex(0.25*( cluvec[indexDCRcol1]->colParticle()->vertex() + cluvec[indexDCRcol2]->colParticle()->vertex() + cluvec[indexDCRacol1]->antiColParticle()->vertex() + cluvec[indexDCRacol2]->antiColParticle()->vertex() )); // set beam remnants for new cluster if (cluvec[indexDCRcol1]->isBeamRemnant(colIdx[indexDCRcol1])) newClusterDCR->setBeamRemnant(0, true); if (cluvec[indexDCRcol2]->isBeamRemnant(colIdx[indexDCRcol2])) newClusterDCR->setBeamRemnant(1, true); if (cluvec[indexDCRacol1]->isBeamRemnant(anticolIdx[indexDCRacol1])) newClusterDCR->setBeamRemnant(2, true); if (cluvec[indexDCRacol2]->isBeamRemnant(anticolIdx[indexDCRacol2])) newClusterDCR->setBeamRemnant(3, true); return std::tuple <ClusterPtr, ClusterPtr> (newClusterMCR,newClusterDCR); } std::tuple <ClusterPtr, ClusterPtr, ClusterPtr> ColourReconnector::_reconnect3Mto3M(ClusterPtr & c1, ClusterPtr & c2, ClusterPtr & c3, const int infos [3]) const { // check if mesonic clusters assert(c1->numComponents()==2); assert(c2->numComponents()==2); assert(c3->numComponents()==2); ClusterVector oldclusters = {c1, c2, c3}; ClusterVector newclusters; for (int i=0; i<3; i++) { if ( i!=infos[i] && _isColour8(oldclusters[i]->colParticle(),oldclusters[infos[i]]->antiColParticle())){ std::cout << "Should never execute! _isColour8 in _reconnect3Mto3M "<< i <<" "<< infos[i]<<" check this earlier" << std::endl; } int c1_col=-1; int c2_anticol=-1; // get which index is coloured and which anticolour for (unsigned int ix=0; ix<2; ++ix) { if (oldclusters[i]->particle(ix)->hasColour(false)) c1_col = ix; if (oldclusters[infos[i]]->particle(ix)->hasColour(true)) c2_anticol = ix; } assert(c1_col>=0); assert(c2_anticol>=0); oldclusters[i]->colParticle()->abandonChild(oldclusters[i]); oldclusters[infos[i]]->antiColParticle()->abandonChild(oldclusters[infos[i]]); // form new cluster ClusterPtr newCluster = new_ptr(Cluster(oldclusters[i]->colParticle(), oldclusters[infos[i]]->antiColParticle())); oldclusters[i]->colParticle()->addChild(newCluster); oldclusters[infos[i]]->antiColParticle()->addChild(newCluster); // set new vertex newCluster->setVertex(0.5*(oldclusters[i]->colParticle()->vertex() + oldclusters[infos[i]]->antiColParticle()->vertex())); // set beam remnants for new cluster if (oldclusters[i]->isBeamRemnant(c1_col)) newCluster->setBeamRemnant(0, true); if (oldclusters[infos[i]]->isBeamRemnant(c2_anticol)) newCluster->setBeamRemnant(1, true); newclusters.push_back(newCluster); } return std::tuple <ClusterPtr, ClusterPtr, ClusterPtr> (newclusters[0], newclusters[1], newclusters[2]); } pair <ClusterPtr, ClusterPtr> ColourReconnector::_reconnectMBtoMB(ClusterPtr & c1, ClusterPtr & c2, const int s0) const { // make c1 the mesonic cluster if (c1->numComponents()==2) { assert(c2->numComponents()==3); } else { return _reconnectMBtoMB(c2,c1,s0); } int c1_col=-1; int c1_anti=-1; // get which index is coloured and which anticolour for (unsigned int ix=0; ix<2; ++ix) { if (c1->particle(ix)->hasColour(false)) c1_col = ix; else if (c1->particle(ix)->hasColour(true)) c1_anti = ix; } assert(c1_col>=0); assert(c1_anti>=0); // pointers for the new clusters ClusterPtr newCluster1; ClusterPtr newCluster2; if (c2->particle(0)->hasColour()==true) { // first case: we have a baryonic clusters // first make the new mesonic cluster c1->antiColParticle()->abandonChild(c1); c2->particleB(s0)->abandonChild(c2); newCluster1 = new_ptr(Cluster(c1->antiColParticle(), c2->particleB(s0))); c1->antiColParticle()->addChild(newCluster1); c2->particleB(s0)->addChild(newCluster1); // set new vertex newCluster1->setVertex(0.5*(c1->antiColParticle()->vertex() + c2->particleB(s0)->vertex())); // set beam remnants for new cluster if (c1->isBeamRemnant(c1_anti)) newCluster1->setBeamRemnant(0, true); if (c2->isBeamRemnant(s0)) newCluster1->setBeamRemnant(1, true); // then the baryonic one c1->colParticle()->abandonChild(c1); c2->particleB((s0+1)%3)->abandonChild(c2); c2->particleB((s0+2)%3)->abandonChild(c2); newCluster2 = new_ptr(Cluster(c1->colParticle(), c2->particleB((s0+1)%3), c2->particleB((s0+2)%3))); c1->colParticle()->addChild(newCluster2); c2->particleB((s0+1)%3)->addChild(newCluster2); c2->particleB((s0+2)%3)->addChild(newCluster2); // set new vertex newCluster2->setVertex(LorentzPoint()); } else { // second case we have an antibaryonic cluster // first make the new mesonic cluster c1->colParticle()->abandonChild(c1); c2->particleB(s0)->abandonChild(c2); newCluster1 = new_ptr(Cluster(c1->colParticle(), c2->particleB(s0))); c1->colParticle()->addChild(newCluster1); c2->particleB(s0)->addChild(newCluster1); // set new vertex newCluster1->setVertex(0.5*(c1->colParticle()->vertex() + c2->particleB(s0)->vertex())); // set beam remnants for new cluster if (c1->isBeamRemnant(c1_col)) newCluster1->setBeamRemnant(0, true); if (c2->isBeamRemnant(s0)) newCluster1->setBeamRemnant(1, true); // then the baryonic one c1->antiColParticle()->abandonChild(c1); c2->particleB((s0+1)%3)->abandonChild(c2); c2->particleB((s0+2)%3)->abandonChild(c2); newCluster2 = new_ptr(Cluster(c1->antiColParticle(), c2->particleB((s0+1)%3), c2->particleB((s0+2)%3))); c1->antiColParticle()->addChild(newCluster2); c2->particleB((s0+1)%3)->addChild(newCluster2); c2->particleB((s0+2)%3)->addChild(newCluster2); // set new vertex newCluster2->setVertex(LorentzPoint()); } return pair <ClusterPtr, ClusterPtr> (newCluster1, newCluster2); } void ColourReconnector::_2Bto2BreconnectionFinder(ClusterPtr & c1, ClusterPtr & c2, int & bswap1, int & bswap2, double min_displ_sum, string & kind_of_reco) const { double tmp_delta; for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { // try swapping particle i of c1 with particle j of c2 tmp_delta = _displacementBaryonic(c2->particle(j), c1->particle((i+1)%3), c1->particle((i+2)%3)); tmp_delta += _displacementBaryonic(c1->particle(i), c2->particle((j+1)%3), c2->particle((j+2)%3)); if (tmp_delta < min_displ_sum) { // if minimal displacement select the 2Bto2B CR option min_displ_sum = tmp_delta; bswap1 = i; bswap2 = j; kind_of_reco = "2Bto2B"; } } } } void ColourReconnector::_BbarBto3MreconnectionFinder(ClusterPtr & c1, ClusterPtr & c2, int & mswap0, int & mswap1, int & mswap2, double min_displ_sum, string & kind_of_reco) const { double pre_tmp_delta; double tmp_delta; for (int p1=0; p1 <3; p1++) { // make sure not to form a mesonic octet if (_isColour8(c1->particle(0), c2->particle(p1))) continue; pre_tmp_delta = _displacement(c1->particle(0), c2->particle(p1)); for (int p2=1; p2<3; p2++) { // make sure not to form a mesonic octet if (_isColour8(c1->particle(1), c2->particle((p1+p2)%3))) continue; if (_isColour8(c1->particle(2), c2->particle(3-p1-((p1+p2)%3)))) continue; tmp_delta = pre_tmp_delta + _displacement(c1->particle(1), c2->particle((p1+p2)%3)); tmp_delta += _displacement(c1->particle(2), c2->particle(3-p1-((p1+p2)%3))); // factor _mesonToBaryonFactor to compare Baryonic an mesonic cluster tmp_delta *=_mesonToBaryonFactor; if (tmp_delta < min_displ_sum) { // if minimal displacement select the 2Bto3M CR option min_displ_sum = tmp_delta; mswap0 = p1; mswap1 = (p1+p2)%3; mswap2 = 3-p1-((p1+p2)%3); kind_of_reco = "2Bto3M"; } } } } void ColourReconnector::_BMtoBMreconnectionfinder(ClusterPtr & c1, ClusterPtr & c2, int & swap, double min_displ_sum, string & kind_of_reco) const { assert(c1->numComponents()==2); assert(c2->numComponents()==3); double tmp_displ = 0; for (int i=0; i<3; i++) { // Differ if the second cluster is baryonic or antibaryonic if (c2->particle(0)->hasColour()) { // c2 is baryonic // veto mesonic octets if (_isColour8(c2->particle(i), c1->antiColParticle())) continue; // factor _mesonToBaryonFactor to compare Baryonic an mesonic cluster tmp_displ = _mesonToBaryonFactor * _displacement(c2->particle(i), c1->antiColParticle()); tmp_displ += _displacementBaryonic(c1->colParticle(), c2->particle((i+1)%3), c2->particle((i+2)%3)); } else { // c2 is antibaryonic // veto mesonic octets if (_isColour8(c2->particle(i), c1->colParticle())) continue; // factor _mesonToBaryonFactor to compare Baryonic an mesonic cluster tmp_displ = _mesonToBaryonFactor * _displacement(c2->particle(i), c1->colParticle()); tmp_displ *= _displacementBaryonic(c1->antiColParticle(), c2->particle((i+1)%3), c2->particle((i+2)%3)); } if (tmp_displ < min_displ_sum) { // if minimal displacement select the MBtoMB CR option min_displ_sum = tmp_displ; swap = i; kind_of_reco = "MBtoMB"; } } return; } void ColourReconnector::_3MtoXreconnectionfinder(std::vector<CluVecIt> & cv, int & swap0, int & swap1, int & swap2, double min_displ_sum, string & kind_of_reco) const { // case of 3M->BbarB CR double _tmp_displ; _tmp_displ = _displacementBaryonic((*cv[0])->colParticle(), (*cv[1])->colParticle(), (*cv[2])->colParticle()); _tmp_displ += _displacementBaryonic((*cv[0])->antiColParticle(), (*cv[1])->antiColParticle(), (*cv[2])->antiColParticle()); if (_tmp_displ < min_displ_sum) { // if minimal displacement select the 3Mto2B CR option kind_of_reco = "3Mto2B"; min_displ_sum = _tmp_displ; } // case for 3M->3M CR /** * if 3Mto3M reco probability (_preco3M_3M) is 0 we skip this loop * since no 3Mto3M CR shall be performed */ int i,j; int i1,i2,i3; for (i = 0; _preco3M_3M && i<3; i++) { // veto mesonic octets if (_isColour8((*cv[0])->colParticle(), (*cv[i])->antiColParticle())) continue; // factor _mesonToBaryonFactor to compare baryonic an mesonic cluster _tmp_displ = _mesonToBaryonFactor * _displacement((*cv[0])->colParticle(), (*cv[i])->antiColParticle()); for (j=1; j<3; j++) { // i1, i2, i3 are pairwise distinct i1=i; i2=((j+i)%3); if (i1==0 && i2==1) continue; i3=(3-i-((j+i)%3)); // veto mesonic octets if (_isColour8((*cv[1])->colParticle(), (*cv[i2])->antiColParticle())) continue; if (_isColour8((*cv[2])->colParticle(), (*cv[i3])->antiColParticle())) continue; _tmp_displ += _mesonToBaryonFactor * _displacement((*cv[1])->colParticle(), (*cv[i2])->antiColParticle()); _tmp_displ += _mesonToBaryonFactor * _displacement((*cv[2])->colParticle(), (*cv[i3])->antiColParticle()); if (_tmp_displ < min_displ_sum) { // if minimal displacement select the 3Mto3M CR option kind_of_reco = "3Mto3M"; min_displ_sum = _tmp_displ; swap0 = i1; swap1 = i2; swap2 = i3; } } } } pair <int,int> ColourReconnector::_shuffle (const PVector & q, const PVector & aq, unsigned maxtries) const { const size_t nclusters = q.size(); assert (nclusters > 1); assert (aq.size() == nclusters); int i, j; unsigned tries = 0; bool octet=false; do { // find two different random integers in the range [0, nclusters) i = UseRandom::irnd( nclusters ); do { j = UseRandom::irnd( nclusters ); } while (i == j); // check if one of the two potential clusters would be a colour octet state octet = _isColour8( q[i], aq[j] ) || _isColour8( q[j], aq[i] ) ; tries++; } while (octet && tries < maxtries); if (octet) i = j = -1; return make_pair(i,j); } bool ColourReconnector::_becomesColour8Cluster(const ClusterPtr & c1, const ClusterPtr & c2) const { return _isColour8(c1->colParticle(),c2->antiColParticle()) || _isColour8(c2->colParticle(),c1->antiColParticle()); } bool ColourReconnector::_isColour8(tcPPtr p, tcPPtr q) const { bool octet = false; if(_octetOption<0) return octet; // make sure we have a triplet and an anti-triplet if ( ( p->hasColour() && q->hasAntiColour() ) || ( p->hasAntiColour() && q->hasColour() ) ) { // true if p and q are originated from a colour octet if ( !p->parents().empty() && !q->parents().empty() ) { octet = ( p->parents()[0] == q->parents()[0] ) && ( p->parents()[0]->data().iColour() == PDT::Colour8 ); } // (Final) option: check if same colour8 parent // or already found an octet. if(_octetOption==0||octet) return octet; // (All) option handling more octets // by browsing particle history/colour lines. tColinePtr cline,aline; // Get colourlines form final states. if(p->hasColour() && q->hasAntiColour()) { cline = p-> colourLine(); aline = q->antiColourLine(); } else { cline = q-> colourLine(); aline = p->antiColourLine(); } // Follow the colourline of p. if ( !p->parents().empty() ) { tPPtr parent = p->parents()[0]; while (parent) { if(parent->data().iColour() == PDT::Colour8) { // Coulour8 particles should have a colour // and an anticolour line. Currently the // remnant has none of those. Since the children // of the remnant are not allowed to emit currently, // the colour octet remnant is handled by the return // statement above. The assert also catches other // colour octets without clines. If the children of // a remnant should be allowed to emit, the remnant // should get appropriate colour lines and // colour states. // See Ticket: #407 // assert(parent->colourLine()&&parent->antiColourLine()); octet = (parent-> colourLine()==cline && parent->antiColourLine()==aline); } if(octet||parent->parents().empty()) break; parent = parent->parents()[0]; } } } return octet; } void ColourReconnector::persistentOutput(PersistentOStream & os) const { os << _hadronSpectrum << _clreco << _crIterations << _algorithm << _annealingFactor << _annealingSteps << _triesPerStepFactor << _initTemp << _preco << _precoBaryonic << _precoDiquark << _preco3M_3M << _preco3M_BBbar << _precoBbarB_3M << _preco2B_2B << _precoMB_MB << _stepFactor << _mesonToBaryonFactor << _baryonEnhancementFactor << _diquarkEnhancementFactor << ounit(_maxDistance, femtometer) << _octetOption << _cr2BeamClusters << _localCR << _causalCR << _debug << _junctionMBCR << _dynamicCR << _diquarkCR << _dynamicCRscale << _dynamicCRalphaS << _phaseSpaceDiquarkFission ; } void ColourReconnector::persistentInput(PersistentIStream & is, int) { is >> _hadronSpectrum >> _clreco >> _crIterations >> _algorithm >> _annealingFactor >> _annealingSteps >> _triesPerStepFactor >> _initTemp >> _preco >> _precoBaryonic >> _precoDiquark >> _preco3M_3M >> _preco3M_BBbar >> _precoBbarB_3M >> _preco2B_2B >> _precoMB_MB >> _stepFactor >> _mesonToBaryonFactor >> _baryonEnhancementFactor >> _diquarkEnhancementFactor >> iunit(_maxDistance, femtometer) >> _octetOption >> _cr2BeamClusters >> _localCR >> _causalCR >> _debug >> _junctionMBCR >> _dynamicCR >> _diquarkCR >> _dynamicCRscale >> _dynamicCRalphaS >> _phaseSpaceDiquarkFission ; } void ColourReconnector::Init() { static ClassDocumentation<ColourReconnector> documentation ("This class is responsible of the colour reconnection."); static Reference<ColourReconnector,HadronSpectrum> interfaceHadronSpectrum("HadronSpectrum", "A reference to the object HadronSpectrum", &Herwig::ColourReconnector::_hadronSpectrum, false, false, true, false); static Switch<ColourReconnector,int> interfaceColourReconnection ("ColourReconnection", "Colour reconnections", &ColourReconnector::_clreco, 0, true, false); static SwitchOption interfaceColourReconnectionNo (interfaceColourReconnection, "No", "Colour reconnections off", 0); static SwitchOption interfaceColourReconnectionYes (interfaceColourReconnection, "Yes", "Colour reconnections on", 1); static Parameter<ColourReconnector, unsigned int> interfaceColourReconnectionIterations ("ColourReconnectionIterations", "Choose the number of iterations the chosen CR algorithm is performed", &ColourReconnector::_crIterations, 1, 1, 1, 100, false, false, Interface::limited); // Algorithm interface static Switch<ColourReconnector, int> interfaceAlgorithm ("Algorithm", "Specifies the colour reconnection algorithm", &ColourReconnector::_algorithm, 0, true, false); static SwitchOption interfaceAlgorithmPlain (interfaceAlgorithm, "Plain", "Plain colour reconnection as in Herwig 2.5.0", 0); static SwitchOption interfaceAlgorithmStatistical (interfaceAlgorithm, "Statistical", "Statistical colour reconnection using simulated annealing", 1); static SwitchOption interfaceAlgorithmBaryonic (interfaceAlgorithm, "Baryonic", "Baryonic cluster reconnection", 2); static SwitchOption interfaceAlgorithmBaryonicMesonic (interfaceAlgorithm, "BaryonicMesonic", "Baryonic cluster reconnection with reconnections to and from Mesonic Clusters", 3); static SwitchOption interfaceAlgorithmBaryonicDiquarkCluster (interfaceAlgorithm, "BaryonicDiquarkCluster", "Baryonic colour reconnection which allows for the formation of DiquarkCluster-like CR", 4); static Switch<ColourReconnector,int> interfaceColourDiquarkCR ("DiquarkCR", "Allow diquark type colour Reconnection", &ColourReconnector::_diquarkCR, 0, true, false); static SwitchOption interfaceDiquarkCRNo (interfaceColourDiquarkCR, "No", "Use regular CR without diquark CR", 0); static SwitchOption interfaceDiquarkCRYes (interfaceColourDiquarkCR, "Yes", "Use CR with diquark CR", 1); static Switch<ColourReconnector,int> interfaceColourDynamicCR ("DynamicCR", "Use dynamic weight for Colour reconnections defined by soft gluon evolution" "\nNOTE: Only for Mesonic CR so far", &ColourReconnector::_dynamicCR, 0, true, false); static SwitchOption interfaceDynamicCRNo (interfaceColourDynamicCR, "No", "Use regular CR with fixed probabilities", 0); static SwitchOption interfaceDynamicCRYes (interfaceColourDynamicCR, "Yes", "Use dynamic CR with kinematic dependent probabilities", 1); static SwitchOption interfaceDynamicCRNotExponentiated (interfaceColourDynamicCR, "NotExponentiated", "Use dynamic CR with kinematic dependent probabilities" ", but without exponentiated soft anomalous dimension", 2); // General Parameters and switches static Parameter<ColourReconnector, double> interfaceDynamicScale ("DynamicScale", "Choose dynamic scale of soft gluon evolution for DynamicCR where" " mu = DynamicScale*(mConstU+mConstU)", &ColourReconnector::_dynamicCRscale, 1.0, 1e-14, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector, double> interfaceDynamicAlphaS ("DynamicAlphaS", "Choose dynamic alphaS of soft gluon evolution for DynamicCR", &ColourReconnector::_dynamicCRalphaS, 0.8, 0.001, 10.0, false, false, Interface::limited); // Statistical CR Parameters: static Parameter<ColourReconnector, double> interfaceMtrpAnnealingFactor ("AnnealingFactor", "The annealing factor is the ratio of the temperatures in two successive " "temperature steps.", &ColourReconnector::_annealingFactor, 0.9, 0.0, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector,unsigned> interfaceMtrpAnnealingSteps ("AnnealingSteps", "Number of temperature steps in the statistical annealing algorithm", &ColourReconnector::_annealingSteps, 50, 1, 10000, false, false, Interface::limited); static Parameter<ColourReconnector,double> interfaceMtrpTriesPerStepFactor ("TriesPerStepFactor", "The number of reconnection tries per temperature steps is the number of " "clusters times this factor.", &ColourReconnector::_triesPerStepFactor, 5.0, 0.0, 100.0, false, false, Interface::limited); static Parameter<ColourReconnector,double> interfaceMtrpInitialTemp ("InitialTemperature", "Factor used to determine the initial temperature from the median of the " "energy change in a few random rearrangements.", &ColourReconnector::_initTemp, 0.1, 0.00001, 100.0, false, false, Interface::limited); // Plain and Baryonic CR Paramters static Parameter<ColourReconnector, double> interfaceRecoProb ("ReconnectionProbability", "Probability that a found two meson to two meson reconnection possibility is actually accepted (used in Plain & Baryonic)", &ColourReconnector::_preco, 0.5, 0.0, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector,double> interfaceRecoProbBaryonic ("ReconnectionProbabilityBaryonic", "Probability that a found reconnection possibility is actually accepted (used in Baryonic)", &ColourReconnector::_precoBaryonic, 0.5, 0.0, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector,double> interfaceRecoProbDiquark ("ReconnectionProbabilityDiquark", "Probability for forming a tetra-quark cluster", &ColourReconnector::_precoDiquark, 0.5, 0.0, 1.0, false, false, Interface::limited); // BaryonicMesonic CR Paramters static Parameter<ColourReconnector, double> interfaceReconnectionProbability3Mto3M ("ReconnectionProbability3Mto3M", "Probability that a reconnection candidate is accepted for reconnecting 3M -> 3M\'", &ColourReconnector::_preco3M_3M, 0.5, 0.0, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector, double> interfaceReconnectionProbability3MtoBBbar ("ReconnectionProbability3MtoBBbar", "Probability that a reconnection candidate is accepted for reconnecting 3M -> B,Bbar", &ColourReconnector::_preco3M_BBbar, 0.5, 0.0, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector, double> interfaceReconnectionProbabilityBbarBto3M ("ReconnectionProbabilityBbarBto3M", "Probability that a reconnection candidate is accepted for reconnecting B,Bbar -> 3M", &ColourReconnector::_precoBbarB_3M, 0.5, 0.0, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector, double> interfaceReconnectionProbability2Bto2B ("ReconnectionProbability2Bto2B", "Probability that a reconnection candidate is accepted for reconnecting 2B -> 2B\' or 2Bbar -> 2Bbar\'", &ColourReconnector::_preco2B_2B, 0.5, 0.0, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector, double> interfaceReconnectionProbabilityMBtoMB ("ReconnectionProbabilityMBtoMB", "Probability that a reconnection candidate is accepted for reconnecting M,B -> M\',B\' or M,Bbar -> M\',Bbar\'", &ColourReconnector::_precoMB_MB, 0.5, 0.0, 1.0, false, false, Interface::limited); static Parameter<ColourReconnector, double> interfaceFactorforStep ("StepFactor", "Factor for how many reconnection-tries are made in the BaryonicMesonic algorithm", &ColourReconnector::_stepFactor, 1.0, 0.11111, 10., false, false, Interface::limited);// at least 3 Clusters -> _stepFactorMin=1/9 static Parameter<ColourReconnector, double> interfaceMesonToBaryonFactor ("MesonToBaryonFactor", "Factor for comparing mesonic clusters to baryonic clusters in the displacement if BaryonicMesonic CR model is chosen", &ColourReconnector::_mesonToBaryonFactor, 2.0, 0.01, 100.0, false, false, Interface::limited); static Parameter<ColourReconnector, double> interfaceBaryonEnhancementFactor ("BaryonEnhancementFactor", "Factor for enhancing the probability of Baryonic CR in dynamic CR", &ColourReconnector::_baryonEnhancementFactor, 1.0, 1e-10, 1e100, false, false, Interface::limited); static Parameter<ColourReconnector, double> interfaceDiquarkEnhancementFactor ("DiquarkEnhancementFactor", "Factor for enhancing the probability of Diquark CR in dynamic CR", &ColourReconnector::_diquarkEnhancementFactor, 1.0, 1e-10, 1e100, false, false, Interface::limited); // General Parameters and switches static Parameter<ColourReconnector, Length> interfaceMaxDistance ("MaxDistance", "Maximum distance between the clusters at which to consider rearrangement" " to avoid colour reconneections of displaced vertices (used in all Algorithms). No unit means femtometer", &ColourReconnector::_maxDistance, femtometer, 1000.*femtometer, 0.0*femtometer, 1e100*femtometer, false, false, Interface::limited); static Switch<ColourReconnector, int> interfaceOctetTreatment ("OctetTreatment", "Which octets are not allowed to be reconnected (used in all Algorithms)", &ColourReconnector::_octetOption, 0, false, false); static SwitchOption interfaceOctetTreatmentFinal (interfaceOctetTreatment, "Final", "Only prevent for the final (usuaslly non-perturbative) g -> q qbar splitting", 0); static SwitchOption interfaceOctetTreatmentAll (interfaceOctetTreatment, "All", "Prevent for all octets", 1); static SwitchOption interfaceOctetTreatmentNone (interfaceOctetTreatment, "None", "Accept all octets", -1); static Switch<ColourReconnector, int> interfaceCR2BeamClusters ("CR2BeamClusters", "Option for colour reconnecting 2 beam remnant clusters if the number of clusters is 2.", &ColourReconnector::_cr2BeamClusters, 0, true, false); static SwitchOption interfaceCR2BeamClustersYes (interfaceCR2BeamClusters, "Yes", "If possible CR 2 beam clusters", 1); static SwitchOption interfaceCR2BeamClustersNo (interfaceCR2BeamClusters, "No", "If possible do not CR 2 beam clusters", 0); static Switch<ColourReconnector, int> interfaceLocalCR ("LocalCR", "Option for colour reconnecting only if clusters are less distant than MaxDistance", &ColourReconnector::_localCR, 0, true, false); static SwitchOption interfaceLocalCRYes (interfaceLocalCR, "Yes", "activate spatial veto", 1); static SwitchOption interfaceLocalCRNo (interfaceLocalCR, "No", "deactivate spatial veto", 0); static Switch<ColourReconnector, int> interfaceCausalCR ("CausalCR", "Option for colour reconnecting only if clusters their vertices " "have a positive spacetime difference", &ColourReconnector::_causalCR, 0, true, false); static SwitchOption interfaceCausalCRYes (interfaceCausalCR, "Yes", "enable causal veto", 1); static SwitchOption interfaceCausalCRNo (interfaceCausalCR, "No", "disable causal veto", 0); static Switch<ColourReconnector, int> interfaceJunction ("Junction", "Option for using Junction-like displacement in rapidity-phi plane to compare baryonic cluster " "instead of pairwise distance (for BaryonicMesonic model)", &ColourReconnector::_junctionMBCR, 1, true, false); static SwitchOption interfaceJunctionYes (interfaceJunction, "Yes", "Using junction-like model instead of pairwise distance model", 1); static SwitchOption interfaceJunctionNo (interfaceJunction, "No", "Using pairwise distance model instead of junction-like model", 0); // Debug static Switch<ColourReconnector, int> interfaceDebug ("Debug", "Make a file with some Information of the BaryonicMesonic Algorithm", &ColourReconnector::_debug, 0, true, false); static SwitchOption interfaceDebugNo (interfaceDebug, "No", "Debug Information for ColourReconnector Off", 0); static SwitchOption interfaceDebugYes (interfaceDebug, "Yes", "Debug Information for ColourReconnector On", 1); static Switch<ColourReconnector,int> interfacePhaseSpaceDiquarkFission ("PhaseSpaceDiquarkFission", "Colour reconnections", &ColourReconnector::_phaseSpaceDiquarkFission, 0, true, false); static SwitchOption interfacePhaseSpaceDiquarkFissionNo (interfacePhaseSpaceDiquarkFission, "No", "Not adding the decay phasespace to Diquark Colour Reconnection", 0); static SwitchOption interfacePhaseSpaceDiquarkFissionYes (interfacePhaseSpaceDiquarkFission, "Yes", "Adding the decay phasespace to Diquark Colour Reconnection", 1); static SwitchOption interfacePhaseSpaceDiquarkFissionConstituentMasses (interfacePhaseSpaceDiquarkFission, "ConstituentMasses", "Adding the decay phasespace to Diquark Colour Reconnection", 2); }