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 27 // Author: Ivana Hrivnacova, IJCLab IN2P3/CNRS, 18/06/2013 28 29 #include "G4AccumulableManager.hh" 30 #include "G4ThreadLocalSingleton.hh" 31 #include "G4Threading.hh" 32 #include "G4AutoLock.hh" 33 34 // mutex in a file scope 35 36 namespace { 37 //Mutex to lock master manager when merging accumulables 38 G4Mutex mergeMutex = G4MUTEX_INITIALIZER; 39 40 void RangeException(const G4String& where, const G4String& message) 41 { 42 G4ExceptionDescription description; 43 description << "Invalid range " << message; 44 G4String method("G4AccumulableManager::"); 45 method.append(where); 46 G4Exception(where, "Analysis_W001", JustWarning, description); 47 } 48 } 49 50 //_____________________________________________________________________________ 51 G4AccumulableManager* G4AccumulableManager::Instance() 52 { 53 static G4ThreadLocalSingleton<G4AccumulableManager> instance; 54 return instance.Instance(); 55 } 56 57 //_____________________________________________________________________________ 58 G4AccumulableManager::G4AccumulableManager() 59 { 60 if (!G4Threading::IsWorkerThread()) { 61 fgMasterInstance = this; 62 } 63 } 64 65 //_____________________________________________________________________________ 66 G4AccumulableManager::~G4AccumulableManager() 67 { 68 // delete only accumulables create by the mager itself 69 for ( auto it : fAccumulablesToDelete ) { 70 delete it; 71 } 72 } 73 74 // 75 // private methods 76 // 77 78 //_____________________________________________________________________________ 79 G4String G4AccumulableManager::GenerateName() const 80 { 81 G4String name = kBaseName; 82 std::ostringstream os; 83 os << fVector.size(); 84 name.append("_"); 85 name.append(os.str()); 86 return name; 87 } 88 89 //_____________________________________________________________________________ 90 G4bool G4AccumulableManager::CheckName( 91 const G4String& name, const G4String& where) const 92 { 93 if (fMap.find(name) == fMap.end()) { 94 return true; 95 } 96 97 G4ExceptionDescription description; 98 description << "Name " << name << " is already used." << G4endl; 99 description << "Parameter will be not created/registered."; 100 G4String method("G4AccumulableManager::"); 101 method.append(where); 102 G4Exception(method, "Analysis_W001", JustWarning, description); 103 return false; 104 } 105 106 //_____________________________________________________________________________ 107 G4bool G4AccumulableManager::CheckType( 108 G4VAccumulable* accumulable, G4AccType type, G4bool warn) const 109 { 110 if (accumulable->GetType() != type) { 111 if (warn) { 112 G4ExceptionDescription description; 113 description << " " << accumulable->GetName() << ": Incompatible type."; 114 G4Exception("G4AccumulableManager::CheckType", 115 "Analysis_W001", JustWarning, description); 116 } 117 return false; 118 } 119 return true; 120 } 121 122 // 123 // public methods 124 // 125 126 //_____________________________________________________________________________ 127 G4bool G4AccumulableManager::Register(G4VAccumulable* accumulable) 128 { 129 auto name = accumulable->GetName(); 130 131 if (G4Accumulables::VerboseLevel > 1 ) { 132 G4cout << "Going to register accumulable \"" << name << "\"" << G4endl; 133 } 134 135 // do not accept name if it is already used 136 if (!CheckName(name, "RegisterAccumulable")) { 137 return false; 138 } 139 140 // generate name if empty 141 if (name.length() == 0u) { 142 name = GenerateName(); 143 accumulable->SetName(name); 144 } 145 146 // set Id 147 accumulable->SetId((G4int)fVector.size()); 148 149 fMap[name] = accumulable; 150 fVector.push_back(accumulable); 151 152 if (G4Accumulables::VerboseLevel > 0 ) { 153 G4cout << "Accumulable registered as \"" << accumulable->GetName() << "\"" << G4endl; 154 } 155 156 return true; 157 } 158 159 // Deprecated functions with long name 160 //_____________________________________________________________________________ 161 G4bool G4AccumulableManager::RegisterAccumulable(G4VAccumulable* accumulable) 162 { 163 return Register(accumulable); 164 } 165 166 //_____________________________________________________________________________ 167 G4VAccumulable* 168 G4AccumulableManager::GetAccumulable(const G4String& name, G4bool warn) const 169 { 170 // get G4VParammeter from the map 171 auto it = fMap.find(name); 172 if ( it == fMap.end() ) { 173 if ( warn) { 174 G4ExceptionDescription description; 175 description << "Accumulable " << name << " does not exist."; 176 G4Exception("G4AccumulableManager::GetAccumulable", 177 "Analysis_W001", JustWarning, description); 178 } 179 return nullptr; 180 } 181 182 return it->second; 183 } 184 185 //_____________________________________________________________________________ 186 G4VAccumulable* 187 G4AccumulableManager::GetAccumulable(G4int id, G4bool warn) const 188 { 189 // get G4VParammeter from the vector 190 if ( id < 0 || id >= G4int(fVector.size()) ) { 191 if ( warn) { 192 G4ExceptionDescription description; 193 description << "Accumulable " << id << " does not exist."; 194 G4Exception("G4AccumulableManager::GetAccumulable", 195 "Analysis_W001", JustWarning, description); 196 } 197 return nullptr; 198 } 199 200 return fVector[id]; 201 } 202 203 //_____________________________________________________________________________ 204 void G4AccumulableManager::Merge() 205 { 206 // Do nothing if there are no accumulables registered 207 // or if master thread 208 if ((fVector.size() == 0u) || (!G4Threading::IsWorkerThread())) { 209 return; 210 } 211 212 // The manager on mastter must exist 213 if (fgMasterInstance == nullptr) { 214 G4ExceptionDescription description; 215 description 216 << "No master G4AccumulableManager instance exists." << G4endl 217 << "Accumulables will not be merged."; 218 G4Exception("G4AccumulableManager::Merge()", 219 "Analysis_W001", JustWarning, description); 220 return; 221 } 222 223 // The worker manager just merges its accumulables to the master 224 // This operation needs a lock 225 // G4cout << "Go to merge accumulables" << G4endl; 226 G4AutoLock lock(&mergeMutex); 227 228 // the other manager has the vector with the "same" accumulables 229 auto it = fVector.begin(); 230 for ( auto itMaster : fgMasterInstance->fVector ) { 231 // G4VAccumulable* masterAccumulable = itMaster; 232 // G4VAccumulable* accumulable = *(it++); 233 // masterAccumulable->Merge(*(accumulable)); 234 itMaster->Merge(*(*(it++))); 235 } 236 lock.unlock(); 237 } 238 239 //_____________________________________________________________________________ 240 void G4AccumulableManager::Reset() 241 { 242 // Reset all accummulables 243 244 for ( auto it : fVector ) { 245 it->Reset(); 246 } 247 } 248 249 //_____________________________________________________________________________ 250 void G4AccumulableManager::Print(G4PrintOptions options) const 251 { 252 for ( auto it : fVector ) { 253 it->Print(options); 254 } 255 } 256 257 //_____________________________________________________________________________ 258 void G4AccumulableManager::Print( 259 G4int startId, G4int count, G4PrintOptions options) const 260 { 261 // check if range is within limits 262 if ( startId < 0 || startId >= G4int(fVector.size()) || 263 count <= 0 || startId + count > G4int(fVector.size()) ) { 264 RangeException("Print", 265 std::to_string(startId) + ", " + std::to_string(count)); 266 return; 267 } 268 269 for ( auto id = startId; id < startId + count; ++id ) { 270 fVector[id]->Print(options); 271 } 272 } 273 274 //_____________________________________________________________________________ 275 void G4AccumulableManager::Print( 276 std::vector<G4VAccumulable*>::iterator startIt, 277 std::vector<G4VAccumulable*>::iterator endIt, 278 G4PrintOptions options) const 279 { 280 // check if range is within limits 281 if ( startIt == fVector.end() || endIt == fVector.end() ) { 282 RangeException("Print", "[startIt, endIt]"); 283 return; 284 } 285 286 for ( auto it = startIt; it != endIt; ++it ) { 287 (*it)->Print(options); 288 } 289 } 290 291 //_____________________________________________________________________________ 292 void G4AccumulableManager::Print( 293 std::vector<G4VAccumulable*>::iterator startIt, std::size_t count, 294 G4PrintOptions options) const 295 { 296 Print(startIt, startIt+count, options); 297 } 298