Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:51

0001 #include "L1Trigger/TrackFindingTMTT/interface/MiniHTstage.h"
0002 #include "L1Trigger/TrackFindingTMTT/interface/Settings.h"
0003 #include "L1Trigger/TrackFindingTMTT/interface/Sector.h"
0004 
0005 using namespace std;
0006 
0007 namespace tmtt {
0008 
0009   MiniHTstage::MiniHTstage(const Settings* settings)
0010       : settings_(settings),
0011         miniHTstage_(settings_->miniHTstage()),
0012         muxOutputsHT_(static_cast<MuxHToutputs::MuxAlgoName>(settings_->muxOutputsHT())),
0013         houghNbinsPt_(settings_->houghNbinsPt()),
0014         houghNbinsPhi_(settings_->houghNbinsPhi()),
0015         miniHoughLoadBalance_(settings_->miniHoughLoadBalance()),
0016         miniHoughNbinsPt_(settings_->miniHoughNbinsPt()),
0017         miniHoughNbinsPhi_(settings_->miniHoughNbinsPhi()),
0018         miniHoughMinPt_(settings_->miniHoughMinPt()),
0019         miniHoughDontKill_(settings_->miniHoughDontKill()),
0020         miniHoughDontKillMinPt_(settings_->miniHoughDontKillMinPt()),
0021         numSubSecsEta_(settings_->numSubSecsEta()),
0022         numPhiNonants_(settings_->numPhiNonants()),
0023         numPhiSecPerNon_(settings_->numPhiSectors() / numPhiNonants_),
0024         numEtaRegions_(settings_->numEtaRegions()),
0025         busySectorKill_(settings_->busySectorKill()),
0026         busySectorNumStubs_(settings_->busySectorNumStubs()),
0027         busySectorMbinRanges_(settings_->busySectorMbinRanges()),
0028         chosenRofPhi_(settings_->chosenRofPhi()),
0029         // Get size of 1st stage HT cells.
0030         binSizeQoverPtAxis_(miniHoughNbinsPt_ * 2. / (float)settings->houghMinPt() / (float)houghNbinsPt_),
0031         binSizePhiTrkAxis_(miniHoughNbinsPhi_ * 2. * M_PI / (float)settings->numPhiSectors() / (float)houghNbinsPhi_),
0032         invPtToDphi_(settings_->invPtToDphi()),
0033         nHTlinksPerNonant_(0) {
0034     nMiniHTcells_ = miniHoughNbinsPt_ * miniHoughNbinsPhi_;
0035 
0036     if (miniHoughLoadBalance_ != 0) {
0037       if (muxOutputsHT_ == MuxHToutputs::MuxAlgoName::mBinPerLink) {  // Multiplexer at output of HT enabled.
0038         nHTlinksPerNonant_ = busySectorMbinRanges_.size() - 1;
0039       } else {
0040         throw cms::Exception("BadConfig") << "MiniHTstage: Unknown MuxOutputsHT configuration option!";
0041       }
0042     }
0043   }
0044 
0045   void MiniHTstage::exec(Array2D<unique_ptr<HTrphi>>& mHtRphis) {
0046     for (unsigned int iPhiNon = 0; iPhiNon < numPhiNonants_; iPhiNon++) {
0047       // Indices are ([link ID, MHT cell], #stubs).
0048       map<pair<unsigned int, unsigned int>, unsigned int> numStubsPerLinkStage1;
0049       // Indices are ([link ID, MHT cell], #stubs).
0050       map<pair<unsigned int, unsigned int>, unsigned int> numStubsPerLinkStage2;
0051       // Indices are (link ID, #stubs).
0052       map<unsigned int, unsigned int> numStubsPerLink;
0053       for (unsigned int iSecInNon = 0; iSecInNon < numPhiSecPerNon_; iSecInNon++) {
0054         unsigned int iPhiSec = iPhiNon * numPhiSecPerNon_ + iSecInNon;
0055         for (unsigned int iEtaReg = 0; iEtaReg < numEtaRegions_; iEtaReg++) {
0056           Sector sector(settings_, iPhiSec, iEtaReg);
0057           const float& phiCentre = sector.phiCentre();
0058           HTrphi* htRphi = mHtRphis(iPhiSec, iEtaReg).get();
0059           const list<L1track2D>& roughTracks = htRphi->trackCands2D();
0060           list<L1track2D> fineTracks;
0061 
0062           for (const L1track2D& roughTrk : roughTracks) {
0063             float roughTrkPhi =
0064                 reco::deltaPhi(roughTrk.phi0() - chosenRofPhi_ * invPtToDphi_ * roughTrk.qOverPt() - phiCentre, 0.);
0065             const pair<unsigned int, unsigned int>& cell = roughTrk.cellLocationHT();
0066             const vector<Stub*>& stubs = roughTrk.stubs();
0067             bool fineTrksFound = false;
0068             bool storeCoarseTrack = false;
0069             const unsigned int& link = roughTrk.optoLinkID();
0070 
0071             if (std::abs(roughTrk.qOverPt()) <
0072                 1. / miniHoughMinPt_) {  // Not worth using mini-HT at low Pt due to scattering.
0073 
0074               for (unsigned int mBin = 0; mBin < miniHoughNbinsPt_; mBin++) {
0075                 float qOverPtBin = roughTrk.qOverPt() - binSizeQoverPtAxis_ / 2. +
0076                                    (mBin + .5) * binSizeQoverPtAxis_ / settings_->miniHoughNbinsPt();
0077                 for (unsigned int cBin = 0; cBin < miniHoughNbinsPhi_; cBin++) {
0078                   float phiBin = reco::deltaPhi(roughTrkPhi - binSizePhiTrkAxis_ / 2. +
0079                                                     (cBin + .5) * binSizePhiTrkAxis_ / settings_->miniHoughNbinsPhi(),
0080                                                 0.);
0081                   const bool mergedCell = false;  // This represents mini cell.
0082                   const bool miniHTcell = true;
0083                   HTcell htCell(settings_,
0084                                 iPhiSec,
0085                                 iEtaReg,
0086                                 sector.etaMin(),
0087                                 sector.etaMax(),
0088                                 qOverPtBin,
0089                                 cell.first + mBin,
0090                                 mergedCell,
0091                                 miniHTcell);
0092                   // Firmware doesn't use bend filter in MHT.
0093                   htCell.disableBendFilter();
0094 
0095                   for (auto& stub : stubs) {
0096                     // Ensure stubs are digitized with respect to the current phi sector.
0097                     if (settings_->enableDigitize())
0098                       stub->digitize(iPhiSec, Stub::DigiStage::HT);
0099                     float phiStub = reco::deltaPhi(
0100                         stub->phi() + invPtToDphi_ * qOverPtBin * (stub->r() - chosenRofPhi_) - phiCentre, 0.);
0101                     float dPhi = reco::deltaPhi(phiBin - phiStub, 0.);
0102                     float dPhiMax = binSizePhiTrkAxis_ / miniHoughNbinsPhi_ / 2. +
0103                                     invPtToDphi_ * binSizeQoverPtAxis_ / (float)miniHoughNbinsPt_ *
0104                                         std::abs(stub->r() - chosenRofPhi_) / 2.;
0105                     if (std::abs(dPhi) <= std::abs(reco::deltaPhi(dPhiMax, 0.)))
0106                       htCell.store(stub, sector.insideEtaSubSecs(stub));
0107                   }
0108                   htCell.end();
0109                   if (htCell.trackCandFound()) {
0110                     // Do load balancing.
0111                     unsigned int trueLinkID = linkIDLoadBalanced(
0112                         link, mBin, cBin, htCell.numStubs(), numStubsPerLinkStage1, numStubsPerLinkStage2);
0113 
0114                     pair<unsigned int, unsigned int> cellLocation(cell.first + mBin, cell.second + cBin);
0115                     pair<float, float> helix2D(
0116                         qOverPtBin, reco::deltaPhi(phiBin + chosenRofPhi_ * invPtToDphi_ * qOverPtBin + phiCentre, 0.));
0117                     L1track2D fineTrk(
0118                         settings_, htCell.stubs(), cellLocation, helix2D, iPhiSec, iEtaReg, trueLinkID, mergedCell);
0119                     // Truncation due to output opto-link bandwidth.
0120                     bool keep(true);
0121                     numStubsPerLink[trueLinkID] += htCell.numStubs();
0122                     if (busySectorKill_ && numStubsPerLink[trueLinkID] > busySectorNumStubs_)
0123                       keep = false;
0124                     if (keep) {
0125                       fineTracks.push_back(fineTrk);
0126                       fineTrksFound = true;
0127                     }
0128                   }
0129                 }
0130               }
0131 
0132             } else {
0133               // Keep rough track if below Pt threshold where mini-HT in use.
0134               storeCoarseTrack = true;
0135             }
0136 
0137             if (storeCoarseTrack || ((not fineTrksFound) && miniHoughDontKill_ &&
0138                                      std::abs(roughTrk.qOverPt()) < 1. / miniHoughDontKillMinPt_)) {
0139               // Keeping original track instead of mini-HTtracks.
0140               // Invent dummy miniHT cells so as to be able to reuse load balancing, trying all combinations to identify the least used link.
0141               pair<unsigned int, unsigned int> bestCell = {0, 0};
0142               unsigned int bestNumStubsPerLink = 999999;
0143               for (unsigned int mBin = 0; mBin < miniHoughNbinsPt_; mBin++) {
0144                 for (unsigned int cBin = 0; cBin < miniHoughNbinsPhi_; cBin++) {
0145                   unsigned int testLinkID = linkIDLoadBalanced(
0146                       link, mBin, cBin, roughTrk.numStubs(), numStubsPerLinkStage1, numStubsPerLinkStage2, true);
0147                   if (numStubsPerLink[testLinkID] < bestNumStubsPerLink) {
0148                     bestCell = {mBin, cBin};
0149                     bestNumStubsPerLink = numStubsPerLink[testLinkID];
0150                   }
0151                 }
0152               }
0153 
0154               // Repeat for best link, this time incremementing stub counters.
0155               unsigned int trueLinkID = linkIDLoadBalanced(link,
0156                                                            bestCell.first,
0157                                                            bestCell.second,
0158                                                            roughTrk.numStubs(),
0159                                                            numStubsPerLinkStage1,
0160                                                            numStubsPerLinkStage2);
0161 
0162               bool keep(true);
0163               numStubsPerLink[trueLinkID] += roughTrk.numStubs();
0164               if (busySectorKill_ && numStubsPerLink[trueLinkID] > busySectorNumStubs_)
0165                 keep = false;
0166               if (keep) {
0167                 fineTracks.push_back(roughTrk);
0168                 fineTracks.back().setOptoLinkID(trueLinkID);
0169               }
0170             }
0171           }
0172           // Replace all existing tracks inside HT array with new ones.
0173           htRphi->replaceTrackCands2D(fineTracks);
0174         }
0175       }
0176     }
0177   }
0178 
0179   //=== Do load balancing
0180   //=== (numStubs is stubs on this track, "link" is link ID before load balancing, and return argument is link ID after load balancing).
0181   //=== (numStubsPerLinkStage* are stub counters per link used to determine best balance. If test=true, then these counters are not to be incrememented).
0182 
0183   unsigned int MiniHTstage::linkIDLoadBalanced(
0184       unsigned int link,
0185       unsigned int mBin,
0186       unsigned int cBin,
0187       unsigned int numStubs,
0188       // Indices are ([link ID, MHT cell], #stubs).
0189       map<pair<unsigned int, unsigned int>, unsigned int>& numStubsPerLinkStage1,
0190       // Indices are ([link ID, MHT cell], #stubs).
0191       map<pair<unsigned int, unsigned int>, unsigned int>& numStubsPerLinkStage2,
0192       bool test) const {
0193     unsigned int mhtCell = miniHoughNbinsPhi_ * mBin + cBin;  // Send each mini-cell to a different output link
0194 
0195     // Number of output links after static load balancing roughly same as number of
0196     // input links with this, with nSep per MHT cell.
0197     unsigned int nSep = std::ceil(float(nHTlinksPerNonant_) / float(nMiniHTcells_));
0198 
0199     unsigned int newLink, newerLink, newererLink;
0200 
0201     enum LoadBalancing { None = 0, Static = 1, Dynamic = 2 };  // Load balancing options
0202 
0203     if (miniHoughLoadBalance_ >= LoadBalancing::Static) {
0204       // Static load balancing, 4 -> 1, with each MHT cell sent to seperate output link.
0205       newLink = link % nSep;  // newLink in range 0 to nSep-1.
0206     } else {
0207       newLink = link;
0208     }
0209 
0210     if (miniHoughLoadBalance_ >= LoadBalancing::Dynamic) {
0211       // 2-stage dynamic load balancing amongst links corresponding to same MHT cell.
0212 
0213       // Dynamically mix pairs of neighbouring links.
0214       unsigned int balancedLinkA = 2 * (newLink / 2);
0215       unsigned int balancedLinkB = balancedLinkA + 1;
0216 
0217       pair<unsigned int, unsigned int> encodedLinkA(balancedLinkA,
0218                                                     mhtCell);  // balancedLink* here in range 0 to nSep-1.
0219       pair<unsigned int, unsigned int> encodedLinkB(balancedLinkB, mhtCell);
0220       if (numStubsPerLinkStage1[encodedLinkA] < numStubsPerLinkStage1[encodedLinkB]) {
0221         newerLink = balancedLinkA;
0222       } else {
0223         newerLink = balancedLinkB;
0224       }
0225       pair<unsigned int, unsigned int> encodedLinkAB(newerLink, mhtCell);
0226       if (not test)
0227         numStubsPerLinkStage1[encodedLinkAB] += numStubs;
0228 
0229       // Dynamically mix pairs of next-to-neighbouring links.
0230       unsigned int balancedLinkY = newerLink;
0231       unsigned int balancedLinkZ = (newerLink + 2) % nSep;
0232 
0233       pair<unsigned int, unsigned int> encodedLinkY(balancedLinkY, mhtCell);
0234       pair<unsigned int, unsigned int> encodedLinkZ(balancedLinkZ, mhtCell);
0235       if (numStubsPerLinkStage2[encodedLinkY] < numStubsPerLinkStage2[encodedLinkZ]) {
0236         newererLink = balancedLinkY;
0237       } else {
0238         newererLink = balancedLinkZ;
0239       }
0240       pair<unsigned int, unsigned int> encodedLinkYZ(newererLink, mhtCell);
0241       if (not test)
0242         numStubsPerLinkStage2[encodedLinkYZ] += numStubs;
0243 
0244     } else {
0245       newererLink = newLink;
0246     }
0247     unsigned int trueLinkID =
0248         (miniHoughLoadBalance_ != LoadBalancing::None) ? nMiniHTcells_ * newererLink + mhtCell : newererLink;
0249     return trueLinkID;
0250   }
0251 
0252 }  // namespace tmtt