Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:30:45

0001 //--- Note that the word "link" appearing in the C++ or comments in this class actually corresponds
0002 //--- to a pair of links in the hardware.
0003 
0004 #include "L1Trigger/TrackFindingTMTT/interface/MuxHToutputs.h"
0005 #include "L1Trigger/TrackFindingTMTT/interface/Settings.h"
0006 #include "L1Trigger/TrackFindingTMTT/interface/PrintL1trk.h"
0007 
0008 #include "FWCore/Utilities/interface/Exception.h"
0009 
0010 #include <sstream>
0011 #include <mutex>
0012 
0013 using namespace std;
0014 
0015 namespace tmtt {
0016 
0017   //=== Initialize constants from configuration parameters.
0018 
0019   MuxHToutputs::MuxHToutputs(const Settings* settings)
0020       : settings_(settings),
0021         muxOutputsHT_(static_cast<MuxAlgoName>(settings_->muxOutputsHT())),
0022         numPhiNonants_(settings_->numPhiNonants()),
0023         numPhiSectors_(settings_->numPhiSectors()),
0024         numPhiSecPerNon_(numPhiSectors_ / numPhiNonants_),
0025         numEtaRegions_(settings_->numEtaRegions()),
0026         busySectorKill_(settings_->busySectorKill()),          // Kill excess tracks flowing out of HT?
0027         busySectorNumStubs_(settings_->busySectorNumStubs()),  // Max. num. of stubs that can be sent within TM period
0028         busySectorMbinRanges_(
0029             settings_->busySectorMbinRanges()),  // Individual m bin (=q/Pt) ranges to be output to opto-links.
0030         busySectorUseMbinRanges_(not busySectorMbinRanges_.empty())  // m bin ranges option disabled if vector empty.
0031   {
0032     // Implemented MUX algorithm relies on same number of sectors per nonant.
0033     if (numPhiSectors_ % numPhiNonants_ != 0)
0034       throw cms::Exception("BadConfig")
0035           << "MuxHToutputs: Number of phi sectors is not a multiple of number of nonants!";
0036 
0037     if (!busySectorUseMbinRanges_)
0038       throw cms::Exception("BadConfig") << "MuxHToutputs: The implemented MUX algorithm requires you to be using the "
0039                                            "busySectorMbinRanges cfg option!";
0040 
0041     // Check that the MUX algorithm implemented in linkID() is not obviously wrong.
0042     this->sanityCheck();
0043 
0044     std::stringstream text;
0045     text << "=== The R-PHI HT output is multiplexed onto " << this->numLinksPerNonant()
0046          << " pairs of opto-links per nonant.";
0047     static std::once_flag printOnce;
0048     std::call_once(
0049         printOnce, [](string t) { PrintL1trk() << t; }, text.str());
0050   }
0051 
0052   //=== Determine which tracks are transmitted on each HT output optical link, taking into account the multiplexing
0053   //=== of multiple (eta,phi) sectors onto single links and the truncation of the tracks caused by the requirement
0054   //=== to output all the tracks within the time-multiplexed period.
0055   //=== This function replaces the 2D track collection in the r-phi HT with the subset surviving the TM cut.
0056 
0057   void MuxHToutputs::exec(Array2D<unique_ptr<HTrphi>>& mHtRphis) const {
0058     // As this loops over sectors in order of increasing sector number, this MUX algorithm always transmits tracks
0059     // from the lowest sector numbers on each link first. So the highest sector numbers are more likely to be
0060     // truncated by the TM period. The algorithm assumes that two or more m-bin ranges from the same sector will never
0061     // be transmitted down the same link, as if this happens, it does not predict the order in which they will be
0062     // transmitted.
0063 
0064     for (unsigned int iPhiNon = 0; iPhiNon < numPhiNonants_; iPhiNon++) {
0065       vector<unsigned int> numStubsPerLink(this->numLinksPerNonant(), 0);
0066 
0067       for (unsigned int iSecInNon = 0; iSecInNon < numPhiSecPerNon_; iSecInNon++) {
0068         unsigned int iPhiSec = iPhiNon * numPhiSecPerNon_ + iSecInNon;
0069 
0070         for (unsigned int iEtaReg = 0; iEtaReg < numEtaRegions_; iEtaReg++) {
0071           HTrphi* htRphi = mHtRphis(iPhiSec, iEtaReg).get();  // Get a mutable version of the r-phi HT.
0072 
0073           list<L1track2D> keptTracks;
0074           const list<L1track2D>& tracks = htRphi->trackCands2D();
0075 
0076           for (const L1track2D& trk : tracks) {
0077             L1track2D trkTmp = trk;
0078             unsigned int nStubs = trkTmp.numStubs();                // #stubs on this track.
0079             unsigned int mBinRange = htRphi->getMbinRange(trkTmp);  // Which m bin range is this track in?
0080             // Get the output optical link corresponding to this sector & m-bin range.
0081             unsigned int link = this->linkID(iSecInNon, iEtaReg, mBinRange);
0082             // Make a note of opto-link number inside track object.
0083             trkTmp.setOptoLinkID(link);
0084 
0085             numStubsPerLink[link] += nStubs;
0086             // Check if this track can be output within the time-multiplexed period.
0087             bool keep = ((not busySectorKill_) || (numStubsPerLink[link] <= busySectorNumStubs_));
0088             // FIX: with 2 GeV threshold, this causes significant truncation.
0089             // Consider using one output link for each phi sector in nonant
0090             if (keep)
0091               keptTracks.push_back(trkTmp);
0092           }
0093 
0094           // Replace the collection of 2D tracks in the r-phi HT with the subset of them surviving the TM cut.
0095           htRphi->replaceTrackCands2D(keptTracks);
0096         }
0097       }
0098     }
0099   }
0100 
0101   //=== Define the number of (eta,phi) sectors that each output opto-link takes tracks from. (Depends on MUX scheme).
0102 
0103   unsigned int MuxHToutputs::muxFactor() const {
0104     if (muxOutputsHT_ == MuxAlgoName::mBinPerLink) {
0105       return numEtaRegions_ * numPhiSecPerNon_;
0106     } else {
0107       throw cms::Exception("BadConfig") << "MuxHToutputs: Unknown MuxOutputsHT configuration option!";
0108     }
0109   }
0110 
0111   //=== Define the MUX algorithm by which tracks from the specified m-bin range in the HT for a given (phi,eta)
0112   //=== sector within a phi nonant are multiplexed onto a single output optical link.
0113 
0114   unsigned int MuxHToutputs::linkID(unsigned int iSecInNon, unsigned int iEtaReg, unsigned int mBinRange) const {
0115     unsigned int link;
0116 
0117     if (muxOutputsHT_ == MuxAlgoName::mBinPerLink) {
0118       //--- This is the Sept. 2019 Mux for the transverse HT readout organised by m-bin. (Each m bin in entire nonant goes to a different link).
0119 
0120       link = 0;
0121       link += mBinRange;
0122 
0123     } else {
0124       throw cms::Exception("BadConfig") << "MuxHToutputs: Unknown MuxOutputsHT configuration option!";
0125     }
0126 
0127     if (link >= this->numLinksPerNonant())
0128       throw cms::Exception("LogicError") << "MuxHToutputs: Calculated link ID exceeded expected number of links! "
0129                                          << link << " " << this->numLinksPerNonant();
0130     return link;
0131   }
0132 
0133   //=== Do sanity check of the MUX algorithm implemented in linkID().
0134 
0135   void MuxHToutputs::sanityCheck() {
0136     if (numPhiSecPerNon_ * numEtaRegions_ % this->muxFactor() != 0)
0137       throw cms::Exception("LogicError")
0138           << "MuxHToutputs: Number of sectors per phi nonant is not a multiple of muxFactor().";
0139 
0140     vector<unsigned int> nObsElementsPerLink(this->numLinksPerNonant(), 0);
0141     for (unsigned int iSecInNon = 0; iSecInNon < numPhiSecPerNon_; iSecInNon++) {
0142       for (unsigned int iEtaReg = 0; iEtaReg < numEtaRegions_; iEtaReg++) {
0143         unsigned int iCorr = (settings_->miniHTstage()) ? 1 : 0;
0144         for (unsigned int mBinRange = 0; mBinRange < busySectorMbinRanges_.size() - iCorr; mBinRange++) {
0145           unsigned int link = this->linkID(iSecInNon, iEtaReg, mBinRange);
0146           nObsElementsPerLink[link] += 1;
0147         }
0148       }
0149     }
0150   }
0151 
0152 }  // namespace tmtt