Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/run/src/G4RunManagerFactory.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 
 28 #include "G4RunManagerFactory.hh"
 29 
 30 #include "G4EnvironmentUtils.hh"
 31 #include "G4MTRunManager.hh"
 32 #include "G4RunManager.hh"
 33 #include "G4TaskRunManager.hh"
 34 #include "G4SubEvtRunManager.hh"
 35 #include "G4Threading.hh"
 36 
 37 #include "templates.hh"
 38 
 39 //============================================================================//
 40 
 41 namespace
 42 {
 43 // failure message
 44 static void fail(const std::string& _prefix, const std::string& _name,
 45                  const std::set<std::string>& _opts, G4int _num)
 46 {
 47   G4ExceptionDescription msg;
 48   msg << _prefix << ": \"" << _name << "\". "
 49       << "Must be one of: ";
 50   std::stringstream ss;
 51   for (const auto& itr : _opts)
 52     ss << ", \"" << itr << "\"";
 53   msg << ss.str().substr(2);
 54   auto mnum = std::string("RunManagerFactory000") + std::to_string(_num);
 55   G4Exception("G4RunManagerFactory::CreateRunManager", mnum.c_str(), FatalException, msg);
 56 }
 57 
 58 static G4RunManager* master_run_manager = nullptr;
 59 static G4MTRunManager* mt_master_run_manager = nullptr;
 60 static G4RunManagerKernel* master_run_manager_kernel = nullptr;
 61 }  // namespace
 62 
 63 //============================================================================//
 64 
 65 G4RunManager* G4RunManagerFactory::CreateRunManager(G4RunManagerType _type,
 66                                                     G4VUserTaskQueue* _queue,
 67                                                     G4bool fail_if_unavail, G4int nthreads)
 68 {
 69   // If the supplied type is not ...Only, then allow override from environment
 70   std::string rm_type = GetName(_type);
 71   if (_type == G4RunManagerType::SerialOnly || _type == G4RunManagerType::MTOnly
 72       || _type == G4RunManagerType::TaskingOnly || _type == G4RunManagerType::TBBOnly
 73       || _type == G4RunManagerType::SubEvtOnly)
 74   {
 75     // MUST fail if unavail in this case
 76     fail_if_unavail = true;
 77   }
 78   else {
 79     // - G4RUN_MANAGER_TYPE can be set to override the "default"
 80     //   - If the requested type isn't available, then it will fall back to the
 81     //   system default
 82     // - G4FORCE_RUN_MANAGER_TYPE can be set to force a specific type
 83     //   - A G4Exception is raised if the requested type is not available
 84     rm_type = G4GetEnv<std::string>("G4RUN_MANAGER_TYPE", GetName(_type),
 85                                     "Overriding G4RunManager type...");
 86     auto force_rm =
 87       G4GetEnv<std::string>("G4FORCE_RUN_MANAGER_TYPE", "", "Forcing G4RunManager type...");
 88 
 89     if (force_rm.length() > 0) {
 90       rm_type = std::move(force_rm);
 91       fail_if_unavail = true;
 92     }
 93     else if (rm_type.empty()) {
 94       rm_type = GetDefault();
 95     }
 96   }
 97 
 98   // At this point will have a string for the RM type we can check for existence
 99   // NB: Comparison at present is case sensitive (needs a comparator in
100   // GetOptions)
101   auto opts = GetOptions();
102   if (opts.find(rm_type) == opts.end()) {
103     if (fail_if_unavail) {
104       fail("Run manager type is not available", rm_type, opts, 1);
105     }
106     else {
107       rm_type = GetDefault();
108     }
109   }
110 
111   // Construct requested RunManager given type
112   _type = GetType(rm_type);
113   G4RunManager* rm = nullptr;
114 
115   switch (_type) {
116     case G4RunManagerType::Serial:
117       rm = new G4RunManager();
118       break;
119     case G4RunManagerType::MT:
120 #if defined(G4MULTITHREADED)
121       rm = new G4MTRunManager();
122 #endif
123       break;
124     case G4RunManagerType::Tasking:
125 #if defined(G4MULTITHREADED)
126       rm = new G4TaskRunManager(_queue, false);
127 #endif
128       break;
129     case G4RunManagerType::TBB:
130 #if defined(G4MULTITHREADED) && defined(GEANT4_USE_TBB)
131       rm = new G4TaskRunManager(_queue, true);
132 #endif
133       break;
134     case G4RunManagerType::SubEvt:
135 #if defined(G4MULTITHREADED)
136 #if defined(GEANT4_USE_TBB)
137       rm = new G4SubEvtRunManager(_queue, true);
138 #else
139       rm = new G4SubEvtRunManager(_queue, false);
140 #endif
141 #endif
142       break;
143     // "Only" types are not handled since they are converted above to main type
144     case G4RunManagerType::SerialOnly:
145       break;
146     case G4RunManagerType::MTOnly:
147       break;
148     case G4RunManagerType::TaskingOnly:
149       break;
150     case G4RunManagerType::TBBOnly:
151       break;
152     case G4RunManagerType::SubEvtOnly:
153       break;
154     case G4RunManagerType::Default:
155       break;
156   }
157 
158   if (rm == nullptr) fail("Failure creating run manager", GetName(_type), GetOptions(), 2);
159 
160   auto mtrm = dynamic_cast<G4MTRunManager*>(rm);
161   if (nthreads > 0 && (mtrm != nullptr)) mtrm->SetNumberOfThreads(nthreads);
162 
163   master_run_manager = rm;
164   mt_master_run_manager = mtrm;
165   master_run_manager_kernel = rm->kernel;
166 
167   G4ConsumeParameters(_queue);
168   return rm;
169 }
170 
171 //============================================================================//
172 
173 std::string G4RunManagerFactory::GetDefault()
174 {
175 #if defined(G4MULTITHREADED)
176   return "Tasking";
177 #else
178   return "Serial";
179 #endif
180 }
181 
182 //============================================================================//
183 
184 std::set<std::string> G4RunManagerFactory::GetOptions()
185 {
186   static auto _instance = []() {
187     std::set<std::string> options = {"Serial"};
188 #if defined(G4MULTITHREADED)
189     options.insert({"MT", "Tasking"});
190 #  if defined(GEANT4_USE_TBB)
191     options.insert("TBB");
192 #  endif
193     options.insert("SubEvt");
194 #endif
195     return options;
196   }();
197   return _instance;
198 }
199 
200 //============================================================================//
201 
202 G4RunManagerType G4RunManagerFactory::GetType(const std::string& key)
203 {
204   // IGNORES CASE!
205   static const auto opts = std::regex::icase;
206 
207   if (std::regex_match(key, std::regex("^(Serial).*", opts))) return G4RunManagerType::Serial;
208   if (std::regex_match(key, std::regex("^(MT).*", opts))) return G4RunManagerType::MT;
209   if (std::regex_match(key, std::regex("^(Task).*", opts))) return G4RunManagerType::Tasking;
210   if (std::regex_match(key, std::regex("^(TBB).*", opts))) return G4RunManagerType::TBB;
211   if (std::regex_match(key, std::regex("^(SubEvt).*", opts))) return G4RunManagerType::SubEvt;
212 
213   return G4RunManagerType::Default;
214 }
215 
216 //============================================================================//
217 
218 std::string G4RunManagerFactory::GetName(G4RunManagerType _type)
219 {
220   switch (_type) {
221     case G4RunManagerType::Serial:
222       return "Serial";
223     case G4RunManagerType::SerialOnly:
224       return "Serial";
225     case G4RunManagerType::MT:
226       return "MT";
227     case G4RunManagerType::MTOnly:
228       return "MT";
229     case G4RunManagerType::Tasking:
230       return "Tasking";
231     case G4RunManagerType::TaskingOnly:
232       return "Tasking";
233     case G4RunManagerType::TBB:
234       return "TBB";
235     case G4RunManagerType::TBBOnly:
236       return "TBB";
237     case G4RunManagerType::SubEvt:
238       return "SubEvt";
239     case G4RunManagerType::SubEvtOnly:
240       return "SubEvt";
241     default:
242       break;
243   };
244   return "";
245 }
246 
247 //============================================================================//
248 
249 G4RunManager* G4RunManagerFactory::GetMasterRunManager()
250 {
251 #if !defined(G4MULTITHREADED)
252   // if serial build just return G4RunManager
253   return G4RunManager::GetRunManager();
254 #else
255   // if the application used G4RunManagerFactory to create the run-manager
256   if (master_run_manager != nullptr) return master_run_manager;
257 
258   // if the application did not use G4RunManagerFactory and is MT
259   if (G4Threading::IsMultithreadedApplication()) {
260     auto mt_rm = GetMTMasterRunManager();
261     if (mt_rm != nullptr) return mt_rm;
262   }
263 
264   // if the application did not use G4RunManagerFactory and is serial
265   return G4RunManager::GetRunManager();
266 #endif
267 }
268 
269 //============================================================================//
270 
271 G4MTRunManager* G4RunManagerFactory::GetMTMasterRunManager()
272 {
273 #if defined(G4MULTITHREADED)
274   // if the application used G4RunManagerFactory to create the run-manager
275   if (mt_master_run_manager != nullptr) return mt_master_run_manager;
276 
277   // if the application did not use G4RunManagerFactory
278   if (G4Threading::IsMultithreadedApplication()) {
279     auto task_rm = G4TaskRunManager::GetMasterRunManager();
280     if (task_rm != nullptr) return task_rm;
281     return G4MTRunManager::GetMasterRunManager();
282   }
283 #endif
284 
285   return nullptr;
286 }
287 
288 //============================================================================//
289 
290 G4RunManagerKernel* G4RunManagerFactory::GetMasterRunManagerKernel()
291 {
292 #if !defined(G4MULTITHREADED)
293   // if serial build just return G4RunManager
294   return G4RunManager::GetRunManager()->kernel;
295 #else
296   // if the application used G4RunManagerFactory to create the run-manager
297   if (master_run_manager_kernel != nullptr) return master_run_manager_kernel;
298 
299   // if the application did not use G4RunManagerFactory and is MT
300   if (G4Threading::IsMultithreadedApplication()) {
301     auto mt_rm = GetMTMasterRunManager();
302     if (mt_rm != nullptr) return mt_rm->kernel;
303   }
304 
305   // if the application did not use G4RunManagerFactory and is serial
306   return G4RunManager::GetRunManager()->kernel;
307 #endif
308 }
309 
310 //============================================================================//
311