diff --git a/MatrixElement/FxFx/FxFxEventHandler.cc b/MatrixElement/FxFx/FxFxEventHandler.cc --- a/MatrixElement/FxFx/FxFxEventHandler.cc +++ b/MatrixElement/FxFx/FxFxEventHandler.cc @@ -1,652 +1,673 @@ // -*- C++ -*- // // Based on: // FxFxEventHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG 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 FxFxEventHandler class. // #include "FxFxEventHandler.h" #include "FxFxReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Handlers/LuminosityFunction.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/Utilities/LoopGuard.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; FxFxEventHandler::~FxFxEventHandler() {} IBPtr FxFxEventHandler::clone() const { return new_ptr(*this); } IBPtr FxFxEventHandler::fullclone() const { return new_ptr(*this); } void FxFxEventHandler::doinit() { EventHandler::doinit(); for ( int i = 0, N = readers().size(); i < N; ++i ) { readers()[i]->init(); //FxFxReader & reader = *readers()[i]; //reader.initialize(*this); //weightnames = reader.optWeightsNamesFunc(); } /* XSecStat* initxsecs = new XSecStat[weightnames.size()]; for(int ww = 0; ww < weightnames.size(); ww++){ initxsecs[ww].reset(); optstats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww])); opthistStats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww])); CrossSection initxs = 0.*picobarn; optxs.insert(std::make_pair<string,CrossSection>(weightnames[ww], initxs)); }*/ ntries = 0; } void FxFxEventHandler::initialize() { if ( lumiFnPtr() ) Repository::clog() << "The LuminosityFunction '" << lumiFnPtr()->name() << "' assigned to the FxFxEventHandler '" << name() << "' will not be active in this run. Instead the incoming " << "particles will be determined by the used FxFxReader objects.\n" << Exception::warning; if ( readers().empty() ) throw FxFxInitError() << "No readers were defined for the FxFxEventHandler '" << name() << "'" << Exception::warning; // Go through all the readers and collect information about cross // sections and processes. typedef map<int,tFxFxReaderPtr> ProcessMap; ProcessMap processes; PDPair incoming; Energy MaxEA = ZERO; Energy MaxEB = ZERO; for ( int i = 0, N = readers().size(); i < N; ++i ) { FxFxReader & reader = *readers()[i]; reader.initialize(*this); weightnames = reader.optWeightsNamesFunc(); // Check that the incoming particles are consistent between the // readers. if ( !incoming.first ) { incoming.first = getParticleData(reader.heprup.IDBMUP.first); if ( !incoming.first ) Throw<FxFxInitError>() << "Unknown beam PID " << reader.heprup.IDBMUP.first << ". Have you created a matching BeamParticle object?" << Exception::runerror; } if ( !incoming.second ) { incoming.second = getParticleData(reader.heprup.IDBMUP.second); if ( !incoming.second ) Throw<FxFxInitError>() << "Unknown beam PID " << reader.heprup.IDBMUP.first << ". Have you created a matching BeamParticle object?" << Exception::runerror; } if ( incoming.first->id() != reader.heprup.IDBMUP.first || incoming.second->id() != reader.heprup.IDBMUP.second ) Repository::clog() << "The different FxFxReader objects in the " << "FxFxEventHandler '" << name() << "' have different " << "types of colliding particles." << Exception::warning; MaxEA = max(MaxEA, reader.heprup.EBMUP.first*GeV); MaxEB = max(MaxEB, reader.heprup.EBMUP.second*GeV); // Check that the weighting of the events in the different readers // is consistent with the ones requested for this event // handler. Also collect the sum of the maximum weights. if ( reader.negativeWeights() && weightOption() > 0 ) throw FxFxInitError() << "The reader '" << reader.name() << "' contains negatively weighted events, " << "which is not allowed for the FxFxEventHandler '" << name() << "'." << Exception::warning; // Check that we do not have the same process numbers in different // readers. for ( int ip = 0; ip < reader.heprup.NPRUP; ++ip ) { if ( reader.heprup.LPRUP[ip] ) { ProcessMap::iterator pit = processes.find(reader.heprup.LPRUP[ip]); if ( pit == processes.end() ) processes[reader.heprup.LPRUP[ip]] = readers()[i]; else if ( warnPNum ) { Throw<FxFxPNumException>() << "In the FxFxEventHandler '" << name() << "', both the '" << pit->second->name() << "' and '" << reader.name() << "' contains sub-process number " << pit->first << ". This process may be double-counted in this run." << Exception::warning; } } } selector().insert(reader.stats.maxXSec(), i); } stats.maxXSec(selector().sum()); histStats.maxXSec(selector().sum()); for (map<string,XSecStat>::iterator it= optstats.begin(); it!=optstats.end(); ++it){ (it->second).maxXSec(selector().sum()); } // Check that we have any cross section at all. if ( stats.maxXSec() <= ZERO ) throw FxFxInitError() << "The sum of the cross sections of the readers in the " << "FxFxEventHandler '" << name() << "' was zero." << Exception::warning; // We now create a LuminosityFunction object to inform others about // the energy of the beam. theIncoming = incoming; lumiFn(new_ptr(LuminosityFunction(MaxEA, MaxEB))); } void FxFxEventHandler::doinitrun() { EventHandler::doinitrun(); stats.reset(); histStats.reset(); for ( int i = 0, N = readers().size(); i < N; ++i ) { readers()[i]->init(); FxFxReader & reader = *readers()[i]; reader.initialize(*this); weightnames = reader.optWeightsNamesFunc(); } // XSecStat initxsecs; XSecStat* initxsecs = new XSecStat[weightnames.size()]; for(size_t ww = 0; ww < weightnames.size(); ww++){ initxsecs[ww].reset(); // optstats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww])); // opthistStats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww])); CrossSection initxs = 0.*picobarn; //optxs.insert(std::make_pair<string,CrossSection>(weightnames[ww], initxs)); optstats.insert(std::make_pair(weightnames[ww], initxsecs[ww])); opthistStats.insert(std::make_pair(weightnames[ww], initxsecs[ww])); optxs.insert(std::make_pair(weightnames[ww], initxs)); } ntries = 0; } EventPtr FxFxEventHandler::generateEvent() { LoopGuard<EventLoopException,FxFxEventHandler> loopGuard(*this, maxLoop()); while ( true ) { loopGuard(); currentReader(readers()[selector().select(UseRandom::current())]); skipEvents(); currentReader()->reset(); double weight = currentReader()->getEvent(); if ( weightOption() == unitweight && weight < 0.0 ) weight = 0.0; if ( weightOption() == unitweight || weightOption() == unitnegweight ) { CrossSection newmax = selector().reweight(weight); if ( newmax > CrossSection() ) increaseMaxXSec(newmax); } select(weight/currentReader()->preweight); histStats.select(weight); if ( !weighted() ) { if ( weightOption() == unitweight || weightOption() == unitnegweight ) { if ( !rndbool(abs(weight)) ) continue; weight = Math::sign(1.0, weight); } else if ( weight == 0.0 ) continue; } else if ( weight == 0.0 ) continue; accept(); // Divide by the bias introduced by the preweights in the reader. weight /= currentReader()->preweight; // fact for weight normalization double fact = theNormWeight ? double(selector().sum()/picobarn) : 1.; try { theLastXComb = currentReader()->getXComb(); - currentEvent(new_ptr(Event(lastParticles(), this, generator()->runName(), - generator()->currentEventNumber(), weight*fact))); + //whether to use the LHE event number or not for the event identification + if(UseLHEEvent==0 || currentReader()->LHEEventNum() == -1) { + currentEvent(new_ptr(Event(lastParticles(), this, generator()->runName(), + generator()->currentEventNumber(), weight*fact ))); + } + else if(UseLHEEvent==1 && currentReader()->LHEEventNum() != -1) { + currentEvent(new_ptr(Event(lastParticles(), this, generator()->runName(), + currentReader()->LHEEventNum(), weight*fact ))); + } currentEvent()->optionalWeights() = currentReader()->optionalEventWeights(); // normalize the optional weights for(map<string,double>::iterator it = currentEvent()->optionalWeights().begin(); it!=currentEvent()->optionalWeights().end();++it) { if(it->first!="ecom"&& it->second!=-999 && it->second!=-111 && it->second!=-222 && it->second!=-333) { it->second *= fact; } } //print optional weights here // cout << "event weight = " << weight << " fact = " << fact << endl; /*for (map<string,double>::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){ std::cout << it->first << " => " << it->second << '\n'; } cout << endl;*/ //print npLO and npNLO // cout << currentReader()->optionalEventnpLO() << "\t" << currentReader()->optionalEventnpNLO() << endl; performCollision(); if ( !currentCollision() ) throw Veto(); return currentEvent(); } catch (Veto) { reject(weight); } catch (Stop) { } catch (Exception &) { reject(weight); throw; } } } void FxFxEventHandler::skipEvents() { if ( weightOption() == 2 || weightOption() == -2 ) return; //does it make sense to skip events if we are using varying weights? // Don't do this for readers which seem to generate events on the fly. if ( currentReader()->active() || currentReader()->NEvents() <= 0 ) return; // Estimate the fration of the total events available from // currentReader() which will be requested. double frac = currentReader()->stats.maxXSec()/stats.maxXSec(); if ( stats.accepted() > 0 ) frac *= double(stats.attempts())/double(stats.accepted()); else frac *= double(stats.attempts() + 1); double xscan = generator()->N()*frac/currentReader()->NEvents(); // Estimate the number of times we need to go through the events for // the currentReader(), and how many events on average we need to // skip for each attempted event to go through the file an integer // number of times. double nscan = ceil(xscan); double meanskip = nscan/xscan - 1.0; // Skip an average numer of steps with a Poissonian distribution. currentReader()-> skip(UseRandom::rndPoisson(meanskip)%currentReader()->NEvents()); } void FxFxEventHandler::select(double weight) { stats.select(weight); currentReader()->select(weight); vector<double> w; for (map<string,double>::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){ w.push_back(it->second); } int ii = 0; for (map<string,XSecStat>::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){ (it->second).select(w[ii]); ii++; } ii = 0; for (map<string,XSecStat>::iterator it= optstats.begin(); it!=optstats.end(); ++it){ (it->second).select(w[ii]); ii++; } } tCollPtr FxFxEventHandler::performCollision() { lastExtractor()->select(lastXCombPtr()); if ( CKKWHandler() ) CKKWHandler()->setXComb(lastXCombPtr()); currentCollision(new_ptr(Collision(lastParticles(), currentEvent(), this))); if ( currentEvent() ) currentEvent()->addCollision(currentCollision()); currentStep(new_ptr(Step(currentCollision(), this))); currentCollision()->addStep(currentStep()); currentStep()->addSubProcess(currentReader()->getSubProcess()); lastExtractor()->constructRemnants(lastXCombPtr()->partonBinInstances(), subProcess(), currentStep()); if ( !currentReader()->cuts().passCuts(*currentCollision()) ) throw Veto(); initGroups(); if ( ThePEG_DEBUG_ITEM(1) ) { if ( currentEvent() ) generator()->logfile() << *currentEvent(); else generator()->logfile() << *currentCollision(); } return continueCollision(); } EventPtr FxFxEventHandler::continueEvent() { try { continueCollision(); } catch (Veto) { const double fact = theNormWeight ? double(selector().sum()/picobarn) : 1.; reject(currentEvent()->weight()/fact); } catch (Stop) { } catch (Exception &) { const double fact = theNormWeight ? double(selector().sum()/picobarn) : 1.; reject(currentEvent()->weight()/fact); throw; } return currentEvent(); } void FxFxEventHandler::dofinish() { EventHandler::dofinish(); if ( selector().compensating() ) generator()->log() << "Warning: The run was ended while the FxFxEventHandler '" << name() << "' was still trying to compensate for weights larger than 1. " << "The cross section estimates may therefore be statistically " << "inaccurate." << endl; } void FxFxEventHandler::statistics(ostream & os) const { if ( statLevel() == 0 ) return; string line = "=======================================" "=======================================\n"; if ( stats.accepted() <= 0 ) { os << line << "No events generated by event handler '" << name() << "'." << endl; return; } os << line << "Statistics for Les Houches event handler \'" << name() << "\':\n" << " " << "generated number of Cross-section\n" << " " << " events attempts (nb)\n"; os << line << "Total:" << setw(42) << stats.accepted() << setw(13) << stats.attempts() << setw(17) << ouniterr(stats.xSec(), stats.xSecErr(), nanobarn) << endl << line; if ( statLevel() == 1 ) return; if ( statLevel() == 2 ) { os << "Per Les Houches Reader breakdown:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { FxFxReader & reader = *readers()[i]; string n = reader.name(); n.resize(37, ' '); os << n << setw(11) << reader.stats.accepted() << setw(13) << reader.stats.attempts() << setw(17) << ouniterr(reader.stats.xSec(), reader.stats.xSecErr(), nanobarn) << endl; } os << line; } else { os << "Per Les Houches Reader (and process #) breakdown:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { FxFxReader & reader = *readers()[i]; string n = reader.name() + " (all)"; n.resize(37, ' '); os << n << setw(11) << reader.stats.accepted() << setw(13) << reader.stats.attempts() << setw(17) << ouniterr(reader.stats.xSec(), reader.stats.xSecErr(), nanobarn) << endl; CrossSection xsectot = reader.stats.xSec(); if ( xsectot != ZERO ) xsectot /= reader.stats.sumWeights(); typedef FxFxReader::StatMap::const_iterator const_iterator; for ( const_iterator i = reader.statmap.begin(); i != reader.statmap.end(); ++i ) { ostringstream ss; ss << reader.name() << " (" << i->first << ")"; string n = ss.str(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted() << setw(13) << i->second.attempts() << setw(17) << ouniterr(i->second.sumWeights()*xsectot, sqrt(i->second.sumWeights2())*xsectot, nanobarn) << endl; } os << line; } } string warn = "Warning: Result may be statistically incorrect since\n" " the following FxFxReaders were oversampled:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { FxFxReader & reader = *readers()[i]; if ( reader.NEvents() > 0 && reader.stats.attempts() > reader.NEvents() ) { os << warn; warn = ""; os << "'" << reader.name() << "' (by a factor " << double(reader.stats.attempts())/double(reader.NEvents()) << ")" << endl; } } } void FxFxEventHandler::increaseMaxXSec(CrossSection maxxsec) { stats.maxXSec(selector().sum()); histStats.maxXSec(selector().sum()); currentReader()->increaseMaxXSec(maxxsec); } void FxFxEventHandler::accept() { ntries++; stats.accept(); histStats.accept(); currentReader()->accept(); for (map<string,XSecStat>::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){ (it->second).accept(); } for (map<string,XSecStat>::iterator it= optstats.begin(); it!=optstats.end(); ++it){ (it->second).accept(); } } void FxFxEventHandler::reject(double w) { ntries++; stats.reject(w); histStats.reject(w); currentReader()->reject(w); vector<double> wv; for (map<string,double>::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){ wv.push_back(it->second); } int ii = 0; for (map<string,XSecStat>::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){ (it->second).reject(wv[ii]); ii++; } ii = 0; for (map<string,XSecStat>::iterator it= optstats.begin(); it!=optstats.end(); ++it){ (it->second).reject(wv[ii]); ii++; } } map<string,CrossSection> FxFxEventHandler::optintegratedXSecMap() const { map<string,CrossSection> result; for (map<string,XSecStat>::const_iterator it= optstats.begin(); it!=optstats.end(); ++it){ result[it->first] = (it->second.sumWeights()/it->second.attempts()) * picobarn; } return result; } CrossSection FxFxEventHandler::histogramScale() const { return histStats.xSec()/histStats.sumWeights(); } CrossSection FxFxEventHandler::integratedXSec() const { return histStats.xSec(); } CrossSection FxFxEventHandler::integratedXSecErr() const { return histStats.xSecErr(); } int FxFxEventHandler::ntriesinternal() const { return stats.attempts(); } void FxFxEventHandler::persistentOutput(PersistentOStream & os) const { os << stats << histStats << theReaders << theSelector << oenum(theWeightOption) << theUnitTolerance << theCurrentReader << warnPNum - << theNormWeight; + << theNormWeight << UseLHEEvent; } void FxFxEventHandler::persistentInput(PersistentIStream & is, int) { is >> stats >> histStats >> theReaders >> theSelector >> ienum(theWeightOption) >> theUnitTolerance >> theCurrentReader >> warnPNum - >> theNormWeight; + >> theNormWeight >> UseLHEEvent;; } ClassDescription<FxFxEventHandler> FxFxEventHandler::initFxFxEventHandler; // Definition of the static class description member. void FxFxEventHandler::setUnitTolerance(double x) { theUnitTolerance = x; selector().tolerance(unitTolerance()); } void FxFxEventHandler::Init() { static ClassDocumentation<FxFxEventHandler> documentation ("This is the main class administrating the selection of hard " "subprocesses from a set of ThePEG::FxFxReader objects."); static RefVector<FxFxEventHandler,FxFxReader> interfaceFxFxReaders ("FxFxReaders", "Objects capable of reading events from an event file or an " "external matrix element generator.", &FxFxEventHandler::theReaders, -1, false, false, true, false, false); static Switch<FxFxEventHandler,WeightOpt> interfaceWeightOption ("WeightOption", "The different ways to weight events in the Les Houches event handler. " "Whether weighted or not and whether or not negative weights are allowed.", &FxFxEventHandler::theWeightOption, unitweight, true, false); static SwitchOption interfaceWeightOptionUnitWeight (interfaceWeightOption, "UnitWeight", "All events have unit weight.", unitweight); static SwitchOption interfaceWeightOptionNegUnitWeight (interfaceWeightOption, "NegUnitWeight", "All events have weight +1 or maybe -1.", unitnegweight); static SwitchOption interfaceWeightOptionVarWeight (interfaceWeightOption, "VarWeight", "Events may have varying but positive weights.", varweight); static SwitchOption interfaceWeightOptionVarNegWeight (interfaceWeightOption, "VarNegWeight", "Events may have varying weights, both positive and negative.", varnegweight); static Switch<FxFxEventHandler,bool> interfaceWarnPNum ("WarnPNum", "Warn if the same process number is used in more than one " "FxFxReader.", &FxFxEventHandler::warnPNum, true, true, false); static SwitchOption interfaceWarnPNumWarning (interfaceWarnPNum, "Warning", "Give a warning message.", true); static SwitchOption interfaceWarnPNumNoWarning (interfaceWarnPNum, "NoWarning", "Don't give a warning message.", false); static Parameter<FxFxEventHandler,double> interfaceUnitTolerance ("UnitTolerance", "If the <interface>WeightOption</interface> is set to unit weight, do not start compensating unless the a weight is found to be this much larger than unity.", &FxFxEventHandler::theUnitTolerance, 1.0e-6, 0.0, 0, true, false, Interface::lowerlim, &FxFxEventHandler::setUnitTolerance, (double(FxFxEventHandler::*)()const)(0), (double(FxFxEventHandler::*)()const)(0), (double(FxFxEventHandler::*)()const)(0), (double(FxFxEventHandler::*)()const)(0)); static Switch<FxFxEventHandler,unsigned int> interfaceWeightNormalization ("WeightNormalization", "How to normalize the output weights", &FxFxEventHandler::theNormWeight, 0, false, false); static SwitchOption interfaceWeightNormalizationUnit (interfaceWeightNormalization, "Normalized", "Standard normalization, i.e. +/- for unweighted events", 0); static SwitchOption interfaceWeightNormalizationCrossSection (interfaceWeightNormalization, "CrossSection", "Normalize the weights to the max cross section in pb", 1); + static Switch<FxFxEventHandler,unsigned int> interfaceEventNumbering + ("EventNumbering", + "How to number the events", + &FxFxEventHandler::UseLHEEvent, 0, false, false); + static SwitchOption interfaceEventNumberingIncremental + (interfaceEventNumbering, + "Incremental", + "Standard incremental numbering (i.e. as they are generated)", + 0); + static SwitchOption interfaceEventNumberingLHE + (interfaceEventNumbering, + "LHE", + "Corresponding to the LHE event number", + 1); interfaceFxFxReaders.rank(10); interfaceWeightOption.rank(9); } diff --git a/MatrixElement/FxFx/FxFxEventHandler.h b/MatrixElement/FxFx/FxFxEventHandler.h --- a/MatrixElement/FxFx/FxFxEventHandler.h +++ b/MatrixElement/FxFx/FxFxEventHandler.h @@ -1,447 +1,452 @@ // -*- C++ -*- // // FxFxEventHandler.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_FxFxEventHandler_H #define THEPEG_FxFxEventHandler_H // // This is the declaration of the FxFxEventHandler class. // #include "ThePEG/Handlers/EventHandler.h" #include "FxFxEventHandler.fh" #include "FxFxReader.fh" #include "ThePEG/Utilities/CompSelector.h" #include "ThePEG/Utilities/XSecStat.h" namespace ThePEG { /** * The FxFxEventHandler inherits from the general EventHandler * class and administers the reading of events generated by external * matrix element generator programs according to the Les Houches * accord. * * The class has a list of <code>FxFxReader</code>s which * typically are connected to files with event data produced by * external matrix element generator programs. When an event is * requested by FxFxEventHandler, one of the readers are chosen, * an event is read in and then passed to the different * <code>StepHandler</code> defined in the underlying * EventHandler class. * * @see \ref FxFxEventHandlerInterfaces "The interfaces" * defined for FxFxEventHandler. */ class FxFxEventHandler: public EventHandler { public: /** * A vector of FxFxReader objects. */ typedef vector<FxFxReaderPtr> ReaderVector; /** * A selector of readers. */ typedef CompSelector<int,CrossSection> ReaderSelector; /** * Enumerate the weighting options. */ enum WeightOpt { unitweight = 1, /**< All events have unit weight. */ unitnegweight = -1, /**< All events have wight +/- 1. */ varweight = 2, /**< Varying positive weights. */ varnegweight = -2 /**< Varying positive or negative weights. */ }; friend class FxFxHandler; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FxFxEventHandler() - : theWeightOption(unitweight), theUnitTolerance(1.0e-6), warnPNum(true), theNormWeight(0) + : theWeightOption(unitweight), theUnitTolerance(1.0e-6), warnPNum(true), theNormWeight(0), UseLHEEvent(0) { selector().tolerance(unitTolerance()); } /** * The destructor. */ virtual ~FxFxEventHandler(); //@} public: /** @name Initialization and finalization functions. */ //@{ /** * Initialize this event handler and all related objects needed to * generate events. */ virtual void initialize(); /** * Write out accumulated statistics about intergrated cross sections * and stuff. */ virtual void statistics(ostream &) const; /** * Histogram scale. A histogram bin which has been filled with the * weights associated with the Event objects should be scaled by * this factor to give the correct cross section. */ virtual CrossSection histogramScale() const; /** * The estimated total integrated cross section of the processes * generated in this run. * @return 0 if no integrated cross section could be estimated. */ virtual CrossSection integratedXSec() const; virtual int ntriesinternal() const; /** * The estimated error in the total integrated cross section of the * processes generated in this run. * @return 0 if no integrated cross section error could be estimated. */ virtual CrossSection integratedXSecErr() const; virtual map<string,CrossSection> optintegratedXSecMap() const; //@} /** @name Functions used for the actual generation */ //@{ /** * Generate an event. */ virtual EventPtr generateEvent(); /** * Create the Event and Collision objects. Used by the * generateEvent() function. */ virtual tCollPtr performCollision(); /** * Continue generating an event if the generation has been stopped * before finishing. */ virtual EventPtr continueEvent(); //@} /** @name Functions to manipulate statistics. */ //@{ /** * An event has been selected. Signal that an event has been * selected with the given \a weight. If unit weights are requested, * the event will be accepted with that weight. This also takes care * of the statistics collection of the selected reader object. */ void select(double weight); /** * Accept the current event, taking care of the statistics * collection of the corresponding reader objects. */ void accept(); /** * Reject the current event, taking care of the statistics * collection of the corresponding reader objects. */ void reject(double weight); /** * Increase the overestimated cross section for the selected reader. */ void increaseMaxXSec(CrossSection maxxsec); /** * Skip some events. To ensure a reader file is scanned an even * number of times, skip a number of events for the selected reader. */ void skipEvents(); //@} /** @name Simple access functions. */ //@{ /** * The way weights are to be treated. */ WeightOpt weightOption() const { return theWeightOption; } /** * If the weight option is set to unit weight, do not start * compensating unless the weight is this much larger than unity. */ double unitTolerance() const { return theUnitTolerance; } /** * Access the list of readers. */ const ReaderVector & readers() const { return theReaders; } /** * The selector to choose readers according to their overestimated * cross section. */ const ReaderSelector & selector() const { return theSelector; } /** * The currently selected reader object. */ tFxFxReaderPtr currentReader() const { return theCurrentReader; } /** * Set the currently selected reader object. */ void currentReader(tFxFxReaderPtr x) { theCurrentReader = x; } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); /** * The currently selected reader object. */ tFxFxReaderPtr theCurrentReader; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} protected: /** * Access the list of readers. */ ReaderVector & readers() { return theReaders; } /** * The selector to choose readers according to their overestimated * cross section. */ ReaderSelector & selector() { return theSelector; } /** * Helper function for the interface; */ void setUnitTolerance(double); /** * Collect statistics for this event handler. */ XSecStat stats; map<string,XSecStat> optstats; map<string,CrossSection> optxs; int ntries; map<string,XSecStat> OptStatsFunc() { return optstats; } map<string,CrossSection> OptXsFunc() { return optxs; } /** * Collect statistics for this event handler. To be used for * histogram scaling. */ XSecStat histStats; map<string,XSecStat> opthistStats; /* * The weight identifiers for the events */ vector<string> weightnames; private: /** * The list of readers. */ ReaderVector theReaders; /** * The selector to choose readers according to their overestimated * cross section. */ ReaderSelector theSelector; /** * The way weights are to be treated. */ WeightOpt theWeightOption; /** * If the weight option is set to unit weight, do not start * compensating unless the weight is this much larger than unity. */ double theUnitTolerance; /** * Warn if the same process number is used in more than one * FxFxReader. */ bool warnPNum; /** * How to normalize the weights */ unsigned int theNormWeight; + /** + * How to number the events + */ + unsigned int UseLHEEvent; + public: /** @cond EXCEPTIONCLASSES */ /** * Exception class used if no readers were assigned. */ class FxFxInitError: public InitException {}; /** * Exception class used if the same process number is used by more * than ne reader. */ class FxFxPNumException: public InitException {}; /** @endcond */ private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription<FxFxEventHandler> initFxFxEventHandler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FxFxEventHandler & operator=(const FxFxEventHandler &) = delete; }; } // CLASSDOC OFF #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FxFxEventHandler. */ template <> struct BaseClassTrait<FxFxEventHandler,1> { /** Typedef of the first base class of FxFxEventHandler. */ typedef EventHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the FxFxEventHandler class and the shared object where it is defined. */ template <> struct ClassTraits<FxFxEventHandler> : public ClassTraitsBase<FxFxEventHandler> { /** Return a platform-independent class name */ static string className() { return "Herwig::FxFxEventHandler"; } /** Return the name of the shared library be loaded to get access to * the FxFxEventHandler class and every other class it uses * (except the base class). */ static string library() { return "HwFxFx.so"; } }; /** @endcond */ } #endif /* THEPEG_FxFxEventHandler_H */ diff --git a/MatrixElement/FxFx/FxFxFileReader.cc b/MatrixElement/FxFx/FxFxFileReader.cc --- a/MatrixElement/FxFx/FxFxFileReader.cc +++ b/MatrixElement/FxFx/FxFxFileReader.cc @@ -1,929 +1,946 @@ // -*- C++ -*- // // FxFxFileReader.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG 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 FxFxFileReader class. // #include "FxFxFileReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include <sstream> #include <iostream> using namespace ThePEG; FxFxFileReader:: FxFxFileReader(const FxFxFileReader & x) : FxFxReader(x), neve(x.neve), ieve(0), LHFVersion(x.LHFVersion), outsideBlock(x.outsideBlock), headerBlock(x.headerBlock), initComments(x.initComments), initAttributes(x.initAttributes), eventComments(x.eventComments), eventAttributes(x.eventAttributes), theFileName(x.theFileName), theQNumbers(x.theQNumbers), theIncludeFxFxTags(x.theIncludeFxFxTags), theIncludeCentral(x.theIncludeCentral), theDecayer(x.theDecayer) {} FxFxFileReader::~FxFxFileReader() {} IBPtr FxFxFileReader::clone() const { return new_ptr(*this); } IBPtr FxFxFileReader::fullclone() const { return new_ptr(*this); } bool FxFxFileReader::preInitialize() const { return true; } void FxFxFileReader::doinit() { FxFxReader::doinit(); // are we using QNUMBERS if(!theQNumbers) return; // parse the header block and create // any new particles needed in QNUMBERS blocks string block = headerBlock; string line = ""; bool readingSLHA = false; int (*pf)(int) = tolower; unsigned int newNumber(0); do { line = StringUtils::car(block,"\r\n"); block = StringUtils::cdr(block,"\r\n"); if(line[0]=='#') continue; // are we reading the SLHA block if(readingSLHA) { // reached the end of slha block ? if(line.find("</slha") != string::npos) { readingSLHA = false; break; } // remove trailing comment from line vector<string> split = StringUtils::split(line,"#"); // check for a qnumbers block transform(split[0].begin(), split[0].end(), split[0].begin(), pf); // if not contine if(split[0].find("block qnumbers")==string::npos) continue; // get name from comment string name; if(split.size()>=2) { name = StringUtils::stripws(split[1]); } else { ++newNumber; ostringstream tname; tname << "NP" << newNumber; name = tname.str(); } // extract the PDG code split = StringUtils::split(split[0]," "); istringstream is(split[2]); long PDGCode(0); is >> PDGCode; // get the charge, spin, colour and whether an antiparticle int charge(0),spin(0),colour(0),anti(0); for(unsigned int ix=0;ix<4;++ix) { line = StringUtils::car(block,"\r\n"); block = StringUtils::cdr(block,"\r\n"); int dummy[2]; istringstream is(line); is >> dummy[0] >> dummy[1]; switch (dummy[0]) { case 1: charge = dummy[1]; break; case 2: spin = dummy[1]; break; case 3: colour = dummy[1]; break; case 4: anti = dummy[1]; break; default: assert(false); } } // check if particles already exist PDPair newParticle; newParticle.first = getParticleData(PDGCode); if(newParticle.first) Throw<SetupException>() << "Particle with PDG code " << PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists. Retaining the original particle" << Exception::warning; if(anti) { newParticle.second = getParticleData(-PDGCode); if(newParticle.second) Throw<SetupException>() << "Anti-particle with PDG code " << -PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists. Retaining the original particle" << Exception::warning; if(( newParticle.first && !newParticle.second ) || ( newParticle.second && !newParticle.first ) ) Throw<SetupException>() << "Either particle or anti-particle with PDG code " << PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists, but not both the particle and antiparticle. " << " Something dodgy here stopping" << Exception::runerror; } // already exists continue if(newParticle.first) continue; // create the particles // particle with no anti particle if( anti == 0 ) { // construct the name if(name=="") { ostringstream temp; temp << PDGCode; name = temp.str(); } // create the ParticleData object newParticle.first = ParticleData::Create(PDGCode,name); } // particle anti-particle pair else { // construct the names string nameAnti; if(name=="") { ostringstream temp; temp << PDGCode; name = temp.str(); ostringstream temp2; temp << -PDGCode; nameAnti = temp2.str(); } else { nameAnti=name; for(string::iterator it=nameAnti.begin();it!=nameAnti.end();++it) { if(*it=='+') nameAnti.replace(it,it+1,"-"); else if(*it=='-') nameAnti.replace(it,it+1,"+"); } if(nameAnti==name) nameAnti += "bar"; } // create the ParticleData objects newParticle = ParticleData::Create(PDGCode,name,nameAnti); } // set the particle properties if(colour==1) colour = 0; newParticle.first->iColour(PDT::Colour(colour)); newParticle.first->iSpin (PDT::Spin (spin )); newParticle.first->iCharge(PDT::Charge(charge)); // register it generator()->preinitRegister(newParticle.first, "/Herwig/Particles/"+newParticle.first->PDGName()); // set the antiparticle properties if(newParticle.second) { if(colour==3||colour==6) colour *= -1; charge = -charge; newParticle.second->iColour(PDT::Colour(colour)); newParticle.second->iSpin (PDT::Spin (spin )); newParticle.second->iCharge(PDT::Charge(charge)); // register it generator()->preinitRegister(newParticle.second, "/Herwig/Particles/"+newParticle.second->PDGName()); } } // start of SLHA block ? else if(line.find("<slha") != string::npos) { readingSLHA = true; } } while(line!=""); // now set any masses/decay modes block = headerBlock; line=""; readingSLHA=false; bool ok=true; do { line = StringUtils::car(block,"\r\n"); block = StringUtils::cdr(block,"\r\n"); // are we reading the SLHA block if(readingSLHA) { // reached the end? if(line.find("</slha") == 0 ) { readingSLHA = false; break; } // make lower case transform(line.begin(),line.end(),line.begin(), pf); // found the mass block ? if(line.find("block mass")!=string::npos) { // read it line = StringUtils::car(block,"\r\n"); // check not at end while(line[0] != 'D' && line[0] != 'B' && line[0] != 'd' && line[0] != 'b' && line != "") { // skip comment lines if(line[0] == '#') { block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); continue; } // get the mass and PGD code istringstream temp(line); long id; double mass; temp >> id >> mass; // skip resetting masses on SM particles // as it can cause problems later on in event generation if(abs(id)<=6 || (abs(id)>=11 && abs(id)<=16) || abs(id)==23 || abs(id)==24) { // Throw<SetupException>() << "Standard model mass for PID " // << id // << " will not be changed." // << Exception::warning; block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); continue; } // magnitude of mass for susy models mass = abs(mass); // set the mass tPDPtr particle = getParticleData(id); if(!particle) throw SetupException() << "FxFxFileReader::doinit() - Particle with PDG code not" << id << " not found." << Exception::runerror; const InterfaceBase * ifb = BaseRepository::FindInterface(particle, "NominalMass"); ostringstream os; os << mass; ifb->exec(*particle, "set", os.str()); // read the next line block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); }; } // found a decay block else if(line.find("decay") == 0) { // get PGD code and width istringstream iss(line); string dummy; long parent(0); Energy width(ZERO); iss >> dummy >> parent >> iunit(width, GeV); // get the ParticleData object PDPtr inpart = getParticleData(parent); if(!inpart) { throw SetupException() << "FxFxFileReader::doinit() - A ParticleData object with the PDG code " << parent << " does not exist. " << Exception::runerror; return; } if ( abs(inpart->id()) == 6 || abs(inpart->id()) == 15 || abs(inpart->id()) == 23 || abs(inpart->id()) == 24 || abs(inpart->id()) == 25 ) { Throw<SetupException>() << "\n" "************************************************************************\n" "* Your LHE file changes the width of " << inpart->PDGName() << ".\n" "* This can cause serious problems in the event generation!\n" "************************************************************************\n" "\n" << Exception::warning; } else if (inpart->width() > ZERO && width <= ZERO) { Throw<SetupException>() << "\n" "************************************************************************\n" "* Your LHE file zeroes the non-zero width of " << inpart->PDGName() << ".\n" "* If " << inpart->PDGName() << " is a decaying SM particle,\n" "* this can cause serious problems in the event generation!\n" "************************************************************************\n" "\n" << Exception::warning; } // set the width inpart->width(width); if( width > ZERO ) { inpart->cTau(hbarc/width); inpart->widthCut(5.*width); inpart->stable(false); } // construct prefix for DecayModes string prefix(inpart->name() + "->"), tag(prefix),line(""); unsigned int nmode(0); // read any decay modes line = StringUtils::car(block,"\r\n"); while(line[0] != 'D' && line[0] != 'B' && line[0] != 'd' && line[0] != 'b' && line[0] != '<' && line != "") { // skip comments if(line[0] == '#') { block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); continue; } // read decay mode and construct the tag istringstream is(line); double brat(0.); unsigned int nda(0),npr(0); is >> brat >> nda; while( true ) { long t; is >> t; if( is.fail() ) break; if( t == abs(parent) ) throw SetupException() << "An error occurred while read a decay of the " << inpart->PDGName() << ". One of its products has the same PDG code " << "as the parent particle in FxFxFileReader::doinit()." << " Please check the Les Houches file.\n" << Exception::runerror; tcPDPtr p = getParticleData(t); if( !p ) throw SetupException() << "FxFxFileReader::doinit() -" << " An unknown PDG code has been encounterd " << "while reading a decay mode. ID: " << t << Exception::runerror; ++npr; tag += p->name() + ","; } if( npr != nda ) throw SetupException() << "FxFxFileReader::doinit() - While reading a decay of the " << inpart->PDGName() << " from an SLHA file, an inconsistency " << "between the number of decay products and the value in " << "the 'NDA' column was found. Please check if the spectrum " << "file is correct.\n" << Exception::warning; // create the DecayMode if( npr > 1 ) { if( nmode==0 ) { generator()->preinitInterface(inpart, "VariableRatio" , "set","false"); if(inpart->massGenerator()) { ok = false; Throw<SetupException>() << inpart->PDGName() << " already has a WidthGenerator set" << " this is incompatible with using QNUMBERS " << "Use\n" << "set " << inpart->fullName() << ":Width_generator NULL\n" << "to fix this." << Exception::warning; } unsigned int ntemp=0; for(DecaySet::const_iterator dit = inpart->decayModes().begin(); dit != inpart->decayModes().end(); ++dit ) { if((**dit).on()) ++ntemp; } if(ntemp!=0) { ok = false; Throw<SetupException>() << inpart->PDGName() << " already has DecayModes" << " this is incompatible with using QNUMBERS " << "Use\n" << "do " << inpart->fullName() << ":SelectDecayModes none\n" << " to fix this." << Exception::warning; } } inpart->stable(false); tag.replace(tag.size() - 1, 1, ";"); DMPtr dm = generator()->findDecayMode(tag); if(!theDecayer) Throw<SetupException>() << "FxFxFileReader::doinit() Decayer must be set using the " << "FxFxFileReader:Decayer" << " must be set to allow the creation of new" << " decay modes." << Exception::runerror; if(!dm) { dm = generator()->preinitCreateDecayMode(tag); if(!dm) Throw<SetupException>() << "FxFxFileReader::doinit() - Needed to create " << "new decaymode but one could not be created for the tag " << tag << Exception::warning; } generator()->preinitInterface(dm, "Decayer", "set", theDecayer->fullName()); ostringstream br; br << setprecision(13) << brat; generator()->preinitInterface(dm, "BranchingRatio", "set", br.str()); generator()->preinitInterface(dm, "Active", "set", "Yes"); if(dm->CC()) { generator()->preinitInterface(dm->CC(), "BranchingRatio", "set", br.str()); generator()->preinitInterface(dm->CC(), "Active", "set", "Yes"); } ++nmode; } tag=prefix; // read the next line block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); }; if(nmode>0) { inpart->update(); if(inpart->CC()) inpart->CC()->update(); } } } // start of SLHA block ? else if(line.find("<slha") != string::npos) { readingSLHA = true; } } while(line!=""); if(!ok) throw SetupException() << "Problem reading QNUMBERS blocks in FxFxFileReader::doinit()" << Exception::runerror; } void FxFxFileReader::initialize(FxFxEventHandler & eh) { FxFxReader::initialize(eh); if ( LHFVersion.empty() ) Throw<FxFxFileError>() << "The file associated with '" << name() << "' does not contain a " << "proper formatted Les Houches event file. The events may not be " << "properly sampled." << Exception::warning; } //vector<string> FxFxFileReader::optWeightNamesFunc() { return optionalWeightsNames; } vector<string> FxFxFileReader::optWeightsNamesFunc() { return optionalWeightsNames; } void FxFxFileReader::open() { if ( filename().empty() ) throw FxFxFileError() << "No Les Houches file name. " << "Use 'set " << name() << ":FileName'." << Exception::runerror; cfile.open(filename()); if ( !cfile ) throw FxFxFileError() << "The FxFxFileReader '" << name() << "' could not open the " << "event file called '" << theFileName << "'." << Exception::runerror; cfile.readline(); if ( !cfile.find("<LesHouchesEvents") ) return; map<string,string> attributes = StringUtils::xmlAttributes("LesHouchesEvents", cfile.getline()); LHFVersion = attributes["version"]; //cout << LHFVersion << endl; if ( LHFVersion.empty() ) return; bool readingHeader = false; bool readingInit = false; headerBlock = ""; // char (cwgtinfo_weights_info[250][15]); string hs; // int cwgtinfo_nn(0); // Loop over all lines until we hit the </init> tag. bool readingInitWeights = false, readingInitWeights_sc = false; string weightinfo; while ( cfile.readline() ) { // found the init block for multiple weights if(cfile.find("<initrwgt")) { /*cout << "reading weights" << endl;*/ readingInitWeights = true; } // found end of init block for multiple weights: end the while loop if(cfile.find("</initrwgt")) { readingInitWeights = false; readingInitWeights_sc = false; continue;} // found the end of init block if(cfile.find("</init")) { readingInit = false; break; } /* read the weight information block * optionalWeightNames will contain information about the weights * this will be appended to the weight information */ if(readingInitWeights) { string scalename = ""; if(cfile.find("<weightgroup")) { /* we found a weight group * start reading the information * within it */ readingInitWeights_sc = true; weightinfo = cfile.getline(); /* to make it shorter, erase some stuff */ string str_weightgroup = "<weightgroup"; string str_arrow = ">"; string str_newline = "\n"; erase_substr(weightinfo, str_weightgroup); erase_substr(weightinfo, str_arrow); erase_substr(weightinfo, str_newline); } /* if we are reading a new weightgroup, go on * until we find the end of it */ if(readingInitWeights_sc && !cfile.find("</weightgroup") && !cfile.find("<weightgroup")) { hs = cfile.getline(); //cout << "hs=" << hs << endl; //cout << "weightinfo= " << weightinfo << endl; //fix for potential new lines: if(!cfile.find("<weight") and !cfile.find("</weightgroup")) { weightinfo = weightinfo + hs; //cout << "weightinfo fixed= " << weightinfo << endl; continue; } istringstream isc(hs); int ws = 0; /* get the name that will be used to identify the scale */ do { string sub; isc >> sub; if(ws==1) { string str_arrow = ">"; erase_substr(sub, str_arrow); scalename = sub; } ++ws; } while (isc); /* now get the relevant information * e.g. scales or PDF sets used */ string startDEL = ">"; //starting delimiter string stopDEL = "</weight>"; //end delimiter unsigned firstLim = hs.find(startDEL); //find start of delimiter // unsigned lastLim = hs.find(stopDEL); //find end of delimitr string scinfo = hs.substr(firstLim); //define the information for the scale erase_substr(scinfo,stopDEL); erase_substr(scinfo,startDEL); scinfo = StringUtils::stripws(scinfo); //cout << "scinfo = " << scinfo << endl; /* fill in the map * indicating the information to be appended to each scale * i.e. scinfo for each scalname */ scalemap[scalename] = scinfo.c_str(); string str_id = "id="; string str_prime = "'"; erase_substr(scalename, str_id); erase_substr(scalename, str_prime); optionalWeightsNames.push_back(scalename); } } if ( cfile.find("<header") ) { // following lines to headerBlock until we hit the end of it. readingHeader = true; headerBlock = cfile.getline() + "\n"; } if ( (cfile.find("<init ") && !cfile.find("<initrwgt")) || cfile.find("<init>") ) { //cout << "found init block" << endl; // We have hit the init block, so we should expect to find the // standard information in the following. But first check for // attributes. initAttributes = StringUtils::xmlAttributes("init", cfile.getline()); readingInit = true; cfile.readline(); if ( !( cfile >> heprup.IDBMUP.first >> heprup.IDBMUP.second >> heprup.EBMUP.first >> heprup.EBMUP.second >> heprup.PDFGUP.first >> heprup.PDFGUP.second >> heprup.PDFSUP.first >> heprup.PDFSUP.second >> heprup.IDWTUP >> heprup.NPRUP ) ) { heprup.NPRUP = -42; LHFVersion = ""; return; } heprup.resize(); for ( int i = 0; i < heprup.NPRUP; ++i ) { cfile.readline(); if ( !( cfile >> heprup.XSECUP[i] >> heprup.XERRUP[i] >> heprup.XMAXUP[i] >> heprup.LPRUP[i] ) ) { heprup.NPRUP = -42; LHFVersion = ""; return; } } } if ( cfile.find("</header") ) { readingHeader = false; headerBlock += cfile.getline() + "\n"; } if ( readingHeader ) { /* We are in the process of reading the header block. Dump the line to headerBlock.*/ headerBlock += cfile.getline() + "\n"; } if ( readingInit ) { // Here we found a comment line. Dump it to initComments. initComments += cfile.getline() + "\n"; } } string central = "central"; if (theIncludeCentral) optionalWeightsNames.push_back(central); // cout << "reading init finished" << endl; if ( !cfile ) { heprup.NPRUP = -42; LHFVersion = ""; return; } } bool FxFxFileReader::doReadEvent() { if ( !cfile ) return false; if ( LHFVersion.empty() ) return false; if ( heprup.NPRUP < 0 ) return false; eventComments = ""; outsideBlock = ""; hepeup.NUP = 0; hepeup.XPDWUP.first = hepeup.XPDWUP.second = 0.0; optionalWeights.clear(); optionalWeightsTemp.clear(); // Keep reading lines until we hit the next event or the end of // the event block. Save any inbetween lines. Exit if we didn't // find an event. while ( cfile.readline() && !cfile.find("<event") ) outsideBlock += cfile.getline() + "\n"; // We found an event. First scan for attributes. eventAttributes = StringUtils::xmlAttributes("event", cfile.getline()); /* information necessary for FxFx merging: * the npLO and npNLO tags */ istringstream ievat(cfile.getline()); int we(0), npLO(-10), npNLO(-10); do { string sub; ievat >> sub; if(we==2) { npLO = atoi(sub.c_str()); } if(we==5) { npNLO = atoi(sub.c_str()); } ++we; } while (ievat); optionalnpLO = npLO; optionalnpNLO = npNLO; std::stringstream npstringstream; npstringstream << "np " << npLO << " " << npNLO; std::string npstrings = npstringstream.str(); /* the FxFx merging information * becomes part of the optionalWeights, labelled -999 * for future reference */ if(theIncludeFxFxTags) optionalWeights[npstrings.c_str()] = -999; string ecomstring = "ecom"; optionalWeights[ecomstring.c_str()] = heprup.EBMUP.first+heprup.EBMUP.second; if ( !cfile.readline() ) return false; // The first line determines how many subsequent particle lines we // have. if ( !( cfile >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP >> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP ) ) return false; hepeup.resize(); // Read all particle lines. for ( int i = 0; i < hepeup.NUP; ++i ) { if ( !cfile.readline() ) return false; if ( !( cfile >> hepeup.IDUP[i] >> hepeup.ISTUP[i] >> hepeup.MOTHUP[i].first >> hepeup.MOTHUP[i].second >> hepeup.ICOLUP[i].first >> hepeup.ICOLUP[i].second >> hepeup.PUP[i][0] >> hepeup.PUP[i][1] >> hepeup.PUP[i][2] >> hepeup.PUP[i][3] >> hepeup.PUP[i][4] >> hepeup.VTIMUP[i] >> hepeup.SPINUP[i] ) ) return false; if(std::isnan(hepeup.PUP[i][0])||std::isnan(hepeup.PUP[i][1])|| std::isnan(hepeup.PUP[i][2])||std::isnan(hepeup.PUP[i][3])|| std::isnan(hepeup.PUP[i][4])) throw Exception() << "nan's as momenta in Les Houches file " << Exception::eventerror; if(hepeup.MOTHUP[i].first -1==i || hepeup.MOTHUP[i].second-1==i) { throw Exception() << "Particle has itself as a mother in Les Houches " << "file, this is not allowed\n" << Exception::eventerror; } } + LHEeventnum = -1; // set the LHEeventnum to -1, this will be the default if the tag <event num> is not found + + // Now read any additional comments and named weights. // read until the end of rwgt is found bool readingWeights = false, readingaMCFast = false, readingMG5ClusInfo = false; while ( cfile.readline() && !cfile.find("</event>")) { if(cfile.find("</applgrid")) { readingaMCFast=false; } //aMCFast weights end if(cfile.find("</rwgt")) { readingWeights=false; } //optional weights end if(cfile.find("</clustering")) { readingMG5ClusInfo=false; } // mg5 mclustering scale info end /* reading of optional weights */ if(readingWeights) { if(!cfile.find("<wgt")) { continue; } istringstream iss(cfile.getline()); int wi = 0; double weightValue(0); string weightName = ""; // we need to put the actual weight value into a double do { string sub; iss >> sub; if(wi==1) { string str_arrow = ">" ; erase_substr(sub, str_arrow); weightName = sub; } if(wi==2) weightValue = atof(sub.c_str()); ++wi; } while (iss); // store the optional weights found in the temporary map //cout << "weightName, weightValue= " << weightName << ", " << weightValue << endl; optionalWeightsTemp[weightName] = weightValue; } /* reading of aMCFast weights */ if(readingaMCFast) { std::stringstream amcfstringstream; amcfstringstream << "aMCFast " << cfile.getline(); std::string amcfstrings = amcfstringstream.str(); string str_newline = "\n"; erase_substr(amcfstrings,str_newline); optionalWeights[amcfstrings.c_str()] = -111; //for the aMCFast we give them a weight -111 for future identification } /* read additional MG5 Clustering information * used in LO merging */ if(readingMG5ClusInfo) { string hs = cfile.getline(); string startDEL = "<clus scale="; //starting delimiter string stopDEL = "</clus>"; //end delimiter unsigned firstLim = hs.find(startDEL); //find start of delimiter // unsigned lastLim = hs.find(stopDEL); //find end of delimitr string mg5clusinfo = hs.substr(firstLim); //define the information for the scale erase_substr(mg5clusinfo,stopDEL); erase_substr(mg5clusinfo,startDEL); string str_arrow = ">"; erase_substr(mg5clusinfo,str_arrow); string str_quotation = "\""; erase_substr(mg5clusinfo,str_quotation); string str_newline= "\n"; erase_substr(mg5clusinfo,str_newline); optionalWeights[mg5clusinfo.c_str()] = -222; //for the mg5 scale info weights we give them a weight -222 for future identification } + + //the event num tag + if(cfile.find("<event num")) { + string hs = cfile.getline(); + string startDEL = "<event num"; //starting delimiter + string stopDEL = "</event num>"; //end delimiter + unsigned firstLim = hs.find(startDEL); + string LHEeventnum_str = hs.substr(firstLim); + erase_substr(LHEeventnum_str,stopDEL); + erase_substr(LHEeventnum_str,startDEL); + string str_arrow = ">"; + erase_substr(LHEeventnum_str,str_arrow); + LHEeventnum = std::stol(LHEeventnum_str, nullptr, 10); + } //store MG5 clustering information if(cfile.find("<scales")) { string hs = cfile.getline(); string startDEL = "<scales"; //starting delimiter string stopDEL = "</scales>"; //end delimiter unsigned firstLim = hs.find(startDEL); //find start of delimiter // unsigned lastLim = hs.find(stopDEL); //find end of delimitr string mg5scinfo = hs.substr(firstLim); //define the information for the scale erase_substr(mg5scinfo,stopDEL); erase_substr(mg5scinfo,startDEL); string str_arrow = ">"; erase_substr(mg5scinfo,str_arrow); string str_newline= "\n"; erase_substr(mg5scinfo,str_newline); optionalWeights[mg5scinfo.c_str()] = -333; //for the mg5 scale info weights we give them a weight -333 for future identification } //determine start of aMCFast weights if(cfile.find("<applgrid")) { readingaMCFast = true;} //determine start of optional weights if(cfile.find("<rwgt")) { readingWeights = true; } //determine start of MG5 clustering scale information if(cfile.find("<clustering")) { readingMG5ClusInfo = true;} } // loop over the optional weights and add the extra information as found in the init for (map<string,double>::const_iterator it=optionalWeightsTemp.begin(); it!=optionalWeightsTemp.end(); ++it){ string itfirst = it->first; erase_substr(itfirst, "'"); erase_substr(itfirst, "\""); for (map<string,string>::const_iterator it2=scalemap.begin(); it2!=scalemap.end(); ++it2){ //find the scale id in the scale information and add this information string it2first = it2->first; erase_substr(it2first, "'"); erase_substr(it2first, "\""); //cout << "itfirst, it2first = " << itfirst << "\t" << it2first << endl; if(itfirst==it2first) { string info = it2->second; string str_newline = "\n"; erase_substr(info, str_newline); //set the optional weights optionalWeights[info] = it->second; } } } /* additionally, we set the "central" scale * this is actually the default event weight */ string central = "central"; if (theIncludeCentral) optionalWeights[central] = hepeup.XWGTUP; if ( !cfile ) return false; return true; } void FxFxFileReader::close() { cfile.close(); } void FxFxFileReader::persistentOutput(PersistentOStream & os) const { os << neve << LHFVersion << outsideBlock << headerBlock << initComments << initAttributes << eventComments << eventAttributes << theFileName << theQNumbers << theIncludeFxFxTags << theIncludeCentral << theDecayer; } void FxFxFileReader::persistentInput(PersistentIStream & is, int) { is >> neve >> LHFVersion >> outsideBlock >> headerBlock >> initComments >> initAttributes >> eventComments >> eventAttributes >> theFileName >> theQNumbers >> theIncludeFxFxTags >> theIncludeCentral >> theDecayer; ieve = 0; } ClassDescription<FxFxFileReader> FxFxFileReader::initFxFxFileReader; // Definition of the static class description member. void FxFxFileReader::Init() { static ClassDocumentation<FxFxFileReader> documentation ("ThePEG::FxFxFileReader is an base class to be used for objects " "which reads event files from matrix element generators. This class is " "able to read plain event files conforming to the Les Houches Event File " "accord."); static Parameter<FxFxFileReader,string> interfaceFileName ("FileName", "The name of a file containing events conforming to the Les Houches " "protocol to be read into ThePEG. A file name ending in " "<code>.gz</code> will be read from a pipe which uses " "<code>zcat</code>. If a file name ends in <code>|</code> the " "preceeding string is interpreted as a command, the output of which " "will be read through a pipe.", &FxFxFileReader::theFileName, "", false, false); interfaceFileName.fileType(); interfaceFileName.rank(11); static Switch<FxFxFileReader,bool> interfaceQNumbers ("QNumbers", "Whether or not to read search for and read a QNUMBERS" " block in the header of the file.", &FxFxFileReader::theQNumbers, false, false, false); static SwitchOption interfaceQNumbersYes (interfaceQNumbers, "Yes", "Use QNUMBERS", true); static SwitchOption interfaceQNumbersNo (interfaceQNumbers, "No", "Don't use QNUMBERS", false); static Switch<FxFxFileReader,bool> interfaceIncludeFxFxTags ("IncludeFxFxTags", "Include FxFx tags", &FxFxFileReader::theIncludeFxFxTags, true, true, false); static SwitchOption interfaceIncludeFxFxTagsYes (interfaceIncludeFxFxTags, "Yes", "Use the FxFx tags", true); static SwitchOption interfaceIncludeFxFxTagsNo (interfaceIncludeFxFxTags, "No", "Don't use the FxFx tags", false); static Switch<FxFxFileReader,bool> interfaceIncludeCentral ("IncludeCentral", "Include definition of central weight", &FxFxFileReader::theIncludeCentral, false, true, false); static SwitchOption interfaceIncludeCentralYes (interfaceIncludeCentral, "Yes", "include definition of central weight", true); static SwitchOption interfaceIncludeCentralNo (interfaceIncludeCentral, "No", "Don't include definition of central weight", false); static Reference<FxFxFileReader,Decayer> interfaceDecayer ("Decayer", "Decayer to use for any decays read from the QNUMBERS Blocks", &FxFxFileReader::theDecayer, false, false, true, true, false); } void FxFxFileReader::erase_substr(std::string& subject, const std::string& search) { size_t pos = 0; while((pos = subject.find(search, pos)) != std::string::npos) { subject.erase( pos, search.length() ); } } diff --git a/MatrixElement/FxFx/FxFxReader.cc b/MatrixElement/FxFx/FxFxReader.cc --- a/MatrixElement/FxFx/FxFxReader.cc +++ b/MatrixElement/FxFx/FxFxReader.cc @@ -1,1601 +1,1605 @@ // -*- C++ -*- // // FxFxReader.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG 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 FxFxReader class. // #include "FxFxReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" //#include "config.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/PDF/NoPDF.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/EventRecord/TmpTransform.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "FxFxEventHandler.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" using namespace ThePEG; FxFxReader::FxFxReader(bool active) : theNEvents(0), position(0), reopened(0), theMaxScan(-1), scanning(false), isActive(active), theCacheFileName(""), doCutEarly(true), preweight(1.0), reweightPDF(false), doInitPDFs(false), theMaxMultCKKW(0), theMinMultCKKW(0), lastweight(1.0), maxFactor(1.0), optionalnpLO(0), optionalnpNLO(0), weightScale(1.0*picobarn), skipping(false), theMomentumTreatment(0), useWeightWarnings(true),theReOpenAllowed(true), theIncludeSpin(true) {} FxFxReader::FxFxReader(const FxFxReader & x) : HandlerBase(x), LastXCombInfo<>(x), heprup(x.heprup), hepeup(x.hepeup), inData(x.inData), inPDF(x.inPDF), outPDF(x.outPDF), thePartonExtractor(x.thePartonExtractor), thePartonBins(x.thePartonBins), theXCombs(x.theXCombs), theCuts(x.theCuts), theNEvents(x.theNEvents), position(x.position), reopened(x.reopened), theMaxScan(x.theMaxScan), scanning(false), isActive(x.isActive), theCacheFileName(x.theCacheFileName), doCutEarly(x.doCutEarly), stats(x.stats), statmap(x.statmap), thePartonBinInstances(x.thePartonBinInstances), reweights(x.reweights), preweights(x.preweights), preweight(x.preweight), reweightPDF(x.reweightPDF), doInitPDFs(x.doInitPDFs), theMaxMultCKKW(x.theMaxMultCKKW), theMinMultCKKW(x.theMinMultCKKW), lastweight(x.lastweight), maxFactor(x.maxFactor), weightScale(x.weightScale), xSecWeights(x.xSecWeights), maxWeights(x.maxWeights), skipping(x.skipping), theMomentumTreatment(x.theMomentumTreatment), useWeightWarnings(x.useWeightWarnings), theReOpenAllowed(x.theReOpenAllowed), theIncludeSpin(x.theIncludeSpin) {} FxFxReader::~FxFxReader() {} void FxFxReader::doinitrun() { HandlerBase::doinitrun(); stats.reset(); for ( StatMap::iterator i = statmap.begin(); i != statmap.end(); ++i ) i->second.reset(); open(); if ( cacheFileName().length() ) openReadCacheFile(); position = 0; reopened = 0; } bool FxFxReader::preInitialize() const { if ( HandlerBase::preInitialize() ) return true; if ( doInitPDFs && ! ( inPDF.first && inPDF.second ) ) return true; return false; } void FxFxReader::doinit() { HandlerBase::doinit(); open(); close(); if ( !heprup.IDBMUP.first || !heprup.IDBMUP.second ) Throw<FxFxInitError>() << "No information about incoming particles were found in " << "FxFxReader '" << name() << "'." << Exception::warning; inData = make_pair(getParticleData(heprup.IDBMUP.first), getParticleData(heprup.IDBMUP.second)); if ( heprup.EBMUP.first <= 0.0 || heprup.EBMUP.second <= 0.0 ) Throw<FxFxInitError>() << "No information about the energy of incoming particles were found in " << "FxFxReader '" << name() << "'." << Exception::warning; if ( doInitPDFs && ! ( inPDF.first && inPDF.second ) ) { initPDFs(); if ( ! ( inPDF.first && inPDF.second ) ) Throw<InitException>() << "FxFxReader '" << name() << "' could not create PDFBase objects in pre-initialization." << Exception::warning; } else if ( !inPDF.first || !inPDF.second ) Throw<FxFxInitError>() << "No information about the PDFs of incoming particles were found in " << "FxFxReader '" << name() << "'." << Exception::warning; } void FxFxReader::initPDFs() { if ( inPDF.first && inPDF.second ) return; string remhname; if ( heprup.PDFSUP.first && !inPDF.first) { inPDF.first = dynamic_ptr_cast<PDFPtr> (generator()->preinitCreate("ThePEG::LHAPDF", fullName() + "/PDFA", "ThePEGLHAPDF.so")); if ( !inPDF.first ) { Throw<InitException>() << "FxFxReader '" << name() << "' could not use information " << "about the PDFs used because the LHAPDF library was not properly " "defined." << Exception::warning; return; } remhname = fullName() + "/DummyRemH"; generator()->preinitCreate("ThePEG::NoRemnants", remhname); generator()->preinitInterface(inPDF.first, "RemnantHandler", "set", remhname); if ( heprup.PDFGUP.first > 0 && heprup.PDFGUP.first < 10 ) { ostringstream os; os << heprup.PDFGUP.first << " " << heprup.PDFSUP.first; generator()->preinitInterface(inPDF.first, "PDFLIBNumbers", "set", os.str()); } else { ostringstream os; os << heprup.PDFGUP.first*1000 + heprup.PDFSUP.first; generator()->preinitInterface(inPDF.first, "PDFNumber", "set", os.str()); } generator()->preinitInterface(inPDF.first, "RangeException", "newdef", "Freeze"); } if ( heprup.PDFSUP.second && !inPDF.second) { inPDF.second = dynamic_ptr_cast<PDFPtr> (generator()->preinitCreate("ThePEG::LHAPDF", fullName() + "/PDFB", "ThePEGLHAPDF.so")); if ( !inPDF.second ) { Throw<InitException>() << "FxFxReader '" << name() << "' could not use information " << "about the PDFs used because the LHAPDF library was not properly " "defined." << Exception::warning; return; } if ( remhname == "" ) { remhname = fullName() + "/DummyRemH"; generator()->preinitCreate("ThePEG::NoRemnants", remhname); } generator()->preinitInterface(inPDF.second, "RemnantHandler", "set", remhname); if ( heprup.PDFGUP.second > 0 && heprup.PDFGUP.second < 10 ) { ostringstream os; os << heprup.PDFGUP.second << " " << heprup.PDFSUP.second; generator()->preinitInterface(inPDF.second, "PDFLIBNumbers", "set", os.str()); } else { ostringstream os; os << heprup.PDFGUP.second*1000 + heprup.PDFSUP.second; generator()->preinitInterface(inPDF.second, "PDFNumber", "set", os.str()); } generator()->preinitInterface(inPDF.second, "RangeException", "newdef", "Freeze"); } if ( ! ( inPDF.first && inPDF.second ) ) Throw<InitException>() << "FxFxReader '" << name() << "' could not find information about the PDFs used." << Exception::warning; } void FxFxReader::initialize(FxFxEventHandler & eh) { Energy2 Smax = ZERO; double Y = 0.0; if ( !theCuts ) { theCuts = eh.cuts(); if ( !theCuts ) Throw<FxFxInitError>() << "No Cuts object was assigned to the FxFxReader '" << name() << "' nor was one\nassigned to the controlling " << "FxFxEventHandler '" << eh.name() << "'.\nAt least one of them " << "needs to have a Cuts object." << Exception::runerror; Smax = cuts().SMax(); Y = cuts().Y(); } theCKKW = eh.CKKWHandler(); if ( !partonExtractor() ) { thePartonExtractor = eh.partonExtractor(); if ( !partonExtractor() ) Throw<FxFxInitError>() << "No PartonExtractor object was assigned to the FxFxReader '" << name() << "' nor was one\nassigned to the controlling " << "FxFxEventHandler '" << eh.name() << "'.\nAt least one of them " << "needs to have a PartonExtractor object." << Exception::runerror; } open(); Energy emax = 2.0*sqrt(heprup.EBMUP.first*heprup.EBMUP.second)*GeV; theCuts->initialize(sqr(emax), 0.5*log(heprup.EBMUP.first/heprup.EBMUP.second)); if ( Smax > ZERO && ( Smax != cuts().SMax() || Y != cuts().Y() ) ) Throw<FxFxInitError>() << "The FxFxReader '" << name() << "' uses the same Cuts object " << "as another FxFxReader which has not got the same energies of " << "the colliding particles. For the generation to work properly " << "different FxFxReader object with different colliding particles " << "must be assigned different (although possibly identical) Cuts " << "objects." << Exception::warning; thePartonBins = partonExtractor()->getPartons(emax, inData, cuts()); for ( int i = 0, N = partonBins().size(); i < N; ++i ) { theXCombs[partonBins()[i]] = new_ptr(XComb(emax, inData, &eh, partonExtractor(), CKKWHandler(), partonBins()[i], theCuts)); partonExtractor()->nDims(partonBins()[i]); } outPDF = make_pair(partonExtractor()->getPDF(inData.first), partonExtractor()->getPDF(inData.second)); close(); if ( !heprup.IDWTUP && useWeightWarnings ) Throw<FxFxInitError>() << "No information about the weighting scheme was found. The events " << "produced by FxFxReader " << name() << " may not be sampled correctly." << Exception::warning; if ( abs(heprup.IDWTUP) > 1 && !eh.weighted() && useWeightWarnings ) Throw<FxFxInitError>() << "FxFxReader " << name() << " has the IDWTUP flag set to " << heprup.IDWTUP << " which is not supported by this reader, the " << "produced events may not be sampled correctly. It is up to " << "sub-classes of FxFxReader to correctly convert to match IDWTUP " << "+/- 1. Will try to make intelligent guesses to get " << "correct statistics.\nIn most cases this should be sufficient. " << "Unset <interface>WeightWarnings</interface> to avoid this message," << "or set <interface>Weighted</interface> to on." << Exception::warning; if ( heprup.IDWTUP != eh.weightOption() && abs(heprup.IDWTUP) < 3 && useWeightWarnings ) Throw<FxFxInitError>() << "FxFxReader " << name() << " has the IDWTUP flag set to " << heprup.IDWTUP << ", which does not correspond\nto the weight option " << eh.weightOption() << " set in " << "the FxFxEventHandler " << eh.name() << ".\n\n" << "Use the following handler setting instead:\n" << " set " << eh.name() << ":WeightOption " << heprup.IDWTUP << "\nWill try to make intelligent guesses to get " << "correct statistics. In most cases this should be sufficient. " << "Unset <interface>WeightWarnings</interface> to avoid this message" << Exception::warning; scan(); initStat(); } long FxFxReader::scan() { open(); // Shall we write the events to a cache file for fast reading? If so // we write to a temporary file if the caches events should be // randomized. if ( cacheFileName().length() ) openWriteCacheFile(); // Keep track of the number of events scanned. long neve = 0; long cuteve = 0; bool negw = false; // If the open() has not already gotten information about subprocesses // and cross sections we have to scan through the events. if ( !heprup.NPRUP || cacheFile() || abs(heprup.IDWTUP) != 1 ) { // why scan if IDWTUP != 1? HoldFlag<> isScanning(scanning); double oldsum = 0.0; vector<int> lprup; vector<double> newmax; vector<long> oldeve; vector<long> neweve; vector<double> sumlprup; vector<double> sumsqlprup; vector<long> nscanned; for ( int i = 0; ( maxScan() < 0 || i < maxScan() ) && readEvent(); ++i ) { if ( !checkPartonBin() ) Throw<FxFxInitError>() << "Found event in LesHouchesReader '" << name() << "' which cannot be handeled by the assigned PartonExtractor '" << partonExtractor()->name() << "'." << Exception::runerror; vector<int>::iterator idit = find(lprup.begin(), lprup.end(), hepeup.IDPRUP); int id = lprup.size(); if ( idit == lprup.end() ) { lprup.push_back(hepeup.IDPRUP); newmax.push_back(0.0); neweve.push_back(0); oldeve.push_back(0); sumlprup.push_back(0.); sumsqlprup.push_back(0.); nscanned.push_back(0); } else { id = idit - lprup.begin(); } ++neve; ++oldeve[id]; oldsum += hepeup.XWGTUP; sumlprup[id] += hepeup.XWGTUP; sumsqlprup[id] += sqr(hepeup.XWGTUP); ++nscanned[id]; if ( cacheFile() ) { if ( eventWeight() == 0.0 ) { ++cuteve; continue; } cacheEvent(); } ++neweve[id]; newmax[id] = max(newmax[id], abs(eventWeight())); if ( eventWeight() < 0.0 ) negw = true; } //end of scanning events xSecWeights.resize(oldeve.size(), 1.0); for ( int i = 0, N = oldeve.size(); i < N; ++i ) if ( oldeve[i] ) xSecWeights[i] = double(neweve[i])/double(oldeve[i]); if ( maxScan() < 0 || neve > NEvents() ) NEvents(neve - cuteve); if ( lprup.size() == heprup.LPRUP.size() ) { for ( int id = 0, N = lprup.size(); id < N; ++id ) { vector<int>::iterator idit = find(heprup.LPRUP.begin(), heprup.LPRUP.end(), hepeup.IDPRUP); if ( idit == heprup.LPRUP.end() ) { Throw<FxFxInitError>() << "When scanning events, the LesHouschesReader '" << name() << "' found undeclared processes." << Exception::warning; heprup.NPRUP = 0; break; } int idh = idit - heprup.LPRUP.begin(); heprup.XMAXUP[idh] = newmax[id]; } } if ( heprup.NPRUP == 0 ) { // No heprup block was supplied or something went wrong. heprup.NPRUP = lprup.size(); heprup.LPRUP.resize(lprup.size()); heprup.XMAXUP.resize(lprup.size()); for ( int id = 0, N = lprup.size(); id < N; ++id ) { heprup.LPRUP[id] = lprup[id]; heprup.XMAXUP[id] = newmax[id]; } } if ( abs(heprup.IDWTUP) != 1 ) { // Try to fix things if abs(heprup.IDWTUP) != 1. double sumxsec = 0.0; if(abs(heprup.IDWTUP)==3) { for ( int id = 0; id < heprup.NPRUP; ++id ) sumxsec += heprup.XSECUP[id]; } else { for ( int id = 0; id < heprup.NPRUP; ++id ) { //set the cross section directly from the event weights read heprup.XSECUP[id] = sumlprup[id]/nscanned[id]; heprup.XERRUP[id] = (sumsqlprup[id]/nscanned[id] - sqr(sumlprup[id]/nscanned[id])) / nscanned[id]; if(fabs(heprup.XERRUP[id]) < 1e-10) { heprup.XERRUP[id] = 0; } if(fabs(newmax[id]) < 1e-10) { newmax[id] = 0; } if(heprup.XERRUP[id] < 0.) { if( heprup.XERRUP[id]/(sumsqlprup[id]/nscanned[id])>-1e-10) heprup.XERRUP[id] = 0.; else { Throw<FxFxInitError>() << "Negative error when scanning events in LesHouschesReader '" << name() << Exception::warning; heprup.XERRUP[id] = 0.; } } heprup.XERRUP[id] = sqrt( heprup.XERRUP[id] ); heprup.XMAXUP[id] = newmax[id]; //cout << "heprup.XMAXUP[id] = " << heprup.XMAXUP[id] << endl; sumxsec += heprup.XSECUP[id]; } } //cout << "sumxsec = " << sumxsec << endl; //weightScale = picobarn*neve*sumxsec/oldsum; weightScale = 1.0*picobarn; // temporary fix? // cout << "weightscale = " << weightScale/picobarn << endl; } } if ( cacheFile() ) closeCacheFile(); if ( negw ) heprup.IDWTUP = min(-abs(heprup.IDWTUP), -1); return neve; } void FxFxReader::setWeightScale(long) {} void FxFxReader::initStat() { stats.reset(); statmap.clear(); if ( heprup.NPRUP <= 0 ) return; double sumx = 0.0; xSecWeights.resize(heprup.NPRUP, 1.0); maxWeights.clear(); for ( int ip = 0; ip < heprup.NPRUP; ++ip ) { sumx = max(heprup.XMAXUP[ip]*xSecWeights[ip], sumx); statmap[heprup.LPRUP[ip]] = XSecStat(heprup.XMAXUP[ip]*weightScale*xSecWeights[ip]); maxWeights[heprup.LPRUP[ip]] = heprup.XMAXUP[ip]; } stats.maxXSec(sumx*weightScale); maxFactor = 1.0; } void FxFxReader::increaseMaxXSec(CrossSection maxxsec) { for ( int i = 0; i < heprup.NPRUP; ++i ) statmap[heprup.LPRUP[i]].maxXSec(statmap[heprup.LPRUP[i]].maxXSec()* maxxsec/stats.maxXSec()); maxFactor *= maxxsec/stats.maxXSec(); stats.maxXSec(maxxsec); } tXCombPtr FxFxReader::getXComb() { if ( lastXCombPtr() ) return lastXCombPtr(); fillEvent(); connectMothers(); tcPBPair sel = createPartonBinInstances(); tXCombPtr lastXC = xCombs()[sel]; // clean up the old XComb object before switching to a new one if ( theLastXComb && theLastXComb != lastXC ) theLastXComb->clean(); theLastXComb = lastXC; lastXCombPtr()->subProcess(SubProPtr()); lastXCombPtr()->setPartonBinInstances(partonBinInstances(), sqr(hepeup.SCALUP)*GeV2); lastXCombPtr()->lastAlphaS(hepeup.AQCDUP); lastXCombPtr()->lastAlphaEM(hepeup.AQEDUP); return lastXCombPtr(); } tSubProPtr FxFxReader::getSubProcess() { getXComb(); if ( subProcess() ) return subProcess(); lastXCombPtr()->subProcess(new_ptr(SubProcess(lastPartons(), tCollPtr(), this))); subProcess()->setOutgoing(outgoing().begin(), outgoing().end()); subProcess()->setIntermediates(intermediates().begin(), intermediates().end()); return subProcess(); } void FxFxReader::fillEvent() { if ( !particleIndex.empty() ) return; particleIndex.clear(); colourIndex.clear(); colourIndex(0, tColinePtr()); createParticles(); createBeams(); } void FxFxReader::reopen() { // If we didn't know how many events there were, we know now. if ( NEvents() <= 0 ) NEvents(position); ++reopened; // How large fraction of the events have we actually used? And how // large will we have used if we go through the file again? double frac = double(stats.attempts())/double(NEvents()); if ( frac*double(reopened + 1)/double(reopened) > 1.0 && NEvents() - stats.attempts() < generator()->N() - generator()->currentEventNumber() ) { if(theReOpenAllowed) generator()->logWarning(FxFxReopenWarning() << "Reopening FxFxReader '" << name() << "' after accessing " << stats.attempts() << " events out of " << NEvents() << Exception::warning); else throw FxFxReopenWarning() << "More events requested than available in FxFxReader " << name() << Exception::runerror; } if ( cacheFile() ) { closeCacheFile(); openReadCacheFile(); if ( !uncacheEvent() ) Throw<FxFxReopenError>() << "Could not reopen FxFxReader '" << name() << "'." << Exception::runerror; } else { close(); open(); if ( !readEvent() ) Throw<FxFxReopenError>() << "Could not reopen FxFxReader '" << name() << "'." << Exception::runerror; } } void FxFxReader::reset() { particleIndex.clear(); colourIndex.clear(); if ( theLastXComb ) theLastXComb->clean(); theLastXComb = tXCombPtr(); } bool FxFxReader::readEvent() { reset(); if ( !doReadEvent() ) return false; // If we are just skipping event we do not need to reweight or do // anything fancy. if ( skipping ) return true; if ( cacheFile() && !scanning ) return true; // Reweight according to the re- and pre-weights objects in the // FxFxReader base class. lastweight = reweight(); if ( !reweightPDF && !cutEarly() ) return true; // We should try to reweight the PDFs or make early cuts here. fillEvent(); double x1 = incoming().first->momentum().plus()/ beams().first->momentum().plus(); if ( reweightPDF && inPDF.first && outPDF.first && inPDF.first != outPDF.first ) { if ( hepeup.XPDWUP.first <= 0.0 ) hepeup.XPDWUP.first = inPDF.first->xfx(inData.first, incoming().first->dataPtr(), sqr(hepeup.SCALUP*GeV), x1); double xf = outPDF.first->xfx(inData.first, incoming().first->dataPtr(), sqr(hepeup.SCALUP*GeV), x1); lastweight *= xf/hepeup.XPDWUP.first; hepeup.XPDWUP.first = xf; } double x2 = incoming().second->momentum().minus()/ beams().second->momentum().minus(); if ( reweightPDF && inPDF.second && outPDF.second && inPDF.second != outPDF.second ) { if ( hepeup.XPDWUP.second <= 0.0 ) hepeup.XPDWUP.second = inPDF.second->xfx(inData.second, incoming().second->dataPtr(), sqr(hepeup.SCALUP*GeV), x2); double xf = outPDF.second->xfx(inData.second, incoming().second->dataPtr(), sqr(hepeup.SCALUP*GeV), x2); lastweight *= xf/hepeup.XPDWUP.second; hepeup.XPDWUP.second = xf; } if ( cutEarly() ) { if ( !cuts().initSubProcess((incoming().first->momentum() + incoming().second->momentum()).m2(), 0.5*log(x1/x2)) ) lastweight = 0.0; tSubProPtr sub = getSubProcess(); TmpTransform<tSubProPtr> tmp(sub, Utilities::getBoostToCM(sub->incoming())); if ( !cuts().passCuts(*sub) ) lastweight = 0.0; } return true; } double FxFxReader::getEvent() { if ( cacheFile() ) { if ( !uncacheEvent() ) reopen(); } else { if ( !readEvent() ) reopen(); } ++position; double max = maxWeights[hepeup.IDPRUP]*maxFactor; // cout << "maxFactor = " << maxFactor << " maxWeights[hepeup.IDPRUP] = " << maxWeights[hepeup.IDPRUP] << endl; // normalize all the weights to the max weight for(map<string,double>::iterator it=optionalWeights.begin(); it!=optionalWeights.end();++it) { if(it->first!="ecom" && it->second!=-999 && it->second!=-111 && it->second!=-222 && it->second!=-333) { it->second = (max != 0.0) ? it->second/max : 0.0; } } //cout << "hepeup.XWGTUP = " << hepeup.XWGTUP << endl; //cout << "max = " << max << " " << eventWeight() << endl; return max != 0.0? eventWeight()/max: 0.0; } void FxFxReader::skip(long n) { HoldFlag<> skipflag(skipping); while ( n-- ) getEvent(); } double FxFxReader::reweight() { preweight = 1.0; if ( reweights.empty() && preweights.empty() && !( CKKWHandler() && maxMultCKKW() > 0 && maxMultCKKW() > minMultCKKW() ) ) return 1.0; fillEvent(); getSubProcess(); for ( int i = 0, N = preweights.size(); i < N; ++i ) { preweights[i]->setXComb(lastXCombPtr()); preweight *= preweights[i]->weight(); } double weight = preweight; for ( int i = 0, N = reweights.size(); i < N; ++i ) { reweights[i]->setXComb(lastXCombPtr()); weight *= reweights[i]->weight(); } // If we are caching events we do not want to do CKKW reweighting. if ( cacheFile() ) return weight; if ( CKKWHandler() && maxMultCKKW() > 0 && maxMultCKKW() > minMultCKKW() ) { CKKWHandler()->setXComb(lastXCombPtr()); weight *= CKKWHandler()->reweightCKKW(minMultCKKW(), maxMultCKKW()); } return weight; } bool FxFxReader::checkPartonBin() { // First find the positions of the incoming partons. pair< vector<int>, vector<int> > inc; for ( int i = 0; i < hepeup.NUP; ++i ) { if ( hepeup.ISTUP[i] == -9 ) { if ( inc.first.empty() ) inc.first.push_back(i); else if ( inc.second.empty() ) inc.second.push_back(i); } else if ( hepeup.ISTUP[i] == -1 ) { if ( inc.first.size() && hepeup.MOTHUP[i].first == inc.first.back() + 1 ) inc.first.push_back(i); else if ( inc.second.size() && hepeup.MOTHUP[i].first == inc.second.back() + 1 ) inc.second.push_back(i); else if ( inc.first.empty() ) { inc.first.push_back(-1); inc.first.push_back(i); } else if ( inc.second.empty() ) { inc.second.push_back(-1); inc.second.push_back(i); } else if ( inc.first.size() <= inc.second.size() ) inc.first.push_back(i); else inc.second.push_back(i); } } // Now store the corresponding id numbers pair< vector<long>, vector<long> > ids; ids.first.push_back(inc.first[0] < 0? heprup.IDBMUP.first: hepeup.IDUP[inc.first[0]]); for ( int i = 1, N = inc.first.size(); i < N; ++i ) ids.first.push_back(hepeup.IDUP[inc.first[i]]); ids.second.push_back(inc.second[0] < 0? heprup.IDBMUP.second: hepeup.IDUP[inc.second[0]]); for ( int i = 1, N = inc.second.size(); i < N; ++i ) ids.second.push_back(hepeup.IDUP[inc.second[i]]); // Find the correct pair of parton bins. PBPair pbp; for ( int i = 0, N = partonBins().size(); i < N; ++i ) { tcPBPtr curr = partonBins()[i].first; int icurr = inc.first.size() - 1; while ( curr && icurr >= 0 ) { if ( curr->parton()->id () != ids.first[icurr] ) break; curr = curr->incoming(); --icurr; } if(!(!partonBins()[i].first->incoming() && !partonBins()[i].first->particle() && partonBins()[i].first->parton()->id () == ids.first[0] && ( inc.first.size()==1 || (inc.first.size()==2 && ids.first[0]==ids.first[1]))) && ( curr || icurr >= 0 ) ) continue; curr = partonBins()[i].second; icurr = inc.second.size() - 1; while ( curr && icurr >= 0 ) { if ( curr->parton()->id () != ids.second[icurr] ) break; curr = curr->incoming(); --icurr; } if(!(!partonBins()[i].second->incoming() && !partonBins()[i].second->particle() && partonBins()[i].second->parton()->id () == ids.second[0] && ( inc.second.size()==1 || (inc.second.size()==2 && ids.second[0]==ids.second[1]))) && ( curr || icurr >= 0 ) ) continue; pbp = partonBins()[i]; } // If we are only checking we return here. return ( pbp.first && pbp.second ); } namespace { bool recursionNotNull(tcPBPtr bin, tcPPtr p) { while ( bin && p ) { if ( p->dataPtr() != bin->parton() ) break; bin = bin->incoming(); p = p->parents().size()? p->parents()[0]: tPPtr(); } return bin || p; } } tcPBPair FxFxReader::createPartonBinInstances() { tcPBPair sel; for ( int i = 0, N = partonBins().size(); i < N; ++i ) { tcPBPtr bin = partonBins()[i].first; tcPPtr p = incoming().first; if ( recursionNotNull(bin,p) ) continue; bin = partonBins()[i].second; p = incoming().second; if ( recursionNotNull(bin,p) ) continue; sel = partonBins()[i]; break; } if ( !sel.first || !sel.second ) Throw<FxFxInconsistencyError>() << "Could not find appropriate PartonBin objects for event produced by " << "FxFxReader '" << name() << "'." << Exception::runerror; Direction<0> dir(true); thePartonBinInstances.first = new_ptr(PartonBinInstance(incoming().first, sel.first, -sqr(hepeup.SCALUP*GeV))); if ( thePartonBinInstances.first->xi() > 1.00001 ) { Throw<FxFxInconsistencyError>() << "Found an event with momentum fraction larger than unity (x1=" << thePartonBinInstances.first->xi() << "). The event will be skipped." << Exception::warning; throw Veto(); } dir.reverse(); thePartonBinInstances.second = new_ptr(PartonBinInstance(incoming().second, sel.second, -sqr(hepeup.SCALUP*GeV))); if ( thePartonBinInstances.second->xi() > 1.00001 ) { Throw<FxFxInconsistencyError>() << "Found an event with momentum fraction larger than unity (x2=" << thePartonBinInstances.second->xi() << "). The event will be skipped." << Exception::warning; throw Veto(); } return sel; } void FxFxReader::createParticles() { theBeams = PPair(); theIncoming = PPair(); theOutgoing = PVector(); theIntermediates = PVector(); for ( int i = 0, N = hepeup.IDUP.size(); i < N; ++i ) { if ( !hepeup.IDUP[i] ) continue; Lorentz5Momentum mom(hepeup.PUP[i][0]*GeV, hepeup.PUP[i][1]*GeV, hepeup.PUP[i][2]*GeV, hepeup.PUP[i][3]*GeV, hepeup.PUP[i][4]*GeV); if(theMomentumTreatment == 1) mom.rescaleEnergy(); else if(theMomentumTreatment == 2) mom.rescaleMass(); PDPtr pd = getParticleData(hepeup.IDUP[i]); if (!pd) { Throw<FxFxInitError>() << "FxFxReader '" << name() << "' found unknown particle ID " << hepeup.IDUP[i] << " in Les Houches common block structure.\n" << "You need to define the new particle in an input file.\n" << Exception::runerror; } if ( ! pd->coloured() && ( hepeup.ICOLUP[i].first != 0 || hepeup.ICOLUP[i].second != 0 ) ) { Throw<FxFxInconsistencyError>() << "FxFxReader " << name() << ": " << pd->PDGName() << " is not a coloured particle.\nIt should not have " << "(anti-)colour lines " << hepeup.ICOLUP[i].first << ' ' << hepeup.ICOLUP[i].second << " set; the event file needs to be fixed." << Exception::runerror; } PPtr p = pd->produceParticle(mom); if(hepeup.ICOLUP[i].first>=0 && hepeup.ICOLUP[i].second >=0) { tColinePtr c = colourIndex(hepeup.ICOLUP[i].first); if ( c ) c->addColoured(p); c = colourIndex(hepeup.ICOLUP[i].second); if ( c ) c->addAntiColoured(p); } else { tColinePtr c1 = colourIndex(abs(hepeup.ICOLUP[i].first )); tColinePtr c2 = colourIndex(abs(hepeup.ICOLUP[i].second)); if(pd->hasColour()) { c1->addColouredIndexed(p,1); c2->addColouredIndexed(p,2); } else { c1->addAntiColouredIndexed(p,1); c2->addAntiColouredIndexed(p,2); } } particleIndex(i + 1, p); switch ( hepeup.ISTUP[i] ) { case -9: if ( !theBeams.first ) theBeams.first = p; else if ( !theBeams.second ) theBeams.second = p; else Throw<FxFxInconsistencyError>() << "To many incoming beam particles in the FxFxReader '" << name() << "'." << Exception::runerror; break; case -1: if ( !theIncoming.first ) theIncoming.first = p; else if ( !theIncoming.second ) theIncoming.second = p; else if ( particleIndex(theIncoming.first) == hepeup.MOTHUP[i].first ) theIncoming.first = p; else if ( particleIndex(theIncoming.second) == hepeup.MOTHUP[i].first ) theIncoming.second = p; else Throw<FxFxInconsistencyError>() << "To many incoming particles to hard subprocess in the " << "FxFxReader '" << name() << "'." << Exception::runerror; p->scale(sqr(hepeup.SCALUP*GeV)); break; case 1: theOutgoing.push_back(p); p->scale(sqr(hepeup.SCALUP*GeV)); break; case -2: case 2: case 3: theIntermediates.push_back(p); break; default: Throw<FxFxInconsistencyError>() << "Unknown status code (" << hepeup.ISTUP[i] << ") in the FxFxReader '" << name() << "'." << Exception::runerror; } // value 9 is defined as "Unknown or unpolarized particles" double spinup = hepeup.SPINUP[i]; if ( abs(spinup - 9) < 1.0e-3 ) spinup = 0.; if ( spinup < -1. || spinup > 1. ) { Throw<FxFxInconsistencyError>() << "Polarization must be between -1 and 1, not " << spinup << " as found in the " << "FxFx event file.\nThe event file needs to be fixed." << Exception::runerror; } if( theIncludeSpin && abs(pd->id()) == ParticleID::tauminus && spinup !=0) { if(pd->iSpin() == PDT::Spin1Half ) { vector<Helicity::SpinorWaveFunction> wave; Helicity::SpinorWaveFunction(wave,p,Helicity::outgoing,true); RhoDMatrix rho(pd->iSpin(),true); rho(0,0) = 0.5*(1.-spinup); rho(1,1) = 0.5*(1.+spinup); p->spinInfo()->rhoMatrix() = rho; p->spinInfo()-> DMatrix() = rho; } } } // check the colour flows, and if necessary create any sources/sinks // hard process // get the particles in the hard process PVector external; for ( int i = 0, N = hepeup.IDUP.size(); i < N; ++i ) { unsigned int moth; switch ( hepeup.ISTUP[i] ) { case -1: external.push_back(particleIndex.find(i+1)); break; case 1: case 2: case 3: moth = hepeup.MOTHUP[i].first; if(moth!=0 && (hepeup.ISTUP[moth]==-1||hepeup.ISTUP[moth]==-2|| hepeup.ISTUP[moth]==-9)) external.push_back(particleIndex.find(i+1)); moth = hepeup.MOTHUP[i].second; if(moth!=0 && (hepeup.ISTUP[moth]==-1||hepeup.ISTUP[moth]==-2|| hepeup.ISTUP[moth]==-9)) external.push_back(particleIndex.find(i+1)); break; case -2: case -9: default: break; } } // check the incoming/outgoing lines match vector<tColinePtr> unMatchedColour,unMatchedAntiColour; for(unsigned int ix=0;ix<external.size();++ix) { vector<tcColinePtr> col = external[ix]->colourInfo()-> colourLines(); vector<tcColinePtr> anti = external[ix]->colourInfo()->antiColourLines(); if(hepeup.ISTUP[particleIndex(external[ix])-1]<0) swap(col,anti); if(!col.empty()) { for(unsigned int ic1=0;ic1<col.size();++ic1) { bool matched=false; for(unsigned int iy=0;iy<external.size();++iy) { + if(iy==ix) continue; vector<tcColinePtr> col2; if(hepeup.ISTUP[particleIndex(external[iy])-1]<0) { if(external[iy]->colourInfo()->colourLines().empty()) continue; col2 = external[iy]->colourInfo()->colourLines(); } else if(hepeup.ISTUP[particleIndex(external[iy])-1]>0) { if(external[iy]->colourInfo()->antiColourLines().empty()) continue; col2 = external[iy]->colourInfo()->antiColourLines(); } for(unsigned int ic2=0;ic2<col2.size();++ic2) { if(col[ic1]==col2[ic2]) { matched=true; break; } } if(matched) break; } if(!matched) unMatchedColour.push_back(const_ptr_cast<tColinePtr>(col[ic1])); } } if(!anti.empty()) { - for(unsigned int ic1=0;ic1<col.size();++ic1) { + for(unsigned int ic1=0;ic1<anti.size();++ic1) { bool matched=false; for(unsigned int iy=0;iy<external.size();++iy) { + if(iy==ix) continue; vector<tcColinePtr> anti2; if(hepeup.ISTUP[particleIndex(external[iy])-1]<0) { - if(external[iy]->colourInfo()->colourLines().empty()) continue; + if(external[iy]->colourInfo()->antiColourLines().empty()) continue; anti2 = external[iy]->colourInfo()->antiColourLines(); } else if(hepeup.ISTUP[particleIndex(external[iy])-1]>0) { - if(external[iy]->colourInfo()->antiColourLines().empty()) continue; + if(external[iy]->colourInfo()->colourLines().empty()) continue; anti2 = external[iy]->colourInfo()->colourLines(); } for(unsigned int ic2=0;ic2<anti2.size();++ic2) { - if(col[ic1]==anti2[ic2]) { + if(anti[ic1]==anti2[ic2]) { matched=true; break; } } if(matched) break; } if(!matched) unMatchedAntiColour.push_back(const_ptr_cast<tColinePtr>(anti[ic1])); } } } // might have source/sink if( unMatchedColour.size() + unMatchedAntiColour.size() != 0) { if(unMatchedColour.size() == 3 ) { unMatchedColour[0]->setSourceNeighbours(unMatchedColour[1], unMatchedColour[2]); } else if(unMatchedColour.size() != 0 && ThePEG_DEBUG_LEVEL) { Throw<FxFxInconsistencyError>() << "FxFxReader '" << name() << "' found inconsistent colour " << "flow in Les Houches common block structure for hard process.\n" << hepeup << Exception::runerror; } if(unMatchedAntiColour.size() == 3 ) { unMatchedAntiColour[0]->setSinkNeighbours(unMatchedAntiColour[1], unMatchedAntiColour[2]); } else if(unMatchedAntiColour.size() != 0 && ThePEG_DEBUG_LEVEL) { Throw<FxFxInconsistencyError>() << "FxFxReader '" << name() << "' found inconsistent colour " << "flow in Les Houches common block structure for hard process.\n" << hepeup << Exception::runerror; } } // any subsequent decays for ( int i = 0, N = hepeup.IDUP.size(); i < N; ++i ) { if(hepeup.ISTUP[i] !=2 && hepeup.ISTUP[i] !=3) continue; PVector external; external.push_back(particleIndex.find(i+1)); for ( int j = 0; j < N; ++j ) { if(hepeup.MOTHUP[j].first==i+1|| hepeup.MOTHUP[j].second==i+1) external.push_back(particleIndex.find(j+1)); } // check the incoming/outgoing lines match vector<tColinePtr> unMatchedColour,unMatchedAntiColour; for(unsigned int ix=0;ix<external.size();++ix) { vector<tcColinePtr> col = external[ix]->colourInfo()-> colourLines(); vector<tcColinePtr> anti = external[ix]->colourInfo()->antiColourLines(); if(ix==0) swap(col,anti); if(!col.empty()) { for(unsigned int ic1=0;ic1<col.size();++ic1) { bool matched=false; for(unsigned int iy=0;iy<external.size();++iy) { if(iy==ix) continue; vector<tcColinePtr> col2; if(iy==0) { if(external[iy]->colourInfo()->colourLines().empty()) continue; col2 = external[iy]->colourInfo()->colourLines(); } else { if(external[iy]->colourInfo()->antiColourLines().empty()) continue; col2 = external[iy]->colourInfo()->antiColourLines(); } for(unsigned int ic2=0;ic2<col2.size();++ic2) { if(col[ic1]==col2[ic2]) { matched=true; break; } } if(matched) break; } if(!matched) unMatchedColour.push_back(const_ptr_cast<tColinePtr>(col[ic1])); } } if(!anti.empty()) { for(unsigned int ic1=0;ic1<anti.size();++ic1) { bool matched=false; for(unsigned int iy=0;iy<external.size();++iy) { if(iy==ix) continue; vector<tcColinePtr> anti2; if(iy==0) { if(external[iy]->colourInfo()->antiColourLines().empty()) continue; anti2 = external[iy]->colourInfo()->antiColourLines(); } else { if(external[iy]->colourInfo()->colourLines().empty()) continue; anti2 = external[iy]->colourInfo()->colourLines(); } for(unsigned int ic2=0;ic2<anti2.size();++ic2) { if(anti[ic1]==anti2[ic2]) { matched=true; break; } } if(matched) break; } if(!matched) unMatchedAntiColour.push_back(const_ptr_cast<tColinePtr>(anti[ic1])); } } } // might have source/sink if( unMatchedColour.size() + unMatchedAntiColour.size() != 0) { if(unMatchedColour.size() == 3 ) { unMatchedColour[0]->setSourceNeighbours(unMatchedColour[1], unMatchedColour[2]); } else if(unMatchedColour.size() != 0 && ThePEG_DEBUG_LEVEL) { Throw<FxFxInconsistencyError>() << "FxFxReader '" << name() << "' found inconsistent colour " << "flow in Les Houches common block structure for decay of \n" << *external[0] << "\n" << hepeup << Exception::runerror; } if(unMatchedAntiColour.size() == 3 ) { unMatchedAntiColour[0]->setSinkNeighbours(unMatchedAntiColour[1], unMatchedAntiColour[2]); } else if(unMatchedAntiColour.size() != 0 && ThePEG_DEBUG_LEVEL) { Throw<FxFxInconsistencyError>() << "FxFxReader '" << name() << "' found inconsistent colour " << "flow in Les Houches common block structure for decay of\n" << *external[0] << "\n" << hepeup << Exception::runerror; } } } } void FxFxReader::createBeams() { if ( !theBeams.first && dynamic_ptr_cast<Ptr<NoPDF>::tcp>(inPDF.first) ) { theBeams.first = theIncoming.first; } else if ( !theBeams.first ) { theBeams.first = getParticleData(heprup.IDBMUP.first)->produceParticle(); double m = theBeams.first->mass()/GeV; theBeams.first->set5Momentum (Lorentz5Momentum(ZERO, ZERO, sqrt(sqr(heprup.EBMUP.first) - sqr(m))*GeV, heprup.EBMUP.first*GeV, m*GeV)); hepeup.IDUP.push_back(heprup.IDBMUP.first); hepeup.ISTUP.push_back(-9); hepeup.MOTHUP.push_back(make_pair(0, 0)); hepeup.ICOLUP.push_back(make_pair(0, 0)); hepeup.VTIMUP.push_back(0.0); hepeup.SPINUP.push_back(0.0); particleIndex(hepeup.IDUP.size(), theBeams.first); hepeup.MOTHUP[particleIndex(theIncoming.first) - 1].first = hepeup.IDUP.size(); } if ( !theBeams.second && dynamic_ptr_cast<Ptr<NoPDF>::tcp>(inPDF.second) ) { theBeams.second = theIncoming.second; } else if ( !theBeams.second ) { theBeams.second = getParticleData(heprup.IDBMUP.second)->produceParticle(); double m = theBeams.second->mass()/GeV; theBeams.second->set5Momentum (Lorentz5Momentum(ZERO, ZERO, -sqrt(sqr(heprup.EBMUP.second) - sqr(m))*GeV, heprup.EBMUP.second*GeV, m*GeV)); hepeup.IDUP.push_back(heprup.IDBMUP.second); hepeup.ISTUP.push_back(-9); hepeup.MOTHUP.push_back(make_pair(0, 0)); hepeup.ICOLUP.push_back(make_pair(0, 0)); hepeup.VTIMUP.push_back(0.0); hepeup.SPINUP.push_back(0.0); particleIndex(hepeup.IDUP.size(), theBeams.second); hepeup.MOTHUP[particleIndex(theIncoming.second) - 1].first = hepeup.IDUP.size(); } } void FxFxReader::connectMothers() { const ObjectIndexer<long,Particle> & pi = particleIndex; for ( int i = 0, N = hepeup.IDUP.size(); i < N; ++i ) { if ( pi(hepeup.MOTHUP[i].first) ) pi(hepeup.MOTHUP[i].first)->addChild(pi(i + 1)); if ( pi(hepeup.MOTHUP[i].second) && hepeup.MOTHUP[i].second != hepeup.MOTHUP[i].first ) pi(hepeup.MOTHUP[i].second)->addChild(pi(i + 1)); } } void FxFxReader::openReadCacheFile() { if ( cacheFile() ) closeCacheFile(); cacheFile().open(cacheFileName(), "r"); position = 0; } void FxFxReader::openWriteCacheFile() { if ( cacheFile() ) closeCacheFile(); cacheFile().open(cacheFileName(), "w"); } void FxFxReader::closeCacheFile() { cacheFile().close(); } void FxFxReader::cacheEvent() const { static vector<char> buff; cacheFile().write(&hepeup.NUP, sizeof(hepeup.NUP)); buff.resize(eventSize(hepeup.NUP)); char * pos = &buff[0]; pos = mwrite(pos, hepeup.IDPRUP); pos = mwrite(pos, hepeup.XWGTUP); pos = mwrite(pos, hepeup.XPDWUP); pos = mwrite(pos, hepeup.SCALUP); pos = mwrite(pos, hepeup.AQEDUP); pos = mwrite(pos, hepeup.AQCDUP); pos = mwrite(pos, hepeup.IDUP[0], hepeup.NUP); pos = mwrite(pos, hepeup.ISTUP[0], hepeup.NUP); pos = mwrite(pos, hepeup.MOTHUP[0], hepeup.NUP); pos = mwrite(pos, hepeup.ICOLUP[0], hepeup.NUP); for ( int i = 0; i < hepeup.NUP; ++i ) pos = mwrite(pos, hepeup.PUP[i][0], 5); pos = mwrite(pos, hepeup.VTIMUP[0], hepeup.NUP); pos = mwrite(pos, hepeup.SPINUP[0], hepeup.NUP); pos = mwrite(pos, lastweight); pos = mwrite(pos, optionalWeights); + pos = mwrite(pos, LHEeventnum); for(size_t ff = 0; ff < optionalWeightsNames.size(); ff++) { pos = mwrite(pos, optionalWeightsNames[ff]); } /* for(int f = 0; f < optionalWeightsNames.size(); f++) { cout << "optionalWeightsNames = " << optionalWeightsNames[f] << endl; }*/ pos = mwrite(pos, optionalnpLO); pos = mwrite(pos, optionalnpNLO); pos = mwrite(pos, preweight); cacheFile().write(&buff[0], buff.size(), 1); } bool FxFxReader::uncacheEvent() { reset(); static vector<char> buff; if ( cacheFile().read(&hepeup.NUP, sizeof(hepeup.NUP)) != 1 ) return false; buff.resize(eventSize(hepeup.NUP)); if ( cacheFile().read(&buff[0], buff.size()) != 1 ) return false; const char * pos = &buff[0]; pos = mread(pos, hepeup.IDPRUP); pos = mread(pos, hepeup.XWGTUP); pos = mread(pos, hepeup.XPDWUP); pos = mread(pos, hepeup.SCALUP); pos = mread(pos, hepeup.AQEDUP); pos = mread(pos, hepeup.AQCDUP); hepeup.IDUP.resize(hepeup.NUP); pos = mread(pos, hepeup.IDUP[0], hepeup.NUP); hepeup.ISTUP.resize(hepeup.NUP); pos = mread(pos, hepeup.ISTUP[0], hepeup.NUP); hepeup.MOTHUP.resize(hepeup.NUP); pos = mread(pos, hepeup.MOTHUP[0], hepeup.NUP); hepeup.ICOLUP.resize(hepeup.NUP); pos = mread(pos, hepeup.ICOLUP[0], hepeup.NUP); hepeup.PUP.resize(hepeup.NUP); for ( int i = 0; i < hepeup.NUP; ++i ) pos = mread(pos, hepeup.PUP[i][0], 5); hepeup.VTIMUP.resize(hepeup.NUP); pos = mread(pos, hepeup.VTIMUP[0], hepeup.NUP); hepeup.SPINUP.resize(hepeup.NUP); pos = mread(pos, hepeup.SPINUP[0], hepeup.NUP); pos = mread(pos, lastweight); pos = mread(pos, optionalWeights); for(size_t ff = 0; ff < optionalWeightsNames.size(); ff++) { pos = mread(pos, optionalWeightsNames[ff]); } pos = mread(pos, optionalnpLO); pos = mread(pos, optionalnpNLO); pos = mread(pos, preweight); + pos = mread(pos, LHEeventnum); // If we are skipping, we do not have to do anything else. if ( skipping ) return true; if ( CKKWHandler() && maxMultCKKW() > 0 && maxMultCKKW() > minMultCKKW() ) { // The cached event has not been submitted to CKKW reweighting, so // we do that now. fillEvent(); getSubProcess(); CKKWHandler()->setXComb(lastXCombPtr()); lastweight *= CKKWHandler()->reweightCKKW(minMultCKKW(), maxMultCKKW()); } return true; } void FxFxReader::persistentOutput(PersistentOStream & os) const { os << heprup.IDBMUP << heprup.EBMUP << heprup.PDFGUP << heprup.PDFSUP << heprup.IDWTUP << heprup.NPRUP << heprup.XSECUP << heprup.XERRUP << heprup.XMAXUP << heprup.LPRUP << hepeup.NUP << hepeup.IDPRUP << hepeup.XWGTUP << hepeup.XPDWUP << hepeup.SCALUP << hepeup.AQEDUP << hepeup.AQCDUP << hepeup.IDUP << hepeup.ISTUP << hepeup.MOTHUP << hepeup.ICOLUP << hepeup.PUP << hepeup.VTIMUP << hepeup.SPINUP << inData << inPDF << outPDF << thePartonExtractor << theCKKW << thePartonBins << theXCombs << theCuts << theNEvents << position << reopened << theMaxScan << isActive << theCacheFileName << doCutEarly << stats << statmap << thePartonBinInstances << theBeams << theIncoming << theOutgoing << theIntermediates << reweights << preweights << preweight << reweightPDF << doInitPDFs - << theLastXComb << theMaxMultCKKW << theMinMultCKKW << lastweight << optionalWeights << optionalnpLO << optionalnpNLO + << theLastXComb << theMaxMultCKKW << theMinMultCKKW << lastweight << optionalWeights << optionalnpLO << optionalnpNLO << LHEeventnum << maxFactor << ounit(weightScale, picobarn) << xSecWeights << maxWeights << theMomentumTreatment << useWeightWarnings << theReOpenAllowed << theIncludeSpin; } void FxFxReader::persistentInput(PersistentIStream & is, int) { if ( cacheFile() ) closeCacheFile(); is >> heprup.IDBMUP >> heprup.EBMUP >> heprup.PDFGUP >> heprup.PDFSUP >> heprup.IDWTUP >> heprup.NPRUP >> heprup.XSECUP >> heprup.XERRUP >> heprup.XMAXUP >> heprup.LPRUP >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP >> hepeup.XPDWUP >> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP >> hepeup.IDUP >> hepeup.ISTUP >> hepeup.MOTHUP >> hepeup.ICOLUP >> hepeup.PUP >> hepeup.VTIMUP >> hepeup.SPINUP >> inData >> inPDF >> outPDF >> thePartonExtractor >> theCKKW >> thePartonBins >> theXCombs >> theCuts >> theNEvents >> position >> reopened >> theMaxScan >> isActive >> theCacheFileName >> doCutEarly >> stats >> statmap >> thePartonBinInstances >> theBeams >> theIncoming >> theOutgoing >> theIntermediates >> reweights >> preweights >> preweight >> reweightPDF >> doInitPDFs - >> theLastXComb >> theMaxMultCKKW >> theMinMultCKKW >> lastweight >> optionalWeights >> optionalnpLO >> optionalnpNLO + >> theLastXComb >> theMaxMultCKKW >> theMinMultCKKW >> lastweight >> optionalWeights >> optionalnpLO >> optionalnpNLO >> LHEeventnum >> maxFactor >> iunit(weightScale, picobarn) >> xSecWeights >> maxWeights >> theMomentumTreatment >> useWeightWarnings >> theReOpenAllowed >> theIncludeSpin; } AbstractClassDescription<FxFxReader> FxFxReader::initFxFxReader; // Definition of the static class description member. void FxFxReader::setBeamA(long id) { heprup.IDBMUP.first = id; } long FxFxReader::getBeamA() const { return heprup.IDBMUP.first; } void FxFxReader::setBeamB(long id) { heprup.IDBMUP.second = id; } long FxFxReader::getBeamB() const { return heprup.IDBMUP.second; } void FxFxReader::setEBeamA(Energy e) { heprup.EBMUP.first = e/GeV; } Energy FxFxReader::getEBeamA() const { return heprup.EBMUP.first*GeV; } void FxFxReader::setEBeamB(Energy e) { heprup.EBMUP.second = e/GeV; } Energy FxFxReader::getEBeamB() const { return heprup.EBMUP.second*GeV; } void FxFxReader::setPDFA(PDFPtr pdf) { inPDF.first = pdf; } PDFPtr FxFxReader::getPDFA() const { return inPDF.first; } void FxFxReader::setPDFB(PDFPtr pdf) { inPDF.second = pdf; } PDFPtr FxFxReader::getPDFB() const { return inPDF.second; } void FxFxReader::Init() { static ClassDocumentation<FxFxReader> documentation ("ThePEG::FxFxReader is an abstract base class to be used " "for objects which reads event files or streams from matrix element " "generators."); static Parameter<FxFxReader,long> interfaceBeamA ("BeamA", "The PDG id of the incoming particle along the positive z-axis. " "If zero the corresponding information is to be deduced from the " "event stream/file.", 0, 0, 0, 0, true, false, false, &FxFxReader::setBeamA, &FxFxReader::getBeamA, 0, 0, 0); static Parameter<FxFxReader,long> interfaceBeamB ("BeamB", "The PDG id of the incoming particle along the negative z-axis. " "If zero the corresponding information is to be deduced from the " "event stream/file.", 0, 0, 0, 0, true, false, false, &FxFxReader::setBeamB, &FxFxReader::getBeamB, 0, 0, 0); static Parameter<FxFxReader,Energy> interfaceEBeamA ("EBeamA", "The energy of the incoming particle along the positive z-axis. " "If zero the corresponding information is to be deduced from the " "event stream/file.", 0, GeV, ZERO, ZERO, 1000000000.0*GeV, true, false, true, &FxFxReader::setEBeamA, &FxFxReader::getEBeamA, 0, 0, 0); static Parameter<FxFxReader,Energy> interfaceEBeamB ("EBeamB", "The energy of the incoming particle along the negative z-axis. " "If zero the corresponding information is to be deduced from the " "event stream/file.", 0, GeV, ZERO, ZERO, 1000000000.0*GeV, true, false, true, &FxFxReader::setEBeamB, &FxFxReader::getEBeamB, 0, 0, 0); static Reference<FxFxReader,PDFBase> interfacePDFA ("PDFA", "The PDF used for incoming particle along the positive z-axis. " "If null the corresponding information is to be deduced from the " "event stream/file.", 0, true, false, true, true, false, &FxFxReader::setPDFA, &FxFxReader::getPDFA, 0); static Reference<FxFxReader,PDFBase> interfacePDFB ("PDFB", "The PDF used for incoming particle along the negative z-axis. " "If null the corresponding information is to be deduced from the " "event stream/file.", 0, true, false, true, true, false, &FxFxReader::setPDFB, &FxFxReader::getPDFB, 0); static Parameter<FxFxReader,long> interfaceMaxScan ("MaxScan", "The maximum number of events to scan to obtain information about " "processes and cross section in the intialization.", &FxFxReader::theMaxScan, -1, 0, 0, true, false, false); static Parameter<FxFxReader,string> interfaceCacheFileName ("CacheFileName", "Name of file used to cache the events form the reader in a fast-readable " "form. If empty, no cache file will be generated.", &FxFxReader::theCacheFileName, "", true, false); interfaceCacheFileName.fileType(); static Switch<FxFxReader,bool> interfaceCutEarly ("CutEarly", "Determines whether to apply cuts to events before converting to " "ThePEG format.", &FxFxReader::doCutEarly, true, true, false); static SwitchOption interfaceCutEarlyYes (interfaceCutEarly, "Yes", "Event are cut before converted.", true); static SwitchOption interfaceCutEarlyNo (interfaceCutEarly, "No", "Events are not cut before converted.", false); static Reference<FxFxReader,PartonExtractor> interfacePartonExtractor ("PartonExtractor", "The PartonExtractor object used to construct remnants. If no object is " "provided the FxFxEventHandler object must provide one instead.", &FxFxReader::thePartonExtractor, true, false, true, true, false); static Reference<FxFxReader,Cuts> interfaceCuts ("Cuts", "The Cuts object to be used for this reader. Note that these " "must not be looser cuts than those used in the actual generation. " "If no object is provided the FxFxEventHandler object must " "provide one instead.", &FxFxReader::theCuts, true, false, true, true, false); static RefVector<FxFxReader,ReweightBase> interfaceReweights ("Reweights", "A list of ThePEG::ReweightBase objects to modify this the weight of " "this reader.", &FxFxReader::reweights, 0, false, false, true, false); static RefVector<FxFxReader,ReweightBase> interfacePreweights ("Preweights", "A list of ThePEG::ReweightBase objects to bias the phase space for this " "reader without influencing the actual cross section.", &FxFxReader::preweights, 0, false, false, true, false); static Switch<FxFxReader,bool> interfaceReweightPDF ("ReweightPDF", "If the PDFs used in the generation for this reader is different " "from the ones assumed by the associated PartonExtractor object, " "should the events be reweighted to fit the latter?", &FxFxReader::reweightPDF, false, true, false); static SwitchOption interfaceReweightPDFNo (interfaceReweightPDF, "No", "The event weights are kept as they are.", false); static SwitchOption interfaceReweightPDFYes (interfaceReweightPDF, "Yes", "The events are reweighted.", true); static Switch<FxFxReader,bool> interfaceInitPDFs ("InitPDFs", "If no PDFs were specified in <interface>PDFA</interface> or " "<interface>PDFB</interface>for this reader, try to extract the " "information from the event file and assign the relevant PDFBase" "objects when the reader is initialized.", &FxFxReader::doInitPDFs, false, true, false); static SwitchOption interfaceInitPDFsYes (interfaceInitPDFs, "Yes", "Extract PDFs during initialization.", true); static SwitchOption interfaceInitPDFsNo (interfaceInitPDFs, "No", "Do not extract PDFs during initialization.", false); static Parameter<FxFxReader,int> interfaceMaxMultCKKW ("MaxMultCKKW", "If this reader is to be used (possibly together with others) for CKKW-" "reweighting and veto, this should give the multiplicity of outgoing " "particles in the highest multiplicity matrix element in the group. " "If set to zero, no CKKW procedure should be applied.", &FxFxReader::theMaxMultCKKW, 0, 0, 0, true, false, Interface::lowerlim); static Parameter<FxFxReader,int> interfaceMinMultCKKW ("MinMultCKKW", "If this reader is to be used (possibly together with others) for CKKW-" "reweighting and veto, this should give the multiplicity of outgoing " "particles in the lowest multiplicity matrix element in the group. If " "larger or equal to <interface>MaxMultCKKW</interface>, no CKKW " "procedure should be applied.", &FxFxReader::theMinMultCKKW, 0, 0, 0, true, false, Interface::lowerlim); static Switch<FxFxReader,unsigned int> interfaceMomentumTreatment ("MomentumTreatment", "Treatment of the momenta supplied by the interface", &FxFxReader::theMomentumTreatment, 0, false, false); static SwitchOption interfaceMomentumTreatmentAccept (interfaceMomentumTreatment, "Accept", "Just accept the momenta given", 0); static SwitchOption interfaceMomentumTreatmentRescaleEnergy (interfaceMomentumTreatment, "RescaleEnergy", "Rescale the energy supplied so it is consistent with the mass", 1); static SwitchOption interfaceMomentumTreatmentRescaleMass (interfaceMomentumTreatment, "RescaleMass", "Rescale the mass supplied so it is consistent with the" " energy and momentum", 2); static Switch<FxFxReader,bool> interfaceWeightWarnings ("WeightWarnings", "Determines if warnings about possible weight incompatibilities should " "be issued when this reader is initialized.", &FxFxReader::useWeightWarnings, true, true, false); static SwitchOption interfaceWeightWarningsWarnAboutWeights (interfaceWeightWarnings, "WarnAboutWeights", "Warn about possible incompatibilities with the weight option in the " "Les Houches common block and the requested weight treatment.", true); static SwitchOption interfaceWeightWarningsDontWarnAboutWeights (interfaceWeightWarnings, "DontWarnAboutWeights", "Do not warn about possible incompatibilities with the weight option " "in the Les Houches common block and the requested weight treatment.", false); static Switch<FxFxReader,bool> interfaceAllowedTopReOpen ("AllowedToReOpen", "Can the file be reopened if more events are requested than the file contains?", &FxFxReader::theReOpenAllowed, true, false, false); static SwitchOption interfaceAllowedTopReOpenYes (interfaceAllowedTopReOpen, "Yes", "Allowed to reopen the file", true); static SwitchOption interfaceAllowedTopReOpenNo (interfaceAllowedTopReOpen, "No", "Not allowed to reopen the file", false); static Switch<FxFxReader,bool> interfaceIncludeSpin ("IncludeSpin", "Use the spin information present in the event file, for tau leptons" " only as this is the only case which makes any sense", &FxFxReader::theIncludeSpin, true, false, false); static SwitchOption interfaceIncludeSpinYes (interfaceIncludeSpin, "Yes", "Use the spin information", true); static SwitchOption interfaceIncludeSpinNo (interfaceIncludeSpin, "No", "Don't use the spin information", false); interfaceCuts.rank(8); interfacePartonExtractor.rank(7); interfaceBeamA.rank(5); interfaceBeamB.rank(4); interfaceEBeamA.rank(3); interfaceEBeamB.rank(2); interfaceMaxMultCKKW.rank(1.5); interfaceMinMultCKKW.rank(1.0); interfaceBeamA.setHasDefault(false); interfaceBeamB.setHasDefault(false); interfaceEBeamA.setHasDefault(false); interfaceEBeamB.setHasDefault(false); interfaceMaxMultCKKW.setHasDefault(false); interfaceMinMultCKKW.setHasDefault(false); } namespace ThePEG { ostream & operator<<(ostream & os, const HEPEUP & h) { os << "<event>\n" << " " << setw(4) << h.NUP << " " << setw(6) << h.IDPRUP << " " << setw(14) << h.XWGTUP << " " << setw(14) << h.SCALUP << " " << setw(14) << h.AQEDUP << " " << setw(14) << h.AQCDUP << "\n"; for ( int i = 0; i < h.NUP; ++i ) os << " " << setw(8) << h.IDUP[i] << " " << setw(2) << h.ISTUP[i] << " " << setw(4) << h.MOTHUP[i].first << " " << setw(4) << h.MOTHUP[i].second << " " << setw(4) << h.ICOLUP[i].first << " " << setw(4) << h.ICOLUP[i].second << " " << setw(14) << h.PUP[i][0] << " " << setw(14) << h.PUP[i][1] << " " << setw(14) << h.PUP[i][2] << " " << setw(14) << h.PUP[i][3] << " " << setw(14) << h.PUP[i][4] << " " << setw(1) << h.VTIMUP[i] << " " << setw(1) << h.SPINUP[i] << std::endl; os << "</event>" << std::endl; return os; } } diff --git a/MatrixElement/FxFx/FxFxReader.h b/MatrixElement/FxFx/FxFxReader.h --- a/MatrixElement/FxFx/FxFxReader.h +++ b/MatrixElement/FxFx/FxFxReader.h @@ -1,1006 +1,1016 @@ // -*- C++ -*- // // FxFxReader.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_FxFxReader_H #define THEPEG_FxFxReader_H // This is the declaration of the FxFxReader class. #include "FxFx.h" #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Utilities/ObjectIndexer.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Utilities/XSecStat.h" #include "ThePEG/PDF/PartonBinInstance.h" #include "ThePEG/PDF/PartonBin.fh" #include "ThePEG/MatrixElement/ReweightBase.h" #include "FxFxEventHandler.fh" #include "FxFxReader.fh" #include "ThePEG/Utilities/CFile.h" #include <cstdio> #include <cstring> namespace ThePEG { /** * FxFxReader is an abstract base class to be used for objects * which reads event files or streams from matrix element * generators. Derived classes must at least implement the open() and * doReadEvent() methods to read in information about the whole run into * the HEPRUP variable and next event into the HEPEUP variable * respectively. Also the close() function to close the file or stream * read must be implemented. Although these functions are named as if * we are reading from event files, they could just as well implement * the actual generation of events. * * After filling the HEPRUP and HEPEUP variables, which are protected * and easily accesible from the sub-class, this base class will then * be responsible for transforming this data to the ThePEG Event * record in the getEvent() method. <code>FxFxReader</code>s can * only be used inside FxFxEventHandler objects. * * In the initialization the virtual open() and scan() functions are * called. Here the derived class must provide the information about * the processes in the variables corresponding to the HEPRUP common * block. Note that the IDWTUP is required to be +/- 1, and sub * classes are required to change the information accordingly to * ensure the correct corss section sampling. Note also that the * controlling FxFxEventHandler may choose to generate weighted * events even if IDWTUP is 1. * * Note that the information given per process in e.g. the XSECUP and * XMAXUP vectors is not used by the FxFxEventHandler and by * default the FxFxReader is not assumed to be able to actively * choose between the sub-processes. Instead, the * FxFxEventHandler can handle several FxFxReader objects * and choose between them. However, a sub-class of FxFxReader * may set the flag isActive, in which case it is assumed to be able * to select between its sub-processes itself. * * The FxFxReader may be assigned a number ReweightBase objects * which either completely reweights the events produced (in the * reweights vector), or only biases the selection without influencing * the cross section (in the preweights vector). Note that it is the * responsibility of a sub-class to call the reweight() function and * multiply the weight according to its return value (typically done * in the readEvent() function). * * @see \ref FxFxReaderInterfaces "The interfaces" * defined for FxFxReader. * @see Event * @see FxFxEventHandler */ class FxFxReader: public HandlerBase, public LastXCombInfo<> { /** * FxFxEventHandler should have access to our private parts. */ friend class FxFxEventHandler; /** * Map for accumulating statistics of cross sections per process * number. */ typedef map<int,XSecStat> StatMap; /** * Map of XComb objects describing the incoming partons indexed by * the corresponding PartonBin pair. */ typedef map<tcPBPair,XCombPtr> XCombMap; /** * A vector of pointers to ReweightBase objects. */ typedef vector<ReweightPtr> ReweightVector; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. If the optional argument is true, the reader * is assumed to be able to produce events on demand for a given * process. */ FxFxReader(bool active = false); /** * Copy-constructor. */ FxFxReader(const FxFxReader &); /** * Destructor. */ virtual ~FxFxReader(); //@} public: /** @name Main virtual fuctions to be overridden in * sub-classes. They are named as if we are reading from event * files, but could equally well implement the actual generation of * events. */ //@{ /** * Open a file or stream with events and read in the run information * into the heprup variable. */ virtual void open() = 0; /** * Read the next event from the file or stream into the * corresponding protected variables. Return false if there is no * more events. */ virtual bool doReadEvent() = 0; /** * Close the file or stream from which events have been read. */ virtual void close() = 0; /** * return the weight names */ // virtual vector<string> optWeightsNamesFunc(); virtual vector<string> optWeightsNamesFunc() = 0; //virtual vector<string*> optWeightNamesFunc() = 0; vector<string> optionalWeightsNames; /** * The ID (e.g. 100x, 2001) for the weight */ // vector<string> optionalWeightsNames; //@} /** @name Other important function which may be overridden in * sub-classes which wants to bypass the basic HEPRUP or HEPEUP * variables or otherwise facilitate the conversion to ThePEG * objects. */ //@{ /** * Initialize. This function is called by the FxFxEventHandler * to which this object is assigned. */ virtual void initialize(FxFxEventHandler & eh); /** * Calls readEvent() or uncacheEvent() to read information into the * FxFx common block variables. This function is called by the * FxFxEventHandler if this reader has been selectod to * produce an event. * * @return the weight asociated with this event. If negative weights * are allowed it should be between -1 and 1, otherwise between 0 * and 1. If outside these limits the previously estimated maximum * is violated. Note that the estimated maximum then should be * updated from the outside. */ virtual double getEvent(); /** * Calls doReadEvent() and performs pre-defined reweightings. A * sub-class overrides this function it must make sure that the * corresponding reweightings are done. */ virtual bool readEvent(); /** * Skip \a n events. Used by FxFxEventHandler to make sure * that a file is scanned an even number of times in case the events * are not ramdomly distributed in the file. */ virtual void skip(long n); /** * Get an XComb object. Converts the information in the Les Houches * common block variables to an XComb object describing the sub * process. This is the way information is conveyed from the reader * to the controlling FxFxEventHandler. */ tXCombPtr getXComb(); /** * Get a SubProcess object corresponding to the information in the * Les Houches common block variables. */ tSubProPtr getSubProcess(); /** * Scan the file or stream to obtain information about cross section * weights and particles etc. This function should fill the * variables corresponding to the /HEPRUP/ common block. The * function returns the number of events scanned. */ virtual long scan(); /** * Take the information corresponding to the HEPRUP common block and * initialize the statistics for this reader. */ virtual void initStat(); /** * Reweights the current event using the reweights and preweights * vectors. It is the responsibility of the sub-class to call this * function after the HEPEUP information has been retrieved. */ double reweight(); /** * Converts the information in the Les Houches common block * variables into a Particle objects. */ virtual void fillEvent(); /** * Removes the particles created in the last generated event, * preparing to produce a new one. */ void reset(); /** * Possibility for subclasses to recover from non-conformant * settings of XMAXUP when an event file has been scanned with \a * neve events. Should set weightScale so that the average XMAXUP * times weightScale gives the cross section for a process. (This is * needed for MadEvent). */ virtual void setWeightScale(long neve); //@} /** @name Access information about the current event. */ //@{ /** * Return the size of this event in bytes. To be used for the cache * file. \a npart is the number of particles. If \a npart is 0, the * number is taken from NUP. */ static size_t eventSize(int N) { return (N + 1)*sizeof(int) + // IDPRUP, ISTUP (7*N + 4)*sizeof(double) + // XWGTUP, SCALUP, AQEDUP, AQCDUP, PUP, // VTIMUP, SPINUP N*sizeof(long) + // IDUP 2*N*sizeof(pair<int,int>) + // MOTHUP, ICOLUP sizeof(pair<double,double>) + // XPDWUP. 2*sizeof(double); // lastweight and preweight } /** * The current event weight given by XWGTUP times possible * reweighting. Note that this is not necessarily the same as what * is returned by getEvent(), which is scaled with the maximum * weight. */ double eventWeight() const { return hepeup.XWGTUP*lastweight; } /** * Return the optional named weights associated to the current event. */ const map<string,double>& optionalEventWeights() const { return optionalWeights; } + /** + * Return the Les Houches event number associated with the current event + */ + const long& LHEEventNum() const { return LHEeventnum; } + /** * Return the optional npLO and npNLO */ const int& optionalEventnpLO() const { return optionalnpLO; } const int& optionalEventnpNLO() const { return optionalnpNLO; } /** * The pair of PartonBinInstance objects describing the current * incoming partons in the event. */ const PBIPair & partonBinInstances() const { return thePartonBinInstances; } /** * Return the instances of the beam particles for the current event. */ const PPair & beams() const { return theBeams; } /** * Return the instances of the incoming particles to the sub process * for the current event. */ const PPair & incoming() const { return theIncoming; } /** * Return the instances of the outgoing particles from the sub process * for the current event. */ const PVector & outgoing() const { return theOutgoing; } /** * Return the instances of the intermediate particles in the sub * process for the current event. */ const PVector & intermediates() const { return theIntermediates; } /** * If this reader is to be used (possibly together with others) for * CKKW reweighting and veto, this should give the multiplicity of * outgoing particles in the highest multiplicity matrix element in * the group. */ int maxMultCKKW() const { return theMaxMultCKKW; } /** * If this reader is to be used (possibly together with others) for * CKKW reweighting and veto, this should give the multiplicity of * outgoing particles in the lowest multiplicity matrix element in * the group. */ int minMultCKKW() const { return theMinMultCKKW; } //@} /** @name Other inlined access functions. */ //@{ /** * The number of events found in this reader. If less than zero the * number of events are unlimited. */ long NEvents() const { return theNEvents; } /** * The number of events produced so far. Is reset to zero if an * event file is reopened. */ long currentPosition() const { return position; } /** * The maximum number of events to scan to collect information about * processes and cross sections. If less than 0, all events will be * scanned. */ long maxScan() const { return theMaxScan; } /** * Return true if this reader is active. */ bool active() const { return isActive; } /** * True if negative weights may be produced. */ bool negativeWeights() const { return heprup.IDWTUP < 0; } /** * The collected cross section statistics for this reader. */ const XSecStat & xSecStats() const { return stats; } /** * Collected statistics about the individual processes. */ const StatMap & processStats() const { return statmap; } /** * Select the current event. It will later be rejected with a * probability given by \a weight. */ void select(double weight) { stats.select(weight); statmap[hepeup.IDPRUP].select(weight); } /** * Accept the current event assuming it was previously selcted. */ void accept() { stats.accept(); statmap[hepeup.IDPRUP].accept(); } /** * Reject the current event assuming it was previously accepted. */ void reject(double w) { stats.reject(w); statmap[hepeup.IDPRUP].reject(w); } /** * Increase the overestimated cross section for this reader. */ virtual void increaseMaxXSec(CrossSection maxxsec); /** * The PartonExtractor object used to construct remnants. */ tPExtrPtr partonExtractor() const { return thePartonExtractor; } /** * Return a possibly null pointer to a CascadeHandler to be used for * CKKW-reweighting. */ tCascHdlPtr CKKWHandler() const { return theCKKW; } /** * The pairs of PartonBin objects describing the partons which can * be extracted by the PartonExtractor object. */ const PartonPairVec & partonBins() const { return thePartonBins; } /** * The map of XComb objects indexed by the corresponding PartonBin * pair. */ const XCombMap & xCombs() const { return theXCombs; } /** * The Cuts object to be used for this reader. */ const Cuts & cuts() const { return *theCuts; } //@} protected: /** @name Functions for manipulating cache files. */ //@{ /** * Name of file used to cache the events form the reader in a * fast-readable form. If empty, no cache file will be generated. */ string cacheFileName() const { return theCacheFileName; } /** * Determines whether to apply cuts to events converting them to * ThePEG format. */ bool cutEarly() const { return doCutEarly; } /** * File stream for the cache. */ CFile cacheFile() const { return theCacheFile;} /** * Open the cache file for reading. */ void openReadCacheFile(); /** * Open the cache file for writing. */ void openWriteCacheFile(); /** * Close the cache file; */ void closeCacheFile(); /** * Write the current event to the cache file. */ void cacheEvent() const; /** * Read an event from the cache file. Return false if something went wrong. */ bool uncacheEvent(); /** * Reopen a reader. If we have reached the end of an event file, * reopen it and issue a warning if we have used up a large fraction * of it. */ void reopen(); /** * Helper function to write a variable to a memory location */ template <typename T> static char * mwrite(char * pos, const T & t, size_t n = 1) { std::memcpy(pos, &t, n*sizeof(T)); return pos + n*sizeof(T); } /** * Helper function to read a variable from a memory location */ template <typename T> static const char * mread(const char * pos, T & t, size_t n = 1) { std::memcpy(&t, pos, n*sizeof(T)); return pos + n*sizeof(T); } //@} /** @name Auxilliary virtual methods which may be verridden by sub-classes. */ //@{ /** * Check the existence of a pair of PartonBin objects corresponding * to the current event. * * @return false if no pair of suitable PartonBin objects was found. */ virtual bool checkPartonBin(); /** * Create instances of all particles in the event and store them * in particleIndex. */ virtual void createParticles(); /** * Using the already created particles create a pair of * PartonBinInstance objects corresponding to the incoming * partons. Return the corresponding PartonBin objects. */ virtual tcPBPair createPartonBinInstances(); /** * Create instances of the incoming beams in the event and store * them in particleIndex. If no beam particles are included in the * event they are created from the run info. */ virtual void createBeams(); /** * Go through the mother indices and connect up the Particles. */ virtual void connectMothers(); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Set functions for some variables not in the Les Houches accord. */ //@{ /** * The number of events in this reader. If less than zero the number * of events is unlimited. */ void NEvents(long x) { theNEvents = x; } /** * The map of XComb objects indexed by the corresponding PartonBin * pair. */ XCombMap & xCombs() { return theXCombs; } //@} /** @name Standard (and non-standard) Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish() { close(); HandlerBase::dofinish(); } /** * Return true if this object needs to be initialized before all * other objects because it needs to extract PDFs from the event file. */ virtual bool preInitialize() const; /** * Called from doinit() to extract PDFs from the event file and add * the corresponding objects to the current EventGenerator. */ virtual void initPDFs(); //@} protected: /** * The HEPRUP common block. */ HEPRUP heprup; /** * The HEPEUP common block. */ HEPEUP hepeup; /** * The ParticleData objects corresponding to the incoming particles. */ tcPDPair inData; /** * The PDFBase objects which has been used for the beam particle * when generating the events being read. Specified in the interface * or derived from PDFGUP and PDFSUP. */ pair<PDFPtr,PDFPtr> inPDF; /** * The PDFBase object to be used in the subsequent generation. */ pair<cPDFPtr,cPDFPtr> outPDF; /** * The PartonExtractor object used to construct remnants. */ PExtrPtr thePartonExtractor; /** * A pointer to a CascadeHandler to be used for CKKW-reweighting. */ tCascHdlPtr theCKKW; /** * The pairs of PartonBin objects describing the partons which can * be extracted by the PartonExtractor object. */ PartonPairVec thePartonBins; /** * The map of XComb objects indexed by the corresponding PartonBin * pair. */ XCombMap theXCombs; /** * The Cuts object to be used for this reader. */ CutsPtr theCuts; /** * The number of events in this reader. If less than zero the number * of events is unlimited. */ long theNEvents; /** * The number of events produced by this reader so far. Is reset * every time an event file is reopened. */ long position; /** * The number of times this reader has been reopened. */ int reopened; /** * The maximum number of events to scan to collect information about * processes and cross sections. If less than 0, all events will be * scanned. */ long theMaxScan; /** * Flag to tell whether we are in the process of scanning. */ bool scanning; /** * True if this is an active reader. */ bool isActive; /** * Name of file used to cache the events form the reader in a * fast-readable form. If empty, no cache file will be generated. */ string theCacheFileName; /** * Determines whether to apply cuts to events before converting them * to ThePEG format. */ bool doCutEarly; /** * Collect statistics for this reader. */ XSecStat stats; /** * Collect statistics for each individual process. */ StatMap statmap; /** * The pair of PartonBinInstance objects describing the current * incoming partons in the event. */ PBIPair thePartonBinInstances; /** * Association between ColourLines and colour indices in the current * translation. */ ObjectIndexer<long,ColourLine> colourIndex; /** * Association between Particles and indices in the current * translation. */ ObjectIndexer<long,Particle> particleIndex; /** * The instances of the beam particles for the current event. */ PPair theBeams; /** * The instances of the incoming particles to the sub process for * the current event. */ PPair theIncoming; /** * The instances of the outgoing particles from the sub process for * the current event. */ PVector theOutgoing; /** * The instances of the intermediate particles in the sub process for * the current event. */ PVector theIntermediates; /** * File stream for the cache. */ CFile theCacheFile; /** * The reweight objects modifying the weights of this reader. */ ReweightVector reweights; /** * The preweight objects modifying the weights of this reader. */ ReweightVector preweights; /** * The factor with which this reader was last pre-weighted. */ double preweight; /** * Should the event be reweighted by PDFs used by the PartonExtractor? */ bool reweightPDF; /** * Should PDFBase objects be constructed from the information in the * event file in the initialization? */ bool doInitPDFs; /** * If this reader is to be used (possibly together with others) for * CKKW reweighting and veto, this should give the multiplicity of * outgoing particles in the highest multiplicity matrix element in * the group. */ int theMaxMultCKKW; /** * If this reader is to be used (possibly together with others) for * CKKW reweighting and veto, this should give the multiplicity of * outgoing particles in the lowest multiplicity matrix element in * the group. */ int theMinMultCKKW; /** * The weight multiplying the last read event due to PDF * reweighting, CKKW reweighting or assigned reweight and preweight * objects. */ double lastweight; /** * The optional weights associated to the last read events. */ map<string,double> optionalWeights; + + /** + * The event number + */ + long LHEeventnum; /** * If the maximum cross section of this reader has been increased * with increaseMaxXSec(), this is the total factor with which it * has been increased. */ double maxFactor; /** * npLO for FxFx merging */ int optionalnpLO; /** * npNLO for FxFx merging */ int optionalnpNLO; /** * The (reweighted) XWGTUP value should be scaled with this cross * section when compared to the overestimated cross section. */ CrossSection weightScale; /** * Individual scales for different sub-processes if reweighted. */ vector<double> xSecWeights; /** * Individual maximum weights for individual (possibly reweighted) * processes. */ map<int,double> maxWeights; /** * Is set to true when getEvent() is called from skip(int). */ bool skipping; /** * Option for the treatment of the momenta supplied */ unsigned int theMomentumTreatment; /** * Set to true if warnings about possible weight incompatibilities * should be issued. */ bool useWeightWarnings; /** * Option to allow reopening of the file */ bool theReOpenAllowed; /** * Use the spin information */ bool theIncludeSpin; private: /** Access function for the interface. */ void setBeamA(long id); /** Access function for the interface. */ long getBeamA() const; /** Access function for the interface. */ void setBeamB(long id); /** Access function for the interface. */ long getBeamB() const; /** Access function for the interface. */ void setEBeamA(Energy e); /** Access function for the interface. */ Energy getEBeamA() const; /** Access function for the interface. */ void setEBeamB(Energy e); /** Access function for the interface. */ Energy getEBeamB() const; /** Access function for the interface. */ void setPDFA(PDFPtr); /** Access function for the interface. */ PDFPtr getPDFA() const; /** Access function for the interface. */ void setPDFB(PDFPtr); /** Access function for the interface. */ PDFPtr getPDFB() const; private: /** * Describe an abstract base class with persistent data. */ static AbstractClassDescription<FxFxReader> initFxFxReader; /** * Private and non-existent assignment operator. */ FxFxReader & operator=(const FxFxReader &) = delete; public: /** @cond EXCEPTIONCLASSES */ /** Exception class used by FxFxReader in case inconsistencies * are encountered. */ class FxFxInconsistencyError: public Exception {}; /** Exception class used by FxFxReader in case more events than available are requested. */ class FxFxReopenWarning: public Exception {}; /** Exception class used by FxFxReader in case reopening an event file fails. */ class FxFxReopenError: public Exception {}; /** Exception class used by FxFxReader in case there is information missing in the initialization phase. */ class FxFxInitError: public InitException {}; /** @endcond */ }; /// Stream output for HEPEUP ostream & operator<<(ostream & os, const HEPEUP & h); } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of FxFxReader. */ template <> struct BaseClassTrait<FxFxReader,1>: public ClassTraitsType { /** Typedef of the base class of FxFxReader. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * FxFxReader class and the shared object where it is * defined. */ template <> struct ClassTraits<FxFxReader> : public ClassTraitsBase<FxFxReader> { /** * Return the class name. */ static string className() { return "Herwig::FxFxReader"; } /** * Return the name of the shared library to be loaded to get access * to the FxFxReader class and every other class it uses * (except the base class). */ static string library() { return "HwFxFx.so"; } }; /** @endcond */ } #endif /* THEPEG_FxFxReader_H */ diff --git a/MatrixElement/Matchbox/Base/SubtractedME.h b/MatrixElement/Matchbox/Base/SubtractedME.h --- a/MatrixElement/Matchbox/Base/SubtractedME.h +++ b/MatrixElement/Matchbox/Base/SubtractedME.h @@ -1,528 +1,536 @@ // -*- C++ -*- // // SubtractedME.h 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. // #ifndef HERWIG_SubtractedME_H #define HERWIG_SubtractedME_H // // This is the declaration of the SubtractedME class. // #include "ThePEG/MatrixElement/MEGroup.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.fh" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief SubtractedME represents a subtracted real emission matrix element. * * @see \ref SubtractedMEInterfaces "The interfaces" * defined for SubtractedME. */ class SubtractedME: public MEGroup, public LastMatchboxXCombInfo { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ SubtractedME(); /** * The destructor. */ virtual ~SubtractedME(); //@} public: /** * Return the factory which produced this matrix element */ Ptr<MatchboxFactory>::tcptr factory() const; /** @name Phasespace and subprocess information */ //@{ /** * For the given event generation setup return an xcomb object * appropriate to this matrix element. */ virtual StdXCombPtr makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec& allPBins, tStdXCombPtr newHead = tStdXCombPtr(), tMEPtr newME = tMEPtr()); /** * Set the XComb object to be used in the next call to * generateKinematics() and dSigHatDR(). */ virtual void setXComb(tStdXCombPtr); /** * Return true, if the same additional random numbers * should be presented to any of the dependent * matrix elements. */ virtual bool uniformAdditional() const { return true; } /** * Return true, if the XComb steering this matrix element * should keep track of the random numbers used to generate * the last phase space point */ virtual bool keepRandomNumbers() const { return true; } /** * Given a process from the head matrix element, * return a list of diagrams which should be considered for * the given dependent matrix element. */ virtual MEBase::DiagramVector dependentDiagrams(const cPDVector& proc, tMEPtr depME) const; /** * Return true, if SubProcessGroups should be * setup from this MEGroup. If not, a single SubProcess * is constructed from the data provided by the * head matrix element. */ virtual bool subProcessGroups() const; /** * Return true, if one of the dependent subprocesses should be * constructed in place of the one driven by the head matrix element * or a full subprocess group. */ virtual bool selectDependentSubProcess() const { return false; } /** * Fill the projectors object of xcombs to choose subprocesses * different than the one currently integrated. */ virtual void fillProjectors(); /** * Return true, if projectors will be used */ virtual bool willProject() const { return virtualShowerSubtraction() || loopSimSubtraction(); } /** * Return true, if this MEGroup will reweight the contributing cross * sections. */ virtual bool groupReweighted() const { return showerApproximation(); } /** * Reweight the head cross section */ virtual double reweightHead(const vector<tStdXCombPtr>&); /** * Reweight the dependent cross section */ virtual double reweightDependent(tStdXCombPtr, const vector<tStdXCombPtr>&); /** * Switch on or off that scales should be calculated from real emission kinematics */ void doRealEmissionScales(); //@} /** @name Methods relevant to matching */ //@{ /** * Inform this matrix element that a new phase space * point is about to be generated, so all caches should * be flushed. */ virtual void flushCaches() { MEGroup::flushCaches(); if ( showerApproximation() ) showerApproximation()->resetBelowCutoff(); } /** * Return the shower approximation. */ Ptr<ShowerApproximation>::tptr showerApproximation() const; /** * Indicate that the shower real emission contribution should be subtracted. */ void doRealShowerSubtraction(); /** * Return true, if the shower real emission contribution should be subtracted. */ bool realShowerSubtraction() const { return theRealShowerSubtraction; } /** * Indicate that the shower virtual contribution should be subtracted. */ void doVirtualShowerSubtraction(); /** * Return true, if the shower virtual contribution should be subtracted. */ bool virtualShowerSubtraction() const { return theVirtualShowerSubtraction; } /** * Indicate that the loopsim matched virtual contribution should be subtracted. */ void doLoopSimSubtraction(); /** * Return true, if the loopsim matched virtual contribution should be subtracted. */ bool loopSimSubtraction() const { return theLoopSimSubtraction; } + /** + * Return true, if this configuration of cross sections should not + * be included due to their relative magnitude. Arguments are head + * cross section and dependent cross section, including all + * reweights. + */ + virtual bool discard(const CrossSection&, const CrossSection&) const { return false; } + //@} /** @name Matrix element and dipole information */ //@{ /** * Return the subtraction dipoles. */ vector<Ptr<SubtractionDipole>::ptr> dipoles(); /** * Return the underlying born matrix elements. */ const vector<Ptr<MatchboxMEBase>::ptr>& borns() const; /** * Access the underlying born matrix elements, * overriding the ones contained in the factory object. */ void setBorns(const vector<Ptr<MatchboxMEBase>::ptr>& newBorns) { theBorns = newBorns; } /** * Build up dipoles needed. */ void getDipoles(); /** * Clone all dipoles. */ void cloneDipoles(const string& prefix = ""); /** * Clone the real emission matrix element. */ void cloneRealME(const string& prefix = ""); /** * Clone all dependencies. */ void cloneDependencies(const string& prefix = "") { cloneDipoles(prefix); cloneRealME(prefix); } /** * Return all dipoles matching the given Born process */ vector<Ptr<SubtractionDipole>::ptr> splitDipoles(const cPDVector&); //@} /** @name Veto scale settings */ //@{ /** * Set veto scales on the particles at the given * SubProcess which has been generated using this * matrix element. */ virtual void setVetoScales(tSubProPtr) const; //@} /** @name Diagnostic information */ //@{ /** * Dump the setup to an ostream */ void print(ostream&) const; /** * Collect information on the last evaluated phasespace * point for verification or debugging purposes. This * only called, if the StdXCombGroup did accumulate * a non-zero cross section from this ME group. */ virtual void lastEventStatistics(); /** * Print debug information on the last event */ void printLastEvent(ostream&) const; /** * Check the subtraction for the last event */ void lastEventSubtraction(); /** * Return true, if verbose */ bool verbose() const; /** * Return true, if verbose */ bool initVerbose() const; //@} /** @name Setup of Subtracted ME objects */ //@{ /** * Return true if this object needs to be initialized before all * other objects (except those for which this function also returns * true). This default version always returns false, but subclasses * may override it to return true. */ virtual bool preInitialize() const { return true; } /** * Simple envelope histogram to keep track of subtraction */ struct SubtractionHistogram { /** * The lower bound */ double lower; /** * The bins, indexed by upper bound. */ map<double,pair<double,double> > bins; /** * Constructor */ SubtractionHistogram(double low = 0.001, double up = 10., unsigned int nbins = 100); /** * Book an event. */ void book(double inv, double diff) { map<double,pair<double,double> >::iterator b = bins.upper_bound(inv); if ( b == bins.end() ) return; b->second.first = min(b->second.first,diff); b->second.second = max(b->second.second,diff); } /** * Write to file given name and invariant. */ void dump(const std::string& prefix, const int& plottype, const bool& scatterplot, const cPDVector& proc, int i, int j) const; /** * Write to persistent ostream */ void persistentOutput(PersistentOStream&) const; /** * Read from persistent istream */ void persistentInput(PersistentIStream&); }; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The underlying born matrix elements, overriding the ones * contained in the factory object. */ vector<Ptr<MatchboxMEBase>::ptr> theBorns; /** * Pointer to the head real emission ME casted to a MatchboxMEBase * object. */ Ptr<MatchboxMEBase>::ptr theReal; /** * Define the key for the collinear subtraction data. */ typedef pair<cPDVector,pair<size_t, size_t> > CollinearSubtractionIndex; /** * subtraction data for collinear limits. */ map<CollinearSubtractionIndex,SubtractionHistogram> collinearHistograms; /** * names of files to which subtraction data is written for all phase space points individually */ map<CollinearSubtractionIndex,string> fnamesCollinearSubtraction; /** * Define the key for the soft subtraction data. */ typedef pair<cPDVector,size_t> SoftSubtractionIndex; /** * subtraction data for soft limits. */ map<SoftSubtractionIndex,SubtractionHistogram> softHistograms; /** * names of files to which subtraction data is written for all phase space points individually */ map<SoftSubtractionIndex,string> fnamesSoftSubtraction; /** * True, if the shower real emission contribution should be subtracted. */ bool theRealShowerSubtraction; /** * True, if the shower virtual contribution should be subtracted. */ bool theVirtualShowerSubtraction; /** * True, if the loopsim matched virtual contribution should be subtracted. */ bool theLoopSimSubtraction; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SubtractedME & operator=(const SubtractedME &) = delete; }; inline PersistentOStream& operator<<(PersistentOStream& os, const SubtractedME::SubtractionHistogram& h) { h.persistentOutput(os); return os; } inline PersistentIStream& operator>>(PersistentIStream& is, SubtractedME::SubtractionHistogram& h) { h.persistentInput(is); return is; } } #endif /* HERWIG_SubtractedME_H */ diff --git a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.cc b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.cc --- a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.cc +++ b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.cc @@ -1,275 +1,277 @@ // -*- C++ -*- // // VBFNLOPhasespace.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 VBFNLOPhasespace class. // #include "VBFNLOPhasespace.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Utilities/GSLBisection.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "VBFNLO/utilities/BLHAinterface.h" #define DEFSTR(s) CPPSTR(s) #define CPPSTR(s) #s using namespace Herwig; VBFNLOPhasespace::VBFNLOPhasespace() : lastSqrtS(0*GeV), needToReshuffle(false), VBFNLOlib_(DEFSTR(VBFNLOLIB)) {} void VBFNLOPhasespace::loadVBFNLO() { if ( ! DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.so") ) { string error1 = DynamicLoader::lastErrorMessage; if ( ! DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.dylib") ) { string error2 = DynamicLoader::lastErrorMessage; if ( ! DynamicLoader::load("libVBFNLO.so") ) { string error3 = DynamicLoader::lastErrorMessage; if ( ! DynamicLoader::load("libVBFNLO.dylib") ) { string error4 = DynamicLoader::lastErrorMessage; throw Exception() << "VBFNLOPhasespace: failed to load libVBFNLO.so/dylib\n" << "Error messages are:\n\n" << "* " << VBFNLOlib_ << "/libVBFNLO.so:\n" << error1 << "\n" << "* " << VBFNLOlib_ << "/libVBFNLO.dylib:\n" << error2 << "\n" << "* libVBFNLO.so:\n" << error3 << "\n" << "* libVBFNLO.dylib:\n" << error4 << "\n" << Exception::runerror; } } } } } VBFNLOPhasespace::~VBFNLOPhasespace() {} IBPtr VBFNLOPhasespace::clone() const { return new_ptr(*this); } IBPtr VBFNLOPhasespace::fullclone() const { return new_ptr(*this); } void VBFNLOPhasespace::setXComb(tStdXCombPtr xco) { MatchboxPhasespace::setXComb(xco); // test for resuffling needToReshuffle = false; if ( xco ) { for ( cPDVector::const_iterator d = mePartonData().begin(); d != mePartonData().end(); ++d ) { // Higgs is massive -> does not need reshuffling if ( ( (**d).id() != ParticleID::h0 ) && ( (**d).hardProcessMass() != ZERO ) ) { needToReshuffle = true; break; } } } // set CMS energy int pStatus = 0; double zero = 0.0; double value = sqrt(lastXCombPtr()->lastS())/GeV; if (value && (value != lastSqrtS/GeV)) { lastSqrtS = value*GeV; string name = "sqrtS"; OLP_SetParameter(const_cast<char*>(name.c_str()),&value,&zero,&pStatus); if ( !pStatus ) throw Exception() << "VBFNLOPhasespace::setXComb(): VBFNLO failed to set parameter '" << name << "' to " << value << "\n" << Exception::runerror; } } double VBFNLOPhasespace::generateTwoToNKinematics(const double* random, vector<Lorentz5Momentum>& momenta) { double weight; int id = olpId()[ProcessType::oneLoopInterference] ? olpId()[ProcessType::oneLoopInterference] : olpId()[ProcessType::treeME2]; double* p = new double[4*momenta.size()]; OLP_PhaseSpacePoint(&id, const_cast<double*>(random), const_cast<double*>(random+1), p, &weight); if (weight < 0) { throw Exception() << "VBFNLOPhasespace::generateTwoToNKinematics(): Negative weight in VBFNLOPhaseSpace\n" << Exception::runerror; } if (weight == 0) { delete[] p; return 0; } for ( size_t i = 0; i < momenta.size(); ++i ) { momenta[i].setT(p[4*i] *GeV); momenta[i].setX(p[4*i+1]*GeV); momenta[i].setY(p[4*i+2]*GeV); momenta[i].setZ(p[4*i+3]*GeV); momenta[i].rescaleMass(); } delete[] p; Energy beamenergy = sqrt(lastXCombPtr()->lastS())/2.; double x1 = momenta[0].e()/beamenergy; double x2 = momenta[1].e()/beamenergy; Energy2 thisSHat = (momenta[0] + momenta[1]).m2(); // reshuffle so that particles have correct mass if ( needToReshuffle ) { // boost final-state into partonic CMS Boost toCMS = (momenta[0]+momenta[1]).findBoostToCM(); for ( size_t i = 2; i < momenta.size(); ++i ) { momenta[i].boost(toCMS); } // copied from MatchboxRambo phasespace double xi; ReshuffleEquation solve(sqrt(thisSHat),mePartonData().begin()+2,mePartonData().end(), momenta.begin()+2,momenta.end()); GSLBisection solver(1e-10,1e-8,10000); try { xi = solver.value(solve,0.0,1.1); } catch (GSLBisection::GSLerror) { return 0.; } catch (GSLBisection::IntervalError) { return 0.; } weight *= pow(xi,3.*(momenta.size()-3.)); Energy num = ZERO; Energy den = ZERO; cPDVector::const_iterator d = mePartonData().begin()+2; for ( vector<Lorentz5Momentum>::iterator k = momenta.begin()+2; k != momenta.end(); ++k, ++d ) { num += (*k).vect().mag2()/(*k).t(); Energy q = (*k).t(); (*k).setT(sqrt(sqr((**d).hardProcessMass())+xi*xi*sqr((*k).t()))); (*k).setVect(xi*(*k).vect()); weight *= q/(*k).t(); den += (*k).vect().mag2()/(*k).t(); (*k).setMass((**d).hardProcessMass()); } // unboost for ( size_t i = 2; i < momenta.size(); ++i ) { momenta[i].boost(-toCMS); } } if ( !matchConstraints(momenta) ) return 0.; lastXCombPtr()->lastX1X2(make_pair(x1,x2)); lastXCombPtr()->lastSHat(thisSHat); weight /= pow(thisSHat/GeV2,momenta.size()-4); weight /= x1*x2; + fillDiagramWeights(); + return weight; } int VBFNLOPhasespace::nDimPhasespace(int nFinal) const { return 3*nFinal; //get this from within VBFNLO int pStatus = 0; double value, zero; string name = "PSdimension"; OLP_GetParameter(const_cast<char*>(name.c_str()),&value,&zero,&pStatus); if ( pStatus != 1) { throw Exception() << "VBFNLOPhasespace::nDimPhasespace(): Cannot get phasespace dimension in VBFNLOPhaseSpace\n" << "error code: " << pStatus << "\n" << Exception::runerror; } // one additional number (first) needed for channel selection // one additional number (last) needed for global phi integration return value+2; } Energy VBFNLOPhasespace::ReshuffleEquation::operator() (double xi) const { cPDVector::const_iterator d = dataBegin; vector<Lorentz5Momentum>::const_iterator p = momentaBegin; Energy res = -w; for ( ; d != dataEnd; ++d, ++p ) { res += sqrt(sqr((**d).hardProcessMass()) + xi*xi*sqr(p->t())); } return res; } void VBFNLOPhasespace::doinit() { loadVBFNLO(); MatchboxPhasespace::doinit(); } void VBFNLOPhasespace::doinitrun() { loadVBFNLO(); MatchboxPhasespace::doinitrun(); } void VBFNLOPhasespace::persistentOutput(PersistentOStream & os) const { os << needToReshuffle << theLastXComb; } void VBFNLOPhasespace::persistentInput(PersistentIStream & is, int) { is >> needToReshuffle >> theLastXComb; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass<VBFNLOPhasespace,MatchboxPhasespace> describeHerwigVBFNLOPhasespace("Herwig::VBFNLOPhasespace", "HwMatchboxVBFNLO.so"); void VBFNLOPhasespace::Init() { static ClassDocumentation<VBFNLOPhasespace> documentation ("VBFNLOPhasespace is an interface to the internal phasespace generator " "of VBFNLO. It uses the information passed via the BLHA interface to " "obtain information on the required channels."); } diff --git a/m4/herwig.m4 b/m4/herwig.m4 --- a/m4/herwig.m4 +++ b/m4/herwig.m4 @@ -1,983 +1,1003 @@ dnl ##### THEPEG ##### AC_DEFUN([HERWIG_CHECK_THEPEG], [ defaultlocation="${prefix}" test "x$defaultlocation" = xNONE && defaultlocation="${ac_default_prefix}" AC_MSG_CHECKING([for libThePEG in]) AC_ARG_WITH(thepeg, AC_HELP_STRING([--with-thepeg=DIR],[location of ThePEG installation]), [], [with_thepeg="${defaultlocation}"]) AC_MSG_RESULT([$with_thepeg]) if test "x$with_thepeg" = "xno"; then AC_MSG_ERROR([Cannot build Herwig without ThePEG. Please set --with-thepeg.]) fi THEPEGLDFLAGS="-L${with_thepeg}/lib/ThePEG" THEPEGHASLHAPDF="no" if test -e ${with_thepeg}/lib/ThePEG/ThePEGLHAPDF.so ; then THEPEGHASLHAPDF="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/ThePEGLHAPDF.so ; then THEPEGHASLHAPDF="yes" fi fi if test "x$THEPEGHASLHAPDF" == "xno" ; then AC_MSG_ERROR([Herwig requires ThePEG to be build with lhapdf.]) fi THEPEGHASFASTJET="no" if test -e ${with_thepeg}/lib/ThePEG/FastJetFinder.so ; then THEPEGHASFASTJET="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/FastJetFinder.so ; then THEPEGHASFASTJET="yes" fi fi if test "x$THEPEGHASFASTJET" == "xno" ; then AC_MSG_ERROR([Herwig requires ThePEG to be build with FastJet.]) fi THEPEGPATH="${with_thepeg}" oldldflags="$LDFLAGS" oldlibs="$LIBS" LDFLAGS="$LDFLAGS $THEPEGLDFLAGS" AC_CHECK_LIB([ThePEG],[debugThePEG],[], [AC_MSG_ERROR([No ThePEG libraries in $THEPEGLDFLAGS. Please set --with-thepeg.])]) AC_SUBST([THEPEGLIB],[-lThePEG]) AC_SUBST(THEPEGLDFLAGS) AC_SUBST(THEPEGPATH) AC_SUBST(THEPEGHASLHAPDF) AC_SUBST(THEPEGHASFASTJET) LIBS="$oldlibs" LDFLAGS="$oldldflags" AC_MSG_CHECKING([for ThePEG headers in]) AC_ARG_WITH([thepeg-headers], AC_HELP_STRING([--with-thepeg-headers=DIR],[location of ThePEG include directory]), [], [with_thepeg_headers="${with_thepeg}/include"]) AC_MSG_RESULT([$with_thepeg_headers]) if test "x$with_thepeg_headers" = "xno"; then AC_MSG_ERROR([Cannot build Herwig without ThePEG headers. Please set --with-thepeg-headers.]) fi THEPEGINCLUDE="-I$with_thepeg_headers" oldcppflags="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $THEPEGINCLUDE" AC_CHECK_HEADER([ThePEG/Config/ThePEG.h],[], [AC_MSG_ERROR([No ThePEG headers in $with_thepeg_headers. Please set --with-thepeg-headers.])]) CPPFLAGS="$oldcppflags" AC_SUBST(THEPEGINCLUDE) AC_MSG_CHECKING([for HepMCAnalysis.so in ThePEG]) THEPEGHASHEPMC="no" if test -e ${with_thepeg}/lib/ThePEG/HepMCAnalysis.so ; then THEPEGHASHEPMC="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/HepMCAnalysis.so ; then THEPEGHASHEPMC="yes" fi fi if test "x$THEPEGHASHEPMC" == "xno" ; then CREATE_HEPMC="# create" AC_MSG_RESULT([not found]) else CREATE_HEPMC="create" AC_MSG_RESULT([found]) fi AC_SUBST([CREATE_HEPMC]) AC_MSG_CHECKING([for RivetAnalysis.so in ThePEG]) THEPEGHASRIVET="no" if test -e ${with_thepeg}/lib/ThePEG/RivetAnalysis.so ; then THEPEGHASRIVET="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/RivetAnalysis.so ; then THEPEGHASRIVET="yes" fi fi if test "x$THEPEGHASRIVET" == "xno" ; then CREATE_RIVET="# create" AC_MSG_RESULT([not found]) else CREATE_RIVET="create" AC_MSG_RESULT([found]) fi AM_CONDITIONAL(HAVE_RIVET,[test x$THEPEGHASRIVET = xyes]) AC_SUBST([CREATE_RIVET]) ]) dnl ##### LOOPTOOLS ##### AC_DEFUN([HERWIG_LOOPTOOLS], [ AC_REQUIRE([AC_PROG_FC]) AC_REQUIRE([AC_FC_LIBRARY_LDFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([HERWIG_COMPILERFLAGS]) AC_MSG_CHECKING([if Looptools build works]) enable_looptools=yes if test "x$GCC" = "xyes"; then case "${host}" in x86_64-*|*-darwin1*) AM_FCFLAGS="$AM_FCFLAGS -fdefault-integer-8" ;; esac AC_LANG_PUSH([Fortran]) oldFCFLAGS="$FCFLAGS" FCFLAGS="$AM_FCFLAGS" AC_COMPILE_IFELSE( AC_LANG_PROGRAM([],[ print *[,]"Hello"]), [], [AC_MSG_RESULT([no]) AC_MSG_ERROR([needs gfortran on 64bit machines])] ) FCFLAGS="$oldFCFLAGS" AC_LANG_POP([Fortran]) fi AC_MSG_RESULT([$enable_looptools]) AC_LANG_PUSH([Fortran]) AC_MSG_CHECKING([checking if fortran compiler compiles argument mismatches]) AC_COMPILE_IFELSE(AC_LANG_SOURCE([[ program temp call a(1.0D0) end program subroutine a(b) double complex b end]]), [AC_MSG_RESULT([yes])], [oldFCFLAGS="$FCFLAGS" FCFLAGS="-std=legacy" AC_MSG_CHECKING([checking if fortran compiler compiles argument mismatches with -std=legacy]) AC_COMPILE_IFELSE(AC_LANG_SOURCE([[ program temp double precision b double complex c b = 1.0D0 c =1.0D0 call a(b) call a(c) end program subroutine a(b) double complex b end]]), [AC_MSG_RESULT([yes]) AM_FCFLAGS="$AM_FCFLAGS -std=legacy"], [AC_MSG_RESULT([no]) AC_MSG_ERROR([fortran compiler won't compile LoopTools])]) FCFLAGS="$oldFCFLAGS -std=legacy"] ) AC_MSG_CHECKING([checking if fortran compiler compiles long lines]) AC_COMPILE_IFELSE(AC_LANG_SOURCE([[ program temp write (*,*) 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' end program]]), [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) oldFCFLAGS="$FCFLAGS" FCFLAGS="-ffixed-line-length-none" AC_MSG_CHECKING([checking if fortran compiler compiles long lines with -ffixed-line-length-none]) AC_COMPILE_IFELSE(AC_LANG_SOURCE([[ program temp write (*,*) 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' end program]]), [AC_MSG_RESULT([yes]) AM_FCFLAGS="$AM_FCFLAGS -ffixed-line-length-none" FCFLAGS="$oldFCFLAGS -ffixed-line-length-none"], [FCFLAGS="-132" AC_MSG_CHECKING([checking if fortran compiler compiles long lines with -132]) AC_COMPILE_IFELSE(AC_LANG_SOURCE([[ program temp write (*,*) 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' end program]]), [AC_MSG_RESULT([yes]) AM_FCFLAGS="$AM_FCFLAGS -132" FCFLAGS="$oldFCFLAGS -132"], [AC_MSG_RESULT([no]) AC_MSG_ERROR([fortran compiler won't compile LoopTools])])]) ] ) AC_LANG_POP([Fortran]) AC_SUBST([F77],[$FC]) AC_SUBST([FFLAGS],[$FCFLAGS]) AC_SUBST([AM_FFLAGS],[$AM_FCFLAGS]) AC_SUBST([FLIBS],[$FCLIBS]) ]) dnl ##### VBFNLO ##### AC_DEFUN([HERWIG_CHECK_VBFNLO], [ AC_MSG_CHECKING([for VBFNLO]) AC_ARG_WITH([vbfnlo], AS_HELP_STRING([--with-vbfnlo=DIR], [Installation path of VBFNLO]), [], [with_vbfnlo=no] ) AC_MSG_RESULT([$with_vbfnlo]) AS_IF([test "x$with_vbfnlo" != "xno"], [AC_CHECK_FILES( ${with_vbfnlo}/lib/VBFNLO/libVBFNLO.so, [have_vbfnlo=lib], [have_vbfnlo=no])], [have_vbfnlo=no]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib64/VBFNLO/libVBFNLO.so, [have_vbfnlo=lib64], [have_vbfnlo=no])]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib/VBFNLO/libVBFNLO.dylib, [have_vbfnlo=lib], [have_vbfnlo=no])]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib64/VBFNLO/libVBFNLO.dylib, [have_vbfnlo=lib64], [have_vbfnlo=no])]) AS_IF([test "x$have_vbfnlo" = "xlib"], [VBFNLOLIBS=${with_vbfnlo}/lib/VBFNLO AC_SUBST(VBFNLOLIBS) ]) AS_IF([test "x$have_vbfnlo" = "xlib64"], [VBFNLOLIBS=${with_vbfnlo}/lib64/VBFNLO AC_SUBST(VBFNLOLIBS) ]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno"], [AC_MSG_ERROR([vbfnlo requested but not found])]) AM_CONDITIONAL(HAVE_VBFNLO,[test "x$have_vbfnlo" = "xlib" -o "x$have_vbfnlo" = "xlib64"]) if test "x$have_vbfnlo" = "xlib" -o "x$have_vbfnlo" = "xlib64" ; then AC_REQUIRE([AC_PROG_SED]) VBFNLOINCLUDE=${with_vbfnlo}/include AC_SUBST(VBFNLOINCLUDE) VBFNLOLIB=$(echo ${with_vbfnlo}/${have_vbfnlo}/VBFNLO | $SED -e 's%/\+%/%g') AC_SUBST(VBFNLOLIB) LOAD_VBFNLO="library" CREATE_VBFNLO="create" INSERT_VBFNLO="insert" SET_VBFNLO="set" DO_VBFNLO="do" MKDIR_VBFNLO="mkdir" else LOAD_VBFNLO="# library" CREATE_VBFNLO="# create" INSERT_VBFNLO="# insert" SET_VBFNLO="# set" DO_VBFNLO="# do" MKDIR_VBFNLO="# mkdir" fi AC_SUBST([LOAD_VBFNLO]) AC_SUBST([CREATE_VBFNLO]) AC_SUBST([INSERT_VBFNLO]) AC_SUBST([SET_VBFNLO]) AC_SUBST([DO_VBFNLO]) AC_SUBST([MKDIR_VBFNLO]) ]) dnl ##### njet ##### AC_DEFUN([HERWIG_CHECK_NJET], [ AC_MSG_CHECKING([for njet]) AC_ARG_WITH([njet], AS_HELP_STRING([--with-njet=DIR], [Installation path of njet]), [], [with_njet=no] ) AC_MSG_RESULT([$with_njet]) AS_IF([test "x$with_njet" != "xno"], [AC_CHECK_FILES( ${with_njet}/lib/libnjet2.so, [have_njet=lib], [have_njet=no])], [have_njet=no]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], [AC_CHECK_FILES( ${with_njet}/lib64/libnjet2.so, [have_njet=lib64], [have_njet=no])]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], [AC_CHECK_FILES( ${with_njet}/lib/libnjet2.dylib, [have_njet=lib], [have_njet=no])]) +AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], + [AC_CHECK_FILES( + ${with_njet}/lib/libnjet3.so, + [have_njet=lib], [have_njet=no])]) + +AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], + [AC_CHECK_FILES( + ${with_njet}/lib64/libnjet3.so, + [have_njet=lib], [have_njet=no])]) + +AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], + [AC_CHECK_FILES( + ${with_njet}/lib/libnjet3.dylib, + [have_njet=lib], [have_njet=no])]) + +AS_IF([test "x$with_njet" != "xno" ], + [AC_CHECK_FILES( + ${with_njet}/include/njet.h, + [njet_include=include], [njet_include=include/njet])]) + AS_IF([test "x$have_njet" = "xlib"], [NJETLIBPATH=${with_njet}/lib AC_SUBST(NJETLIBPATH) - NJETINCLUDEPATH=${with_njet}/include + NJETINCLUDEPATH=${with_njet}/$njet_include AC_SUBST(NJETINCLUDEPATH) NJETPREFIX=${with_njet} AC_SUBST(NJETPREFIX) ]) AS_IF([test "x$have_njet" = "xlib64"], [NJETLIBPATH=${with_njet}/lib64 AC_SUBST(NJETLIBPATH) - NJETINCLUDEPATH=${with_njet}/include + NJETINCLUDEPATH=${with_njet}/$njet_include AC_SUBST(NJETINCLUDEPATH) NJETPREFIX=${with_njet} AC_SUBST(NJETPREFIX) ]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno"], [AC_MSG_ERROR([njet requested but not found])]) AM_CONDITIONAL(HAVE_NJET,[test "x$have_njet" = "xlib" -o "x$have_njet" = "xlib64"]) AS_IF([test "x$with_njet" != "xno"],[AC_MSG_CHECKING([for Njet version]) tmp_njetversion=[$(${with_njet}/bin/njet.py --version 2>&1 | grep -oE '[0-9]{4}$')] AS_IF([test -z "$tmp_njetversion"], [tmp_njetversion=1023]) AC_MSG_RESULT([${tmp_njetversion}]) NJET_VERSION=${tmp_njetversion} AC_SUBST(NJET_VERSION) ]) if test "x$have_njet" = "xlib" -o "x$have_njet" = "xlib64" ; then LOAD_NJET="library" CREATE_NJET="create" INSERT_NJET="insert" DO_NJET="do" else LOAD_NJET="# library" CREATE_NJET="# create" INSERT_NJET="# insert" DO_NJET="# do" fi AC_SUBST([LOAD_NJET]) AC_SUBST([CREATE_NJET]) AC_SUBST([INSERT_NJET]) AC_SUBST([DO_NJET]) ]) dnl ##### gosam ##### AC_DEFUN([HERWIG_CHECK_GOSAM], [ AC_MSG_CHECKING([for GoSam]) AC_ARG_WITH([gosam], AS_HELP_STRING([--with-gosam=DIR], [Installation path of GoSam]), [], [with_gosam=no] ) AC_MSG_RESULT([$with_gosam]) AS_IF([test "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/bin/gosam.py, [have_gosam=lib], [have_gosam=no])], [have_gosam=no]) AS_IF([test "x$have_gosam" = "xlib"], [GOSAMPREFIX=${with_gosam} AC_SUBST(GOSAMPREFIX) ]) AS_IF([test "x$with_gosam" != "xno" -a "x$have_gosam" = "xno"], [AC_MSG_ERROR([GoSam requested but not found])]) AS_IF([test "x$with_gosam" != "xno"], [AC_MSG_CHECKING([for GoSam version >= 2.0.4]) tmp_gosamversion=[$(${with_gosam}/bin/gosam.py --version | grep 'GoSam.*rev' | cut -d' ' -f2)] AX_COMPARE_VERSION([${tmp_gosamversion}],[lt],[2.0.4], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Herwig requires GoSam 2.0.4 or later, found ${tmp_gosamversion}])], [AC_MSG_RESULT([yes])])]) AM_CONDITIONAL(HAVE_GOSAM,[test "x$have_gosam" = "xlib" ]) if test "x$have_gosam" = "xlib" ; then LOAD_GOSAM="library" CREATE_GOSAM="create" INSERT_GOSAM="insert" DO_GOSAM="do" else LOAD_GOSAM="# library" CREATE_GOSAM="# create" INSERT_GOSAM="# insert" DO_GOSAM="# do" fi AC_SUBST([LOAD_GOSAM]) AC_SUBST([CREATE_GOSAM]) AC_SUBST([INSERT_GOSAM]) AC_SUBST([DO_GOSAM]) ]) dnl ##### gosam-contrib ##### AC_DEFUN([HERWIG_CHECK_GOSAM_CONTRIB], [ AC_MSG_CHECKING([for gosam-contrib]) AC_ARG_WITH([gosam-contrib], AS_HELP_STRING([--with-gosam-contrib=DIR], [Installation path of gosam-contrib]), [], [with_gosam_contrib=no] ) AC_MSG_RESULT([$with_gosam_contrib]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib/libsamurai.so, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib64/libsamurai.so, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib/libsamurai.dylib, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib64/libsamurai.dylib, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_MSG_ERROR([GoSam requested without requesting GoSam-Contrib])]) AS_IF([test "x$with_gosam_contrib" != "xno"], [AC_CHECK_FILES( ${with_gosam_contrib}/lib/libsamurai.so, [have_gosam_contrib=lib], [have_gosam_contrib=no])], [have_gosam_contrib=no]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib64/libsamurai.so, [have_gosam_contrib=lib64], [have_gosam_contrib=no])]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib/libsamurai.dylib, [have_gosam_contrib=lib], [have_gosam_contrib=no])]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib64/libsamurai.dylib, [have_gosam_contrib=lib64], [have_gosam_contrib=no])]) AS_IF([test "x$have_gosam_contrib" != "xno"], [GOSAMCONTRIBPREFIX=${with_gosam_contrib} AC_SUBST(GOSAMCONTRIBPREFIX) ]) AS_IF([test "x$have_gosam_contrib" = "xlib"], [GOSAMCONTRIBLIBS=${with_gosam_contrib}/lib AC_SUBST(GOSAMCONTRIBLIBS) ]) AS_IF([test "x$have_gosam_contrib" = "xlib64"], [GOSAMCONTRIBLIBS=${with_gosam_contrib}/lib64 AC_SUBST(GOSAMCONTRIBLIBS) ]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno"], [AC_MSG_ERROR([GoSam-Contrib requested but not found])]) AM_CONDITIONAL(HAVE_GOSAM_CONTRIB,[test "x$have_gosam_contrib" = "xlib" -o "x$have_gosam_contrib" = "xlib64"]) if test "x$have_gosam_contrib" = "xlib" -o "x$have_gosam_contrib" = "xlib64" ; then LOAD_GOSAM_CONTRIB="library" CREATE_GOSAM_CONTRIB="create" INSERT_GOSAM_CONTRIB="insert" else LOAD_GOSAM_CONTRIB="# library" CREATE_GOSAM_CONTRIB="# create" INSERT_GOSAM_CONTRIB="# insert" fi AC_SUBST([LOAD_GOSAM_CONTRIB]) AC_SUBST([CREATE_GOSAM_CONTRIB]) AC_SUBST([INSERT_GOSAM_CONTRIB]) ]) dnl ##### OpenLoops ##### AC_DEFUN([HERWIG_CHECK_OPENLOOPS], [ AC_MSG_CHECKING([for OpenLoops]) AC_ARG_WITH([openloops], AS_HELP_STRING([--with-openloops=DIR], [Installation path of OpenLoops]), [], [with_openloops=no] ) AC_MSG_RESULT([$with_openloops]) AS_IF([test "x$with_openloops" != "xno"], [AC_CHECK_FILES( ${with_openloops}/lib/libopenloops.so, [have_openloops=lib], [have_openloops=no])], [have_openloops=no]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib/libopenloops.dylib, [have_openloops=lib], [have_openloops=no])]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib64/libopenloops.so, [have_openloops=lib64], [have_openloops=no])]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib64/libopenloops.dylib, [have_openloops=lib64], [have_openloops=no])]) AS_IF([test "x$have_openloops" = "xlib"], [OPENLOOPSLIBS=${with_openloops}/lib AC_SUBST(OPENLOOPSLIBS) ]) AS_IF([test "x$have_openloops" = "xlib64"], [OPENLOOPSLIBS=${with_openloops}/lib64 AC_SUBST(OPENLOOPSLIBS) ]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno"], [AC_MSG_ERROR([OpenLoops requested but not found])]) AM_CONDITIONAL(HAVE_OPENLOOPS,[test "x$have_openloops" = "xlib" -o "x$have_openloops" = "xlib64"]) if test "x$have_openloops" = "xlib" -o "x$have_openloops" = "xlib64" ; then OPENLOOPSPREFIX=${with_openloops} LOAD_OPENLOOPS="library" CREATE_OPENLOOPS="create" INSERT_OPENLOOPS="insert" SET_OPENLOOPS="set" DO_OPENLOOPS="do" MKDIR_OPENLOOPS="mkdir" else LOAD_OPENLOOPS="# library" CREATE_OPENLOOPS="# create" INSERT_OPENLOOPS="# insert" SET_OPENLOOPS="# set" DO_OPENLOOPS="# do" MKDIR_OPENLOOPS="# mkdir" fi AC_SUBST([OPENLOOPSPREFIX]) AC_SUBST([LOAD_OPENLOOPS]) AC_SUBST([CREATE_OPENLOOPS]) AC_SUBST([INSERT_OPENLOOPS]) AC_SUBST([SET_OPENLOOPS]) AC_SUBST([DO_OPENLOOPS]) AC_SUBST([MKDIR_OPENLOOPS]) ]) ######################################### dnl ##### madgraph ##### AC_DEFUN([HERWIG_CHECK_MADGRAPH], [ AC_MSG_CHECKING([for MadGraph]) AC_ARG_WITH([madgraph], AS_HELP_STRING([--with-madgraph=DIR], [Installation path of MadGraph]), [], [with_madgraph=no] ) AC_MSG_RESULT([$with_madgraph]) AS_IF([test "x$with_madgraph" != "xno"], [AC_CHECK_FILES( ${with_madgraph}/bin/mg5_aMC, [have_madgraph=yes], [have_madgraph=no])], [have_madgraph=no]) AS_IF([test "x$have_madgraph" = "xyes"], [MADGRAPHPREFIX=${with_madgraph} AC_SUBST(MADGRAPHPREFIX) ]) AS_IF([test "x$with_madgraph" != "xno" -a "x$have_madgraph" = "xno"], [AC_MSG_ERROR([MadGraph requested but not found])]) AM_CONDITIONAL(HAVE_MADGRAPH,[test "x$have_madgraph" = "xyes" ]) if test "x$have_madgraph" = "xyes" ; then LOAD_MADGRAPH="library" CREATE_MADGRAPH="create" INSERT_MADGRAPH="insert" SET_MADGRAPH="set" DO_MADGRAPH="do" else LOAD_MADGRAPH="# library" CREATE_MADGRAPH="# create" INSERT_MADGRAPH="# insert" SET_MADGRAPH="# set" DO_MADGRAPH="# do" fi AC_SUBST([LOAD_MADGRAPH]) AC_SUBST([CREATE_MADGRAPH]) AC_SUBST([INSERT_MADGRAPH]) AC_SUBST([SET_MADGRAPH]) AC_SUBST([DO_MADGRAPH]) ]) AC_DEFUN([HERWIG_CHECK_PYTHIA], [ dnl check if a directory is specified for Pythia AC_ARG_WITH(pythia, [AC_HELP_STRING([--with-pythia=dir], [Assume the given directory for Pythia])]) dnl search for the pythia-config script if test "$with_pythia" = ""; then AC_PATH_PROG(pythiaconfig, pythia8-config, no) else AC_PATH_PROG(pythiaconfig, pythia8-config, no, ${with_pythia}/bin) fi if test "${pythiaconfig}" = "no"; then AC_MSG_CHECKING(Pythia) AC_MSG_RESULT(no); PYTHIA8LIB= # $2 else PYTHIA8DATA=`${pythiaconfig} --datadir`/xmldoc PYTHIA8LIB="-L`${pythiaconfig} --libdir` -lpythia8" fi AC_SUBST(PYTHIA8DATA) AC_SUBST(PYTHIA8LIB) ]) dnl CHECK PYTHIA END dnl ##### EvtGen ##### AC_DEFUN([HERWIG_CHECK_EVTGEN], [ AC_MSG_CHECKING([for evtgen]) AC_ARG_WITH([evtgen], AS_HELP_STRING([--with-evtgen=DIR], [Installation path of EvtGen]), [], [with_evtgen=no] ) AC_MSG_RESULT([$with_evtgen]) AS_IF([test "x$with_evtgen" != "xno"], [AC_CHECK_FILES( ${with_evtgen}/lib/libEvtGenExternal.so, [have_evtgen=lib], [have_evtgen=no])], [have_evtgen=no]) AS_IF([test "x$with_evtgen" != "xno" -a "x$have_evtgen" = "xno"], [AC_CHECK_FILES( ${with_evtgen}/lib64/libEvtGenExternal.so, [have_evtgen=lib64], [have_evtgen=no])]) AS_IF([test "x$with_evtgen" != "xno" -a "x$have_evtgen" = "xno" ], [AC_CHECK_FILES( ${with_evtgen}/lib/libEvtGenExternal.dylib, [have_evtgen=lib], [have_evtgen=no])]) AS_IF([test "x$have_evtgen" = "xlib" -o "x$have_evtgen" = "xlib64" ], [EVTGENPREFIX=${with_evtgen} AC_SUBST(EVTGENPREFIX) ]) AS_IF([test "x$with_evtgen" != "xno" -a "x$have_evtgen" = "xno"], [AC_MSG_ERROR([EvtGen requested but not found])]) AC_SUBST([EVTGENINCLUDE],[-I$EVTGENPREFIX/include]) AM_CONDITIONAL(HAVE_EVTGEN,[test "x$have_evtgen" = "xlib" -o "x$have_evtgen" = "xlib64"]) if test "x$have_evtgen" = "xlib" ; then LOAD_EVTGEN_DECAYS="read EvtGenBDecays.in" LOAD_EVTGEN_DECAYER="read EvtGenDecayer.in" EVTGENLIBS="-L$with_evtgen/lib -lEvtGen -lEvtGenExternal" elif test "x$have_evtgen" = "xlib64" ; then LOAD_EVTGEN_DECAYS="read EvtGenBDecays.in" LOAD_EVTGEN_DECAYER="read EvtGenDecayer.in" EVTGENLIBS="-L$with_evtgen/lib64 -lEvtGen -lEvtGenExternal" else LOAD_EVTGEN_DECAYS="read HerwigBDecays.in" LOAD_EVTGEN_DECAYER="#read EvtGenDecayer.in" EVTGENLIBS="" fi AC_SUBST([LOAD_EVTGEN_DECAYS]) AC_SUBST([LOAD_EVTGEN_DECAYER]) AC_SUBST([EVTGENLIBS]) ]) dnl ###### GSL ###### AC_DEFUN([HERWIG_CHECK_GSL], [ AC_MSG_CHECKING([for gsl location]) GSLINCLUDE="" GSLLIBS="" AC_ARG_WITH(gsl, AC_HELP_STRING([--with-gsl=DIR],[location of gsl installation @<:@default=system libs@:>@]), [], [with_gsl=system]) if test "x$with_gsl" = "xno"; then AC_MSG_ERROR([libgsl is required. Please install the GNU scientific library and header files.]) fi if test "x$with_gsl" = "xsystem"; then AC_MSG_RESULT([in system libraries]) oldlibs="$LIBS" AC_CHECK_LIB(m,main) AC_CHECK_LIB(gslcblas,main) AC_CHECK_LIB(gsl,main,[], [ AC_MSG_ERROR([Cannot find libgsl. Please install the GNU scientific library and header files or use --with-gsl=.]) ] ) GSLLIBS="$LIBS" GSLPATH="$with_gsl" LIBS=$oldlibs else if test "`uname -m`" = "x86_64" -a -e "$with_gsl/lib64/libgsl.a" -a -d "$with_gsl/include/gsl"; then AC_MSG_RESULT([found in $with_gsl]) GSLLIBS="-L$with_gsl/lib64 -R$with_gsl/lib64 -lgslcblas -lgsl" GSLINCLUDE="-I$with_gsl/include" GSLPATH="$with_gsl" elif test -e "$with_gsl/lib/libgsl.a" -a -d "$with_gsl/include/gsl"; then AC_MSG_RESULT([found in $with_gsl]) GSLLIBS="-L$with_gsl/lib -R$with_gsl/lib -lgslcblas -lgsl" GSLINCLUDE="-I$with_gsl/include" GSLPATH="$with_gsl" else AC_MSG_RESULT([not found]) AC_MSG_ERROR([Can't find $with_gsl/lib/libgsl.a or the headers in $with_gsl/include]) fi fi AC_SUBST(GSLINCLUDE) AC_SUBST(GSLLIBS) AC_SUBST(GSLPATH) ]) dnl ##### COMPILERFLAGS ##### AC_DEFUN([HERWIG_COMPILERFLAGS], [ AC_REQUIRE([HERWIG_CHECK_GSL]) AC_REQUIRE([HERWIG_CHECK_THEPEG]) AC_REQUIRE([BOOST_REQUIRE]) AC_REQUIRE([AX_COMPILER_VENDOR]) AM_CPPFLAGS="-I\$(top_builddir)/include $THEPEGINCLUDE \$(GSLINCLUDE) \$(BOOST_CPPFLAGS)" AC_MSG_CHECKING([for debugging mode]) AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[debug mode, use --enable-debug=slow for additional options that slow down the run.]), [], [enable_debug=no] ) AC_MSG_RESULT([$enable_debug]) if test "x$enable_debug" = "xno"; then debugflags="" else debugflags="-g" fi dnl -Wfloat-equal -fvisibility-inlines-hidden -Wctor-dtor-privacy -Weffc++ if test -n "$GCC"; then warnflags="-pedantic -Wall -Wextra -Wno-overloaded-virtual" if test "x$enable_debug" = "xslow"; then debugflags="$debugflags -fno-inline" AM_CPPFLAGS="$AM_CPPFLAGS -D_GLIBCXX_DEBUG" fi fi dnl do an actual capability check on ld instead of this workaround case "${host}" in *-darwin*) ;; *) AM_LDFLAGS="-Wl,--enable-new-dtags" ;; esac case "${ax_cv_cxx_compiler_vendor}" in gnu) AM_CXXFLAGS="-pedantic -Wall -W" ;; clang) AM_CXXFLAGS="-pedantic -Wall -Wno-overloaded-virtual -Wno-unused-function -Wno-unused-parameter" dnl -Wno-unneeded-internal-declaration ;; intel) AM_CXXFLAGS="-strict-ansi -Wall -wd13000,1418,981,444,383,1599,1572,2259,980" ;; esac AC_SUBST(AM_CPPFLAGS) AC_SUBST(AM_CFLAGS, ["$warnflags $debugflags"]) AC_SUBST(AM_CXXFLAGS,["$AM_CXXFLAGS $warnflags $debugflags"]) AC_SUBST(AM_FCFLAGS, ["$debugflags"]) AC_SUBST(AM_LDFLAGS) ]) AC_DEFUN([HERWIG_ENABLE_MODELS], [ AC_MSG_CHECKING([if BSM models should be built]) AC_ARG_ENABLE(models, AC_HELP_STRING([--disable-models],[Turn off compilation of BSM models.]), [], [enable_models=yes] ) AC_MSG_RESULT([$enable_models]) LOAD_BSM="" if test "$enable_models" = "yes"; then LOAD_BSM="read BSMlibs.in" fi AC_SUBST(LOAD_BSM) AM_CONDITIONAL(WANT_BSM,[test "$enable_models" = "yes"]) ]) AC_DEFUN([HERWIG_OVERVIEW], [ FCSTRING=`$FC --version | head -1` CXXSTRING=`$CXX --version | head -1` CCSTRING=`$CC --version | head -1` if test "x$PYTHON" != "x:" then python_was_found="yes, using Python $PYTHON_VERSION" else python_was_found="no, requires Python >= 2.6" fi cat << _HW_EOF_ > config.herwig ***************************************************** *** $PACKAGE_STRING configuration summary *** Please include this information in bug reports! ***-------------------------------------------------- *** Prefix: $prefix *** *** BSM models: $enable_models *** UFO converter: ${python_was_found} *** *** Herwig debug mode: $enable_debug *** *** ThePEG: $with_thepeg *** ThePEG headers: $with_thepeg_headers *** *** GoSam: $with_gosam *** GoSam-Contrib: $with_gosam_contrib *** MadGraph: $with_madgraph *** njet: $with_njet ${NJET_VERSION} *** OpenLoops: $with_openloops *** VBFNLO: $with_vbfnlo *** *** EvtGen: $with_evtgen *** GSL: $with_gsl *** boost: ${BOOST_CPPFLAGS:-system} *** Fastjet: ${fjconfig} *** *** Host: $host *** CC: $CCSTRING *** CXX: $CXXSTRING *** FC: $FCSTRING *** *** CXXFLAGS: $CXXFLAGS *** FCFLAGS: $FCFLAGS ***************************************************** _HW_EOF_ ])