Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-28 07:45:42

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Seeding2/GbtsGeometry.hpp"
0010 
0011 #include "Acts/Utilities/MathHelpers.hpp"
0012 
0013 #include <algorithm>
0014 #include <cmath>
0015 #include <cstring>
0016 #include <iostream>
0017 
0018 namespace Acts::Experimental {
0019 
0020 GbtsLayer::GbtsLayer(const GbtsLayerDescription& layerDescription,
0021                      const float etaBinWidth, const std::int32_t bin0)
0022     : m_layerDescription(layerDescription) {
0023   if (m_layerDescription.type == GbtsLayerType::Barrel) {
0024     m_r1 = m_layerDescription.refCoord;
0025     m_r2 = m_layerDescription.refCoord;
0026     m_z1 = m_layerDescription.minBound;
0027     m_z2 = m_layerDescription.maxBound;
0028   } else if (m_layerDescription.type == GbtsLayerType::Endcap) {
0029     m_r1 = m_layerDescription.minBound;
0030     m_r2 = m_layerDescription.maxBound;
0031     m_z1 = m_layerDescription.refCoord;
0032     m_z2 = m_layerDescription.refCoord;
0033   } else {
0034     throw std::runtime_error("invalid layer type");
0035   }
0036 
0037   const float t1 = m_z1 / m_r1;
0038   const float eta1 = -std::log(fastHypot(1, t1) - t1);
0039 
0040   const float t2 = m_z2 / m_r2;
0041   const float eta2 = -std::log(fastHypot(1, t2) - t2);
0042 
0043   m_minEta = eta1;
0044   m_maxEta = eta2;
0045 
0046   if (m_maxEta < m_minEta) {
0047     m_minEta = eta2;
0048     m_maxEta = eta1;
0049   }
0050 
0051   // increasing them slightly to avoid range_check exceptions
0052   m_maxEta += 1e-6;
0053   m_minEta -= 1e-6;
0054 
0055   const float deltaEta = m_maxEta - m_minEta;
0056 
0057   std::uint32_t binCounter = bin0;
0058 
0059   if (deltaEta < etaBinWidth) {
0060     m_nBins = 1;
0061     m_bins.push_back(binCounter++);
0062     m_etaBin = deltaEta;
0063     if (m_layerDescription.type == GbtsLayerType::Barrel) {
0064       m_minRadius.push_back(m_layerDescription.refCoord - 2.0f);
0065       m_maxRadius.push_back(m_layerDescription.refCoord + 2.0f);
0066       m_minBinCoord.push_back(m_layerDescription.minBound);
0067       m_maxBinCoord.push_back(m_layerDescription.maxBound);
0068     } else if (m_layerDescription.type == GbtsLayerType::Endcap) {
0069       m_minRadius.push_back(m_layerDescription.minBound - 2.0f);
0070       m_maxRadius.push_back(m_layerDescription.maxBound + 2.0f);
0071       m_minBinCoord.push_back(m_layerDescription.minBound);
0072       m_maxBinCoord.push_back(m_layerDescription.maxBound);
0073     } else {
0074       throw std::runtime_error("invalid layer type");
0075     }
0076   } else {
0077     const auto nB = static_cast<std::uint32_t>(deltaEta / etaBinWidth);
0078     m_nBins = nB;
0079     if (deltaEta - etaBinWidth * nB > 0.5f * etaBinWidth) {
0080       m_nBins++;
0081     }
0082 
0083     m_etaBin = deltaEta / m_nBins;
0084 
0085     if (m_nBins == 1) {
0086       m_bins.push_back(binCounter++);
0087       if (m_layerDescription.type == GbtsLayerType::Barrel) {
0088         m_minRadius.push_back(m_layerDescription.refCoord - 2.0f);
0089         m_maxRadius.push_back(m_layerDescription.refCoord + 2.0f);
0090         m_minBinCoord.push_back(m_layerDescription.minBound);
0091         m_maxBinCoord.push_back(m_layerDescription.maxBound);
0092       } else if (m_layerDescription.type == GbtsLayerType::Endcap) {
0093         m_minRadius.push_back(m_layerDescription.minBound - 2.0f);
0094         m_maxRadius.push_back(m_layerDescription.maxBound + 2.0f);
0095         m_minBinCoord.push_back(m_layerDescription.minBound);
0096         m_maxBinCoord.push_back(m_layerDescription.maxBound);
0097       } else {
0098         throw std::runtime_error("invalid layer type");
0099       }
0100     } else {
0101       float eta = m_minEta + 0.5f * m_etaBin;
0102 
0103       for (std::uint32_t i = 1; i <= m_nBins; ++i) {
0104         m_bins.push_back(binCounter++);
0105 
0106         float e1 = eta - 0.5f * m_etaBin;
0107         float e2 = eta + 0.5f * m_etaBin;
0108 
0109         if (m_layerDescription.type == GbtsLayerType::Barrel) {
0110           m_minRadius.push_back(m_layerDescription.refCoord - 2.0f);
0111           m_maxRadius.push_back(m_layerDescription.refCoord + 2.0f);
0112           const float z1 = m_layerDescription.refCoord * std::sinh(e1);
0113           m_minBinCoord.push_back(z1);
0114           const float z2 = m_layerDescription.refCoord * std::sinh(e2);
0115           m_maxBinCoord.push_back(z2);
0116         } else if (m_layerDescription.type == GbtsLayerType::Endcap) {
0117           // for the positive endcap larger eta corresponds to smaller radius
0118           if (m_layerDescription.refCoord > 0) {
0119             std::swap(e1, e2);
0120           }
0121           float r = m_layerDescription.refCoord / std::sinh(e1);
0122           m_minBinCoord.push_back(r);
0123           m_minRadius.push_back(r - 2.0f);
0124           r = m_layerDescription.refCoord / std::sinh(e2);
0125           m_maxBinCoord.push_back(r);
0126           m_maxRadius.push_back(r + 2.0f);
0127         } else {
0128           throw std::runtime_error("invalid layer type");
0129         }
0130 
0131         eta += m_etaBin;
0132       }
0133     }
0134   }
0135 }
0136 
0137 bool GbtsLayer::checkCompatibility(const GbtsLayer& otherLayer,
0138                                    const std::uint32_t b1,
0139                                    const std::uint32_t b2, const float minZ0,
0140                                    const float maxZ0) const {
0141   const float z1min = m_minBinCoord.at(b1);
0142   const float z1max = m_maxBinCoord.at(b1);
0143   const float r1 = m_layerDescription.refCoord;
0144 
0145   const float tol = 5.0f;
0146 
0147   if (m_layerDescription.type == GbtsLayerType::Barrel &&
0148       otherLayer.m_layerDescription.type == GbtsLayerType::Barrel) {
0149     const float minB2 = otherLayer.m_minBinCoord.at(b2);
0150     const float maxB2 = otherLayer.m_maxBinCoord.at(b2);
0151 
0152     const float r2 = otherLayer.m_layerDescription.refCoord;
0153 
0154     const float A = r2 / (r2 - r1);
0155     const float B = r1 / (r2 - r1);
0156 
0157     const float z0Min = z1min * A - maxB2 * B;
0158     const float z0Max = z1max * A - minB2 * B;
0159 
0160     if (z0Max < minZ0 - tol || z0Min > maxZ0 + tol) {
0161       return false;
0162     }
0163 
0164     return true;
0165   }
0166 
0167   if (m_layerDescription.type == GbtsLayerType::Barrel &&
0168       otherLayer.m_layerDescription.type == GbtsLayerType::Endcap) {
0169     const float z2 = otherLayer.m_layerDescription.refCoord;
0170     const float r2max = otherLayer.m_maxBinCoord.at(b2);
0171     float r2min = otherLayer.m_minBinCoord.at(b2);
0172 
0173     if (r2max <= r1) {
0174       return false;
0175     }
0176 
0177     if (r2min <= r1) {
0178       r2min = r1 + 1e-3f;
0179     }
0180 
0181     float z0Max = 0;
0182     float z0Min = 0;
0183 
0184     if (z2 > 0) {
0185       z0Max = (z1max * r2max - z2 * r1) / (r2max - r1);
0186       z0Min = (z1min * r2min - z2 * r1) / (r2min - r1);
0187     } else {
0188       z0Max = (z1max * r2min - z2 * r1) / (r2min - r1);
0189       z0Min = (z1min * r2max - z2 * r1) / (r2max - r1);
0190     }
0191 
0192     if (z0Max < minZ0 - tol || z0Min > maxZ0 + tol) {
0193       return false;
0194     }
0195     return true;
0196   }
0197 
0198   if (m_layerDescription.type == GbtsLayerType::Endcap &&
0199       otherLayer.m_layerDescription.type == GbtsLayerType::Endcap) {
0200     const float z2 = otherLayer.m_layerDescription.refCoord;
0201     const float z1 = m_layerDescription.refCoord;
0202     const float r2max = otherLayer.m_maxBinCoord.at(b2);
0203     const float r2min = otherLayer.m_minBinCoord.at(b2);
0204     const float r1max = m_maxBinCoord.at(b1);
0205     const float r1min = m_minBinCoord.at(b1);
0206 
0207     if (r1min >= r2max) {
0208       return false;
0209     }
0210 
0211     if (z2 > 0) {  // positive endcap
0212 
0213       const float z0Max = z1 - r1min * (z2 - z1) / (r2max - r1min);
0214 
0215       if (z0Max < minZ0 - tol) {
0216         return false;
0217       }
0218 
0219       if (r2min > r1max) {
0220         const float z0Min = z1 - r1max * (z2 - z1) / (r2min - r1max);
0221 
0222         if (z0Min > maxZ0 + tol) {
0223           return false;
0224         }
0225       }
0226     } else {  // negative endcap
0227       const float z0Min = z1 - r1min * (z2 - z1) / (r2max - r1min);
0228 
0229       if (z0Min > maxZ0 + tol) {
0230         return false;
0231       }
0232 
0233       if (r2min > r1max) {
0234         const float z0Max = z1 - r1max * (z2 - z1) / (r2min - r1max);
0235 
0236         if (z0Max < minZ0 - tol) {
0237           return false;
0238         }
0239       }
0240     }
0241     return true;
0242   }
0243 
0244   if (m_layerDescription.type == GbtsLayerType::Endcap &&
0245       otherLayer.m_layerDescription.type == GbtsLayerType::Barrel) {
0246     const float z1 = m_layerDescription.refCoord;
0247     const float r1max = m_maxBinCoord.at(b1);
0248     const float r1min = m_minBinCoord.at(b1);
0249 
0250     const float z2min = otherLayer.m_minBinCoord.at(b2);
0251     const float z2max = otherLayer.m_maxBinCoord.at(b2);
0252     const float r2 = otherLayer.m_layerDescription.refCoord;
0253 
0254     if (r2 < r1min) {
0255       return false;
0256     }
0257 
0258     // interval 1
0259 
0260     float z0Min = z1 - (z2max - z1) / (r2 / r1max - 1);
0261     float z0Max = z1 - (z2max - z1) / (r2 / r1min - 1);
0262 
0263     if (z0Min > z0Max) {
0264       std::swap(z0Min, z0Max);
0265     }
0266 
0267     bool beyondRange = (z0Max < minZ0 - tol || z0Min > maxZ0 + tol);
0268 
0269     if (!beyondRange) {
0270       return true;
0271     }
0272 
0273     // interval 2
0274 
0275     z0Min = z1 - (z2min - z1) / (r2 / r1max - 1);
0276     z0Max = z1 - (z2min - z1) / (r2 / r1min - 1);
0277 
0278     if (z0Min > z0Max) {
0279       std::swap(z0Min, z0Max);
0280     }
0281 
0282     beyondRange = (z0Max < minZ0 - tol || z0Min > maxZ0 + tol);
0283 
0284     if (!beyondRange) {
0285       return true;
0286     }
0287 
0288     return false;
0289   }
0290 
0291   return true;
0292 }
0293 
0294 std::int32_t GbtsLayer::getEtaBin(const float zh, const float rh) const {
0295   if (m_bins.size() == 1) {
0296     return m_bins.at(0);
0297   }
0298 
0299   const float t1 = zh / rh;
0300   const float eta = -std::log(fastHypot(1, t1) - t1);
0301 
0302   std::int32_t idx = static_cast<std::int32_t>((eta - m_minEta) / m_etaBin);
0303   if (idx < 0) {
0304     idx = 0;
0305   } else if (idx >= static_cast<std::int32_t>(m_bins.size())) {
0306     idx = static_cast<std::int32_t>(m_bins.size()) - 1;
0307   }
0308 
0309   // index in the global storage
0310   return m_bins.at(idx);
0311 }
0312 
0313 GbtsGeometry::GbtsGeometry(
0314     const std::vector<GbtsLayerDescription>& layerDescriptions,
0315     const GbtsLayerConnectionMap& layerConnections)
0316     : m_etaBinWidth(layerConnections.etaBinWidth) {
0317   // TODO configurable z0 range
0318   const float minZ0 = -168.0f;
0319   const float maxZ0 = 168.0f;
0320 
0321   for (const GbtsLayerDescription& layer : layerDescriptions) {
0322     const GbtsLayer& pL = createLayer(layer, m_nEtaBins);
0323     m_nEtaBins += pL.numOfBins();
0324   }
0325 
0326   // calculating bin tables in the connector...
0327   // calculate bin pairs for graph edge building
0328 
0329   std::int32_t lastBin1 = -1;
0330 
0331   for (const auto& [layer, vConn] : layerConnections.connectionMap) {
0332     for (const auto& connection : vConn) {
0333       const std::uint32_t src = connection->src;  // n2 : the new connectors
0334       const std::uint32_t dst = connection->dst;  // n1
0335 
0336       const GbtsLayer* pL1 = layerById(dst);
0337       const GbtsLayer* pL2 = layerById(src);
0338       if (pL1 == nullptr) {
0339         std::cout << " skipping invalid dst layer " << dst << std::endl;
0340         continue;
0341       }
0342       if (pL2 == nullptr) {
0343         std::cout << " skipping invalid src layer " << src << std::endl;
0344         continue;
0345       }
0346 
0347       const std::uint32_t nSrcBins = pL2->numOfBins();
0348       const std::uint32_t nDstBins = pL1->numOfBins();
0349 
0350       connection->binTable.resize(nSrcBins * nDstBins, 0);
0351       // loop over bins in Layer 1
0352       for (std::uint32_t b1 = 0; b1 < nDstBins; ++b1) {
0353         // loop over bins in Layer 2
0354         for (std::uint32_t b2 = 0; b2 < nSrcBins; ++b2) {
0355           if (!pL1->checkCompatibility(*pL2, b1, b2, minZ0, maxZ0)) {
0356             continue;
0357           }
0358           const std::uint32_t address = b1 + b2 * nDstBins;
0359           connection->binTable.at(address) = 1;
0360 
0361           const std::int32_t bin1Idx = pL1->bins().at(b1);
0362           const std::int32_t bin2Idx = pL2->bins().at(b2);
0363 
0364           if (bin1Idx != lastBin1) {
0365             // adding a new group
0366             m_binGroups.emplace_back(bin1Idx,
0367                                      std::vector<std::uint32_t>(1, bin2Idx));
0368             lastBin1 = bin1Idx;
0369           } else {
0370             // extend the last group
0371             m_binGroups.back().second.push_back(bin2Idx);
0372           }
0373         }
0374       }
0375     }
0376   }
0377   // find stages of eta-bin pairs using the graph ablation algorithm
0378 
0379   BinConnections binMap;
0380 
0381   // 1. create a map of bin-to-bin connections
0382 
0383   // initialize with empty links
0384 
0385   for (const auto& [bin1, bin2s] : m_binGroups) {
0386     // add to the map
0387 
0388     auto& bin1Links = binMap[bin1];
0389 
0390     for (const auto& bin2 : bin2s) {
0391       auto& bin2Links = binMap[bin2];
0392 
0393       bin1Links.second.push_back(bin2);  // incoming link bin1 <- bin2
0394       bin2Links.first.push_back(bin1);   // outgoing link bin2 -> bin1
0395     }
0396   }
0397 
0398   // copy bin map as original is still needed
0399   const BinConnections originalBinMap = binMap;
0400 
0401   // 2. find stages starting from the last one (i.e. bin1 with no outgoing
0402   // connections)
0403 
0404   // data for all stages
0405   std::vector<std::uint32_t> stageData;
0406   // defines the start and end of stage contents
0407   std::vector<std::size_t> stageOffsets;
0408 
0409   stageOffsets.reserve(51);  // 50 stages -> offsets needs +1
0410   stageOffsets.push_back(0);
0411 
0412   std::vector<std::uint32_t> exitBins;
0413   while (!binMap.empty()) {
0414     exitBins.clear();
0415 
0416     // 2a. find all bins with zero outgoing links
0417 
0418     for (const auto& bl : binMap) {
0419       auto& binLinks = bl.second;
0420       auto& outLinks = binLinks.first;
0421 
0422       if (!outLinks.empty()) {
0423         continue;
0424       }
0425 
0426       exitBins.push_back(bl.first);
0427     }
0428 
0429     // order exit bins (important for graph building)
0430     std::sort(exitBins.begin(), exitBins.end());
0431 
0432     // 2b. add a new stage: vector of bin1
0433 
0434     stageData.insert(stageData.end(), exitBins.begin(), exitBins.end());
0435     stageOffsets.push_back(stageData.size());
0436 
0437     // 2c. remove links : graph ablation
0438 
0439     for (const std::uint32_t& bin1Key : exitBins) {
0440       auto p1 = binMap.find(bin1Key);
0441       if (p1 == binMap.end()) {
0442         continue;
0443       }
0444       auto& bin1Links = p1->second;
0445 
0446       for (const std::uint32_t bin2Key : bin1Links.second) {
0447         const auto p2 = binMap.find(bin2Key);
0448         if (p2 == binMap.end()) {
0449           continue;
0450         }
0451 
0452         auto& binLinks = p2->second;
0453         std::vector<std::uint32_t>& links = binLinks.first;
0454 
0455         std::erase(links, bin1Key);
0456       }
0457     }
0458 
0459     // 2d. finally, remove all exit bin1s from the map
0460 
0461     for (auto bin1Key : exitBins) {
0462       binMap.erase(bin1Key);
0463     }
0464   }
0465 
0466   // 3. Refill binGroups with staged bin pair collections.
0467 
0468   m_binGroups.clear();
0469 
0470   // number of stages:
0471   const std::size_t nStages = stageOffsets.size() - 1;
0472 
0473   // reverse order filling
0474   for (std::size_t stageIndex = nStages; stageIndex-- > 0;) {
0475     const std::size_t begin = stageOffsets[stageIndex];
0476     const std::size_t end = stageOffsets[stageIndex + 1];
0477 
0478     for (std::size_t k = begin; k < end; ++k) {
0479       const std::uint32_t bin1Idx = stageData[k];
0480 
0481       const auto p = originalBinMap.find(bin1Idx);
0482       if (p == originalBinMap.end()) {
0483         continue;
0484       }
0485 
0486       const auto& binLists = p->second;
0487       const std::vector<std::uint32_t>& bin2List = binLists.second;
0488 
0489       // store the group
0490       m_binGroups.emplace_back(bin1Idx, std::vector<std::uint32_t>(bin2List));
0491     }
0492   }
0493 }
0494 
0495 const GbtsLayer* GbtsGeometry::layerById(std::uint32_t id) const {
0496   if (const auto it = m_layerFromUserIdMap.find(id);
0497       it != m_layerFromUserIdMap.end()) {
0498     return &m_layers.at(it->second);
0499   }
0500   return nullptr;
0501 }
0502 
0503 const GbtsLayer& GbtsGeometry::layerByIndex(std::int32_t idx) const {
0504   return m_layers.at(idx);
0505 }
0506 
0507 const GbtsLayer& GbtsGeometry::createLayer(
0508     const GbtsLayerDescription& layerDescription, std::uint32_t bin0) {
0509   const std::uint32_t layerIndex = m_layers.size();
0510   GbtsLayer& ref = m_layers.emplace_back(layerDescription, m_etaBinWidth, bin0);
0511   m_layerFromUserIdMap.try_emplace(layerDescription.id, layerIndex);
0512   return ref;
0513 }
0514 
0515 }  // namespace Acts::Experimental