diff --git a/CalibCalorimetry/HcalPlugins/src/HcalHardcodeCalibrations.cc b/CalibCalorimetry/HcalPlugins/src/HcalHardcodeCalibrations.cc
index 99ef352423218..b54fc63b0ddad 100644
--- a/CalibCalorimetry/HcalPlugins/src/HcalHardcodeCalibrations.cc
+++ b/CalibCalorimetry/HcalPlugins/src/HcalHardcodeCalibrations.cc
@@ -25,7 +25,7 @@
 
 #include "HcalHardcodeCalibrations.h"
 
-//#define DebugLog
+//#define EDM_ML_DEBUG
 
 // class decleration
 //
@@ -34,12 +34,14 @@ using namespace cms;
 
 namespace {
 
-  const std::vector<HcalGenericDetId>& allCells(const HcalTopology& hcaltopology, bool killHE = false) {
+  const std::vector<HcalGenericDetId>& allCells(const HcalTopology& hcaltopology,
+                                                const ZdcTopology& zdctopology,
+                                                bool killHE = false) {
     static std::vector<HcalGenericDetId> result;
     int maxDepth = hcaltopology.maxDepth();
 
-#ifdef DebugLog
-    std::cout << std::endl << "HcalHardcodeCalibrations:   maxDepth = " << maxDepth << std::endl;
+#ifdef EDM_ML_DEBUG
+    edm::LogVerbatim("HcalCalib") << std::endl << "HcalHardcodeCalibrations:   maxDepth = " << maxDepth;
 #endif
 
     if (result.empty()) {
@@ -52,52 +54,83 @@ namespace {
                 continue;
               if (hcaltopology.valid(cell)) {
                 result.push_back(cell);
-#ifdef DebugLog
-                std::cout << " HcalHardcodedCalibrations: det|eta|phi|depth = " << det << "|" << eta << "|" << phi
-                          << "|" << depth << std::endl;
+#ifdef EDM_ML_DEBUG
+                edm::LogVerbatim("HcalCalib") << " HcalHardcodedCalibrations: det|eta|phi|depth = " << det << "|" << eta
+                                              << "|" << phi << "|" << depth;
 #endif
               }
             }
           }
         }
       }
-      ZdcTopology zdctopology;
       HcalZDCDetId zcell;
       HcalZDCDetId::Section section = HcalZDCDetId::EM;
       for (int depth = 1; depth < 6; depth++) {
         zcell = HcalZDCDetId(section, true, depth);
-        if (zdctopology.valid(zcell))
+        if (zdctopology.valid(zcell)) {
           result.push_back(zcell);
+#ifdef EDM_ML_DEBUG
+          edm::LogVerbatim("HcalCalib") << " ZDC cell : " << zcell;
+#endif
+        }
         zcell = HcalZDCDetId(section, false, depth);
-        if (zdctopology.valid(zcell))
+        if (zdctopology.valid(zcell)) {
           result.push_back(zcell);
+#ifdef EDM_ML_DEBUG
+          edm::LogVerbatim("HcalCalib") << " ZDC cell : " << zcell;
+#endif
+        }
       }
       section = HcalZDCDetId::HAD;
       for (int depth = 1; depth < 5; depth++) {
         zcell = HcalZDCDetId(section, true, depth);
-        if (zdctopology.valid(zcell))
+        if (zdctopology.valid(zcell)) {
           result.push_back(zcell);
+#ifdef EDM_ML_DEBUG
+          edm::LogVerbatim("HcalCalib") << " ZDC cell : " << zcell;
+#endif
+        }
         zcell = HcalZDCDetId(section, false, depth);
-        if (zdctopology.valid(zcell))
+        if (zdctopology.valid(zcell)) {
           result.push_back(zcell);
+#ifdef EDM_ML_DEBUG
+          edm::LogVerbatim("HcalCalib") << " ZDC cell : " << zcell;
+#endif
+        }
       }
       section = HcalZDCDetId::LUM;
       for (int depth = 1; depth < 3; depth++) {
         zcell = HcalZDCDetId(section, true, depth);
-        if (zdctopology.valid(zcell))
+        if (zdctopology.valid(zcell)) {
           result.push_back(zcell);
+#ifdef EDM_ML_DEBUG
+          edm::LogVerbatim("HcalCalib") << " ZDC cell : " << zcell;
+#endif
+        }
         zcell = HcalZDCDetId(section, false, depth);
-        if (zdctopology.valid(zcell))
+        if (zdctopology.valid(zcell)) {
           result.push_back(zcell);
+#ifdef EDM_ML_DEBUG
+          edm::LogVerbatim("HcalCalib") << " ZDC cell : " << zcell;
+#endif
+        }
       }
       section = HcalZDCDetId::RPD;
       for (int depth = 1; depth < 17; depth++) {
         zcell = HcalZDCDetId(section, true, depth);
-        if (zdctopology.valid(zcell))
+        if (zdctopology.valid(zcell)) {
           result.push_back(zcell);
+#ifdef EDM_ML_DEBUG
+          edm::LogVerbatim("HcalCalib") << " ZDC cell : " << zcell;
+#endif
+        }
         zcell = HcalZDCDetId(section, false, depth);
-        if (zdctopology.valid(zcell))
+        if (zdctopology.valid(zcell)) {
           result.push_back(zcell);
+#ifdef EDM_ML_DEBUG
+          edm::LogVerbatim("HcalCalib") << " ZDC cell : " << zcell;
+#endif
+        }
       }
 
       // HcalGenTriggerTower (HcalGenericSubdetector = 5)
@@ -112,9 +145,9 @@ namespace {
               HcalTrigTowerDetId cell(eta, phi, depth, vers);
               if (hcaltopology.validHT(cell)) {
                 result.push_back(cell);
-#ifdef DebugLog
-                std::cout << " HcalHardcodedCalibrations: eta|phi|depth|vers = " << eta << "|" << phi << "|" << depth
-                          << "|" << vers << std::endl;
+#ifdef EDM_ML_DEBUG
+                edm::LogVerbatim("HcalCalib") << " HcalHardcodedCalibrations: eta|phi|depth|vers = " << eta << "|"
+                                              << phi << "|" << depth << "|" << vers;
 #endif
               }
             }
@@ -133,7 +166,9 @@ HcalHardcodeCalibrations::HcalHardcodeCalibrations(const edm::ParameterSet& iCon
       hf_recalibration(nullptr),
       setHEdsegm(false),
       setHBdsegm(false) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::HcalHardcodeCalibrations->...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::HcalHardcodeCalibrations->...";
+#endif
 
   if (iConfig.exists("GainWidthsForTrigPrims"))
     switchGainWidthsForTrigPrims = iConfig.getParameter<bool>("GainWidthsForTrigPrims");
@@ -183,72 +218,94 @@ HcalHardcodeCalibrations::HcalHardcodeCalibrations(const edm::ParameterSet& iCon
       hf_recalibration =
           std::make_unique<HFRecalibration>(iConfig.getParameter<edm::ParameterSet>("HFRecalParameterBlock"));
 
-#ifdef DebugLog
-    std::cout << " HcalHardcodeCalibrations:  iLumi = " << iLumi << std::endl;
+#ifdef EDM_ML_DEBUG
+    edm::LogVerbatim("HcalCalib") << " HcalHardcodeCalibrations:  iLumi = " << iLumi;
 #endif
   }
 
   std::vector<std::string> toGet = iConfig.getUntrackedParameter<std::vector<std::string>>("toGet");
   for (auto& objectName : toGet) {
     bool all = objectName == "all";
-#ifdef DebugLog
-    std::cout << "Load parameters for " << objectName << std::endl;
+#ifdef EDM_ML_DEBUG
+    edm::LogVerbatim("HcalCalib") << "Load parameters for " << objectName;
 #endif
     if ((objectName == "Pedestals") || all) {
-      topoTokens_[kPedestals] = setWhatProduced(this, &HcalHardcodeCalibrations::producePedestals).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::producePedestals);
+      topoTokens_[kPedestals] = c.consumes();
+      zdcTopoTokens_[kPedestals] = c.consumes();
       findingRecord<HcalPedestalsRcd>();
     }
     if ((objectName == "PedestalWidths") || all) {
-      topoTokens_[kPedestalWidths] = setWhatProduced(this, &HcalHardcodeCalibrations::producePedestalWidths).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::producePedestalWidths);
+      topoTokens_[kPedestalWidths] = c.consumes();
+      zdcTopoTokens_[kPedestalWidths] = c.consumes();
       findingRecord<HcalPedestalWidthsRcd>();
     }
     if ((objectName == "EffectivePedestals") || all) {
-      topoTokens_[kEffectivePedestals] =
-          setWhatProduced(this, &HcalHardcodeCalibrations::produceEffectivePedestals, edm::es::Label("effective"))
-              .consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceEffectivePedestals, edm::es::Label("effective"));
+      topoTokens_[kEffectivePedestals] = c.consumes();
+      zdcTopoTokens_[kEffectivePedestals] = c.consumes();
       findingRecord<HcalPedestalsRcd>();
     }
     if ((objectName == "EffectivePedestalWidths") || all) {
-      topoTokens_[kEffectivePedestalWidths] =
-          setWhatProduced(this, &HcalHardcodeCalibrations::produceEffectivePedestalWidths, edm::es::Label("effective"))
-              .consumes();
+      auto c =
+          setWhatProduced(this, &HcalHardcodeCalibrations::produceEffectivePedestalWidths, edm::es::Label("effective"));
+      topoTokens_[kEffectivePedestalWidths] = c.consumes();
+      zdcTopoTokens_[kEffectivePedestalWidths] = c.consumes();
       findingRecord<HcalPedestalWidthsRcd>();
     }
     if ((objectName == "Gains") || all) {
-      topoTokens_[kGains] = setWhatProduced(this, &HcalHardcodeCalibrations::produceGains).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceGains);
+      topoTokens_[kGains] = c.consumes();
+      zdcTopoTokens_[kGains] = c.consumes();
       findingRecord<HcalGainsRcd>();
     }
     if ((objectName == "GainWidths") || all) {
-      topoTokens_[kGainWidths] = setWhatProduced(this, &HcalHardcodeCalibrations::produceGainWidths).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceGainWidths);
+      topoTokens_[kGainWidths] = c.consumes();
+      zdcTopoTokens_[kGainWidths] = c.consumes();
       findingRecord<HcalGainWidthsRcd>();
     }
     if ((objectName == "PFCuts") || all) {
-      topoTokens_[kPFCuts] = setWhatProduced(this, &HcalHardcodeCalibrations::producePFCuts).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::producePFCuts);
+      topoTokens_[kPFCuts] = c.consumes();
+      zdcTopoTokens_[kPFCuts] = c.consumes();
       findingRecord<HcalPFCutsRcd>();
     }
     if ((objectName == "QIEData") || all) {
-      topoTokens_[kQIEData] = setWhatProduced(this, &HcalHardcodeCalibrations::produceQIEData).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceQIEData);
+      topoTokens_[kQIEData] = c.consumes();
+      zdcTopoTokens_[kQIEData] = c.consumes();
       findingRecord<HcalQIEDataRcd>();
     }
     if ((objectName == "QIETypes") || all) {
-      topoTokens_[kQIETypes] = setWhatProduced(this, &HcalHardcodeCalibrations::produceQIETypes).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceQIETypes);
+      topoTokens_[kQIETypes] = c.consumes();
+      zdcTopoTokens_[kQIETypes] = c.consumes();
       findingRecord<HcalQIETypesRcd>();
     }
     if ((objectName == "ChannelQuality") || (objectName == "channelQuality") || all) {
-      topoTokens_[kChannelQuality] = setWhatProduced(this, &HcalHardcodeCalibrations::produceChannelQuality).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceChannelQuality);
+      topoTokens_[kChannelQuality] = c.consumes();
+      zdcTopoTokens_[kChannelQuality] = c.consumes();
       findingRecord<HcalChannelQualityRcd>();
     }
     if ((objectName == "ElectronicsMap") || (objectName == "electronicsMap") || all) {
-      topoTokens_[kElectronicsMap] = setWhatProduced(this, &HcalHardcodeCalibrations::produceElectronicsMap).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceElectronicsMap);
+      topoTokens_[kElectronicsMap] = c.consumes();
+      zdcTopoTokens_[kElectronicsMap] = c.consumes();
       findingRecord<HcalElectronicsMapRcd>();
     }
     if ((objectName == "ZSThresholds") || (objectName == "zsThresholds") || all) {
-      topoTokens_[kZSThresholds] = setWhatProduced(this, &HcalHardcodeCalibrations::produceZSThresholds).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceZSThresholds);
+      topoTokens_[kZSThresholds] = c.consumes();
+      zdcTopoTokens_[kZSThresholds] = c.consumes();
       findingRecord<HcalZSThresholdsRcd>();
     }
     if ((objectName == "RespCorrs") || (objectName == "ResponseCorrection") || all) {
       auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceRespCorrs);
       topoTokens_[kRespCorrs] = c.consumes();
+      zdcTopoTokens_[kRespCorrs] = c.consumes();
       if (he_recalibration) {
         heDarkeningToken_ = c.consumes(edm::ESInputTag("", "HE"));
       }
@@ -258,29 +315,39 @@ HcalHardcodeCalibrations::HcalHardcodeCalibrations(const edm::ParameterSet& iCon
       findingRecord<HcalRespCorrsRcd>();
     }
     if ((objectName == "LUTCorrs") || (objectName == "LUTCorrection") || all) {
-      topoTokens_[kLUTCorrs] = setWhatProduced(this, &HcalHardcodeCalibrations::produceLUTCorrs).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceLUTCorrs);
+      topoTokens_[kLUTCorrs] = c.consumes();
+      zdcTopoTokens_[kLUTCorrs] = c.consumes();
       findingRecord<HcalLUTCorrsRcd>();
     }
     if ((objectName == "PFCorrs") || (objectName == "PFCorrection") || all) {
-      topoTokens_[kPFCorrs] = setWhatProduced(this, &HcalHardcodeCalibrations::producePFCorrs).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::producePFCorrs);
+      topoTokens_[kPFCorrs] = c.consumes();
+      zdcTopoTokens_[kPFCorrs] = c.consumes();
       findingRecord<HcalPFCorrsRcd>();
     }
     if ((objectName == "TimeCorrs") || (objectName == "TimeCorrection") || all) {
-      topoTokens_[kTimeCorrs] = setWhatProduced(this, &HcalHardcodeCalibrations::produceTimeCorrs).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceTimeCorrs);
+      topoTokens_[kTimeCorrs] = c.consumes();
+      zdcTopoTokens_[kTimeCorrs] = c.consumes();
       findingRecord<HcalTimeCorrsRcd>();
     }
     if ((objectName == "L1TriggerObjects") || (objectName == "L1Trigger") || all) {
-      topoTokens_[kL1TriggerObjects] =
-          setWhatProduced(this, &HcalHardcodeCalibrations::produceL1TriggerObjects).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceL1TriggerObjects);
+      topoTokens_[kL1TriggerObjects] = c.consumes();
+      zdcTopoTokens_[kL1TriggerObjects] = c.consumes();
       findingRecord<HcalL1TriggerObjectsRcd>();
     }
     if ((objectName == "ValidationCorrs") || (objectName == "ValidationCorrection") || all) {
-      topoTokens_[kValidationCorrs] =
-          setWhatProduced(this, &HcalHardcodeCalibrations::produceValidationCorrs).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceValidationCorrs);
+      topoTokens_[kValidationCorrs] = c.consumes();
+      zdcTopoTokens_[kValidationCorrs] = c.consumes();
       findingRecord<HcalValidationCorrsRcd>();
     }
     if ((objectName == "LutMetadata") || (objectName == "lutMetadata") || all) {
-      topoTokens_[kLutMetadata] = setWhatProduced(this, &HcalHardcodeCalibrations::produceLutMetadata).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceLutMetadata);
+      topoTokens_[kLutMetadata] = c.consumes();
+      zdcTopoTokens_[kLutMetadata] = c.consumes();
       findingRecord<HcalLutMetadataRcd>();
     }
     if ((objectName == "DcsValues") || all) {
@@ -292,33 +359,45 @@ HcalHardcodeCalibrations::HcalHardcodeCalibrations(const edm::ParameterSet& iCon
       findingRecord<HcalDcsMapRcd>();
     }
     if ((objectName == "RecoParams") || all) {
-      topoTokens_[kRecoParams] = setWhatProduced(this, &HcalHardcodeCalibrations::produceRecoParams).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceRecoParams);
+      topoTokens_[kRecoParams] = c.consumes();
+      zdcTopoTokens_[kRecoParams] = c.consumes();
       findingRecord<HcalRecoParamsRcd>();
     }
     if ((objectName == "LongRecoParams") || all) {
-      topoTokens_[kLongRecoParams] = setWhatProduced(this, &HcalHardcodeCalibrations::produceLongRecoParams).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceLongRecoParams);
+      topoTokens_[kLongRecoParams] = c.consumes();
+      zdcTopoTokens_[kLongRecoParams] = c.consumes();
       findingRecord<HcalLongRecoParamsRcd>();
     }
     if ((objectName == "ZDCLowGainFractions") || all) {
-      topoTokens_[kZDCLowGainFractions] =
-          setWhatProduced(this, &HcalHardcodeCalibrations::produceZDCLowGainFractions).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceZDCLowGainFractions);
+      topoTokens_[kZDCLowGainFractions] = c.consumes();
+      zdcTopoTokens_[kZDCLowGainFractions] = c.consumes();
       findingRecord<HcalZDCLowGainFractionsRcd>();
     }
     if ((objectName == "MCParams") || all) {
-      topoTokens_[kMCParams] = setWhatProduced(this, &HcalHardcodeCalibrations::produceMCParams).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceMCParams);
+      topoTokens_[kMCParams] = c.consumes();
+      zdcTopoTokens_[kMCParams] = c.consumes();
       findingRecord<HcalMCParamsRcd>();
     }
     if ((objectName == "FlagHFDigiTimeParams") || all) {
-      topoTokens_[kFlagHFDigiTimeParams] =
-          setWhatProduced(this, &HcalHardcodeCalibrations::produceFlagHFDigiTimeParams).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceFlagHFDigiTimeParams);
+      topoTokens_[kFlagHFDigiTimeParams] = c.consumes();
+      zdcTopoTokens_[kFlagHFDigiTimeParams] = c.consumes();
       findingRecord<HcalFlagHFDigiTimeParamsRcd>();
     }
     if ((objectName == "FrontEndMap") || (objectName == "frontEndMap") || all) {
-      topoTokens_[kFrontEndMap] = setWhatProduced(this, &HcalHardcodeCalibrations::produceFrontEndMap).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceFrontEndMap);
+      topoTokens_[kFrontEndMap] = c.consumes();
+      zdcTopoTokens_[kFrontEndMap] = c.consumes();
       findingRecord<HcalFrontEndMapRcd>();
     }
     if ((objectName == "SiPMParameters") || all) {
-      topoTokens_[kSiPMParameters] = setWhatProduced(this, &HcalHardcodeCalibrations::produceSiPMParameters).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceSiPMParameters);
+      topoTokens_[kSiPMParameters] = c.consumes();
+      zdcTopoTokens_[kSiPMParameters] = c.consumes();
       findingRecord<HcalSiPMParametersRcd>();
     }
     if ((objectName == "SiPMCharacteristics") || all) {
@@ -326,8 +405,9 @@ HcalHardcodeCalibrations::HcalHardcodeCalibrations(const edm::ParameterSet& iCon
       findingRecord<HcalSiPMCharacteristicsRcd>();
     }
     if ((objectName == "TPChannelParameters") || all) {
-      topoTokens_[kTPChannelParameters] =
-          setWhatProduced(this, &HcalHardcodeCalibrations::produceTPChannelParameters).consumes();
+      auto c = setWhatProduced(this, &HcalHardcodeCalibrations::produceTPChannelParameters);
+      topoTokens_[kTPChannelParameters] = c.consumes();
+      zdcTopoTokens_[kTPChannelParameters] = c.consumes();
       findingRecord<HcalTPChannelParametersRcd>();
     }
     if ((objectName == "TPParameters") || all) {
@@ -346,19 +426,26 @@ void HcalHardcodeCalibrations::setIntervalFor(const edm::eventsetup::EventSetupR
                                               const edm::IOVSyncValue& iTime,
                                               edm::ValidityInterval& oInterval) {
   std::string record = iKey.name();
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::setIntervalFor-> key: " << record << " time: " << iTime.eventID()
-                       << '/' << iTime.time().value();
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::setIntervalFor-> key: " << record
+                           << " time: " << iTime.eventID() << '/' << iTime.time().value();
+#endif
   oInterval = edm::ValidityInterval(edm::IOVSyncValue::beginOfTime(), edm::IOVSyncValue::endOfTime());  //infinite
 }
 
 std::unique_ptr<HcalPedestals> HcalHardcodeCalibrations::producePedestals_(
-    const HcalPedestalsRcd& rec, const edm::ESGetToken<HcalTopology, HcalRecNumberingRecord>& token, bool eff) {
+    const HcalPedestalsRcd& rec,
+    const edm::ESGetToken<HcalTopology, HcalRecNumberingRecord>& token,
+    const edm::ESGetToken<ZdcTopology, HcalRecNumberingRecord>& zdctoken,
+    bool eff) {
   std::string seff = eff ? "Effective" : "";
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produce" << seff << "Pedestals-> ...";
-
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produce" << seff << "Pedestals-> ...";
+#endif
   auto const& topo = rec.get(token);
+  auto const& zdcTopo = rec.get(zdctoken);
   auto result = std::make_unique<HcalPedestals>(&topo, false);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalPedestal item = dbHardcode.makePedestal(cell, false, eff, &topo, iLumi);
     result->addValues(item);
@@ -367,12 +454,18 @@ std::unique_ptr<HcalPedestals> HcalHardcodeCalibrations::producePedestals_(
 }
 
 std::unique_ptr<HcalPedestalWidths> HcalHardcodeCalibrations::producePedestalWidths_(
-    const HcalPedestalWidthsRcd& rec, const edm::ESGetToken<HcalTopology, HcalRecNumberingRecord>& token, bool eff) {
+    const HcalPedestalWidthsRcd& rec,
+    const edm::ESGetToken<HcalTopology, HcalRecNumberingRecord>& token,
+    const edm::ESGetToken<ZdcTopology, HcalRecNumberingRecord>& zdctoken,
+    bool eff) {
   std::string seff = eff ? "Effective" : "";
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produce" << seff << "PedestalWidths-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produce" << seff << "PedestalWidths-> ...";
+#endif
   auto const& topo = rec.get(token);
+  auto const& zdcTopo = rec.get(zdctoken);
   auto result = std::make_unique<HcalPedestalWidths>(&topo, false);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalPedestalWidth item = dbHardcode.makePedestalWidth(cell, eff, &topo, iLumi);
     result->addValues(item);
@@ -381,28 +474,31 @@ std::unique_ptr<HcalPedestalWidths> HcalHardcodeCalibrations::producePedestalWid
 }
 
 std::unique_ptr<HcalPedestals> HcalHardcodeCalibrations::producePedestals(const HcalPedestalsRcd& rec) {
-  return producePedestals_(rec, topoTokens_[kPedestals], false);
+  return producePedestals_(rec, topoTokens_[kPedestals], zdcTopoTokens_[kPedestals], false);
 }
 
 std::unique_ptr<HcalPedestals> HcalHardcodeCalibrations::produceEffectivePedestals(const HcalPedestalsRcd& rec) {
-  return producePedestals_(rec, topoTokens_[kEffectivePedestals], true);
+  return producePedestals_(rec, topoTokens_[kEffectivePedestals], zdcTopoTokens_[kEffectivePedestals], true);
 }
 
 std::unique_ptr<HcalPedestalWidths> HcalHardcodeCalibrations::producePedestalWidths(const HcalPedestalWidthsRcd& rec) {
-  return producePedestalWidths_(rec, topoTokens_[kPedestalWidths], false);
+  return producePedestalWidths_(rec, topoTokens_[kPedestalWidths], zdcTopoTokens_[kPedestalWidths], false);
 }
 
 std::unique_ptr<HcalPedestalWidths> HcalHardcodeCalibrations::produceEffectivePedestalWidths(
     const HcalPedestalWidthsRcd& rec) {
-  return producePedestalWidths_(rec, topoTokens_[kEffectivePedestalWidths], true);
+  return producePedestalWidths_(
+      rec, topoTokens_[kEffectivePedestalWidths], zdcTopoTokens_[kEffectivePedestalWidths], true);
 }
 
 std::unique_ptr<HcalGains> HcalHardcodeCalibrations::produceGains(const HcalGainsRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceGains-> ...";
-
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceGains-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kGains]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kGains]);
   auto result = std::make_unique<HcalGains>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalGain item = dbHardcode.makeGain(cell);
     result->addValues(item);
@@ -411,17 +507,27 @@ std::unique_ptr<HcalGains> HcalHardcodeCalibrations::produceGains(const HcalGain
 }
 
 std::unique_ptr<HcalGainWidths> HcalHardcodeCalibrations::produceGainWidths(const HcalGainWidthsRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceGainWidths-> ...";
-
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceGainWidths-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kGainWidths]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kGainWidths]);
   auto result = std::make_unique<HcalGainWidths>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     // for Upgrade - include TrigPrims, for regular case - only HcalDetId
     if (switchGainWidthsForTrigPrims) {
+#ifdef EDM_ML_DEBUG
+      edm::LogVerbatim("HcalCalib") << " HcalGainWidths cell (with TPs) : " << std::hex << cell.rawId() << std::dec
+                                    << "  " << cell;
+#endif
       HcalGainWidth item = dbHardcode.makeGainWidth(cell);
       result->addValues(item);
     } else if (!cell.isHcalTrigTowerDetId()) {
+#ifdef EDM_ML_DEBUG
+      edm::LogVerbatim("HcalCalib") << " HcalGainWidths cell (without TPs) : " << std::hex << cell.rawId() << std::dec
+                                    << "  " << cell;
+#endif
       HcalGainWidth item = dbHardcode.makeGainWidth(cell);
       result->addValues(item);
     }
@@ -430,11 +536,13 @@ std::unique_ptr<HcalGainWidths> HcalHardcodeCalibrations::produceGainWidths(cons
 }
 
 std::unique_ptr<HcalPFCuts> HcalHardcodeCalibrations::producePFCuts(const HcalPFCutsRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::producePFCuts-> ...";
-
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::producePFCuts-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kPFCuts]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kPFCuts]);
   auto result = std::make_unique<HcalPFCuts>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     // Use only standard Hcal channels for now, no TrigPrims
     if (!cell.isHcalTrigTowerDetId()) {
@@ -446,16 +554,17 @@ std::unique_ptr<HcalPFCuts> HcalHardcodeCalibrations::producePFCuts(const HcalPF
 }
 
 std::unique_ptr<HcalQIEData> HcalHardcodeCalibrations::produceQIEData(const HcalQIEDataRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceQIEData-> ...";
-
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceQIEData-> ...";
+#endif
   /*
-  std::cout << std::endl << ">>>  HcalHardcodeCalibrations::produceQIEData"
-	    << std::endl;  
+  edm::LogVerbatim("HcalCalib")  << ">>>  HcalHardcodeCalibrations::produceQIEData";
   */
 
   auto const& topo = rcd.get(topoTokens_[kQIEData]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kQIEData]);
   auto result = std::make_unique<HcalQIEData>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalQIECoder coder = dbHardcode.makeQIECoder(cell);
     result->addCoder(coder);
@@ -464,11 +573,14 @@ std::unique_ptr<HcalQIEData> HcalHardcodeCalibrations::produceQIEData(const Hcal
 }
 
 std::unique_ptr<HcalQIETypes> HcalHardcodeCalibrations::produceQIETypes(const HcalQIETypesRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceQIETypes-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceQIETypes-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kQIETypes]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kQIETypes]);
 
   auto result = std::make_unique<HcalQIETypes>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalQIEType item = dbHardcode.makeQIEType(cell);
     result->addValues(item);
@@ -477,11 +589,14 @@ std::unique_ptr<HcalQIETypes> HcalHardcodeCalibrations::produceQIETypes(const Hc
 }
 
 std::unique_ptr<HcalChannelQuality> HcalHardcodeCalibrations::produceChannelQuality(const HcalChannelQualityRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceChannelQuality-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceChannelQuality-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kChannelQuality]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kChannelQuality]);
 
   auto result = std::make_unique<HcalChannelQuality>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     // Special: removal of (non-instrumented) layer "-1"("nose") = depth 1
     // from Upgrade HE, either from
@@ -516,8 +631,11 @@ std::unique_ptr<HcalChannelQuality> HcalHardcodeCalibrations::produceChannelQual
 }
 
 std::unique_ptr<HcalRespCorrs> HcalHardcodeCalibrations::produceRespCorrs(const HcalRespCorrsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceRespCorrs-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceRespCorrs-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kRespCorrs]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kRespCorrs]);
 
   //set depth segmentation for HB/HE recalib - only happens once
   if ((he_recalibration && !setHEdsegm) || (hb_recalibration && !setHBdsegm)) {
@@ -538,7 +656,7 @@ std::unique_ptr<HcalRespCorrs> HcalHardcodeCalibrations::produceRespCorrs(const
   }
 
   auto result = std::make_unique<HcalRespCorrs>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (const auto& cell : cells) {
     double corr = 1.0;
 
@@ -560,22 +678,22 @@ std::unique_ptr<HcalRespCorrs> HcalHardcodeCalibrations::produceRespCorrs(const
       int depth_ = HcalDetId(cell).depth();
       int ieta_ = HcalDetId(cell).ieta();
       corr *= hb_recalibration->getCorr(ieta_, depth_);
-#ifdef DebugLog
-      std::cout << "HB ieta, depth = " << ieta_ << ",  " << depth_ << "   corr = " << corr << std::endl;
+#ifdef EDM_ML_DEBUG
+      edm::LogVerbatim("HcalCalib") << "HB ieta, depth = " << ieta_ << ",  " << depth_ << "   corr = " << corr;
 #endif
     } else if ((he_recalibration != nullptr) && (cell.genericSubdet() == HcalGenericDetId::HcalGenEndcap)) {
       int depth_ = HcalDetId(cell).depth();
       int ieta_ = HcalDetId(cell).ieta();
       corr *= he_recalibration->getCorr(ieta_, depth_);
-#ifdef DebugLog
-      std::cout << "HE ieta, depth = " << ieta_ << ",  " << depth_ << "   corr = " << corr << std::endl;
+#ifdef EDM_ML_DEBUG
+      edm::LogVerbatim("HcalCalib") << "HE ieta, depth = " << ieta_ << ",  " << depth_ << "   corr = " << corr;
 #endif
     } else if ((hf_recalibration != nullptr) && (cell.genericSubdet() == HcalGenericDetId::HcalGenForward)) {
       int depth_ = HcalDetId(cell).depth();
       int ieta_ = HcalDetId(cell).ieta();
       corr = hf_recalibration->getCorr(ieta_, depth_, iLumi);
-#ifdef DebugLog
-      std::cout << "HF ieta, depth = " << ieta_ << ",  " << depth_ << "   corr = " << corr << std::endl;
+#ifdef EDM_ML_DEBUG
+      edm::LogVerbatim("HcalCalib") << "HF ieta, depth = " << ieta_ << ",  " << depth_ << "   corr = " << corr;
 #endif
     }
 
@@ -586,11 +704,14 @@ std::unique_ptr<HcalRespCorrs> HcalHardcodeCalibrations::produceRespCorrs(const
 }
 
 std::unique_ptr<HcalLUTCorrs> HcalHardcodeCalibrations::produceLUTCorrs(const HcalLUTCorrsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceLUTCorrs-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceLUTCorrs-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kLUTCorrs]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kLUTCorrs]);
 
   auto result = std::make_unique<HcalLUTCorrs>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalLUTCorr item(cell.rawId(), 1.0);
     result->addValues(item);
@@ -599,11 +720,14 @@ std::unique_ptr<HcalLUTCorrs> HcalHardcodeCalibrations::produceLUTCorrs(const Hc
 }
 
 std::unique_ptr<HcalPFCorrs> HcalHardcodeCalibrations::producePFCorrs(const HcalPFCorrsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::producePFCorrs-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::producePFCorrs-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kPFCorrs]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kPFCorrs]);
 
   auto result = std::make_unique<HcalPFCorrs>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalPFCorr item(cell.rawId(), 1.0);
     result->addValues(item);
@@ -612,11 +736,14 @@ std::unique_ptr<HcalPFCorrs> HcalHardcodeCalibrations::producePFCorrs(const Hcal
 }
 
 std::unique_ptr<HcalTimeCorrs> HcalHardcodeCalibrations::produceTimeCorrs(const HcalTimeCorrsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceTimeCorrs-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceTimeCorrs-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kTimeCorrs]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kTimeCorrs]);
 
   auto result = std::make_unique<HcalTimeCorrs>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalTimeCorr item(cell.rawId(), 0.0);
     result->addValues(item);
@@ -625,11 +752,14 @@ std::unique_ptr<HcalTimeCorrs> HcalHardcodeCalibrations::produceTimeCorrs(const
 }
 
 std::unique_ptr<HcalZSThresholds> HcalHardcodeCalibrations::produceZSThresholds(const HcalZSThresholdsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceZSThresholds-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceZSThresholds-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kZSThresholds]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kZSThresholds]);
 
   auto result = std::make_unique<HcalZSThresholds>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalZSThreshold item = dbHardcode.makeZSThreshold(cell);
     result->addValues(item);
@@ -639,11 +769,14 @@ std::unique_ptr<HcalZSThresholds> HcalHardcodeCalibrations::produceZSThresholds(
 
 std::unique_ptr<HcalL1TriggerObjects> HcalHardcodeCalibrations::produceL1TriggerObjects(
     const HcalL1TriggerObjectsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceL1TriggerObjects-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceL1TriggerObjects-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kL1TriggerObjects]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kL1TriggerObjects]);
 
   auto result = std::make_unique<HcalL1TriggerObjects>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalL1TriggerObject item(cell.rawId(), 0., 1., 0);
     result->addValues(item);
@@ -655,20 +788,26 @@ std::unique_ptr<HcalL1TriggerObjects> HcalHardcodeCalibrations::produceL1Trigger
 }
 
 std::unique_ptr<HcalElectronicsMap> HcalHardcodeCalibrations::produceElectronicsMap(const HcalElectronicsMapRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceElectronicsMap-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceElectronicsMap-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kElectronicsMap]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kElectronicsMap]);
 
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   return dbHardcode.makeHardcodeMap(cells);
 }
 
 std::unique_ptr<HcalValidationCorrs> HcalHardcodeCalibrations::produceValidationCorrs(
     const HcalValidationCorrsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceValidationCorrs-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceValidationCorrs-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kValidationCorrs]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kValidationCorrs]);
 
   auto result = std::make_unique<HcalValidationCorrs>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalValidationCorr item(cell.rawId(), 1.0);
     result->addValues(item);
@@ -677,15 +816,18 @@ std::unique_ptr<HcalValidationCorrs> HcalHardcodeCalibrations::produceValidation
 }
 
 std::unique_ptr<HcalLutMetadata> HcalHardcodeCalibrations::produceLutMetadata(const HcalLutMetadataRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceLutMetadata-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceLutMetadata-> ...";
+#endif
   auto const& topo = rcd.get(topoTokens_[kLutMetadata]);
+  auto const& zdcTopo = rcd.get(zdcTopoTokens_[kLutMetadata]);
 
   auto result = std::make_unique<HcalLutMetadata>(&topo);
 
   result->setRctLsb(0.5);
   result->setNominalGain(0.177);  // for HBHE SiPMs
 
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (const auto& cell : cells) {
     float rcalib = 1.;
     int granularity = 1;
@@ -703,23 +845,29 @@ std::unique_ptr<HcalLutMetadata> HcalHardcodeCalibrations::produceLutMetadata(co
 }
 
 std::unique_ptr<HcalDcsValues> HcalHardcodeCalibrations::produceDcsValues(const HcalDcsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceDcsValues-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceDcsValues-> ...";
+#endif
   auto result = std::make_unique<HcalDcsValues>();
   return result;
 }
 
 std::unique_ptr<HcalDcsMap> HcalHardcodeCalibrations::produceDcsMap(const HcalDcsMapRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceDcsMap-> ...";
-
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceDcsMap-> ...";
+#endif
   return dbHardcode.makeHardcodeDcsMap();
 }
 
 std::unique_ptr<HcalRecoParams> HcalHardcodeCalibrations::produceRecoParams(const HcalRecoParamsRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceRecoParams-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceRecoParams-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kRecoParams]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kRecoParams]);
 
   auto result = std::make_unique<HcalRecoParams>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalRecoParam item = dbHardcode.makeRecoParam(cell);
     result->addValues(item);
@@ -728,11 +876,14 @@ std::unique_ptr<HcalRecoParams> HcalHardcodeCalibrations::produceRecoParams(cons
 }
 
 std::unique_ptr<HcalTimingParams> HcalHardcodeCalibrations::produceTimingParams(const HcalTimingParamsRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceTimingParams-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceTimingParams-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kTimingParams]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kTimingParams]);
 
   auto result = std::make_unique<HcalTimingParams>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalTimingParam item = dbHardcode.makeTimingParam(cell);
     result->addValues(item);
@@ -741,11 +892,14 @@ std::unique_ptr<HcalTimingParams> HcalHardcodeCalibrations::produceTimingParams(
 }
 
 std::unique_ptr<HcalLongRecoParams> HcalHardcodeCalibrations::produceLongRecoParams(const HcalLongRecoParamsRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceLongRecoParams-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceLongRecoParams-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kLongRecoParams]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kLongRecoParams]);
 
   auto result = std::make_unique<HcalLongRecoParams>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   std::vector<unsigned int> mSignal;
   mSignal.push_back(4);
   mSignal.push_back(5);
@@ -765,11 +919,14 @@ std::unique_ptr<HcalLongRecoParams> HcalHardcodeCalibrations::produceLongRecoPar
 
 std::unique_ptr<HcalZDCLowGainFractions> HcalHardcodeCalibrations::produceZDCLowGainFractions(
     const HcalZDCLowGainFractionsRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceZDCLowGainFractions-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceZDCLowGainFractions-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kZDCLowGainFractions]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kZDCLowGainFractions]);
 
   auto result = std::make_unique<HcalZDCLowGainFractions>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalZDCLowGainFraction item(cell.rawId(), 0.0);
     result->addValues(item);
@@ -778,12 +935,13 @@ std::unique_ptr<HcalZDCLowGainFractions> HcalHardcodeCalibrations::produceZDCLow
 }
 
 std::unique_ptr<HcalMCParams> HcalHardcodeCalibrations::produceMCParams(const HcalMCParamsRcd& rec) {
-  //  std::cout << std::endl << " .... HcalHardcodeCalibrations::produceMCParams ->"<< std::endl;
-
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceMCParams-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceMCParams-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kMCParams]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kMCParams]);
   auto result = std::make_unique<HcalMCParams>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalMCParam item = dbHardcode.makeMCParam(cell);
     result->addValues(item);
@@ -793,11 +951,14 @@ std::unique_ptr<HcalMCParams> HcalHardcodeCalibrations::produceMCParams(const Hc
 
 std::unique_ptr<HcalFlagHFDigiTimeParams> HcalHardcodeCalibrations::produceFlagHFDigiTimeParams(
     const HcalFlagHFDigiTimeParamsRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceFlagHFDigiTimeParams-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceFlagHFDigiTimeParams-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kFlagHFDigiTimeParams]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kFlagHFDigiTimeParams]);
 
   auto result = std::make_unique<HcalFlagHFDigiTimeParams>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
 
   std::vector<double> coef;
   coef.push_back(0.93);
@@ -818,20 +979,26 @@ std::unique_ptr<HcalFlagHFDigiTimeParams> HcalHardcodeCalibrations::produceFlagH
 }
 
 std::unique_ptr<HcalFrontEndMap> HcalHardcodeCalibrations::produceFrontEndMap(const HcalFrontEndMapRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceFrontEndMap-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceFrontEndMap-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kFrontEndMap]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kFrontEndMap]);
 
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
 
   return dbHardcode.makeHardcodeFrontEndMap(cells);
 }
 
 std::unique_ptr<HcalSiPMParameters> HcalHardcodeCalibrations::produceSiPMParameters(const HcalSiPMParametersRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceSiPMParameters-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceSiPMParameters-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kSiPMParameters]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kSiPMParameters]);
 
   auto result = std::make_unique<HcalSiPMParameters>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     HcalSiPMParameter item = dbHardcode.makeHardcodeSiPMParameter(cell, &topo, iLumi);
     result->addValues(item);
@@ -841,18 +1008,22 @@ std::unique_ptr<HcalSiPMParameters> HcalHardcodeCalibrations::produceSiPMParamet
 
 std::unique_ptr<HcalSiPMCharacteristics> HcalHardcodeCalibrations::produceSiPMCharacteristics(
     const HcalSiPMCharacteristicsRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceSiPMCharacteristics-> ...";
-
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceSiPMCharacteristics-> ...";
+#endif
   return dbHardcode.makeHardcodeSiPMCharacteristics();
 }
 
 std::unique_ptr<HcalTPChannelParameters> HcalHardcodeCalibrations::produceTPChannelParameters(
     const HcalTPChannelParametersRcd& rec) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceTPChannelParameters-> ...";
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceTPChannelParameters-> ...";
+#endif
   auto const& topo = rec.get(topoTokens_[kTPChannelParameters]);
+  auto const& zdcTopo = rec.get(zdcTopoTokens_[kTPChannelParameters]);
 
   auto result = std::make_unique<HcalTPChannelParameters>(&topo);
-  const std::vector<HcalGenericDetId>& cells = allCells(topo, dbHardcode.killHE());
+  const std::vector<HcalGenericDetId>& cells = allCells(topo, zdcTopo, dbHardcode.killHE());
   for (auto cell : cells) {
     // Thinking about Phase2 and the new FIR filter,
     // for now, don't put TT in TPChannelParams
@@ -865,8 +1036,9 @@ std::unique_ptr<HcalTPChannelParameters> HcalHardcodeCalibrations::produceTPChan
 }
 
 std::unique_ptr<HcalTPParameters> HcalHardcodeCalibrations::produceTPParameters(const HcalTPParametersRcd& rcd) {
-  edm::LogInfo("HCAL") << "HcalHardcodeCalibrations::produceTPParameters-> ...";
-
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCAL") << "HcalHardcodeCalibrations::produceTPParameters-> ...";
+#endif
   auto result = std::make_unique<HcalTPParameters>();
   dbHardcode.makeHardcodeTPParameters(*result);
   return result;
diff --git a/CalibCalorimetry/HcalPlugins/src/HcalHardcodeCalibrations.h b/CalibCalorimetry/HcalPlugins/src/HcalHardcodeCalibrations.h
index 28ea7ca9a8f2c..24b52e3972c7a 100644
--- a/CalibCalorimetry/HcalPlugins/src/HcalHardcodeCalibrations.h
+++ b/CalibCalorimetry/HcalPlugins/src/HcalHardcodeCalibrations.h
@@ -13,6 +13,7 @@
 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
 #include "Geometry/CaloTopology/interface/HcalTopology.h"
+#include "Geometry/ForwardGeometry/interface/ZdcTopology.h"
 #include "CondFormats/HcalObjects/interface/AllObjects.h"
 #include "CalibCalorimetry/HcalAlgos/interface/HBHERecalibration.h"
 #include "CondFormats/DataRecord/interface/HcalTPParametersRcd.h"
@@ -68,9 +69,13 @@ class HcalHardcodeCalibrations : public edm::ESProducer, public edm::EventSetupR
 
   std::unique_ptr<HcalPedestals> producePedestals_(const HcalPedestalsRcd& rcd,
                                                    const edm::ESGetToken<HcalTopology, HcalRecNumberingRecord>&,
+                                                   const edm::ESGetToken<ZdcTopology, HcalRecNumberingRecord>&,
                                                    bool eff);
   std::unique_ptr<HcalPedestalWidths> producePedestalWidths_(
-      const HcalPedestalWidthsRcd& rcd, const edm::ESGetToken<HcalTopology, HcalRecNumberingRecord>&, bool eff);
+      const HcalPedestalWidthsRcd& rcd,
+      const edm::ESGetToken<HcalTopology, HcalRecNumberingRecord>&,
+      const edm::ESGetToken<ZdcTopology, HcalRecNumberingRecord>&,
+      bool eff);
   std::unique_ptr<HcalPedestals> producePedestals(const HcalPedestalsRcd& rcd);
   std::unique_ptr<HcalPedestalWidths> producePedestalWidths(const HcalPedestalWidthsRcd& rcd);
   std::unique_ptr<HcalPedestals> produceEffectivePedestals(const HcalPedestalsRcd& rcd);
@@ -147,6 +152,7 @@ class HcalHardcodeCalibrations : public edm::ESProducer, public edm::EventSetupR
   std::unique_ptr<HBHERecalibration> he_recalibration;
   std::unique_ptr<HFRecalibration> hf_recalibration;
   std::unordered_map<int, edm::ESGetToken<HcalTopology, HcalRecNumberingRecord>> topoTokens_;
+  std::unordered_map<int, edm::ESGetToken<ZdcTopology, HcalRecNumberingRecord>> zdcTopoTokens_;
   edm::ESGetToken<HBHEDarkening, HBHEDarkeningRecord> heDarkeningToken_;
   edm::ESGetToken<HBHEDarkening, HBHEDarkeningRecord> hbDarkeningToken_;
   bool switchGainWidthsForTrigPrims;
diff --git a/CondFormats/HcalObjects/interface/HcalCondObjectContainer.h b/CondFormats/HcalObjects/interface/HcalCondObjectContainer.h
index 59ef2a5480089..9814c72ef21ed 100644
--- a/CondFormats/HcalObjects/interface/HcalCondObjectContainer.h
+++ b/CondFormats/HcalObjects/interface/HcalCondObjectContainer.h
@@ -29,6 +29,7 @@ class HcalCondObjectContainerBase {
   HcalCondObjectContainerBase& operator=(HcalCondObjectContainerBase const& o) {
     topo_ = o.topo();
     packedIndexVersion_ = o.packedIndexVersion_;
+    kSizeForDenseIndexing_ = o.kSizeForDenseIndexing_;
     return *this;
   }
 #ifndef __GCCXML__
@@ -47,6 +48,7 @@ class HcalCondObjectContainerBase {
 
 private:
   const HcalTopology* topo_ COND_TRANSIENT;
+  uint32_t kSizeForDenseIndexing_ COND_TRANSIENT;
 
   COND_SERIALIZABLE;
 };
diff --git a/CondFormats/HcalObjects/src/HcalCondObjectContainerBase.cc b/CondFormats/HcalObjects/src/HcalCondObjectContainerBase.cc
index abf0a95ce3b52..032bafd60f12f 100644
--- a/CondFormats/HcalObjects/src/HcalCondObjectContainerBase.cc
+++ b/CondFormats/HcalObjects/src/HcalCondObjectContainerBase.cc
@@ -1,4 +1,5 @@
 #include "Geometry/CaloTopology/interface/HcalTopology.h"
+#include "Geometry/HcalCommonData/interface/HcalTopologyMode.h"
 #include "CondFormats/HcalObjects/interface/HcalCondObjectContainer.h"
 #include "DataFormats/HcalDetId/interface/HcalCastorDetId.h"
 #include "DataFormats/HcalDetId/interface/HcalCalibDetId.h"
@@ -9,9 +10,14 @@
 #include "FWCore/Utilities/interface/Exception.h"
 
 HcalCondObjectContainerBase::HcalCondObjectContainerBase(const HcalTopology* topo)
-    : packedIndexVersion_(0), topo_(topo) {
-  if (topo)
+    : packedIndexVersion_(0), topo_(topo), kSizeForDenseIndexing_(HcalZDCDetId::kSizeForDenseIndexingRun1) {
+  if (topo) {
     packedIndexVersion_ = topo->topoVersion();
+    HcalTopologyMode::Mode mode = topo->mode();
+    kSizeForDenseIndexing_ = (((mode == HcalTopologyMode::Run3) || (mode == HcalTopologyMode::Run4))
+                                  ? HcalZDCDetId::kSizeForDenseIndexingRun3
+                                  : HcalZDCDetId::kSizeForDenseIndexingRun1);
+  }
 }
 
 void HcalCondObjectContainerBase::setTopo(const HcalTopology* topo) {
@@ -19,6 +25,9 @@ void HcalCondObjectContainerBase::setTopo(const HcalTopology* topo) {
     edm::LogError("HCAL") << std::string("Inconsistent dense packing between current topology (") << topo->topoVersion()
                           << ") and calibration object (" << packedIndexVersion_ << ")";
   topo_ = topo;
+  packedIndexVersion_ = topo_->topoVersion();
+  kSizeForDenseIndexing_ =
+      ((packedIndexVersion_ >= 10) ? HcalZDCDetId::kSizeForDenseIndexingRun3 : HcalZDCDetId::kSizeForDenseIndexingRun1);
 }
 
 unsigned int HcalCondObjectContainerBase::indexFor(DetId fId) const {
@@ -114,7 +123,7 @@ unsigned int HcalCondObjectContainerBase::sizeFor(DetId fId) const {
     if (fId.subdetId() == HcalCastorDetId::SubdetectorId) {
       retval = HcalCastorDetId::kSizeForDenseIndexing;
     } else if (fId.subdetId() == HcalZDCDetId::SubdetectorId) {
-      retval = HcalZDCDetId::kSizeForDenseIndexing;
+      retval = kSizeForDenseIndexing_;
     }
   }
   return retval;
diff --git a/CondTools/Geometry/plugins/calowriters.cc b/CondTools/Geometry/plugins/calowriters.cc
index 0621569a1a3b5..bb2b547f1e39b 100644
--- a/CondTools/Geometry/plugins/calowriters.cc
+++ b/CondTools/Geometry/plugins/calowriters.cc
@@ -8,6 +8,8 @@
 #include "Geometry/HcalTowerAlgo/interface/CaloGeometryDBHcal.h"
 #include "Geometry/HcalTowerAlgo/interface/CaloGeometryDBCaloTower.h"
 #include "Geometry/ForwardGeometry/interface/ZdcGeometry.h"
+#include "Geometry/ForwardGeometry/interface/ZdcTopology.h"
+#include "Geometry/ForwardGeometry/interface/CaloGeometryDBZdc.h"
 #include "Geometry/ForwardGeometry/interface/CastorGeometry.h"
 #include "Geometry/Records/interface/HcalRecNumberingRecord.h"
 #include "Geometry/HGCalGeometry/interface/HGCalGeometry.h"
@@ -322,6 +324,114 @@ CaloGeometryDBEP<HGCalGeometry, CaloGeometryDBWriter>::produceAligned(
   return ptr;
 }
 
+template <>
+CaloGeometryDBEP<ZdcGeometry, CaloGeometryDBWriter>::PtrType
+CaloGeometryDBEP<ZdcGeometry, CaloGeometryDBWriter>::produceAligned(const typename ZdcGeometry::AlignedRecord& iRecord) {
+  const auto [alignPtr, globalPtr] = getAlignGlobal(iRecord);
+
+  TrVec tvec;
+  DimVec dvec;
+  IVec ivec;
+  IVec dins;
+
+  const auto& pG = iRecord.get(geometryToken_);
+
+  pG.getSummary(tvec, ivec, dvec, dins);
+
+  CaloGeometryDBWriter::writeIndexed(tvec, dvec, ivec, dins, ZdcGeometry::dbString());
+  //*********************************************************************************************
+
+  const auto& zdcTopology = iRecord.get(additionalTokens_.topology);
+
+  // We know that the numer of shapes chanes with changing depth
+  // so, this check is temporary disabled. We need to implement
+  // a way either to store or calculate the number of shapes or be able
+  // to deal with only max numer of shapes.
+  assert(dvec.size() <= ZdcGeometry::k_NumberOfShapes * ZdcGeometry::k_NumberOfParametersPerShape);
+  ZdcGeometry* zdcGeometry = new ZdcGeometry(&zdcTopology);
+  PtrType ptr(zdcGeometry);
+
+  const unsigned int nTrParm(tvec.size() / zdcTopology.kSizeForDenseIndexing());
+
+  ptr->fillDefaultNamedParameters();
+  ptr->allocateCorners(zdcTopology.kSizeForDenseIndexing());
+  ptr->allocatePar(zdcGeometry->numberOfShapes(), ZdcGeometry::k_NumberOfParametersPerShape);
+
+  for (unsigned int i(0); i < dins.size(); ++i) {
+    const unsigned int nPerShape(ZdcGeometry::k_NumberOfParametersPerShape);
+    DimVec dims;
+    dims.reserve(nPerShape);
+
+    const unsigned int indx(ivec.size() == 1 ? 0 : i);
+
+    DimVec::const_iterator dsrc(dvec.begin() + ivec[indx] * nPerShape);
+
+    for (unsigned int j(0); j != nPerShape; ++j) {
+      dims.push_back(*dsrc);
+      ++dsrc;
+    }
+
+    const CCGFloat* myParm(CaloCellGeometry::getParmPtr(dims, ptr->parMgr(), ptr->parVecVec()));
+
+    const DetId id(zdcTopology.denseId2detId(dins[i]));
+
+    const unsigned int iGlob(nullptr == globalPtr ? 0 : ZdcGeometry::alignmentTransformIndexGlobal(id));
+
+    assert(nullptr == globalPtr || iGlob < globalPtr->m_align.size());
+
+    const AlignTransform* gt(nullptr == globalPtr ? nullptr : &globalPtr->m_align[iGlob]);
+
+    assert(nullptr == gt || iGlob == ZdcGeometry::alignmentTransformIndexGlobal(DetId(gt->rawId())));
+
+    const unsigned int iLoc(nullptr == alignPtr ? 0 : ZdcGeometry::alignmentTransformIndexLocal(id));
+
+    assert(nullptr == alignPtr || iLoc < alignPtr->m_align.size());
+
+    const AlignTransform* at(nullptr == alignPtr ? nullptr : &alignPtr->m_align[iLoc]);
+
+    assert(nullptr == at || (ZdcGeometry::alignmentTransformIndexLocal(DetId(at->rawId())) == iLoc));
+
+    Pt3D lRef;
+    Pt3DVec lc(8, Pt3D(0, 0, 0));
+    zdcGeometry->localCorners(lc, &dims.front(), dins[i], lRef);
+
+    const Pt3D lBck(0.25 * (lc[4] + lc[5] + lc[6] + lc[7]));  // ctr rear  face in local
+    const Pt3D lCor(lc[0]);
+
+    //----------------------------------- create transform from 6 numbers ---
+    const unsigned int jj(i * nTrParm);
+    Tr3D tr;
+    const ROOT::Math::Translation3D tl(tvec[jj], tvec[jj + 1], tvec[jj + 2]);
+    const ROOT::Math::EulerAngles ea(6 == nTrParm ? ROOT::Math::EulerAngles(tvec[jj + 3], tvec[jj + 4], tvec[jj + 5])
+                                                  : ROOT::Math::EulerAngles());
+    const ROOT::Math::Transform3D rt(ea, tl);
+    double xx, xy, xz, dx;
+    double yx, yy, yz, dy;
+    double zx, zy, zz, dz;
+    rt.GetComponents(xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz);
+    tr = Tr3D(CLHEP::HepRep3x3(xx, xy, xz, yx, yy, yz, zx, zy, zz), CLHEP::Hep3Vector(dx, dy, dz));
+
+    // now prepend alignment(s) for final transform
+    const Tr3D atr(nullptr == at ? tr
+                                 : (nullptr == gt ? at->transform() * tr : at->transform() * gt->transform() * tr));
+    //--------------------------------- done making transform  ---------------
+
+    const Pt3D gRef(atr * lRef);
+    const GlobalPoint fCtr(gRef.x(), gRef.y(), gRef.z());
+    const Pt3D gBck(atr * lBck);
+    const GlobalPoint fBck(gBck.x(), gBck.y(), gBck.z());
+    const Pt3D gCor(atr * lCor);
+    const GlobalPoint fCor(gCor.x(), gCor.y(), gCor.z());
+
+    assert(zdcTopology.detId2denseId(id) == dins[i]);
+    ptr->newCell(fCtr, fBck, fCor, myParm, id);
+  }
+
+  ptr->initializeParms();  // initializations; must happen after cells filled
+
+  return ptr;
+}
+
 template class CaloGeometryDBEP<EcalBarrelGeometry, CaloGeometryDBWriter>;
 template class CaloGeometryDBEP<EcalEndcapGeometry, CaloGeometryDBWriter>;
 template class CaloGeometryDBEP<EcalPreshowerGeometry, CaloGeometryDBWriter>;
diff --git a/Configuration/Geometry/python/GeometryRecoDB_cff.py b/Configuration/Geometry/python/GeometryRecoDB_cff.py
index a62a12eeb66e8..e2f00a4b68d40 100644
--- a/Configuration/Geometry/python/GeometryRecoDB_cff.py
+++ b/Configuration/Geometry/python/GeometryRecoDB_cff.py
@@ -21,6 +21,7 @@
 from Geometry.EcalMapping.EcalMappingRecord_cfi import *
 from Geometry.HcalCommonData.hcalDBConstants_cff import *
 from Geometry.HcalEventSetup.hcalTopologyIdeal_cfi import *
+from Geometry.ForwardGeometry.zdcTopologyEP_cfi import *
 
 #  Alignment
 from Geometry.TrackerGeometryBuilder.idealForDigiTrackerGeometryDB_cff import *
diff --git a/Geometry/CaloGeometry/src/CaloGenericDetId.cc b/Geometry/CaloGeometry/src/CaloGenericDetId.cc
index 354f23eca212e..e53c05e15656b 100644
--- a/Geometry/CaloGeometry/src/CaloGenericDetId.cc
+++ b/Geometry/CaloGeometry/src/CaloGenericDetId.cc
@@ -67,11 +67,7 @@ bool CaloGenericDetId::validDetId() const {
   } else if (isHcal()) {
     edm::LogError("CaloGenericDetIdError") << "No support for HB/HE/HO/HF in CaloGenericDetId";
     throw cms::Exception("No support");
-
     returnValue = false;
-  } else if (isZDC()) {
-    const HcalZDCDetId zdid(rawId());
-    returnValue = HcalZDCDetId::validDetId(zdid.section(), zdid.channel());
   } else if (isCastor()) {
     const HcalCastorDetId zdid(rawId());
     returnValue = HcalCastorDetId::validDetId(zdid.section(), zdid.zside() > 0, zdid.sector(), zdid.module());
diff --git a/Geometry/CaloTopology/src/HcalTopology.cc b/Geometry/CaloTopology/src/HcalTopology.cc
index b3c7a500bb728..c550077058b81 100644
--- a/Geometry/CaloTopology/src/HcalTopology.cc
+++ b/Geometry/CaloTopology/src/HcalTopology.cc
@@ -195,14 +195,18 @@ HcalTopology::HcalTopology(HcalTopologyMode::Mode mode,
       HFSize_(kHFSizePreLS1),
       HTSize_(kHTSizePreLS1),
       CALIBSize_(kCALIBSizePreLS1),
-      numberOfShapes_((mode == HcalTopologyMode::SLHC) ? 500 : 87) {
+      numberOfShapes_(
+          ((mode == HcalTopologyMode::SLHC) || (mode_ == HcalTopologyMode::Run3) || (mode_ == HcalTopologyMode::Run4))
+              ? 500
+              : 87) {
   if (mode_ == HcalTopologyMode::LHC) {
-    topoVersion_ = 0;                            //DL
-    HBSize_ = kHBSizePreLS1;                     // qie-per-fiber * fiber/rm * rm/rbx * rbx/barrel * barrel/hcal
-    HESize_ = kHESizePreLS1;                     // qie-per-fiber * fiber/rm * rm/rbx * rbx/endcap * endcap/hcal
-    HOSize_ = kHOSizePreLS1;                     // ieta * iphi * 2
-    HFSize_ = kHFSizePreLS1;                     // phi * eta * depth * pm
-  } else if (mode_ == HcalTopologyMode::SLHC) {  // need to know more eventually
+    topoVersion_ = 0;         //DL
+    HBSize_ = kHBSizePreLS1;  // qie-per-fiber * fiber/rm * rm/rbx * rbx/barrel * barrel/hcal
+    HESize_ = kHESizePreLS1;  // qie-per-fiber * fiber/rm * rm/rbx * rbx/endcap * endcap/hcal
+    HOSize_ = kHOSizePreLS1;  // ieta * iphi * 2
+    HFSize_ = kHFSizePreLS1;  // phi * eta * depth * pm
+  } else if ((mode_ == HcalTopologyMode::SLHC) || (mode_ == HcalTopologyMode::Run3) ||
+             (mode_ == HcalTopologyMode::Run4)) {  // need to know more eventually
     HBSize_ = maxDepthHB * 16 * IPHI_MAX * 2;
     HESize_ = maxDepthHE * (29 - 16 + 1) * maxPhiHE_ * 2;
     HOSize_ = 15 * IPHI_MAX * 2;                // ieta * iphi * 2
@@ -567,7 +571,8 @@ bool HcalTopology::validRaw(const HcalDetId& id) const {
 
   if (ok) {
     if (subdet == HcalBarrel) {
-      if (mode_ == HcalTopologyMode::SLHC || mode_ == HcalTopologyMode::H2HE) {
+      if ((mode_ == HcalTopologyMode::SLHC) || (mode_ == HcalTopologyMode::H2HE) || (mode_ == HcalTopologyMode::Run3) ||
+          (mode_ == HcalTopologyMode::Run4)) {
         if ((aieta > lastHBRing()) || (depth > hcons_->getMaxDepth(0, aieta, iphi, zside)) ||
             (depth < hcons_->getMinDepth(0, aieta, iphi, zside)))
           ok = false;
@@ -576,7 +581,8 @@ bool HcalTopology::validRaw(const HcalDetId& id) const {
           ok = false;
       }
     } else if (subdet == HcalEndcap) {
-      if (mode_ == HcalTopologyMode::SLHC || mode_ == HcalTopologyMode::H2HE) {
+      if ((mode_ == HcalTopologyMode::SLHC) || (mode_ == HcalTopologyMode::H2HE) || (mode_ == HcalTopologyMode::Run3) ||
+          (mode_ == HcalTopologyMode::Run4)) {
         if ((depth > hcons_->getMaxDepth(1, aieta, iphi, zside)) ||
             (depth < hcons_->getMinDepth(1, aieta, iphi, zside)) || (aieta < firstHERing()) || (aieta > lastHERing())) {
           ok = false;
@@ -817,7 +823,8 @@ int HcalTopology::decAIEta(const HcalDetId& id, HcalDetId neighbors[2]) const {
 void HcalTopology::depthBinInformation(
     HcalSubdetector subdet, int etaRing, int iphi, int zside, int& nDepthBins, int& startingBin) const {
   if (subdet == HcalBarrel) {
-    if (mode_ == HcalTopologyMode::SLHC || mode_ == HcalTopologyMode::H2HE) {
+    if ((mode_ == HcalTopologyMode::SLHC) || (mode_ == HcalTopologyMode::H2HE) || (mode_ == HcalTopologyMode::Run3) ||
+        (mode_ == HcalTopologyMode::Run4)) {
       startingBin = hcons_->getMinDepth(0, etaRing, iphi, zside);
       if (etaRing == lastHBRing()) {
         nDepthBins = hcons_->getDepthEta16(1, iphi, zside) - startingBin + 1;
@@ -834,7 +841,8 @@ void HcalTopology::depthBinInformation(
       }
     }
   } else if (subdet == HcalEndcap) {
-    if (mode_ == HcalTopologyMode::SLHC || mode_ == HcalTopologyMode::H2HE) {
+    if ((mode_ == HcalTopologyMode::SLHC) || (mode_ == HcalTopologyMode::H2HE) || (mode_ == HcalTopologyMode::Run3) ||
+        (mode_ == HcalTopologyMode::Run4)) {
       if (etaRing == firstHERing()) {
         startingBin = hcons_->getDepthEta16(2, iphi, zside);
       } else {
@@ -888,14 +896,17 @@ bool HcalTopology::incrementDepth(HcalDetId& detId) const {
     } else if (subdet == HcalBarrel && etaRing == lastHBRing()) {
       // overlap
       subdet = HcalEndcap;
-      if (mode_ == HcalTopologyMode::SLHC || mode_ == HcalTopologyMode::H2HE)
+      if ((mode_ == HcalTopologyMode::SLHC) || (mode_ == HcalTopologyMode::H2HE) || (mode_ == HcalTopologyMode::Run3) ||
+          (mode_ == HcalTopologyMode::Run4))
         depth = hcons_->getDepthEta16(2, iphi, zside);
-    } else if (subdet == HcalEndcap && etaRing == lastHERing() - 1 && mode_ != HcalTopologyMode::SLHC) {
+    } else if ((subdet == HcalEndcap) && (etaRing == lastHERing() - 1) && (mode_ != HcalTopologyMode::SLHC) &&
+               (mode_ != HcalTopologyMode::Run3) && (mode_ != HcalTopologyMode::Run4)) {
       // guard ring HF29 is behind HE 28
       subdet = HcalForward;
       (ieta > 0) ? ++ieta : --ieta;
       depth = 1;
-    } else if (subdet == HcalEndcap && etaRing == lastHERing() && mode_ != HcalTopologyMode::SLHC) {
+    } else if ((subdet == HcalEndcap) && (etaRing == lastHERing()) && (mode_ != HcalTopologyMode::SLHC) &&
+               (mode_ != HcalTopologyMode::Run3) && (mode_ != HcalTopologyMode::Run4)) {
       // split cells go to bigger granularity.  Ring 29 -> 28
       (ieta > 0) ? --ieta : ++ieta;
     } else {
@@ -928,8 +939,9 @@ bool HcalTopology::decrementDepth(HcalDetId& detId) const {
         break;
       }
     }
-  } else if (subdet == HcalEndcap && etaRing == lastHERing() && depth == hcons_->getDepthEta29(iphi, zside, 0) &&
-             mode_ != HcalTopologyMode::SLHC) {
+  } else if ((subdet == HcalEndcap) && (etaRing == lastHERing()) && (depth == hcons_->getDepthEta29(iphi, zside, 0)) &&
+             (mode_ != HcalTopologyMode::SLHC) && (mode_ != HcalTopologyMode::Run3) &&
+             (mode_ != HcalTopologyMode::Run4)) {
     (ieta > 0) ? --ieta : ++ieta;
   } else if (depth <= 0) {
     if (subdet == HcalForward && etaRing == firstHFRing()) {
diff --git a/Geometry/ForwardGeometry/BuildFile.xml b/Geometry/ForwardGeometry/BuildFile.xml
index 92ea1d2655ea1..087d04db51f65 100644
--- a/Geometry/ForwardGeometry/BuildFile.xml
+++ b/Geometry/ForwardGeometry/BuildFile.xml
@@ -2,6 +2,7 @@
   <lib name="1"/>
 </export>
 <use name="Geometry/CaloGeometry"/>
+<use name="Geometry/HcalCommonData"/>
 <use name="Geometry/CaloTopology"/>
 <use name="Geometry/VeryForwardGeometryBuilder"/>
 <use name="DataFormats/HcalDetId"/>
diff --git a/Geometry/ForwardGeometry/interface/CaloGeometryDBZdc.h b/Geometry/ForwardGeometry/interface/CaloGeometryDBZdc.h
new file mode 100644
index 0000000000000..b16f761e9fee1
--- /dev/null
+++ b/Geometry/ForwardGeometry/interface/CaloGeometryDBZdc.h
@@ -0,0 +1,17 @@
+#ifndef Geometry_ForwardGeometry_CaloGeometryDBZdc_h
+#define Geometry_ForwardGeometry_CaloGeometryDBZdc_h
+
+#include "Geometry/CaloEventSetup/interface/CaloGeometryDBEP.h"
+#include "Geometry/ForwardGeometry/interface/ZdcGeometry.h"
+
+namespace calogeometryDBEPimpl {
+  template <>
+  struct AdditionalTokens<ZdcGeometry> {
+    void makeTokens(edm::ESConsumesCollectorT<ZdcGeometry::AlignedRecord>& cc) {
+      topology = cc.consumesFrom<ZdcTopology, HcalRecNumberingRecord>(edm::ESInputTag{});
+    }
+    edm::ESGetToken<ZdcTopology, HcalRecNumberingRecord> topology;
+  };
+}  // namespace calogeometryDBEPimpl
+
+#endif
diff --git a/Geometry/ForwardGeometry/interface/ZdcGeometry.h b/Geometry/ForwardGeometry/interface/ZdcGeometry.h
index eaab12a8ca8d7..9c83f38113384 100644
--- a/Geometry/ForwardGeometry/interface/ZdcGeometry.h
+++ b/Geometry/ForwardGeometry/interface/ZdcGeometry.h
@@ -24,6 +24,7 @@ class ZdcGeometry : public CaloSubdetectorGeometry {
   typedef HcalZDCDetId DetIdType;
 
   static constexpr int k_NumberOfCellsForCorners = HcalZDCDetId::kSizeForDenseIndexing;
+  uint32_t k_NumberOfCellsForCornersN;
 
   static constexpr int k_NumberOfShapes = 3;
 
@@ -63,7 +64,7 @@ class ZdcGeometry : public CaloSubdetectorGeometry {
                   CaloSubdetectorGeometry::IVec& dins) const override;
 
 protected:
-  unsigned int indexFor(const DetId& id) const override { return HcalZDCDetId(id).denseIndex(); }
+  unsigned int indexFor(const DetId& id) const override { return theTopology->detId2DenseIndex(id); }
 
   // Modify the RawPtr class
   const CaloCellGeometry* getGeometryRawPtr(uint32_t index) const override;
diff --git a/Geometry/ForwardGeometry/interface/ZdcHardcodeGeometryLoader.h b/Geometry/ForwardGeometry/interface/ZdcHardcodeGeometryLoader.h
index 67cb51305a129..06ea1158e0439 100644
--- a/Geometry/ForwardGeometry/interface/ZdcHardcodeGeometryLoader.h
+++ b/Geometry/ForwardGeometry/interface/ZdcHardcodeGeometryLoader.h
@@ -17,11 +17,10 @@ class ZdcHardcodeGeometryLoader {
 public:
   typedef CaloSubdetectorGeometry* ReturnType;
 
-  ZdcHardcodeGeometryLoader();
   explicit ZdcHardcodeGeometryLoader(const ZdcTopology& ht);
-  virtual ~ZdcHardcodeGeometryLoader() { delete theTopology; }
+  ~ZdcHardcodeGeometryLoader() {}
 
-  virtual ReturnType load(DetId::Detector det, int subdet);
+  ReturnType load(DetId::Detector det, int subdet);
   ReturnType load();
   void setAddRPD(bool flag) { m_zdcAddRPD = flag; }
 
@@ -30,7 +29,7 @@ class ZdcHardcodeGeometryLoader {
   void fill(HcalZDCDetId::Section section, CaloSubdetectorGeometry* cg);
   void makeCell(const HcalZDCDetId& detId, CaloSubdetectorGeometry* geom) const;
 
-  ZdcTopology* theTopology;
+  //  ZdcTopology* theTopology;
   const ZdcTopology* extTopology;
   bool m_zdcAddRPD;
   float theEMSectiondX;
diff --git a/Geometry/ForwardGeometry/interface/ZdcTopology.h b/Geometry/ForwardGeometry/interface/ZdcTopology.h
index 38d19badd05f2..e11f3c144c9df 100644
--- a/Geometry/ForwardGeometry/interface/ZdcTopology.h
+++ b/Geometry/ForwardGeometry/interface/ZdcTopology.h
@@ -4,6 +4,8 @@
 #include <vector>
 #include "DataFormats/HcalDetId/interface/HcalZDCDetId.h"
 #include "Geometry/CaloTopology/interface/CaloSubdetectorTopology.h"
+#include "Geometry/HcalCommonData/interface/HcalTopologyMode.h"
+#include "Geometry/HcalCommonData/interface/HcalDDDRecConstants.h"
 
 /** \class ZDCTopology
 
@@ -13,7 +15,9 @@
 
 class ZdcTopology : public CaloSubdetectorTopology {
 public:
-  ZdcTopology();
+  ZdcTopology(const HcalDDDRecConstants* hcons);
+
+  HcalTopologyMode::Mode mode() const { return mode_; }
   /** Exlucde a cell*/
   void exclude(const HcalZDCDetId& id);
   /** Exclude a side*/
@@ -49,15 +53,14 @@ class ZdcTopology : public CaloSubdetectorTopology {
   int firstCell(HcalZDCDetId::Section section) const;
   int lastCell(HcalZDCDetId::Section section) const;
 
-private:
-  bool validRaw(const HcalZDCDetId& id) const;
+  uint32_t kSizeForDenseIndexing() const;
+  bool validDenseIndex(uint32_t din) const { return (din < kSizeForDenseIndexing()); }
 
-  std::vector<HcalZDCDetId> exclusionList_;
+  DetId denseId2detId(uint32_t di) const override;
+  uint32_t detId2DenseIndex(const DetId& id) const;
 
-  bool excludeEM_, excludeHAD_, excludeLUM_, excludeRPD_, excludeZP_, excludeZN_;
-
-  int firstEMModule_, lastEMModule_, firstHADModule_, lastHADModule_, firstLUMModule_, lastLUMModule_, firstRPDModule_,
-      lastRPDModule_;
+private:
+  bool validRaw(const HcalZDCDetId& id) const;
 
   bool isExcluded(const HcalZDCDetId& id) const;
 
@@ -69,6 +72,16 @@ class ZdcTopology : public CaloSubdetectorTopology {
   int lastHADModule() const { return lastHADModule_; }
   int lastLUMModule() const { return lastLUMModule_; }
   int lastRPDModule() const { return lastRPDModule_; }
+
+  const HcalDDDRecConstants* hcons_;
+  HcalTopologyMode::Mode mode_;
+
+  std::vector<HcalZDCDetId> exclusionList_;
+
+  bool excludeEM_, excludeHAD_, excludeLUM_, excludeRPD_, excludeZP_, excludeZN_;
+
+  int firstEMModule_, lastEMModule_, firstHADModule_, lastHADModule_, firstLUMModule_, lastLUMModule_, firstRPDModule_,
+      lastRPDModule_;
 };
 
 #endif
diff --git a/Geometry/ForwardGeometry/plugins/SealModule.cc b/Geometry/ForwardGeometry/plugins/SealModule.cc
index 89150ba014e23..2a30006079525 100644
--- a/Geometry/ForwardGeometry/plugins/SealModule.cc
+++ b/Geometry/ForwardGeometry/plugins/SealModule.cc
@@ -1,5 +1,7 @@
+#include "Geometry/ForwardGeometry/plugins/ZdcTopologyEP.h"
 #include "Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.h"
 #include "Geometry/ForwardGeometry/plugins/CastorHardcodeGeometryEP.h"
 //define this as a plug-in
+DEFINE_FWK_EVENTSETUP_MODULE(ZdcTopologyEP);
 DEFINE_FWK_EVENTSETUP_MODULE(CastorHardcodeGeometryEP);
 DEFINE_FWK_EVENTSETUP_MODULE(ZdcHardcodeGeometryEP);
diff --git a/Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.cc b/Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.cc
index 2c622b9c3c6ff..94d151d2381ef 100644
--- a/Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.cc
+++ b/Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.cc
@@ -17,17 +17,18 @@
 #include "Geometry/Records/interface/ZDCGeometryRecord.h"
 #include "Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.h"
 #include "Geometry/ForwardGeometry/interface/ZdcGeometry.h"
+#include "Geometry/ForwardGeometry/interface/ZdcTopology.h"
 #include "FWCore/MessageLogger/interface/MessageLogger.h"
 
 ZdcHardcodeGeometryEP::ZdcHardcodeGeometryEP(const edm::ParameterSet& ps)
     : m_loader(nullptr),
-      m_topology(),
       m_applyAlignment(ps.getParameter<bool>("applyAlignment")),
       m_zdcAddRPD(ps.getParameter<bool>("zdcAddRPD")) {
   //the following line is needed to tell the framework what
   // data is being produced
-  setWhatProduced(this, ZdcGeometry::producerTag());
-
+  //auto cc = setWhatProduced(this, &ZdcHardcodeGeometryEP::produce, ZdcGeometry::producerTag());
+  auto cc = setWhatProduced(this, ZdcGeometry::producerTag());
+  m_zdcTopoToken = cc.consumesFrom<ZdcTopology, HcalRecNumberingRecord>(edm::ESInputTag{});
   // disable
   //   setWhatProduced( this,
   //		    &ZdcHardcodeGeometryEP::produceIdeal,
@@ -44,6 +45,7 @@ ZdcHardcodeGeometryEP::~ZdcHardcodeGeometryEP() {}
 
 ZdcHardcodeGeometryEP::ReturnType ZdcHardcodeGeometryEP::produce(const ZDCGeometryRecord& iRecord) {
   //   ZdcHardcodeGeometryLoader loader ( m_topology ) ;
+  const ZdcTopology& m_topology = iRecord.get(m_zdcTopoToken);
   m_loader = std::make_unique<ZdcHardcodeGeometryLoader>(m_topology);
   m_loader->setAddRPD(m_zdcAddRPD);
   return ReturnType(m_loader->load());
diff --git a/Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.h b/Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.h
index 528e3e1d13cb7..94f3b79c32558 100644
--- a/Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.h
+++ b/Geometry/ForwardGeometry/plugins/ZdcHardcodeGeometryEP.h
@@ -7,8 +7,11 @@
 // user include files
 #include "FWCore/Framework/interface/ModuleFactory.h"
 #include "FWCore/Framework/interface/ESProducer.h"
+#include "FWCore/Utilities/interface/ESGetToken.h"
+#include "Geometry/Records/interface/HcalRecNumberingRecord.h"
 #include "Geometry/Records/interface/ZDCGeometryRecord.h"
 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
+#include "Geometry/ForwardGeometry/interface/ZdcTopology.h"
 #include "Geometry/ForwardGeometry/interface/ZdcHardcodeGeometryLoader.h"
 
 //
@@ -29,10 +32,9 @@ class ZdcHardcodeGeometryEP : public edm::ESProducer {
 private:
   // ----------member data ---------------------------
 
+  edm::ESGetToken<ZdcTopology, HcalRecNumberingRecord> m_zdcTopoToken;
   std::unique_ptr<ZdcHardcodeGeometryLoader> m_loader;
 
-  ZdcTopology m_topology;
-
   bool m_applyAlignment;
   bool m_zdcAddRPD;
 };
diff --git a/Geometry/ForwardGeometry/plugins/ZdcTopologyEP.cc b/Geometry/ForwardGeometry/plugins/ZdcTopologyEP.cc
new file mode 100644
index 0000000000000..fa126dc293792
--- /dev/null
+++ b/Geometry/ForwardGeometry/plugins/ZdcTopologyEP.cc
@@ -0,0 +1,54 @@
+// -*- C++ -*-
+//
+// Package:    ZdcTopologyEP
+// Class:      ZdcTopologyEP
+//
+/**\class ZdcTopologyEP ZdcTopologyEP.h tmp/ZdcTopologyEP/interface/ZdcTopologyEP.h
+
+ Description: <one line class summary>
+
+ Implementation:
+     <Notes on implementation>
+*/
+//
+// Original Author:  Jeremiah Mans
+//         Created:  Mon Oct  3 11:35:27 CDT 2005
+//
+//
+
+#include "Geometry/ForwardGeometry/plugins/ZdcTopologyEP.h"
+#include "Geometry/HcalCommonData/interface/HcalDDDRecConstants.h"
+#include "FWCore/Utilities/interface/Exception.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+
+#define EDM_ML_DEBUG
+
+ZdcTopologyEP::ZdcTopologyEP(const edm::ParameterSet& conf)
+    : m_hdcToken{setWhatProduced(this, &ZdcTopologyEP::produce).consumes<HcalDDDRecConstants>(edm::ESInputTag{})},
+      m_restrictions(conf.getUntrackedParameter<std::string>("Exclude")) {
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCalGeom") << "ZdcTopologyEP::ZdcTopologyEP with Exclude: " << m_restrictions;
+#endif
+}
+
+void ZdcTopologyEP::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+  edm::ParameterSetDescription desc;
+  desc.addUntracked<std::string>("Exclude", "");
+  descriptions.add("zdcTopologyEP", desc);
+}
+
+// ------------ method called to produce the data  ------------
+ZdcTopologyEP::ReturnType ZdcTopologyEP::produce(const HcalRecNumberingRecord& iRecord) {
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCalGeom") << "ZdcTopologyEP::produce(const HcalRecNumberingRecord& iRecord)";
+#endif
+  const HcalDDDRecConstants& hdc = iRecord.get(m_hdcToken);
+
+#ifdef EDM_ML_DEBUG
+  edm::LogVerbatim("HCalGeom") << "mode = " << hdc.getTopoMode();
+#endif
+  ReturnType myTopo(new ZdcTopology(&hdc));
+  return myTopo;
+}
diff --git a/Geometry/ForwardGeometry/plugins/ZdcTopologyEP.h b/Geometry/ForwardGeometry/plugins/ZdcTopologyEP.h
new file mode 100644
index 0000000000000..29539e0435f2e
--- /dev/null
+++ b/Geometry/ForwardGeometry/plugins/ZdcTopologyEP.h
@@ -0,0 +1,33 @@
+#ifndef GEOMETRY_HCALEVENTSETUP_ZDCTOPOLOGYEP_H
+#define GEOMETRY_HCALEVENTSETUP_ZDCTOPOLOGYEP_H 1
+
+#include <memory>
+
+#include "FWCore/Framework/interface/ModuleFactory.h"
+#include "FWCore/Framework/interface/ESProducer.h"
+
+#include "Geometry/ForwardGeometry/interface/ZdcTopology.h"
+#include "Geometry/Records/interface/HcalRecNumberingRecord.h"
+#include "Geometry/Records/interface/IdealGeometryRecord.h"
+
+namespace edm {
+  class ConfigurationDescriptions;
+}
+
+class ZdcTopologyEP : public edm::ESProducer {
+public:
+  ZdcTopologyEP(const edm::ParameterSet&);
+
+  using ReturnType = std::unique_ptr<ZdcTopology>;
+
+  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+  ReturnType produce(const HcalRecNumberingRecord&);
+
+private:
+  // ----------member data ---------------------------
+  edm::ESGetToken<HcalDDDRecConstants, HcalRecNumberingRecord> m_hdcToken;
+  std::string m_restrictions;
+  bool m_mergePosition;
+};
+#endif
diff --git a/Geometry/ForwardGeometry/plugins/moduleDB.cc b/Geometry/ForwardGeometry/plugins/moduleDB.cc
index 62af5df76d52a..3e29230c8d874 100644
--- a/Geometry/ForwardGeometry/plugins/moduleDB.cc
+++ b/Geometry/ForwardGeometry/plugins/moduleDB.cc
@@ -1,16 +1,125 @@
+#include "Geometry/CaloEventSetup/interface/CaloGeometryDBEP.h"
+#include "Geometry/CaloEventSetup/interface/CaloGeometryDBReader.h"
 #include "Geometry/ForwardGeometry/interface/ZdcGeometry.h"
+#include "Geometry/ForwardGeometry/interface/CaloGeometryDBZdc.h"
 #include "Geometry/ForwardGeometry/interface/CastorGeometry.h"
 
-#include "Geometry/CaloEventSetup/interface/CaloGeometryDBEP.h"
-#include "Geometry/CaloEventSetup/interface/CaloGeometryDBReader.h"
+template class CaloGeometryDBEP<CastorGeometry, CaloGeometryDBReader>;
+
+typedef CaloGeometryDBEP<CastorGeometry, CaloGeometryDBReader> CastorGeometryFromDBEP;
+
+DEFINE_FWK_EVENTSETUP_MODULE(CastorGeometryFromDBEP);
+
+template <>
+CaloGeometryDBEP<ZdcGeometry, CaloGeometryDBReader>::PtrType
+CaloGeometryDBEP<ZdcGeometry, CaloGeometryDBReader>::produceAligned(const typename ZdcGeometry::AlignedRecord& iRecord) {
+  const auto [alignPtr, globalPtr] = getAlignGlobal(iRecord);
+
+  TrVec tvec;
+  DimVec dvec;
+  IVec ivec;
+  IVec dins;
+
+  const auto& pG = iRecord.get(geometryToken_);
+
+  tvec = pG.getTranslation();
+  dvec = pG.getDimension();
+  ivec = pG.getIndexes();
+  dins = pG.getDenseIndices();
+  //*********************************************************************************************
+
+  const auto& zdcTopology = iRecord.get(additionalTokens_.topology);
+
+  assert(dvec.size() <= ZdcGeometry::k_NumberOfShapes * ZdcGeometry::k_NumberOfParametersPerShape);
+  ZdcGeometry* zdcGeometry = new ZdcGeometry(&zdcTopology);
+  PtrType ptr(zdcGeometry);
+
+  const unsigned int nTrParm(tvec.size() / zdcTopology.kSizeForDenseIndexing());
+
+  assert(dvec.size() == ZdcGeometry::k_NumberOfShapes * ZdcGeometry::k_NumberOfParametersPerShape);
+
+  ptr->fillDefaultNamedParameters();
+
+  ptr->allocateCorners(zdcTopology.kSizeForDenseIndexing());
+  ptr->allocatePar(zdcGeometry->numberOfShapes(), ZdcGeometry::k_NumberOfParametersPerShape);
+
+  for (unsigned int i(0); i < dins.size(); ++i) {
+    const unsigned int nPerShape(ZdcGeometry::k_NumberOfParametersPerShape);
+    DimVec dims;
+    dims.reserve(nPerShape);
+
+    const unsigned int indx(ivec.size() == 1 ? 0 : i);
+
+    DimVec::const_iterator dsrc(dvec.begin() + ivec[indx] * nPerShape);
+
+    for (unsigned int j(0); j != nPerShape; ++j) {
+      dims.emplace_back(*dsrc);
+      ++dsrc;
+    }
+
+    const CCGFloat* myParm(CaloCellGeometry::getParmPtr(dims, ptr->parMgr(), ptr->parVecVec()));
+
+    const DetId id(zdcTopology.denseId2detId(dins[i]));
+
+    const unsigned int iGlob(nullptr == globalPtr ? 0 : ZdcGeometry::alignmentTransformIndexGlobal(id));
+
+    assert(nullptr == globalPtr || iGlob < globalPtr->m_align.size());
+
+    const AlignTransform* gt(nullptr == globalPtr ? nullptr : &globalPtr->m_align[iGlob]);
+
+    assert(nullptr == gt || iGlob == ZdcGeometry::alignmentTransformIndexGlobal(DetId(gt->rawId())));
+
+    const unsigned int iLoc(nullptr == alignPtr ? 0 : ZdcGeometry::alignmentTransformIndexLocal(id));
+
+    assert(nullptr == alignPtr || iLoc < alignPtr->m_align.size());
+
+    const AlignTransform* at(nullptr == alignPtr ? nullptr : &alignPtr->m_align[iLoc]);
+
+    assert(nullptr == at || (ZdcGeometry::alignmentTransformIndexLocal(DetId(at->rawId())) == iLoc));
+
+    const CaloGenericDetId gId(id);
+
+    Pt3D lRef;
+    Pt3DVec lc(8, Pt3D(0, 0, 0));
+    zdcGeometry->localCorners(lc, &dims.front(), dins[i], lRef);
+
+    const Pt3D lBck(0.25 * (lc[4] + lc[5] + lc[6] + lc[7]));  // ctr rear  face in local
+    const Pt3D lCor(lc[0]);
+
+    //----------------------------------- create transform from 6 numbers ---
+    const unsigned int jj(i * nTrParm);
+    Tr3D tr;
+    const ROOT::Math::Translation3D tl(tvec[jj], tvec[jj + 1], tvec[jj + 2]);
+    const ROOT::Math::EulerAngles ea(6 == nTrParm ? ROOT::Math::EulerAngles(tvec[jj + 3], tvec[jj + 4], tvec[jj + 5])
+                                                  : ROOT::Math::EulerAngles());
+    const ROOT::Math::Transform3D rt(ea, tl);
+    double xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz;
+    rt.GetComponents(xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz);
+    tr = Tr3D(CLHEP::HepRep3x3(xx, xy, xz, yx, yy, yz, zx, zy, zz), CLHEP::Hep3Vector(dx, dy, dz));
+
+    // now prepend alignment(s) for final transform
+    const Tr3D atr(nullptr == at ? tr
+                                 : (nullptr == gt ? at->transform() * tr : at->transform() * gt->transform() * tr));
+    //--------------------------------- done making transform  ---------------
+
+    const Pt3D gRef(atr * lRef);
+    const GlobalPoint fCtr(gRef.x(), gRef.y(), gRef.z());
+    const Pt3D gBck(atr * lBck);
+    const GlobalPoint fBck(gBck.x(), gBck.y(), gBck.z());
+    const Pt3D gCor(atr * lCor);
+    const GlobalPoint fCor(gCor.x(), gCor.y(), gCor.z());
+
+    assert(zdcTopology.detId2denseId(id) == dins[i]);
+
+    ptr->newCell(fCtr, fBck, fCor, myParm, id);
+  }
+  ptr->initializeParms();  // initializations; must happen after cells filled
+
+  return ptr;
+}
 
 template class CaloGeometryDBEP<ZdcGeometry, CaloGeometryDBReader>;
-template class CaloGeometryDBEP<CastorGeometry, CaloGeometryDBReader>;
 
 typedef CaloGeometryDBEP<ZdcGeometry, CaloGeometryDBReader> ZdcGeometryFromDBEP;
 
 DEFINE_FWK_EVENTSETUP_MODULE(ZdcGeometryFromDBEP);
-
-typedef CaloGeometryDBEP<CastorGeometry, CaloGeometryDBReader> CastorGeometryFromDBEP;
-
-DEFINE_FWK_EVENTSETUP_MODULE(CastorGeometryFromDBEP);
diff --git a/Geometry/ForwardGeometry/python/ZdcGeometry_cfi.py b/Geometry/ForwardGeometry/python/ZdcGeometry_cfi.py
index 6b04c020fa78a..9d7c92533ebbf 100644
--- a/Geometry/ForwardGeometry/python/ZdcGeometry_cfi.py
+++ b/Geometry/ForwardGeometry/python/ZdcGeometry_cfi.py
@@ -1,3 +1,4 @@
+from Geometry.ForwardGeometry.zdcTopologyEP_cfi import *
 from Geometry.ForwardGeometry.zdcHardcodeGeometryEP_cfi import zdcHardcodeGeometryEP
 from Configuration.Eras.Modifier_zdcAddRPD_cff import zdcAddRPD
 
diff --git a/Geometry/ForwardGeometry/src/ES_ZdcGeometry.cc b/Geometry/ForwardGeometry/src/ES_ZdcGeometry.cc
new file mode 100644
index 0000000000000..054e5049382a0
--- /dev/null
+++ b/Geometry/ForwardGeometry/src/ES_ZdcGeometry.cc
@@ -0,0 +1,6 @@
+#include "Geometry/ForwardGeometry/interface/ZdcTopology.h"
+#include "Geometry/ForwardGeometry/interface/ZdcGeometry.h"
+#include "FWCore/Utilities/interface/typelookup.h"
+
+TYPELOOKUP_DATA_REG(ZdcTopology);
+TYPELOOKUP_DATA_REG(ZdcGeometry);
diff --git a/Geometry/ForwardGeometry/src/ZdcGeometry.cc b/Geometry/ForwardGeometry/src/ZdcGeometry.cc
index 96298732c381f..2efe05fa73ce1 100644
--- a/Geometry/ForwardGeometry/src/ZdcGeometry.cc
+++ b/Geometry/ForwardGeometry/src/ZdcGeometry.cc
@@ -20,18 +20,22 @@ typedef CaloSubdetectorGeometry::CCGFloat CCGFloat;
 //#define EDM_ML_DEBUG
 
 ZdcGeometry::ZdcGeometry()
-    : theTopology(new ZdcTopology),
+    : k_NumberOfCellsForCornersN(HcalZDCDetId::kSizeForDenseIndexingRun1),
+      theTopology(nullptr),
       lastReqDet_(DetId::Detector(0)),
       lastReqSubdet_(0),
       m_ownsTopology(true),
-      m_cellVec(k_NumberOfCellsForCorners) {}
+      m_cellVec(k_NumberOfCellsForCornersN) {
+  edm::LogWarning("HCalGeom") << "ZdcGeometry::Wrong constructor called";
+}
 
 ZdcGeometry::ZdcGeometry(const ZdcTopology* topology)
-    : theTopology(topology),
+    : k_NumberOfCellsForCornersN(topology->kSizeForDenseIndexing()),
+      theTopology(topology),
       lastReqDet_(DetId::Detector(0)),
       lastReqSubdet_(0),
       m_ownsTopology(false),
-      m_cellVec(k_NumberOfCellsForCorners) {}
+      m_cellVec(k_NumberOfCellsForCornersN) {}
 
 ZdcGeometry::~ZdcGeometry() {
   if (m_ownsTopology)
@@ -81,7 +85,7 @@ void ZdcGeometry::newCell(const GlobalPoint& f1,
 #endif
   assert(cgid.isZDC());
 
-  const unsigned int di(cgid.denseIndex());
+  const unsigned int di(theTopology->detId2DenseIndex(detId));
 
   m_cellVec[di] = IdealZDCTrapezoid(f1, cornersMgr(), parm);
   addValidID(detId);
diff --git a/Geometry/ForwardGeometry/src/ZdcHardcodeGeometryLoader.cc b/Geometry/ForwardGeometry/src/ZdcHardcodeGeometryLoader.cc
index b4439931e3fe0..ff8feb964fb63 100644
--- a/Geometry/ForwardGeometry/src/ZdcHardcodeGeometryLoader.cc
+++ b/Geometry/ForwardGeometry/src/ZdcHardcodeGeometryLoader.cc
@@ -7,13 +7,7 @@
 
 typedef CaloCellGeometry::CCGFloat CCGFloat;
 
-ZdcHardcodeGeometryLoader::ZdcHardcodeGeometryLoader() : theTopology(new ZdcTopology), extTopology(theTopology) {
-  init();
-}
-
-ZdcHardcodeGeometryLoader::ZdcHardcodeGeometryLoader(const ZdcTopology& ht) : theTopology(nullptr), extTopology(&ht) {
-  init();
-}
+ZdcHardcodeGeometryLoader::ZdcHardcodeGeometryLoader(const ZdcTopology& ht) : extTopology(&ht) { init(); }
 
 void ZdcHardcodeGeometryLoader::init() {}
 
@@ -56,7 +50,7 @@ void ZdcHardcodeGeometryLoader::fill(HcalZDCDetId::Section section, ReturnType g
       zdcIds.emplace_back(id);
   }
   if (geom->cornersMgr() == nullptr)
-    geom->allocateCorners(HcalZDCDetId::kSizeForDenseIndexing);
+    geom->allocateCorners(extTopology->kSizeForDenseIndexing());
   if (geom->parMgr() == nullptr)
     geom->allocatePar(ZdcGeometry::k_NumberOfParametersPerShape * ZdcGeometry::k_NumberOfShapes,
                       ZdcGeometry::k_NumberOfParametersPerShape);
diff --git a/Geometry/ForwardGeometry/src/ZdcTopology.cc b/Geometry/ForwardGeometry/src/ZdcTopology.cc
index 649caea0a70fa..56bd818f52dee 100644
--- a/Geometry/ForwardGeometry/src/ZdcTopology.cc
+++ b/Geometry/ForwardGeometry/src/ZdcTopology.cc
@@ -5,8 +5,9 @@
 #include <iostream>
 #include <algorithm>
 
-ZdcTopology::ZdcTopology()
-    : excludeEM_(false),
+ZdcTopology::ZdcTopology(const HcalDDDRecConstants* hcons)
+    : hcons_(hcons),
+      excludeEM_(false),
       excludeHAD_(false),
       excludeLUM_(false),
       excludeRPD_(false),
@@ -19,7 +20,12 @@ ZdcTopology::ZdcTopology()
       firstLUMModule_(1),
       lastLUMModule_(HcalZDCDetId::kDepLUM),
       firstRPDModule_(1),
-      lastRPDModule_(HcalZDCDetId::kDepRPD) {}
+      lastRPDModule_(HcalZDCDetId::kDepRPD) {
+  mode_ = (HcalTopologyMode::Mode)(hcons_->getTopoMode());
+  excludeRPD_ = (mode_ < HcalTopologyMode::Mode::Run3);
+  edm::LogVerbatim("ForwardGeom") << "ZdcTopology : Mode " << mode_ << ":" << HcalTopologyMode::Mode::Run3
+                                  << " ExcludeRPD " << excludeRPD_;
+}
 
 bool ZdcTopology::valid(const HcalZDCDetId& id) const {
   // check the raw rules
@@ -161,9 +167,9 @@ bool ZdcTopology::validRaw(const HcalZDCDetId& id) const {
     ok = false;
   else if (id.channel() <= 0)
     ok = false;
+  //else if (!(id.section() == HcalZDCDetId::EM || id.section() == HcalZDCDetId::HAD || id.section() == HcalZDCDetId::LUM))
   else if (!(id.section() == HcalZDCDetId::EM || id.section() == HcalZDCDetId::HAD ||
-             id.section() == HcalZDCDetId::LUM))
-    //else if (!(id.section() == HcalZDCDetId::EM || id.section() == HcalZDCDetId::HAD || id.section()== HcalZDCDetId::LUM || id.section()== HcalZDCDetId::RPD))
+             id.section() == HcalZDCDetId::LUM || id.section() == HcalZDCDetId::RPD))
     ok = false;
   else if (id.section() == HcalZDCDetId::EM && id.channel() > HcalZDCDetId::kDepEM)
     ok = false;
@@ -356,3 +362,45 @@ int ZdcTopology::lastCell(HcalZDCDetId::Section section) const {
   }
   return lastCell;
 }
+
+uint32_t ZdcTopology::kSizeForDenseIndexing() const {
+  return (mode_ >= HcalTopologyMode::Mode::Run3 ? HcalZDCDetId::kSizeForDenseIndexingRun3
+                                                : HcalZDCDetId::kSizeForDenseIndexingRun1);
+}
+
+DetId ZdcTopology::denseId2detId(uint32_t di) const {
+  if (validDenseIndex(di)) {
+    bool lz(false);
+    uint32_t dp(0);
+    HcalZDCDetId::Section se(HcalZDCDetId::Unknown);
+    if (di >= 2 * HcalZDCDetId::kDepRun1) {
+      lz = (di >= (HcalZDCDetId::kDepRun1 + HcalZDCDetId::kDepTot));
+      se = HcalZDCDetId::RPD;
+      dp = 1 + ((di - 2 * HcalZDCDetId::kDepRun1) % HcalZDCDetId::kDepRPD);
+    } else {
+      lz = (di >= HcalZDCDetId::kDepRun1);
+      uint32_t in = (di % HcalZDCDetId::kDepRun1);
+      se = (in < HcalZDCDetId::kDepEM
+                ? HcalZDCDetId::EM
+                : (in < HcalZDCDetId::kDepEM + HcalZDCDetId::kDepHAD ? HcalZDCDetId::HAD : HcalZDCDetId::LUM));
+      dp = (se == HcalZDCDetId::EM ? in + 1
+                                   : (se == HcalZDCDetId::HAD ? in - HcalZDCDetId::kDepEM + 1
+                                                              : in - HcalZDCDetId::kDepEM - HcalZDCDetId::kDepHAD + 1));
+    }
+    return static_cast<DetId>(HcalZDCDetId(se, lz, dp));
+  }
+  return DetId();
+}
+
+uint32_t ZdcTopology::detId2DenseIndex(const DetId& id) const {
+  HcalZDCDetId detId(id);
+  const int32_t se(detId.section());
+  uint32_t di = (detId.channel() - 1 +
+                 (se == HcalZDCDetId::RPD
+                      ? 2 * HcalZDCDetId::kDepRun1 + (detId.zside() < 0 ? 0 : HcalZDCDetId::kDepRPD)
+                      : ((detId.zside() < 0 ? 0 : HcalZDCDetId::kDepRun1) +
+                         (se == HcalZDCDetId::HAD
+                              ? HcalZDCDetId::kDepEM
+                              : (se == HcalZDCDetId::LUM ? HcalZDCDetId::kDepEM + HcalZDCDetId::kDepHAD : 0)))));
+  return di;
+}
diff --git a/Geometry/HcalCommonData/data/hcalRecNumbering/2021/v2/hcalRecNumbering.xml b/Geometry/HcalCommonData/data/hcalRecNumbering/2021/v2/hcalRecNumbering.xml
new file mode 100644
index 0000000000000..ba48e7d98b885
--- /dev/null
+++ b/Geometry/HcalCommonData/data/hcalRecNumbering/2021/v2/hcalRecNumbering.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<DDDefinition>
+
+<ConstantsSection  label="hcalRecNumbering.xml" eval="true">
+  <Vector name="etagroup" type="numeric" nEntries="29">
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+  </Vector>
+  <Vector name="phigroup" type="numeric" nEntries="29">
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+  </Vector>
+  <Vector name="layerGroupRecEta1" type="numeric" nEntries="19">
+    1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4
+  </Vector>
+  <Vector name="layerGroupRecEta16" type="numeric" nEntries="19">
+    1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+  </Vector>
+  <Vector name="layerGroupRecEta17" type="numeric" nEntries="19">
+    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
+  </Vector>
+  <Vector name="layerGroupRecEta18" type="numeric" nEntries="19">
+    1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5
+  </Vector>
+  <Vector name="layerGroupRecEta19" type="numeric" nEntries="19">
+    1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6
+  </Vector>
+  <Vector name="layerGroupRecEta26" type="numeric" nEntries="19">
+    1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7
+  </Vector>
+</ConstantsSection>
+
+<SpecParSection label="hcalRecNumbering.xml" eval="true">
+  <SpecPar name="hcal">
+    <PartSelector path="//HBS.*"/>
+    <PartSelector path="//HTS.*"/>
+    <PartSelector path="//HES.*"/>
+    <PartSelector path="//HVQX"/>
+    <Parameter name="OnlyForHcalRecNumbering" value="HCAL" eval="false"/>
+    <Parameter name="TopologyMode" value="HcalTopologyMode::Run3" eval="false"/>
+    <Parameter name="TriggerMode"  value="HcalTopologyMode::TriggerMode_2021" eval="false"/>
+  </SpecPar>
+</SpecParSection>
+
+</DDDefinition>
diff --git a/Geometry/HcalCommonData/data/hcalRecNumbering/NoHE/v3/hcalRecNumbering.xml b/Geometry/HcalCommonData/data/hcalRecNumbering/NoHE/v3/hcalRecNumbering.xml
new file mode 100644
index 0000000000000..bcfee49616e34
--- /dev/null
+++ b/Geometry/HcalCommonData/data/hcalRecNumbering/NoHE/v3/hcalRecNumbering.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<DDDefinition>
+
+<ConstantsSection  label="hcalRecNumbering.xml" eval="true">
+  <Vector name="etagroup" type="numeric" nEntries="16">
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+  </Vector>
+  <Vector name="phigroup" type="numeric" nEntries="16">
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+  </Vector>
+  <Vector name="layerGroupRecEta1" type="numeric" nEntries="19">
+    1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4
+  </Vector>
+  <Vector name="layerGroupRecEta16" type="numeric" nEntries="19">
+    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
+  </Vector>
+</ConstantsSection>
+
+<SpecParSection label="hcalRecNumbering.xml" eval="true">
+  <SpecPar name="hcal">
+    <PartSelector path="//HBS.*"/>
+    <PartSelector path="//HTS.*"/>
+    <PartSelector path="//HVQX"/>
+    <Parameter name="OnlyForHcalRecNumbering" value="HCAL" eval="false"/>
+    <Parameter name="TopologyMode" value="HcalTopologyMode::Run4" eval="false"/>
+    <Parameter name="TriggerMode"  value="HcalTopologyMode::TriggerMode_2021" eval="false"/>
+  </SpecPar>
+</SpecParSection>
+
+</DDDefinition>
diff --git a/Geometry/HcalCommonData/interface/HcalTopologyMode.h b/Geometry/HcalCommonData/interface/HcalTopologyMode.h
index 53c692135e129..4a3aa4de0f93c 100644
--- a/Geometry/HcalCommonData/interface/HcalTopologyMode.h
+++ b/Geometry/HcalCommonData/interface/HcalTopologyMode.h
@@ -23,7 +23,7 @@ class StringToEnumParser {
 };
 
 namespace HcalTopologyMode {
-  enum Mode { LHC = 0, H2 = 1, SLHC = 2, H2HE = 3 };
+  enum Mode { LHC = 0, H2 = 1, SLHC = 2, H2HE = 3, Run3 = 4, Run4 = 5 };
 
   enum TriggerMode {
     TriggerMode_2009 = 0,        // HF is summed in 3x2 regions
diff --git a/Geometry/HcalTowerAlgo/src/HcalHardcodeGeometryLoader.cc b/Geometry/HcalTowerAlgo/src/HcalHardcodeGeometryLoader.cc
index 134d65d28ecf4..e95aa09c1bc6e 100644
--- a/Geometry/HcalTowerAlgo/src/HcalHardcodeGeometryLoader.cc
+++ b/Geometry/HcalTowerAlgo/src/HcalHardcodeGeometryLoader.cc
@@ -84,12 +84,13 @@ std::vector<HcalHardcodeGeometryLoader::HBHOCellParameters> HcalHardcodeGeometry
                            HBRMAX};
   float slhcDepths[4] = {HBRMIN, 214., 239., HBRMAX};
 #ifdef EDM_ML_DEBUG
-  edm::LogVerbatim("HCalGeom") << "FlexiGeometryLoader called for " << topology.mode() << ":" << HcalTopologyMode::SLHC;
+  edm::LogVerbatim("HCalGeom") << "FlexiGeometryLoader called for " << topology.mode() << ":" << HcalTopologyMode::SLHC
+                               << ":" << HcalTopologyMode::Run3 << ":" << HcalTopologyMode::Run4;
 #endif
   std::vector<HcalHardcodeGeometryLoader::HBHOCellParameters> result;
   for (int iring = 1; iring <= 16; ++iring) {
     std::vector<float> depths;
-    if (topology.mode() != HcalTopologyMode::SLHC) {
+    if ((topology.mode() != HcalTopologyMode::SLHC) && (topology.mode() != HcalTopologyMode::Run4)) {
       if (iring == 15) {
         for (float ring15Depth : ring15Depths)
           depths.emplace_back(ring15Depth);
@@ -277,7 +278,7 @@ std::vector<HcalHardcodeGeometryLoader::HECellParameters> HcalHardcodeGeometryLo
     int iring = iringm16 + 16;
     std::vector<float> depths;
     unsigned int startingDepth = 1;
-    if (topology.mode() != HcalTopologyMode::SLHC) {
+    if ((topology.mode() != HcalTopologyMode::SLHC) && (topology.mode() != HcalTopologyMode::Run4)) {
       if (iring == 16) {
         for (float ring16Depth : ring16Depths)
           depths.emplace_back(ring16Depth);
@@ -361,7 +362,8 @@ std::vector<HcalHardcodeGeometryLoader::HECellParameters> HcalHardcodeGeometryLo
 #endif
         int stepPhi = (iring >= topology.firstHEDoublePhiRing() ? 2 : 1);
         int deltaPhi = (iring >= topology.firstHEDoublePhiRing() ? 10 : 5);
-        if (topology.mode() != HcalTopologyMode::SLHC && iring == topology.lastHERing() - 1 && idepth == ndepth - 1) {
+        if ((topology.mode() != HcalTopologyMode::SLHC) && (topology.mode() != HcalTopologyMode::Run4) &&
+            (iring == topology.lastHERing() - 1) && (idepth == ndepth - 1)) {
 #ifdef EDM_ML_DEBUG
           edm::LogVerbatim("HCalGeom") << "HE iEta " << iring << " Depth " << depthIndex << " Eta " << etamin << ":"
                                        << etaBounds[iringm16 + 2];
diff --git a/Geometry/Records/interface/ZDCGeometryRecord.h b/Geometry/Records/interface/ZDCGeometryRecord.h
index 41f37b3bfbdce..8876e49b49a99 100644
--- a/Geometry/Records/interface/ZDCGeometryRecord.h
+++ b/Geometry/Records/interface/ZDCGeometryRecord.h
@@ -13,6 +13,7 @@
 #include "FWCore/Framework/interface/EventSetupRecordImplementation.h"
 #include "FWCore/Framework/interface/DependentRecordImplementation.h"
 #include "Geometry/Records/interface/IdealGeometryRecord.h"
+#include "Geometry/Records/interface/HcalRecNumberingRecord.h"
 #include "CondFormats/AlignmentRecord/interface/ZDCAlignmentRcd.h"
 #include "CondFormats/AlignmentRecord/interface/ZDCAlignmentErrorRcd.h"
 #include "CondFormats/AlignmentRecord/interface/ZDCAlignmentErrorExtendedRcd.h"
@@ -23,6 +24,9 @@
 class ZDCGeometryRecord
     : public edm::eventsetup::DependentRecordImplementation<ZDCGeometryRecord,
                                                             edm::mpl::Vector<IdealGeometryRecord,
+                                                                             HcalParametersRcd,
+                                                                             HcalSimNumberingRecord,
+                                                                             HcalRecNumberingRecord,
                                                                              ZDCAlignmentRcd,
                                                                              ZDCAlignmentErrorRcd,
                                                                              ZDCAlignmentErrorExtendedRcd,
diff --git a/HLTrigger/Configuration/python/customizeHLTforCMSSW.py b/HLTrigger/Configuration/python/customizeHLTforCMSSW.py
index 0ddcdca2f3ff3..ce48719e55565 100644
--- a/HLTrigger/Configuration/python/customizeHLTforCMSSW.py
+++ b/HLTrigger/Configuration/python/customizeHLTforCMSSW.py
@@ -261,6 +261,18 @@ def checkHLTfor43774(process):
 
     return process
 
+# Adding zdc Topology producer
+def customizeHLTfor46011(process):
+    """Add topology producer for ZDC"""
+
+    if hasattr(process, 'ZdcGeometryFromDBEP'):
+        process.ZdcTopologyEP = cms.ESProducer( "ZdcTopologyEP",
+                                                Exclude = cms.untracked.string( "" ),
+                                                appendToDataLabel = cms.string( "" )
+        )
+
+    return process
+
 def customizeHLTfor44576(process):
     """Ensure TrackerAdditionalParametersPerDetRcd ESProducer is run when needed"""
     for esprod in esproducers_by_type(process, 'TrackerGeometricDetESModule'):
@@ -327,5 +339,6 @@ def customizeHLTforCMSSW(process, menuType="GRun"):
     process = checkHLTfor43774(process)
     process = customizeHLTfor44576(process)
     process = customizeHLTfor45063(process)
-
+    process = customizeHLTfor46011(process)
+    
     return process
diff --git a/SimCalorimetry/HcalSimProducers/src/HcalDigitizer.cc b/SimCalorimetry/HcalSimProducers/src/HcalDigitizer.cc
index 2858830c551ef..612a894d32be9 100644
--- a/SimCalorimetry/HcalSimProducers/src/HcalDigitizer.cc
+++ b/SimCalorimetry/HcalSimProducers/src/HcalDigitizer.cc
@@ -204,6 +204,7 @@ HcalDigitizer::HcalDigitizer(const edm::ParameterSet &ps, edm::ConsumesCollector
       std::make_unique<QIE10Digitizer>(theHFQIE10Response.get(), theHFQIE10ElectronicsSim.get(), doEmpty);
   theHFDigitizer = std::make_unique<HFDigitizer>(theHFResponse.get(), theHFElectronicsSim.get(), doEmpty);
 
+  // temporary move until Run3 ZDC will be added
   theZDCDigitizer = std::make_unique<ZDCDigitizer>(theZDCResponse.get(), theZDCElectronicsSim.get(), doEmpty);
 
   testNumbering_ = ps.getParameter<bool>("TestNumbering");
@@ -233,7 +234,8 @@ HcalDigitizer::HcalDigitizer(const edm::ParameterSet &ps, edm::ConsumesCollector
       theHFDigitizer->setDebugCaloSamples(true);
     if (theHFQIE10Digitizer)
       theHFQIE10Digitizer->setDebugCaloSamples(true);
-    theZDCDigitizer->setDebugCaloSamples(true);
+    if (theZDCDigitizer)
+      theZDCDigitizer->setDebugCaloSamples(true);
   }
 
   // option to ignore Geant time distribution in SimHits, for debugging
@@ -298,8 +300,10 @@ void HcalDigitizer::setHONoiseSignalGenerator(HcalBaseSignalGenerator *noiseGene
 void HcalDigitizer::setZDCNoiseSignalGenerator(HcalBaseSignalGenerator *noiseGenerator) {
   noiseGenerator->setParameterMap(&theParameterMap);
   noiseGenerator->setElectronicsSim(theZDCElectronicsSim.get());
-  theZDCDigitizer->setNoiseSignalGenerator(noiseGenerator);
-  theZDCAmplifier->setNoiseSignalGenerator(noiseGenerator);
+  if (theZDCDigitizer) {
+    theZDCDigitizer->setNoiseSignalGenerator(noiseGenerator);
+    theZDCAmplifier->setNoiseSignalGenerator(noiseGenerator);
+  }
 }
 
 void HcalDigitizer::initializeEvent(edm::Event const &e, edm::EventSetup const &eventSetup) {
@@ -336,7 +340,8 @@ void HcalDigitizer::initializeEvent(edm::Event const &e, edm::EventSetup const &
     theHFQIE10Digitizer->initializeHits();
   if (theHFDigitizer)
     theHFDigitizer->initializeHits();
-  theZDCDigitizer->initializeHits();
+  if (theZDCDigitizer)
+    theZDCDigitizer->initializeHits();
 }
 
 void HcalDigitizer::accumulateCaloHits(edm::Handle<std::vector<PCaloHit>> const &hcalHandle,
@@ -414,7 +419,7 @@ void HcalDigitizer::accumulateCaloHits(edm::Handle<std::vector<PCaloHit>> const
   }
 
   if (isZDC) {
-    if (zdcgeo) {
+    if (zdcgeo && theZDCDigitizer) {
       theZDCDigitizer->add(*zdcHandle.product(), bunchCrossing, engine);
     }
   } else {
@@ -488,7 +493,7 @@ void HcalDigitizer::finalizeEvent(edm::Event &e, const edm::EventSetup &eventSet
     if (theHFQIE10Digitizer)
       theHFQIE10Digitizer->run(*hfQIE10Result, engine);
   }
-  if (isZDC && zdcgeo) {
+  if (isZDC && zdcgeo && theZDCDigitizer) {
     theZDCDigitizer->run(*zdcResult, engine);
   }
 
@@ -538,8 +543,9 @@ void HcalDigitizer::finalizeEvent(edm::Event &e, const edm::EventSetup &eventSet
     if (theHFQIE10Digitizer)
       csResult->insert(
           csResult->end(), theHFQIE10Digitizer->getCaloSamples().begin(), theHFQIE10Digitizer->getCaloSamples().end());
-    csResult->insert(
-        csResult->end(), theZDCDigitizer->getCaloSamples().begin(), theZDCDigitizer->getCaloSamples().end());
+    if (theZDCDigitizer)
+      csResult->insert(
+          csResult->end(), theZDCDigitizer->getCaloSamples().begin(), theZDCDigitizer->getCaloSamples().end());
     e.put(std::move(csResult), "HcalSamples");
   }
 
@@ -637,7 +643,8 @@ void HcalDigitizer::updateGeometry(const edm::EventSetup &eventSetup) {
   // handle mixed QIE8/10 scenario in HF
   buildHFQIECells(hfCells, eventSetup);
 
-  theZDCDigitizer->setDetIds(zdcCells);
+  if (theZDCDigitizer)
+    theZDCDigitizer->setDetIds(zdcCells);
 
   // fill test hits collection if desired and empty
   if (injectTestHits_ && injectedHits_.empty() && !injectedHitsCells_.empty() && !injectedHitsEnergy_.empty()) {
diff --git a/SimCalorimetry/HcalTrigPrimProducers/plugins/HcalTrigPrimDigiProducer.cc b/SimCalorimetry/HcalTrigPrimProducers/plugins/HcalTrigPrimDigiProducer.cc
index 3fddb13fd68e5..bfefcc516b523 100644
--- a/SimCalorimetry/HcalTrigPrimProducers/plugins/HcalTrigPrimDigiProducer.cc
+++ b/SimCalorimetry/HcalTrigPrimProducers/plugins/HcalTrigPrimDigiProducer.cc
@@ -179,7 +179,7 @@ void HcalTrigPrimDigiProducer::beginRun(const edm::Run& run, const edm::EventSet
     if (hcalTTDetId.null())
       continue;
 
-    int aieta = abs(hcalTTDetId.ieta());
+    int aieta = std::abs(hcalTTDetId.ieta());
     // Do not let ieta 29 in the map
     if (aieta >= lastHERing)
       continue;
@@ -376,7 +376,7 @@ void HcalTrigPrimDigiProducer::produce(edm::Event& iEvent, const edm::EventSetup
   if (runZS_)
     theAlgo_.runZS(*result);
 
-  //  edm::LogInfo("HcalTrigPrimDigiProducer") << "HcalTrigPrims: " << result->size();
+  edm::LogInfo("HcalTrigPrimDigiProducer") << "HcalTrigPrims: " << result->size();
 
   // Step D: Put outputs into event
   iEvent.put(std::move(result));