#include "SHERPA/LundTools/Lund_Interface.H" #include "SHERPA/LundTools/Lund_Wrapper.H" #include "ATOOLS/Phys/Particle.H" #include "ATOOLS/Phys/Blob.H" #include "ATOOLS/Phys/Blob_List.H" #include "ATOOLS/Org/Run_Parameter.H" #include "ATOOLS/Math/Random.H" #include "ATOOLS/Org/Message.H" #include "ATOOLS/Org/Exception.H" #include "MODEL/Main/Running_AlphaS.H" #include "ATOOLS/Org/MyStrStream.H" #include #include #include "ATOOLS/Org/Message.H" #include "ATOOLS/Org/Scoped_Settings.H" #include "SHERPA/Tools/HepEvt_Interface.H" #include "ATOOLS/Org/CXXFLAGS.H" using namespace SHERPA; using namespace ATOOLS; using namespace std; bool Lund_Interface::s_exportas=false; size_t Lund_Interface::s_errors=0; size_t Lund_Interface::s_maxerrors=0; int * Lund_Interface::s_saved_mrpy=new int[6]; double * Lund_Interface::s_saved_rrpy=new double[100]; ATOOLS::Blob_List *Lund_Interface::s_bloblist=NULL; Lund_Interface::Lund_Interface(): m_maxtrials(2), p_hepevt(NULL), m_compress(true),m_writeout(false), p_phep(new double[5*HEPEVT_CB_SIZE]), p_vhep(new double[4*HEPEVT_CB_SIZE]), p_jmohep(new int[2*HEPEVT_CB_SIZE]), p_jdahep(new int[2*HEPEVT_CB_SIZE]) { RegisterDefaults(); exh->AddTerminatorObject(this); // determine baseline settings from beams // NOTE that these are no default settings, because they get not replaced if // we set an entry or entries in the run card (or command line), they only // get amended. string beam[2], frame("CMS"); Flavour flav[2]; for (size_t i=0;i<2;++i) flav[i]=rpa->gen.Bunch(i); if (flav[0].Kfcode()==kf_e && flav[1].Kfcode()==kf_p_plus) { if (flav[0].IsAnti()) beam[0]="e+"; else beam[0]="e-"; if (flav[1].IsAnti()) beam[1]="p-"; else beam[1]="p+"; pysubs.msub[9]=1; } else if (flav[0].Kfcode()==kf_p_plus && flav[1].Kfcode()==kf_e) { if (flav[0].IsAnti()) beam[0]="p-"; else beam[0]="p+"; if (flav[1].IsAnti()) beam[1]="e+"; else beam[1]="e-"; pysubs.msub[9]=1; } else if (flav[0]==Flavour(kf_e) && flav[1]==Flavour(kf_photon)) { if (flav[0].IsAnti()) beam[0]="e+"; else beam[0]="e-"; beam[1]="gamma"; pysubs.msub[33]=1; } else if (flav[0]==Flavour(kf_photon) && flav[1]==Flavour(kf_e)) { beam[0]="gamma"; if (flav[1].IsAnti()) beam[1]="e+"; else beam[1]="e-"; pysubs.msub[33]=1; } else if (flav[0]==Flavour(kf_photon) && flav[1]==Flavour(kf_photon)) { for (size_t i=0;i<2;++i) beam[i]="gamma"; pysubs.msub[57]=1; } else if (flav[0].Kfcode()==kf_e && flav[1].Kfcode()==kf_e) { for (size_t i=0;i<2;++i) if (flav[i].IsAnti()) beam[i]="e+"; else beam[i]="e-"; pysubs.msub[0]=1; pypars.mstp[47]=1; pydat1.mstj[100]=5; } else { for (size_t i=0;i<2;++i) if (flav[i].IsAnti()) beam[i]="p-"; else beam[i]="p+"; pysubs.msub[0]=1; pypars.mstp[47]=1; pydat1.mstj[100]=5; } s_maxerrors=rpa->gen.NumberOfEvents(); vector > help; pysubs.msel=0; // default hadronisation parameters pydat1.parj[21-1]=0.36; pydat1.parj[41-1]=0.3; pydat1.parj[42-1]=0.6; Settings& s = Settings::GetMainSettings(); ReadSettings(s, "MSUB", pysubs.msub); ReadSettings(s, "CKIN", pysubs.ckin); ReadSettings(s, "MSTJ", pydat1.mstj); ReadSettings(s, "MSTP", pypars.mstp); ReadSettings(s, "MSTU", pydat1.mstu); ReadSettings(s, "PARP", pypars.parp); ReadSettings(s, "PARJ", pydat1.parj); ReadSettings(s, "PARU", pydat1.paru); for (const auto& row : s["KFIN"].GetMatrix()) { if (row.size() != 3) THROW(inconsistent_option, "KFIN setting entries must have exactly three values."); if (row[0] < 1) THROW(inconsistent_option, "The first value of a KFIN entry must be greater than 0."); if (row[1] < -40) THROW(inconsistent_option, "The second value of a KFIN entry must be greater than -40."); pysubs.kfin[row[1] + 40][row[0] - 1] = row[2]; } for (const auto& row : s["MDME"].GetMatrix()) { if (row.size() != 3) THROW(inconsistent_option, "MDME setting entries must have exactly three values."); if (row[0] < 1) THROW(inconsistent_option, "The first value of an MDME entry must be greater than 0."); if (row[1] < 1 || row[1] > 2) THROW(inconsistent_option, "The second value of an MDME entry must be either 1 or 2."); pydat3.mdme[row[1] - 1][row[0] - 1] = row[2]; } for (const auto& row : s["MDCYKF"].GetMatrix()) { if (row.size() != 3) THROW(inconsistent_option, "MDCYKF setting entries must have exactly three values."); if (row[0] < 1) THROW(inconsistent_option, "The first value of an MDCYKF entry must be greater than 0."); if (row[1] < 1 || row[1] > 3) THROW(inconsistent_option, "The second value for an MDCYKF setting entry must be either 1, 2 or 3."); msg_Tracking()<<"Lund_Interface::Lund_Interface(..): " <<"Set MDCY("<=2) pydat3.mdme[1-1][i-1]=Min(0,pydat3.mdme[1-1][i-1]); } pyinit(frame.c_str(),beam[0].c_str(),beam[1].c_str(),100.0); // replacement ends here if (msg_LevelIsDebugging()) ListLundParameters(); pylist(0); } void Lund_Interface::RegisterDefaults() const { Settings& s = Settings::GetMainSettings(); // empty matrix defaults s.DeclareMatrixSettingsWithEmptyDefault({ "MSUB", "MSTP", "MSTJ", "KFIN", "CKIN", "MSTU", "PARP", "PARJ", "PARU", "MDME", "MDCYKF" }); } template void Lund_Interface::ReadSettings(Settings& settings, const std::string& key, T *target) const { for (const auto& row : settings[key].GetMatrix()) { if (row.size() != 2) THROW(inconsistent_option, key + " setting entries must have exactly two values."); if (row[0] < 1) THROW(inconsistent_option, "The first value of a " + key + " entry must be greater than 0."); target[(size_t)row[0] - 1] = row[1]; } } bool Lund_Interface::IsAllowedDecay(kf_code can) { int kc=pycomp(SherpaToIdhep(Flavour(can))); if (kc>0 && kc<501 && pydat3.mdcy[1-1][kc-1]==1) return true; return false; } void Lund_Interface::SwitchOffDecays(kf_code kfc) { int kc = pycomp(SherpaToIdhep(Flavour(kfc))); if(kc>500) return; pydat3.mdcy[1-1][kc-1]=0; } void Lund_Interface::AdjustProperties(Flavour flav) { int kc = pycomp(SherpaToIdhep(flav)); if(kc>500) return; // adjust mass double pythiamass = pydat2.pmas[1-1][kc-1]; double sherpamass = flav.HadMass(); flav.SetMass(pythiamass); if( !(abs(sherpamass-pythiamass)/sherpamass < 1.e-2) ) { msg_Info()<max+Accu()) return -1.0; else return peak; } else { double finalmin = min>(peak-w_cut)? min : peak-w_cut; double finalmax = max<(peak+w_cut)? max : peak+w_cut; if(finalmin>finalmax) return -1.0; else return flav.RelBWMass(finalmin, finalmax, this->Mass(flav)); } } Lund_Interface::~Lund_Interface() { exh->RemoveTerminatorObject(this); NextFile(false); if (p_hepevt) { p_hepevt->SetNhep(0); p_hepevt->SetIsthep(NULL); p_hepevt->SetIdhep(NULL); p_hepevt->SetJmohep(NULL); p_hepevt->SetJdahep(NULL); p_hepevt->SetPhep(NULL); p_hepevt->SetVhep(NULL); delete p_hepevt; p_hepevt = NULL; } if (p_jmohep) { delete [] p_jmohep; p_jmohep = NULL; } if (p_jdahep) { delete [] p_jdahep; p_jdahep = NULL; } if (p_phep) { delete [] p_phep; p_phep = NULL; } if (p_vhep) { delete [] p_vhep; p_vhep = NULL; } } Return_Value::code Lund_Interface::Hadronize(Blob_List *bloblist) { s_bloblist=bloblist; int nhep(0); for (Blob_List::iterator blit=bloblist->begin();blit!=bloblist->end();++blit) { if ((*blit)->Has(blob_status::needs_hadronization)) { if ((*blit)->Type()!=btp::Fragmentation) { msg_Error()<<"Error in "<SetTypeSpec("Pythia_v6.214"); Return_Value::code result=Return_Value::Nothing; for(size_t trials=0; trialsgen.Beam1().IsHadron() || !rpa->gen.Beam2().IsHadron()) { msg_Tracking()<NInP()!=1 || blob->InParticle(0)->Status()!=part_status::active) { msg_Error()<Status()="<Status()<NInP()="<NInP()<Status()="<InParticle(0)->Status()<InParticle(0); Flavour fl = part->Flav(); int kc = pycomp(SherpaToIdhep(fl))-1; double peak = pydat2.pmas[1-1][kc]; double w_cut = pydat2.pmas[3-1][kc]; if( part->FinalMass()+Accu() < peak-w_cut || part->FinalMass()-Accu() > peak+w_cut) { return Return_Value::Retry_Method; } int nhep(0); int idhep = SherpaToIdhep(fl); hepevt.idhep[nhep] = idhep; for (short int j=1;j<4;++j) hepevt.phep[nhep][j-1]=part->Momentum()[j]; hepevt.phep[nhep][3] = part->Momentum()[0]; hepevt.phep[nhep][4] = part->FinalMass(); for (short int j=0;j<4;++j) hepevt.vhep[nhep][j]=0.0; hepevt.isthep[nhep]=1; hepevt.jmohep[nhep][0]=0; hepevt.jmohep[nhep][1]=0; hepevt.jdahep[nhep][0]=0; hepevt.jdahep[nhep][1]=0; nhep++; hepevt.nevhep=0; hepevt.nhep=nhep; pyhepc(2); pydat1.mstu[70-1]=1; pydat1.mstu[71-1]=hepevt.nhep; int ip(1); pydecy(ip); if (pydat1.mstu[24-1]!=0) { msg_Tracking()<<"ERROR in "< "<gen.NumberOfGeneratedEvents()/100) || rpa->gen.NumberOfGeneratedEvents()<200) { msg_Tracking()<<" Up to now: "<SetStatus(part_status::decayed); pyhepc(1); FillOutgoingParticlesInBlob(blob); return Return_Value::Success; } int Lund_Interface::IsConnectedToRemnant(Particle *p,int anti) { DEBUG_FUNC("("<GetFlow(1)<<","<GetFlow(2)<<") "<Find(btp::Beam)); for (int i(0);iInParticle(0)->Flav().IsHadron()) continue; if (remnants[i]==p->ProductionBlob()) continue; msg_Debugging()<<*remnants[i]; for (int j(1);jNOutP();++j) { if (remnants[i]->OutParticle(j)->GetFlow(3-anti)== p->GetFlow(anti)) { msg_Debugging()<<"connected to "<CMS()[j]; hepevt.phep[nhep][3]=blob->CMS()[0]; double pabs=(blob->CMS()).Abs2(); if (pabs<0) hepevt.phep[nhep][4]=0.0; else hepevt.phep[nhep][4]=sqrt(pabs); for (short int j=0;j<4;++j) hepevt.vhep[nhep][j]=0.0; hepevt.isthep[nhep]=1; hepevt.jmohep[nhep][0]=0; hepevt.jmohep[nhep][1]=0; hepevt.jdahep[nhep][0]=0; hepevt.jdahep[nhep][1]=0; // gluon rings int gluonring(1); for (int i(0);iNInP();++i) if (blob->InParticle(i)->Flav().StrongCharge()==3) { gluonring=false; break; } if (gluonring) { Particle * part = blob->InParticle(0); Flavour flav = Flavour(kf_d); if (ran->Get()<0.5) flav = Flavour(kf_u); Particle *help1(new Particle(-1,flav,0.5*part->Momentum())); Particle *help2(new Particle(-1,flav.Bar(),0.5*part->Momentum())); help1->SetStatus(part_status::active); help2->SetStatus(part_status::active); AddPartonToString(help1,nhep); for (int i(1);iNInP();++i) AddPartonToString(blob->InParticle(i),nhep); AddPartonToString(help2,nhep); delete help2; delete help1; return nhep; } // gluons connected to remnant for (int i(0);iNInP();++i) { Particle * part = blob->InParticle(i); int c1(IsConnectedToRemnant(part,1)); int c2(IsConnectedToRemnant(part,2)); if (part->GetFlow(1) && part->GetFlow(2) && (c1^c2)) { Flavour flav = Flavour(kf_d); if (ran->Get()<0.5) flav = Flavour(kf_u); double x(ran->Get()), m(flav.HadMass()); if (part->Momentum()[0]Momentum()[0],ran->Get()); if (!c1 && c2) x=1.0-pow(m/part->Momentum()[0],ran->Get()); Particle *help1(new Particle(-1,flav,x*part->Momentum())); Particle *help2(new Particle(-1,flav.Bar(),(1.0-x)*part->Momentum())); help1->SetStatus(part_status::active); help2->SetStatus(part_status::active); AddPartonToString(help2,nhep); AddPartonToString(help1,nhep); delete help2; delete help1; } } else { AddPartonToString(part,nhep); } } return nhep; } Return_Value::code Lund_Interface::StringFragmentation(Blob *blob,Blob_List *bloblist,int nhep) { hepevt.nevhep=0; hepevt.nhep=nhep; pyhepc(2); pydat1.mstu[70-1]=1; pydat1.mstu[71-1]=hepevt.nhep; int ip(1); pyprep(ip); pystrf(ip); pyhepc(1); bool goon(true), flag(false); if(hepevt.nhep<=nhep) { goon=false; flag=true;} while(goon) { goon=false; for(int i=0; iNInP();i++) cms+=blob->InParticle(i)->Momentum(); msg_Tracking()<<"ERROR in "<gen.NumberOfGeneratedEvents()/100) || rpa->gen.NumberOfGeneratedEvents()<200) { msg_Tracking()<<" Up to now: "<Flav()); for (short int j=1; j<4; ++j) hepevt.phep[nhep][j-1]=parton->Momentum()[j]; hepevt.phep[nhep][3]=parton->Momentum()[0]; double pabs=(parton->Momentum()).Abs2(); if (pabs<0) hepevt.phep[nhep][4]=0.0; else hepevt.phep[nhep][4]=sqrt(pabs); for (short int j=1;j<4;++j) hepevt.vhep[nhep][j-1]=parton->XProd()[j]; hepevt.vhep[nhep][3]=parton->XProd()[0]; hepevt.isthep[nhep]=1; hepevt.jmohep[nhep][0]=0; hepevt.jmohep[nhep][1]=0; hepevt.jdahep[nhep][0]=0; hepevt.jdahep[nhep][1]=0; nhep++; } void Lund_Interface::FillFragmentationBlob(Blob *blob) { Particle *particle; Flavour flav; Vec4D momentum, position; for (int i=0;iSetNumber(0); particle->SetStatus(part_status::active); particle->SetInfo('P'); particle->SetFinalMass(hepevt.phep[j][4]); blob->SetPosition(position); blob->AddToOutParticles(particle); } } } blob->SetStatus(blob_status::needs_hadrondecays); } 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;jSetNumber(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()<>pydatr.mrpy[i]; } for(int i=0;i<100;i++) { myinstream>>pydatr.rrpy[i]; } myinstream.close(); } else msg_Error()<<"ERROR in "<gen.Variable("SHERPA_STATUS_PATH")); if (path=="") return; RestoreStatus(); WriteOutStatus((path+"/Lund_random.dat").c_str()); } void Lund_Interface::Error(const int error) { ++s_errors; if (s_errors>s_maxerrors) { THROW(critical_error,"Pythia calls PYERRM("+ ToString(error)+")"); } else { msg_Tracking()<<"Lund_Interface::Error("<gen.NumberOfGeneratedEvents()<<"." <GetOutStream(); if (outfile!=NULL) { oldfile=m_outfile+ToString(m_curfile)+string(".evts"); if (newfile) (*outfile)<<(m_outfile+ToString(++m_curfile)+string(".evts"))<SetNhep(0); p_hepevt->SetIsthep(NULL); p_hepevt->SetIdhep(NULL); p_hepevt->SetJmohep(NULL); p_hepevt->SetJdahep(NULL); p_hepevt->SetPhep(NULL); p_hepevt->SetVhep(NULL); delete p_hepevt; p_hepevt = NULL; } return; } string file = string(m_outfile+ToString(m_curfile)+string(".evts")); p_hepevt->ChangeOutStream(file,m_evtsperfile); } Return_Value::code Lund_Interface::OneEvent(Blob_List * const blobs,double &weight) { bool okay = false; for (int i=0;i<200;i++) { pyevnt(); pyhepc(1); //pylist(2); weight=1.; //*=pypars.pari[10]; for (int i=0;iSetNhep(hepevt.nhep); p_hepevt->SetIsthep(hepevt.isthep); p_hepevt->SetIdhep(hepevt.idhep); p_hepevt->SetJmohep(p_jmohep); p_hepevt->SetJdahep(p_jdahep); p_hepevt->SetPhep(p_phep); p_hepevt->SetVhep(p_vhep); if (msg_LevelIsDebugging()) pylist(3); if (p_hepevt->HepEvt2Sherpa(blobs)) { okay = true; break; } } if (okay) return Return_Value::Success; return Return_Value::Nothing; } Flavour Lund_Interface::IdhepToSherpa(long int idhep) { // This is not a simple conversion of PDG or HepEvt <-> Sherpa // since Pythia is using the same swapped codes for a_0 and f_0 as Sherpa kf_code kfc = (kf_code) abs(idhep); if (abs(idhep)==91) kfc=kf_cluster; else if (abs(idhep)==92) kfc=kf_string; return Flavour(kfc, idhep<0); } long int Lund_Interface::SherpaToIdhep(const Flavour& flav) { // This is not a simple conversion of PDG or HepEvt <-> Sherpa // since Pythia is using the same swapped codes for a_0 and f_0 as Sherpa long int idhep=flav.Kfcode(); if (idhep==kf_cluster) idhep=91; else if (idhep==kf_string) idhep=92; return (flav.IsAnti() ? -idhep : idhep); }