Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 /// \file parallel/ThreadsafeScorers/src/TSRun.cc 27 /// \brief Implementation of the TSRun class 28 // 29 // 30 // 31 // 32 /// TSRun contains five hits collections types: 33 /// 1) a thread-local hits map, 34 /// 2) a global atomic hits map 35 /// 3) a global "mutex" hits map 36 /// 4) a global G4StatAnalysis hits deque 37 /// 5) a global G4ConvergenceTester hits deque 38 /// 39 /// The thread-local hits map is the same as you will find in many other 40 /// examples. 41 /// 42 /// The atomics hits map is the purpose of this example. Code-wise, the 43 /// implementation looks extremely similar to the thread-local version with 44 /// 3 primary exceptions: 45 /// (1) construction - there should only be one instance so it should be a 46 /// static member variable or a pointer/reference to a single instance 47 /// (2) It does not need to, nor should be, summed in G4Run::Merge() 48 /// (3) destruction -- it should only be cleared by the master thread since 49 /// there is only one instance. 50 /// 51 /// The "mutex" hits map is also included as reference for checking the results 52 /// accumulated by the thread-local hits maps and atomic hits maps. The 53 /// differences w.r.t. this hits maps are computed in 54 /// TSRunAction::EndOfRunAction 55 /// 56 /// The "G4StatAnalysis" and "G4ConvergenceTester" hits deques are 57 /// memory-efficient version of the standard G4THitsMap. While maps are 58 /// ideal for scoring at the G4Event-level, where sparsity w.r.t. indices 59 /// is common; at the G4Run-level, these data structures require much 60 /// less memory overhead. Due to a lack of 61 /// G4ConvergenceTester::operator+=(G4ConvergenceTester), the static version 62 /// of G4ConvergenceTester is the only valid way to use G4ConvergenceTester 63 /// in a scoring container. This is not the case for G4StatAnalysis, which 64 /// can be used in lieu of G4double. 65 /// 66 // 67 // 68 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 69 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 70 71 #include "TSRun.hh" 72 73 #include "TSDetectorConstruction.hh" 74 75 #include "G4MultiFunctionalDetector.hh" 76 #include "G4SDManager.hh" 77 #include "G4VPrimitiveScorer.hh" 78 79 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 80 81 std::vector<G4TAtomicHitsMap<G4double>*> TSRun::fAtomicRunMaps; 82 83 std::map<G4String, TSRun::MutexHitsMap_t> TSRun::fMutexRunMaps; 84 85 std::vector<G4StatContainer<G4ConvergenceTester>*> TSRun::fConvMaps; 86 87 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 88 89 TSRun::TSRun(const G4String& mfd_name) : G4Run() 90 { 91 ConstructMFD(mfd_name); 92 } 93 94 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 95 96 TSRun::~TSRun() 97 { 98 //--- Clear HitsMap for RUN 99 for (unsigned i = 0; i < fRunMaps.size(); ++i) 100 delete fRunMaps[i]; 101 102 if (!G4Threading::IsWorkerThread()) { 103 for (unsigned i = 0; i < fAtomicRunMaps.size(); ++i) 104 delete fAtomicRunMaps[i]; 105 106 for (auto& itr : fConvMaps) 107 delete itr; 108 109 fAtomicRunMaps.clear(); 110 fMutexRunMaps.clear(); 111 fConvMaps.clear(); 112 } 113 } 114 115 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 116 117 // clear all data members. 118 void TSRun::ConstructMFD(const G4String& mfdName) 119 { 120 G4SDManager* SDman = G4SDManager::GetSDMpointer(); 121 //================================================= 122 // Initalize RunMaps for accumulation. 123 // Get CollectionIDs for HitCollections. 124 //================================================= 125 G4MultiFunctionalDetector* mfd = 126 (G4MultiFunctionalDetector*)(SDman->FindSensitiveDetector(mfdName)); 127 // 128 if (mfd) { 129 //--- Loop over the registered primitive scorers. 130 for (G4int icol = 0; icol < mfd->GetNumberOfPrimitives(); icol++) { 131 // Get Primitive Scorer object. 132 G4VPrimitiveScorer* scorer = mfd->GetPrimitive(icol); 133 // collection name and collectionID for HitsCollection, 134 // where type of HitsCollection is G4THitsMap in case 135 // of primitive scorer. 136 // The collection name is given by <MFD name>/<Primitive 137 // Scorer name>. 138 G4String collectionName = scorer->GetName(); 139 G4String fullCollectionName = mfdName + "/" + collectionName; 140 G4int collectionID = SDman->GetCollectionID(fullCollectionName); 141 // 142 if (collectionID >= 0) { 143 G4cout << "++ " << fullCollectionName << " id " << collectionID << G4endl; 144 // Store obtained HitsCollection information into data members. 145 // And, creates new G4THitsMap for accumulating quantities during RUN. 146 fCollNames.push_back(fullCollectionName); 147 fCollIDs.push_back(collectionID); 148 fRunMaps.push_back(new G4THitsMap<G4double>(mfdName, collectionName)); 149 fStatMaps.push_back(new G4StatContainer<G4StatAnalysis>( 150 mfdName, collectionName, TSDetectorConstruction::Instance()->GetTotalTargets())); 151 if (!G4Threading::IsWorkerThread()) { 152 fAtomicRunMaps.push_back(new G4TAtomicHitsMap<G4double>(mfdName, collectionName)); 153 fMutexRunMaps[fCollNames[collectionID]].clear(); 154 fConvMaps.push_back(new G4StatContainer<G4ConvergenceTester>( 155 mfdName, collectionName, TSDetectorConstruction::Instance()->GetTotalTargets())); 156 } 157 } 158 else { 159 G4cout << "** collection " << fullCollectionName << " not found. " << G4endl; 160 } 161 } 162 } 163 } 164 165 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 166 // 167 // RecordEvent is called at end of event. 168 // For scoring purpose, the resultant quantity in a event, 169 // is accumulated during a TSRun. 170 void TSRun::RecordEvent(const G4Event* aEvent) 171 { 172 G4Run::RecordEvent(aEvent); 173 174 //============================= 175 // HitsCollection of This Event 176 //============================ 177 G4HCofThisEvent* HCE = aEvent->GetHCofThisEvent(); 178 if (!HCE) return; 179 180 for (unsigned i = 0; i < fCollIDs.size(); ++i) { 181 G4int fCollID = fCollIDs.at(i); 182 //======================================================= 183 // Sum up HitsMap of this Event into HitsMap of this RUN 184 //======================================================= 185 G4THitsMap<G4double>* EvtMap = 0; 186 if (fCollID >= 0) // Collection is attached to HCE 187 EvtMap = static_cast<G4THitsMap<G4double>*>(HCE->GetHC(fCollID)); 188 else 189 G4cout << " Error EvtMap Not Found " << G4endl; 190 191 if (EvtMap) { 192 //=== Sum up HitsMap of this event to HitsMap of RUN.=== 193 { 194 *fRunMaps[fCollID] += *EvtMap; 195 } 196 //=== Sum up HitsMap of this event to StatMap of RUN.=== 197 { 198 // G4StatAnalysis map 199 *fStatMaps[fCollID] += *EvtMap; 200 } 201 //=== Sum up HitsMap of this event to atomic HitsMap of RUN.=== 202 { 203 *fAtomicRunMaps[fCollID] += *EvtMap; 204 } 205 //=== Sum up HitsMap of this event to MutexMap of RUN.=== 206 { 207 // mutex run map 208 static G4Mutex mtx = G4MUTEX_INITIALIZER; 209 G4AutoLock lock(&mtx); 210 for (const auto& itr : *EvtMap) 211 fMutexRunMaps[fCollNames[fCollID]][itr.first] += *itr.second; 212 } 213 //=== Sum up HitsMap of this event to MutexMap of RUN.=== 214 { 215 // G4ConvergenceTester run map 216 static G4Mutex mtx = G4MUTEX_INITIALIZER; 217 G4AutoLock lock(&mtx); 218 *fConvMaps[fCollID] += *EvtMap; 219 } 220 } 221 } 222 } 223 224 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 225 226 // Merge hits map from threads 227 void TSRun::Merge(const G4Run* aTSRun) 228 { 229 const TSRun* localTSRun = static_cast<const TSRun*>(aTSRun); 230 231 for (unsigned i = 0; i < fRunMaps.size(); ++i) { 232 *fRunMaps[i] += *localTSRun->fRunMaps[i]; 233 *fStatMaps[i] += *localTSRun->fStatMaps[i]; 234 } 235 236 G4Run::Merge(aTSRun); 237 } 238 239 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 240 241 // Access HitsMap. 242 // by full description of collection name, that is 243 // <MultiFunctional Detector Name>/<Primitive Scorer Name> 244 G4THitsMap<G4double>* TSRun::GetHitsMap(const G4String& collName) const 245 { 246 for (unsigned i = 0; i < fCollNames.size(); ++i) { 247 if (collName == fCollNames[i]) return fRunMaps[i]; 248 } 249 250 G4Exception("TSRun", collName.c_str(), JustWarning, 251 "GetHitsMap failed to locate the requested HitsMap"); 252 return nullptr; 253 } 254 255 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 256 257 // Access AtomicsHitsMap. 258 // by full description of collection name, that is 259 // <MultiFunctional Detector Name>/<Primitive Scorer Name> 260 G4TAtomicHitsMap<G4double>* TSRun::GetAtomicHitsMap(const G4String& collName) const 261 { 262 for (unsigned i = 0; i < fCollNames.size(); ++i) { 263 if (collName == fCollNames[i]) return fAtomicRunMaps[i]; 264 } 265 266 G4Exception("TSRun", collName.c_str(), JustWarning, 267 "GetHitsMap failed to locate the requested AtomicHitsMap"); 268 return nullptr; 269 } 270 271 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 272 273 // Access AtomicsHitsMap. 274 // by full description of collection name, that is 275 // <MultiFunctional Detector Name>/<Primitive Scorer Name> 276 TSRun::MutexHitsMap_t* TSRun::GetMutexHitsMap(const G4String& collName) const 277 { 278 if (fMutexRunMaps.find(collName) != fMutexRunMaps.end()) return &fMutexRunMaps[collName]; 279 280 G4Exception("TSRun", collName.c_str(), JustWarning, 281 "GetHitsMap failed to locate the requested MutexHitsMap"); 282 return nullptr; 283 } 284 285 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 286 287 // Access StatMap. 288 // by full description of collection name, that is 289 // <MultiFunctional Detector Name>/<Primitive Scorer Name> 290 G4StatContainer<G4StatAnalysis>* TSRun::GetStatMap(const G4String& collName) const 291 { 292 for (unsigned i = 0; i < fCollNames.size(); ++i) { 293 if (collName == fCollNames[i]) return fStatMaps[i]; 294 } 295 296 G4Exception("TSRun", collName.c_str(), JustWarning, 297 "GetStatMap failed to locate the requested StatMap"); 298 return nullptr; 299 } 300 301 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 302 303 G4StatContainer<G4ConvergenceTester>* TSRun::GetConvMap(const G4String& collName) const 304 { 305 for (unsigned i = 0; i < fCollNames.size(); ++i) { 306 if (collName == fCollNames[i]) return fConvMaps[i]; 307 } 308 309 G4Exception("TSRun", collName.c_str(), JustWarning, 310 "GetHitsMap failed to locate the requested AtomicHitsMap"); 311 return nullptr; 312 } 313