Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-15 07:45:30

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 /// \file TSRun.cc
0027 /// \brief Implementation of the TSRun class
0028 ///
0029 /// TSRun contains five hits collections types:
0030 ///   - 1) a thread-local hits map,
0031 ///   - 2) a global atomic hits map
0032 ///   - 3) a global "mutex" hits map
0033 ///   - 4) a global G4StatAnalysis hits deque
0034 ///   - 5) a global G4ConvergenceTester hits deque
0035 ///
0036 /// The thread-local hits map is the same as you will find in many other
0037 ///     examples.
0038 ///
0039 /// The atomics hits map is the purpose of this example. Code-wise, the
0040 ///     implementation looks extremely similar to the thread-local version with
0041 ///     3 primary exceptions:
0042 ///     - (1) construction - there should only be one instance so it should be a
0043 ///           static member variable or a pointer/reference to a single instance
0044 ///     - (2) It does not need to, nor should be, summed in G4Run::Merge()
0045 ///     - (3) destruction -- it should only be cleared by the master thread since
0046 ///           there is only one instance.
0047 ///
0048 /// The "mutex" hits map is also included as reference for checking the results
0049 ///     accumulated by the thread-local hits maps and atomic hits maps. The
0050 ///     differences w.r.t. this hits maps are computed in
0051 ///     TSRunAction::EndOfRunAction
0052 ///
0053 /// The "G4StatAnalysis" and "G4ConvergenceTester" hits deques are
0054 ///     memory-efficient version of the standard G4THitsMap. While maps are
0055 ///     ideal for scoring at the G4Event-level, where sparsity w.r.t. indices
0056 ///     is common; at the G4Run-level, these data structures require much
0057 ///     less memory overhead. Due to a lack of
0058 ///     G4ConvergenceTester::operator+=(G4ConvergenceTester), the static version
0059 ///     of G4ConvergenceTester is the only valid way to use G4ConvergenceTester
0060 ///     in a scoring container. This is not the case for G4StatAnalysis, which
0061 ///     can be used in lieu of G4double.
0062 ///
0063 //
0064 //
0065 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0066 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0067 
0068 #include "TSRun.hh"
0069 
0070 #include "TSDetectorConstruction.hh"
0071 
0072 #include "G4MultiFunctionalDetector.hh"
0073 #include "G4SDManager.hh"
0074 #include "G4VPrimitiveScorer.hh"
0075 
0076 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0077 
0078 std::vector<G4TAtomicHitsMap<G4double>*> TSRun::fAtomicRunMaps;
0079 
0080 std::map<G4String, TSRun::MutexHitsMap_t> TSRun::fMutexRunMaps;
0081 
0082 std::vector<G4StatContainer<G4ConvergenceTester>*> TSRun::fConvMaps;
0083 
0084 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0085 
0086 TSRun::TSRun(const G4String& mfd_name) : G4Run()
0087 {
0088   ConstructMFD(mfd_name);
0089 }
0090 
0091 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0092 
0093 TSRun::~TSRun()
0094 {
0095   //--- Clear HitsMap for RUN
0096   for (unsigned i = 0; i < fRunMaps.size(); ++i)
0097     delete fRunMaps[i];
0098 
0099   if (!G4Threading::IsWorkerThread()) {
0100     for (unsigned i = 0; i < fAtomicRunMaps.size(); ++i)
0101       delete fAtomicRunMaps[i];
0102 
0103     for (auto& itr : fConvMaps)
0104       delete itr;
0105 
0106     fAtomicRunMaps.clear();
0107     fMutexRunMaps.clear();
0108     fConvMaps.clear();
0109   }
0110 }
0111 
0112 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0113 
0114 //    clear all data members.
0115 void TSRun::ConstructMFD(const G4String& mfdName)
0116 {
0117   G4SDManager* SDman = G4SDManager::GetSDMpointer();
0118   //=================================================
0119   //  Initalize RunMaps for accumulation.
0120   //  Get CollectionIDs for HitCollections.
0121   //=================================================
0122   G4MultiFunctionalDetector* mfd =
0123     (G4MultiFunctionalDetector*)(SDman->FindSensitiveDetector(mfdName));
0124   //
0125   if (mfd) {
0126     //--- Loop over the registered primitive scorers.
0127     for (G4int icol = 0; icol < mfd->GetNumberOfPrimitives(); icol++) {
0128       // Get Primitive Scorer object.
0129       G4VPrimitiveScorer* scorer = mfd->GetPrimitive(icol);
0130       // collection name and collectionID for HitsCollection,
0131       // where type of HitsCollection is G4THitsMap in case
0132       // of primitive scorer.
0133       // The collection name is given by <MFD name>/<Primitive
0134       // Scorer name>.
0135       G4String collectionName = scorer->GetName();
0136       G4String fullCollectionName = mfdName + "/" + collectionName;
0137       G4int collectionID = SDman->GetCollectionID(fullCollectionName);
0138       //
0139       if (collectionID >= 0) {
0140         G4cout << "++ " << fullCollectionName << " id " << collectionID << G4endl;
0141         // Store obtained HitsCollection information into data members.
0142         // And, creates new G4THitsMap for accumulating quantities during RUN.
0143         fCollNames.push_back(fullCollectionName);
0144         fCollIDs.push_back(collectionID);
0145         fRunMaps.push_back(new G4THitsMap<G4double>(mfdName, collectionName));
0146         fStatMaps.push_back(new G4StatContainer<G4StatAnalysis>(
0147           mfdName, collectionName, TSDetectorConstruction::Instance()->GetTotalTargets()));
0148         if (!G4Threading::IsWorkerThread()) {
0149           fAtomicRunMaps.push_back(new G4TAtomicHitsMap<G4double>(mfdName, collectionName));
0150           fMutexRunMaps[fCollNames[collectionID]].clear();
0151           fConvMaps.push_back(new G4StatContainer<G4ConvergenceTester>(
0152             mfdName, collectionName, TSDetectorConstruction::Instance()->GetTotalTargets()));
0153         }
0154       }
0155       else {
0156         G4cout << "** collection " << fullCollectionName << " not found. " << G4endl;
0157       }
0158     }
0159   }
0160 }
0161 
0162 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0163 //
0164 //  RecordEvent is called at end of event.
0165 //  For scoring purpose, the resultant quantity in a event,
0166 //  is accumulated during a TSRun.
0167 void TSRun::RecordEvent(const G4Event* aEvent)
0168 {
0169   G4Run::RecordEvent(aEvent);
0170 
0171   //=============================
0172   // HitsCollection of This Event
0173   //============================
0174   G4HCofThisEvent* HCE = aEvent->GetHCofThisEvent();
0175   if (!HCE) return;
0176 
0177   for (unsigned i = 0; i < fCollIDs.size(); ++i) {
0178     G4int fCollID = fCollIDs.at(i);
0179     //=======================================================
0180     // Sum up HitsMap of this Event into HitsMap of this RUN
0181     //=======================================================
0182     G4THitsMap<G4double>* EvtMap = 0;
0183     if (fCollID >= 0)  // Collection is attached to HCE
0184       EvtMap = static_cast<G4THitsMap<G4double>*>(HCE->GetHC(fCollID));
0185     else
0186       G4cout << " Error EvtMap Not Found " << G4endl;
0187 
0188     if (EvtMap) {
0189       //=== Sum up HitsMap of this event to HitsMap of RUN.===
0190       {
0191         *fRunMaps[fCollID] += *EvtMap;
0192       }
0193       //=== Sum up HitsMap of this event to StatMap of RUN.===
0194       {
0195         // G4StatAnalysis map
0196         *fStatMaps[fCollID] += *EvtMap;
0197       }
0198       //=== Sum up HitsMap of this event to atomic HitsMap of RUN.===
0199       {
0200         *fAtomicRunMaps[fCollID] += *EvtMap;
0201       }
0202       //=== Sum up HitsMap of this event to MutexMap of RUN.===
0203       {
0204         // mutex run map
0205         static G4Mutex mtx = G4MUTEX_INITIALIZER;
0206         G4AutoLock lock(&mtx);
0207         for (const auto& itr : *EvtMap)
0208           fMutexRunMaps[fCollNames[fCollID]][itr.first] += *itr.second;
0209       }
0210       //=== Sum up HitsMap of this event to MutexMap of RUN.===
0211       {
0212         // G4ConvergenceTester run map
0213         static G4Mutex mtx = G4MUTEX_INITIALIZER;
0214         G4AutoLock lock(&mtx);
0215         *fConvMaps[fCollID] += *EvtMap;
0216       }
0217     }
0218   }
0219 }
0220 
0221 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0222 
0223 // Merge hits map from threads
0224 void TSRun::Merge(const G4Run* aTSRun)
0225 {
0226   const TSRun* localTSRun = static_cast<const TSRun*>(aTSRun);
0227 
0228   for (unsigned i = 0; i < fRunMaps.size(); ++i) {
0229     *fRunMaps[i] += *localTSRun->fRunMaps[i];
0230     *fStatMaps[i] += *localTSRun->fStatMaps[i];
0231   }
0232 
0233   G4Run::Merge(aTSRun);
0234 }
0235 
0236 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0237 
0238 // Access HitsMap.
0239 // by full description of collection name, that is
0240 // <MultiFunctional Detector Name>/<Primitive Scorer Name>
0241 G4THitsMap<G4double>* TSRun::GetHitsMap(const G4String& collName) const
0242 {
0243   for (unsigned i = 0; i < fCollNames.size(); ++i) {
0244     if (collName == fCollNames[i]) return fRunMaps[i];
0245   }
0246 
0247   G4Exception("TSRun", collName.c_str(), JustWarning,
0248               "GetHitsMap failed to locate the requested HitsMap");
0249   return nullptr;
0250 }
0251 
0252 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0253 
0254 // Access AtomicsHitsMap.
0255 // by full description of collection name, that is
0256 // <MultiFunctional Detector Name>/<Primitive Scorer Name>
0257 G4TAtomicHitsMap<G4double>* TSRun::GetAtomicHitsMap(const G4String& collName) const
0258 {
0259   for (unsigned i = 0; i < fCollNames.size(); ++i) {
0260     if (collName == fCollNames[i]) return fAtomicRunMaps[i];
0261   }
0262 
0263   G4Exception("TSRun", collName.c_str(), JustWarning,
0264               "GetHitsMap failed to locate the requested AtomicHitsMap");
0265   return nullptr;
0266 }
0267 
0268 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0269 
0270 // Access AtomicsHitsMap.
0271 // by full description of collection name, that is
0272 // <MultiFunctional Detector Name>/<Primitive Scorer Name>
0273 TSRun::MutexHitsMap_t* TSRun::GetMutexHitsMap(const G4String& collName) const
0274 {
0275   if (fMutexRunMaps.find(collName) != fMutexRunMaps.end()) return &fMutexRunMaps[collName];
0276 
0277   G4Exception("TSRun", collName.c_str(), JustWarning,
0278               "GetHitsMap failed to locate the requested MutexHitsMap");
0279   return nullptr;
0280 }
0281 
0282 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0283 
0284 // Access StatMap.
0285 // by full description of collection name, that is
0286 // <MultiFunctional Detector Name>/<Primitive Scorer Name>
0287 G4StatContainer<G4StatAnalysis>* TSRun::GetStatMap(const G4String& collName) const
0288 {
0289   for (unsigned i = 0; i < fCollNames.size(); ++i) {
0290     if (collName == fCollNames[i]) return fStatMaps[i];
0291   }
0292 
0293   G4Exception("TSRun", collName.c_str(), JustWarning,
0294               "GetStatMap failed to locate the requested StatMap");
0295   return nullptr;
0296 }
0297 
0298 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0299 
0300 G4StatContainer<G4ConvergenceTester>* TSRun::GetConvMap(const G4String& collName) const
0301 {
0302   for (unsigned i = 0; i < fCollNames.size(); ++i) {
0303     if (collName == fCollNames[i]) return fConvMaps[i];
0304   }
0305 
0306   G4Exception("TSRun", collName.c_str(), JustWarning,
0307               "GetHitsMap failed to locate the requested AtomicHitsMap");
0308   return nullptr;
0309 }