double Mixing_Handler::DetermineMixingTime(Particle* decayer, bool checkforpartstatus) const { double time = decayer->Time(); Blob* motherblob = decayer->ProductionBlob(); if(motherblob->Type()==btp::Hadron_Mixing) { decayer = motherblob->InParticle(0); motherblob = decayer->ProductionBlob(); } Particle* sister = NULL; if(motherblob->Type()!=btp::Fragmentation || (motherblob->NInP()==2 && motherblob->NOutP()==2 && motherblob->InParticle(0)->Flav()==motherblob->OutParticle(0)->Flav() && motherblob->InParticle(1)->Flav()==motherblob->OutParticle(1)->Flav())) { // check if particle was produced coherently Particle_Vector sisters = motherblob->GetOutParticles(); for(Particle_Vector::const_iterator it=sisters.begin(); it!=sisters.end(); it++) { if((*it)!=decayer && decayer->Flav()==(*it)->Flav().Bar()) { sister = (*it); break; } } } // in coherent production, special rules apply: if(sister) { if((checkforpartstatus && sister->Status()==part_status::decayed) || (!checkforpartstatus && sister->DecayBlob())) { time = time - sister->Time(); } else time = 0.0; } return time; }
void Lund_Interface::FillOutgoingParticlesInBlob(Blob *blob) { Flavour flav; Vec4D momentum; Particle * particle; int n_q(0), n_g(0); Particle_Vector partons; for (int j=hepevt.jdahep[0][0]-1;j<hepevt.jdahep[0][1];j++) { int idhep = hepevt.idhep[j]; flav=IdhepToSherpa(idhep); momentum=Vec4D(hepevt.phep[j][3],hepevt.phep[j][0], hepevt.phep[j][1],hepevt.phep[j][2]); // don't fill blob position vector here, because decay is in CMS until boosting back particle = new Particle(-1,flav,momentum); particle->SetNumber(0); particle->SetStatus(part_status::active); particle->SetInfo('D'); particle->SetFinalMass(hepevt.phep[j][4]); blob->AddToOutParticles(particle); if(abs(idhep)>0 && abs(idhep)<7) { n_q++; partons.push_back(particle); } else if(abs(idhep)==21) { n_g++; partons.push_back(particle); } } size_t n=partons.size(); if(n>0) blob->SetStatus(blob_status::needs_showers); if(n_q==2 && n_g==0 && n==2) { if(partons[0]->Flav().IsAnti()) { partons[0]->SetFlow(2,-1); partons[1]->SetFlow(1,partons[0]->GetFlow(2)); } else { partons[0]->SetFlow(1,-1); partons[1]->SetFlow(2,partons[0]->GetFlow(1)); } } else if(n_q==0 && n_g==2 && n==2) { partons[0]->SetFlow(2,-1); partons[0]->SetFlow(1,-1); partons[1]->SetFlow(2,partons[0]->GetFlow(1)); partons[1]->SetFlow(1,partons[0]->GetFlow(2)); } else if(n_q==0 && n_g==3 && n==3) { partons[0]->SetFlow(2,-1); partons[0]->SetFlow(1,-1); partons[1]->SetFlow(2,partons[0]->GetFlow(1)); partons[1]->SetFlow(1,-1); partons[2]->SetFlow(2,partons[1]->GetFlow(1)); partons[2]->SetFlow(1,partons[0]->GetFlow(2)); } else if(n>0) { msg_Error()<<METHOD<<" wasn't able to set the color flow for"<<endl<<*blob<<endl; } }
void Signal_Process_FS_QED_Correction::FillBlob (Blob * blob, const Flavour& resflav, Particle_Vector& pv) { Vec4D sum(MomentumSum(pv)); for (Particle_Vector::iterator it=pv.begin();it!=pv.end();) { blob->AddToOutParticles(*it); pv.erase(it); } blob->AddToInParticles(new Particle(-1,resflav,sum,'R')); blob->InParticle(0)->SetFinalMass(blob->InParticle(0)->Momentum().Mass()); }
Vec4D Signal_Process_FS_QED_Correction::MomentumSum (const Particle_Vector& partvec) { Vec4D sum(0.,0.,0.,0.); for (size_t i=0;i<partvec.size();++i) { sum += partvec[i]->Momentum(); } return sum; }
void Signal_Process_FS_QED_Correction::FillBlob (Blob * blob, const Subprocess_Info& spi, Particle_Vector& pv) { // find the leptons owned by this subprocess Particle_Vector localpv; bool onlyleptons(true); for (size_t i=0;i<spi.m_ps.size();++i) { if (spi.m_ps[i].m_fl.Strong()) onlyleptons=false; for (Particle_Vector::iterator it=pv.begin();it!=pv.end();) { if ((*it)->Flav()==spi.m_ps[i].m_fl) { localpv.push_back(*it); pv.erase(it); } else ++it; } } if (onlyleptons) FillBlob(blob,spi.m_fl,localpv); else FillBlob(blob,DetermineGenericResonance(localpv),localpv); }
Blob_Vector Signal_Process_FS_QED_Correction::BuildResonantBlobs (Particle_Vector& pv) { DEBUG_FUNC(""); // get production subprocesses for the active process std::string name(p_mehandler->Process()->Name()); SubInfoVector siv(m_proc_lep_map[name]); // create blobs accordingly (only if lepton list is unambiguous) Blob_Vector blobs; msg_Debugging()<<siv.size()<<" subprocess infos for process " <<name<<std::endl; msg_Debugging()<<"Particle content unambiguous? " <<(ContainsNoAmbiguities(pv)?"yes":"no")<<std::endl; if (siv.size() && ContainsNoAmbiguities(pv)) { for (size_t i=0;i<siv.size();++i) { blobs.push_back(new Blob(Vec4D(0.,0.,0.,0.))); FillBlob(blobs[i],*siv[i],pv); msg_Debugging()<<"built decay blob for subprocess:"<<endl; msg_Debugging()<<*blobs[i]<<endl; } } // find/reconstruct possible resonances in the final state std::vector<Particle_Vector> rpvs; std::vector<Flavour> rfl; const Vertex_List& vlist(m_proc_restab_map[name]); if (m_findresonances && pv.size()>1 && FindResonances(pv,rpvs,rfl,vlist)) { for (size_t i=0;i<rpvs.size();++i) { blobs.push_back(new Blob(Vec4D(0.,0.,0.,0.))); FillBlob(*blobs.rbegin(),rfl[i],rpvs[i]); msg_Debugging()<<"built blob for identified resonance:"<<endl; msg_Debugging()<<**blobs.rbegin()<<endl; } } // otherwise create global resonant blob // if there are leptons not contained in defined resonant blobs if (pv.size()) { blobs.push_back(new Blob(Vec4D(0.,0.,0.,0.))); FillBlob(*blobs.rbegin(),DetermineGenericResonance(pv),pv); msg_Debugging()<<"built generic blob:"<<endl; msg_Debugging()<<**blobs.rbegin()<<endl; } return blobs; }
bool Signal_Process_FS_QED_Correction::PutOnMassShell (const Particle_Vector& partvec) { // if massless in ME put on mass shell for YFS bool allonshell(true); kf_code kfc; std::vector<double>masses(partvec.size(),0.); for (size_t i=0;i<partvec.size();++i) { kfc=partvec[i]->Flav().Kfcode(); if(kfc==kf_graviton || kfc==kf_gscalar) masses[i]=sqrt(fabs(partvec[i]->Momentum().Abs2())); else masses[i]=partvec[i]->Flav().Mass(1); //If one of the two squared masses is zero, IsEqual always returns 0. if (!IsEqual(partvec[i]->Momentum().Abs2(),sqr(masses[i]),1E-4)) allonshell=false; } if (allonshell) return true; Momenta_Stretcher momstretch; return momstretch.StretchMomenta(partvec,masses); }
bool Signal_Process_FS_QED_Correction::ContainsNoAmbiguities (const Particle_Vector& pv) { // look whether any particle occurs more than once std::set<std::string> checklist; for (size_t i=0;i<pv.size();++i) { if (checklist.find(pv[i]->Flav().IDName()) == checklist.end()) checklist.insert(pv[i]->Flav().IDName()); else return false; } return true; }
Flavour Signal_Process_FS_QED_Correction::DetermineGenericResonance (const Particle_Vector& partvec) { int chargesum(0); for (size_t i=0;i<partvec.size();++i) chargesum+=partvec[i]->Flav().IntCharge(); if (chargesum==0) return Flavour(kf_PhotonsHelperNeutral); else if (chargesum==3) return Flavour(kf_PhotonsHelperPlus); else if (chargesum==-3) return Flavour(kf_PhotonsHelperPlus).Bar(); else if (chargesum==6) return Flavour(kf_PhotonsHelperPlusPlus); else if (chargesum==-6) return Flavour(kf_PhotonsHelperPlusPlus).Bar(); else if (chargesum==9) return Flavour(kf_PhotonsHelperPlusPlusPlus); else if (chargesum==-9) return Flavour(kf_PhotonsHelperPlusPlusPlus).Bar(); // i got no clue what this might be return Flavour(kf_none); }
void Hard_Decay_Handler::AssignPhotons(const Particle_Vector& daughters, ParticlePair_Vector& photons) { // for every photon, find charged particle that's closest // ignore radiation off charged resonance for now if (photons.size()) { Particle_Vector cdaughters; for (size_t i(0);i<daughters.size();++i) if (daughters[i]->Flav().Charge()) cdaughters.push_back(daughters[i]); if (cdaughters.size()==1) { for (size_t i(0);i<photons.size();++i) photons[i].second=cdaughters[0]; } else { Vec4D cmom(0.,0.,0.,0.); Vec4D_Vector cmoms; for (size_t i(0);i<cdaughters.size();++i) { cmoms.push_back(cdaughters[i]->Momentum()); cmom+=cmoms[i]; } Poincare ccms(cmom); for (size_t i(0);i<cdaughters.size();++i) ccms.Boost(cmoms[i]); for (size_t i(0);i<photons.size();++i){ Vec4D pmom(photons[i].first->Momentum()); ccms.Boost(pmom); size_t id(0); double dR(pmom.DR(cmoms[0])); for (size_t j(1);j<cmoms.size();++j) { double dRj(pmom.DR(cmoms[j])); if (dRj<dR) { id=j; dR=dRj; } } photons[i].second=cdaughters[id]; } } for (size_t i(0);i<photons.size();++i) { if (photons[i].first==photons[i].second) THROW(fatal_error,"Photon has not been assigned."); msg_Debugging()<<photons[i].first->Flav()<<" " <<photons[i].first->Momentum() <<" assigned to "<<photons[i].second->Flav()<<std::endl; } } }
Vec4D Dress_Blob_Base::CalculateMomentumSum(const Particle_Vector& partvec) { Vec4D sum = Vec4D(0.,0.,0.,0.); for (unsigned int i=0; i<partvec.size(); i++) sum+=partvec[i]->Momentum(); return sum; }
void Dress_Blob_Base::DeleteAll(Particle_Vector& pv) { while (pv.size() != 0) { delete pv[pv.size()-1]; pv.pop_back(); } }
bool Signal_Process_FS_QED_Correction::FindResonances (Particle_Vector& pv,std::vector<Particle_Vector>& rpvs,Flavour_Vector& rfl, const Vertex_List& vlist) { if (vlist.empty()) return false; DEBUG_FUNC("find resonances in "<<pv.size()<<" particles"); // find a combination in pv for which a vertex exists such that the // IS flavour is on-shell within m_resdist times its width // book-keep first to later disentangle competing resonances // need to book-keep i,j,k,abs(mij-mk)/wk std::map<double,std::vector<size_t> > restab; for (size_t i(0);i<pv.size();++i) { for (size_t j(i+1);j<pv.size();++j) { for (size_t k(0);k<vlist.size();++k) { double mdist(abs((pv[i]->Momentum()+pv[j]->Momentum()).Mass() -vlist[k]->in[0].Mass())/vlist[k]->in[0].Width()); if (vlist[k]->nleg==3 && ((pv[i]->Flav()==vlist[k]->in[1] && pv[j]->Flav()==vlist[k]->in[2]) || (pv[i]->Flav()==vlist[k]->in[2] && pv[j]->Flav()==vlist[k]->in[1])) && mdist<m_resdist) { size_t ida[3]={i,j,k}; restab[mdist]=std::vector<size_t>(ida,ida+3); } } } } if (restab.empty()) { msg_Debugging()<<"no resonances found"<<std::endl; return false; } if (msg_LevelIsDebugging()) { msg_Debugging()<<"resonances found:\n"; for (std::map<double,std::vector<size_t> >::const_iterator it=restab.begin();it!=restab.end();++it) msg_Debugging()<<it->second[0]<<it->second[1]<<it->second[2]<<": " <<vlist[it->second[2]]->in[0]<<" -> " <<vlist[it->second[2]]->in[1]<<" " <<vlist[it->second[2]]->in[2] <<", |m-M|/W="<<it->first<<std::endl; } Particle_Vector usedparts; for (std::map<double,std::vector<size_t> >::const_iterator it=restab.begin(); it!=restab.end();++it) { bool valid(true); for (size_t i(0);i<usedparts.size();++i) if (pv[it->second[0]]==usedparts[i] || pv[it->second[1]]==usedparts[i]) { valid=false; break; } if (!valid) continue; usedparts.push_back(pv[it->second[0]]); usedparts.push_back(pv[it->second[1]]); msg_Debugging()<<"constructing decay: "<<vlist[it->second[2]]->in[0]<<" -> " <<vlist[it->second[2]]->in[1]<<" " <<vlist[it->second[2]]->in[2]<<"\n"; rfl.push_back(vlist[it->second[2]]->in[0]); Particle_Vector parts; parts.push_back(pv[it->second[0]]); parts.push_back(pv[it->second[1]]); rpvs.push_back(parts); } for (Particle_Vector::iterator it=usedparts.begin();it!=usedparts.end();++it) for (Particle_Vector::iterator pit=pv.begin();pit!=pv.end();++pit) if (*it==*pit) { pv.erase(pit); break; } return true; }
Return_Value::code Signal_Process_FS_QED_Correction::Treat (Blob_List * bloblist, double & weight) { if (!m_on) return Return_Value::Nothing; if (bloblist->empty()) { msg_Error()<<"Signal_Process_FS_QED_Correction::Treat" <<"("<<bloblist<<","<<weight<<"): "<<endl <<" Blob list contains "<<bloblist->size()<<" entries."<<endl <<" Continue and hope for the best."<<endl; return Return_Value::Error; } // look for QCD corrected hard process in need for QED Blob * sigblob(bloblist->FindLast(btp::Shower)); if (!sigblob) return Return_Value::Nothing; // if already treated -> nothing to do if (sigblob->TypeSpec()=="YFS-type_QED_Corrections_to_ME") return Return_Value::Nothing; if (sigblob->TypeSpec()=="setting_leptons_on-shell") return Return_Value::Nothing; // extract FS leptons // two vectors -> the ones from the blob and the ones to be massive DEBUG_FUNC(m_qed); Particle_Vector fslep(sigblob->GetOutParticles()); Particle_Vector mfslep; for (Particle_Vector::iterator it=fslep.begin();it!=fslep.end();) { if ((*it)->Flav().Strong() || (*it)->Flav().IsDiQuark() || (*it)->DecayBlob()!=NULL) { fslep.erase(it); } else { mfslep.push_back(new Particle(-1,(*it)->Flav(),(*it)->Momentum(),'F')); (*mfslep.rbegin())->SetNumber(0); (*mfslep.rbegin())->SetOriginalPart(*it); (*mfslep.rbegin())->SetFinalMass((*it)->FinalMass()); ++it; } } // if no leptons, nothing to do // if only one lepton, cannot do anything if (fslep.size()<2) { sigblob->UnsetStatus(blob_status::needs_extraQED); for (Particle_Vector::iterator it=mfslep.begin();it!=mfslep.end();++it) delete *it; return Return_Value::Nothing; } // if switched off or no need for QED stop here and build a blob if (!m_qed || !sigblob->Has(blob_status::needs_extraQED)) { Blob * onshellblob = bloblist->AddBlob(btp::QED_Radiation); onshellblob->SetTypeSpec("setting_leptons_on-shell"); if (sigblob->Has(blob_status::needs_extraQED)) sigblob->UnsetStatus(blob_status::needs_extraQED); for (Particle_Vector::iterator it=fslep.begin();it!=fslep.end();++it) { (*it)->SetInfo('H'); (*it)->SetStatus(part_status::decayed); onshellblob->AddToInParticles(*it); } for (Particle_Vector::iterator it=mfslep.begin();it!=mfslep.end();++it) { onshellblob->AddToOutParticles(*it); } onshellblob->SetStatus(blob_status::needs_hadronization); return Return_Value::Success; } // put them on-shell (spoils consistency of pertubative calculation, // but necessary for YFS) if (!PutOnMassShell(mfslep)) { msg_Error()<<"Signal_Process_FS_QED_Correction::Treat(" <<bloblist<<","<<weight<<"): \n" <<" Leptons could not be put on their mass shell.\n" <<" Trying new event.\n" <<" The event contained a "; for (Particle_Vector::iterator it=mfslep.begin();it!=mfslep.end();++it) msg_Error()<<(*it)->Flav().ShellName()<<"-"; if (mfslep.size()==2) msg_Error()<<"pair"; else msg_Error()<<"set"; msg_Error()<<" of too little invariant mass to be put\n" <<" on their mass shell. If you are sensitive to this specific" <<" signature consider\n to set the respective particles" <<" massive in the perturbative calculation using\n" <<" 'MASSIVE[<id>]=1' to avoid this problem.\n"; for (Particle_Vector::iterator it=mfslep.begin();it!=mfslep.end();++it) delete *it; return Return_Value::New_Event; } // build effective verteces for resonant production // use subprocess infos if possible Blob_Vector blobs = BuildResonantBlobs(mfslep); // add radiation for (Blob_Vector::iterator it=blobs.begin();it!=blobs.end();++it) { // do nothing if no resonance determined if ((*it)->InParticle(0)->Flav().Kfcode()!=kf_none) { (*it)->SetStatus(blob_status::needs_extraQED); if (!p_sphotons->AddRadiation(*it)) { msg_Error()<<"Signal_Process_FS_QED_Correction::Treat("<<bloblist <<","<<weight<<"): "<<endl <<" Higher order QED corrections failed."<<endl <<" Retrying event."<<endl; for (Particle_Vector::iterator it=mfslep.begin();it!=mfslep.end();++it) delete *it; for (Blob_Vector::iterator it=blobs.begin();it!=blobs.end();++it) delete *it; return Return_Value::Retry_Event; } } } for (Blob_Vector::iterator it=blobs.begin();it!=blobs.end();++it) { msg_Debugging()<<**it<<endl; (*it)->DeleteInParticles(); } sigblob->UnsetStatus(blob_status::needs_extraQED); // build new QED radiation blob Blob * QEDblob = bloblist->AddBlob(btp::QED_Radiation); QEDblob->SetTypeSpec("YFS-type_QED_Corrections_to_ME"); for (Particle_Vector::iterator it=fslep.begin();it!=fslep.end();++it) { // set info back to hard process, otherwise // check for momentum conservation does not work (*it)->SetInfo('H'); (*it)->SetStatus(part_status::decayed); QEDblob->AddToInParticles(*it); } // first fill in all LO particles for (Blob_Vector::iterator it=blobs.begin();it!=blobs.end();++it) { while ((*it)->NOutP() && (*it)->OutParticle(0)->Info()!='S') { Particle * part((*it)->RemoveOutParticle(0,true)); QEDblob->AddToOutParticles(part); } } // then append all photons for (Blob_Vector::iterator it=blobs.begin();it!=blobs.end();++it) { while ((*it)->NOutP()) { Particle * part((*it)->RemoveOutParticle(0,true)); QEDblob->AddToOutParticles(part); } } QEDblob->SetStatus(blob_status::needs_hadronization); for (size_t i=0;i<blobs.size();++i) { delete blobs[i]; blobs[i]=NULL; } return Return_Value::Success; }
void Hard_Decay_Handler::AddDecayClustering(ATOOLS::Cluster_Amplitude*& ampl, Blob* blob, size_t& imax, size_t idmother) { DEBUG_FUNC("blob->Id()="<<blob->Id()<<" idmother="<<ID(idmother)); DEBUG_VAR(*blob); Particle_Vector daughters; ParticlePair_Vector photons; for (size_t i(0);i<blob->GetOutParticles().size();++i) { Particle * p(blob->OutParticle(i)); if (p->Info()=='S') photons.push_back(make_pair(p,p)); else daughters.push_back(p); } std::sort(photons.begin(),photons.end(),ParticlePairFirstEnergySort()); msg_Debugging()<<"daughters: "; for (size_t i(0);i<daughters.size();++i) msg_Debugging()<<daughters[i]->Flav().IDName()<<" "; msg_Debugging()<<" + "<<photons.size()<<" soft photon(s)"<<std::endl; AssignPhotons(daughters,photons); if (daughters.size()==2) { msg_Debugging()<<"1 to 2 case"<<std::endl; Cluster_Amplitude* copy=ampl->InitPrev(); copy->CopyFrom(ampl); copy->SetFlag(1); copy->SetMS(ampl->MS()); Cluster_Leg *lij(ampl->IdLeg(idmother)); copy->SetKT2(lij->Mom().Abs2()); for (size_t i=0; i<ampl->Legs().size(); ++i) ampl->Leg(i)->SetStat(ampl->Leg(i)->Stat()|1); lij->SetStat(1|2|4); size_t idk(0); for (size_t i=0; i<copy->Legs().size(); ++i) { copy->Leg(i)->SetK(0); if (copy->Leg(i)->Id()!=idmother && (copy->Leg(i)->Col().m_i==lij->Col().m_j || copy->Leg(i)->Col().m_j==lij->Col().m_i)) idk=copy->Leg(i)->Id(); } if (lij->Col().m_i==0 && lij->Col().m_j==0) { // Ad hoc EW partner size_t ampl_nout=ampl->Legs().size()-ampl->NIn(); if (ampl_nout==1) idk=ampl->Leg(0)->Id(); else { size_t select=ampl->Legs().size(); do { select=ampl->NIn()+floor(ran->Get()*ampl_nout); } while (ampl->Leg(select)->Id()&idmother || select>ampl->Legs().size()-1); idk=ampl->Leg(select)->Id(); } } if (idk==0) THROW(fatal_error,"Colour partner not found"); lij->SetK(idk); Cluster_Leg *d1(copy->IdLeg(idmother)); size_t stat1(0), stat2(0); d1->SetMom(RecombinedMomentum(daughters[0],photons,stat1)); d1->SetStat(stat1); d1->SetFlav(daughters[0]->Flav()); copy->CreateLeg(RecombinedMomentum(daughters[1],photons,stat2), daughters[1]->RefFlav()); size_t idnew=1<<(++imax); copy->Legs().back()->SetId(idnew); copy->Legs().back()->SetStat(stat2); Cluster_Amplitude::SetColours(ampl->IdLeg(idmother), copy->IdLeg(idmother), copy->Legs().back()); DEBUG_VAR(*copy); Cluster_Amplitude* tmp=copy; while (tmp->Next()) { tmp=tmp->Next(); for (size_t i=0; i<tmp->Legs().size(); ++i) { if (tmp->Leg(i)->Id()&idmother) { tmp->Leg(i)->SetId(tmp->Leg(i)->Id()|idnew); } if (tmp->Leg(i)->K()&idmother) { tmp->Leg(i)->SetK(tmp->Leg(i)->K()|idnew); } } DEBUG_VAR(*tmp); } std::vector<size_t> ids; ids.push_back(idmother); ids.push_back(idnew); while (photons.size()) AddPhotonsClustering(copy, daughters, photons, imax, ids); if (daughters[0]->DecayBlob()) AddDecayClustering(copy, daughters[0]->DecayBlob(), imax, idmother); if (daughters[1]->DecayBlob()) AddDecayClustering(copy, daughters[1]->DecayBlob(), imax, idnew); ampl=copy; } else if (daughters.size()==3) { msg_Debugging()<<"1 to 3 case"<<std::endl; // structure m -> 0 P[->1 2] // propagator always combines daughters 1+2 Cluster_Amplitude* step1=ampl->InitPrev(); step1->CopyFrom(ampl); step1->SetFlag(1); step1->SetMS(ampl->MS()); Cluster_Leg *lij(ampl->IdLeg(idmother)); step1->SetKT2(lij->Mom().Abs2()); if (!lij) THROW(fatal_error,"Cluster leg of id "+ToString(idmother) +" not found."); for (size_t i=0; i<ampl->Legs().size(); ++i) ampl->Leg(i)->SetStat(ampl->Leg(i)->Stat()|1); lij->SetStat(1|2|4); size_t idk(0); for (size_t i=0; i<step1->Legs().size(); ++i) { step1->Leg(i)->SetK(0); if (step1->Leg(i)->Id()!=idmother) if (step1->Leg(i)->Col().m_i==lij->Col().m_j || step1->Leg(i)->Col().m_j==lij->Col().m_i) idk=step1->Leg(i)->Id(); } if (lij->Col().m_i==0 && lij->Col().m_j==0) { // Ad hoc EW partner size_t ampl_nout=ampl->Legs().size()-ampl->NIn(); if (ampl_nout==1) idk=ampl->Leg(0)->Id(); else { size_t select=ampl->Legs().size(); do { select=ampl->NIn()+floor(ran->Get()*ampl_nout); } while (ampl->Leg(select)->Id()&idmother || select>ampl->Legs().size()-1); idk=ampl->Leg(select)->Id(); } } if (idk==0) THROW(fatal_error,"Colour partner not found"); lij->SetK(idk); Cluster_Leg *d1(step1->IdLeg(idmother)); size_t stat1(0),stat2(0),stat3(0); d1->SetMom(RecombinedMomentum(daughters[0],photons,stat1)); d1->SetStat(stat1); d1->SetFlav(daughters[0]->Flav()); // todo: 1->2 qcd shower with ew fs recoil partner // d1->SetK(idmother);// not that simple: w->qq' has color connection in fs Decay_Channel* dc(NULL); Blob_Data_Base* data = (*blob)["dc"]; if (data) { dc=data->Get<Decay_Channel*>(); DEBUG_VAR(*dc); } else THROW(fatal_error, "Internal error."); Comix1to3* amp=dynamic_cast<Comix1to3*>(dc->GetDiagrams()[0]); if (!amp) THROW(fatal_error, "Internal error."); Flavour prop_flav=amp->Prop(); Vec4D momd2=RecombinedMomentum(daughters[1],photons,stat2); Vec4D momd3=RecombinedMomentum(daughters[2],photons,stat3); Vec4D prop_mom=momd2+momd3; step1->CreateLeg(prop_mom, prop_flav); size_t idnew1=1<<(++imax); step1->Legs().back()->SetId(idnew1); step1->Legs().back()->SetStat(0); Cluster_Amplitude::SetColours(ampl->IdLeg(idmother), step1->IdLeg(idmother), step1->Legs().back()); DEBUG_VAR(*step1); Cluster_Amplitude* tmp=step1; while (tmp->Next()) { tmp=tmp->Next(); for (size_t i=0; i<tmp->Legs().size(); ++i) { if (tmp->Leg(i)->Id()&idmother) { tmp->Leg(i)->SetId(tmp->Leg(i)->Id()|idnew1); } if (tmp->Leg(i)->K()&idmother) { tmp->Leg(i)->SetK(tmp->Leg(i)->K()|idnew1); } } DEBUG_VAR(*tmp); } Cluster_Amplitude* step2=step1->InitPrev(); step2->CopyFrom(step1); step2->SetFlag(1); step2->SetMS(step1->MS()); for (size_t i=0; i<step1->Legs().size(); ++i) step1->Leg(i)->SetStat(step1->Leg(i)->Stat()|1); step1->IdLeg(idnew1)->SetStat(1|4); step1->IdLeg(idnew1)->SetK(idk); for (size_t i=0; i<step2->Legs().size(); ++i) step2->Leg(i)->SetK(0); Cluster_Leg *d2(step2->IdLeg(idnew1)); d2->SetMom(momd2); d2->SetStat(stat2); d2->SetFlav(daughters[1]->Flav()); step2->CreateLeg(momd3, daughters[2]->Flav()); size_t idnew2=1<<(++imax); step2->Legs().back()->SetId(idnew2); step2->Legs().back()->SetStat(stat3); Cluster_Amplitude::SetColours(step1->IdLeg(idnew1), step2->IdLeg(idnew1), step2->Legs().back()); DEBUG_VAR(*step2); tmp=step2; while (tmp->Next()) { tmp=tmp->Next(); for (size_t i=0; i<tmp->Legs().size(); ++i) { if (tmp->Leg(i)->Id()&idnew1) { tmp->Leg(i)->SetId(tmp->Leg(i)->Id()|idnew2); } if (tmp->Leg(i)->K()&idnew1) { tmp->Leg(i)->SetK(tmp->Leg(i)->K()|idnew2); } } DEBUG_VAR(*tmp); } std::vector<size_t> ids; ids.push_back(idmother); ids.push_back(idnew1); ids.push_back(idnew2); while (photons.size()) AddPhotonsClustering(step2,daughters,photons,imax,ids); if (daughters[0]->DecayBlob()) AddDecayClustering(step2, daughters[0]->DecayBlob(), imax, idmother); if (daughters[1]->DecayBlob()) AddDecayClustering(step2, daughters[1]->DecayBlob(), imax, idnew1); if (daughters[2]->DecayBlob()) AddDecayClustering(step2, daughters[2]->DecayBlob(), imax, idnew2); ampl=step2; } else { PRINT_VAR(*blob); THROW(fatal_error, "1 -> n not implemented yet."); } }