ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4PhysListRegistry.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4PhysListRegistry.cc
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 // -------------------------------------------------------------------
29 //
30 // GEANT4 Class file
31 //
32 // File name: G4PhysListRegistry
33 //
34 // Author R. Hatcher 2014-10-15
35 //
36 // Modifications: based on G4PhysicsConstructorRegistry
37 //
38 //#define G4VERBOSE 1
39 
40 #include "G4ios.hh"
41 #include <iomanip>
42 #include <algorithm>
43 
44 #include "G4PhysListRegistry.hh"
45 #include "G4VModularPhysicsList.hh"
46 #include "G4PhysListStamper.hh"
47 
49 // include G4_REFERENCE_PHYSCONSTR_FACTORY() macros here to pull them in
50 // for static builds. Would do this in G4PhysicsConstructorRegistry
51 // but that causes a circular dependency when the phys_ctor libs
52 // are broken in a "granular" build.
53 #define REGREF PhysListReg // REGREF is used to make instances unique
54 #include "G4RegisterPhysicsConstructors.icc"
55 
56 // include this with this compilation unit so static builds pull them in
57 #include "G4RegisterPhysLists.icc"
58 
60 
61 const int doReplace = 0x01; // _ (ReplacePhysics) vs. + (RegisterPhysics)
62 const int isCtorName = 0x02; // true if actual physCtor name vs. ext name
63 
65 {
66  if ( 0 == theInstance) {
67  static G4ThreadLocal G4PhysListRegistry *manager_G4MT_TLS_ = 0;
68  if (!manager_G4MT_TLS_) manager_G4MT_TLS_ = new G4PhysListRegistry;
69  G4PhysListRegistry &manager = *manager_G4MT_TLS_;
70  theInstance = &manager;
71  }
72 
73  // common EM overrides
74  theInstance->AddPhysicsExtension("EM0","G4EmStandardPhysics");
75  theInstance->AddPhysicsExtension("EMV","G4EmStandardPhysics_option1");
76  theInstance->AddPhysicsExtension("EMX","G4EmStandardPhysics_option2");
77  theInstance->AddPhysicsExtension("EMY","G4EmStandardPhysics_option3");
78  theInstance->AddPhysicsExtension("EMZ","G4EmStandardPhysics_option4");
79  theInstance->AddPhysicsExtension("LIV","G4EmLivermorePhysics");
80  theInstance->AddPhysicsExtension("PEN","G4EmPenelopePhysics");
81  // the GS EM extension originally required double underscores
82  // support either one or two as __GS is confusing to users
83  // same for __SS
84  theInstance->AddPhysicsExtension("GS","G4EmStandardPhysicsGS");
85  theInstance->AddPhysicsExtension("_GS","G4EmStandardPhysicsGS");
86  theInstance->AddPhysicsExtension("SS","G4EmStandardPhysicsSS");
87  theInstance->AddPhysicsExtension("_SS","G4EmStandardPhysicsSS");
88 
89  return theInstance;
90 }
91 
93  : verbose(1)
94  , unknownFatal(0)
95  , systemDefault("FTFP_BERT")
96 {
98 }
99 
101 {
102 }
103 
105 {
106  if ( name == "" ) userDefault = systemDefault;
107  else userDefault = name;
108 }
109 
111 {
112  factories[name] = factory;
113 }
114 
116 {
117  // a mapping from short extension names to actual physics process constructors
118  physicsExtensions[name] = procname;
119 }
120 
123 {
124  //
125  //
126  G4String plBase = "";
127  std::vector<G4String> physExt;
128  std::vector<G4int> physReplace;
129  G4bool allKnown =
130  DeconstructPhysListName(name,plBase,physExt,physReplace,verbose);
131 
132  size_t npc = physExt.size();
133  if ( verbose > 0 ) {
134  G4cout << "G4PhysListRegistry::GetModularPhysicsList <"
135  << name << ">"
136  << ", as \"" << plBase << "\" with extensions \"";
137  for ( size_t ipc = 0; ipc < npc; ++ipc )
138  G4cout << ((physReplace[ipc]&doReplace)?"_":"+") << physExt[ipc];
139  G4cout << "\"" << G4endl;
140  }
141 
142  if ( ! allKnown ) {
143  // couldn't match what the user wanted ...
144  G4cout << "### G4PhysListRegistry WARNING: " << name
145  << " is not known" << G4endl << G4endl;
146  if ( ! unknownFatal ) return 0;
147 
149  ED << "The factory for the physicslist ["<< name << "] does not exist!"
150  << G4endl;
151  if ( plBase == "" ) {
152  ED << "Could determine no sensible base physics list" << G4endl;
153  } else {
154  ED << "One or more of the extensions does not exist [ ";
155  for ( size_t ipc = 0; ipc < physExt.size(); ++ipc ) {
156  ED << physExt[ipc] << " ";
157  }
158  ED << "]" << G4endl;
159  }
160  G4Exception("G4PhysListRegistry::GetModularPhysicsList",
161  "PhysicsList002", FatalException, ED);
162  return 0;
163  }
164 
165  // if we want this method "const" then the next line becomes more complex
166  // because there is no const version of [] (which adds an entry if the
167  // key doesn't exist)
168  G4VModularPhysicsList* pl = factories[plBase]->Instantiate(verbose);
169  G4PhysicsConstructorRegistry* pcRegistry =
171  G4int ver = pl->GetVerboseLevel();
172  pl->SetVerboseLevel(0);
173  for ( size_t ipc = 0; ipc < npc; ++ipc ) {
174  // got back a list of short names, need to use the map to get the
175  // full physics constructor name
176  G4String extName = physExt[ipc];
177  G4String pcname =
178  ((physReplace[ipc]&isCtorName)) ? extName : physicsExtensions[extName];
179  // this doesn't have a verbose option ... it should
180  // but G4PhysicsConstructorFactory doesn't support it
181  G4VPhysicsConstructor* pctor = pcRegistry->GetPhysicsConstructor(pcname);
182  G4String reporreg = "";
183  if (( physReplace[ipc] & doReplace)) {
184  pl->ReplacePhysics(pctor);
185  reporreg = "ReplacePhysics ";
186  } else {
187  pl->RegisterPhysics(pctor);
188  reporreg = "RegisterPhysics";
189  }
190  if ( verbose > 0 ) G4cout << "<<< " << reporreg << " with " << pcname
191  << " \"" << extName << "\"" << G4endl;
192  }
193  pl->SetVerboseLevel(ver);
194  G4cout << "<<< Reference Physics List " << name << " is built" << G4endl;
195  G4cout << G4endl; // old factory has this
196 
197  return pl;
198 }
199 
202 {
203  //
204  // instantiate PhysList by environment variable "PHYSLIST"
205  // if not set use default
206  G4String name = "";
207  char* path = std::getenv("PHYSLIST");
208  if (path) {
209  name = G4String(path);
210  } else {
211  name = userDefault;
212  G4cout << "### G4PhysListRegistry WARNING: "
213  << " environment variable PHYSLIST is not defined"
214  << G4endl
215  << " Default Physics Lists " << name
216  << " is instantiated"
217  << G4endl;
218  }
219  return GetModularPhysicsList(name);
220 }
221 
223 {
224  G4String plBase = "";
225  std::vector<G4String> physExt;
226  std::vector<G4int> physReplace;
227  G4bool allKnown = DeconstructPhysListName(name,plBase,physExt,physReplace,1);
228  return allKnown;
229 }
230 
232  G4String& plBase,
233  std::vector<G4String>& physExt,
234  std::vector<G4int>& replace,
235  G4int verb) const
236 {
237  // Take apart a name given to us by the user
238  // this name might be a base PhysList + unknown number of extensions
239  // Extensions preceeded with a "_" should use
240  // ReplacePhysics()
241  // those proceeded with a "+" should use
242  // RegisterPhysics()
243  // the former is in line with previous behaviour, while the second allows
244  // additional flexibility
245  plBase = "";
246  physExt.clear();
247  replace.clear();
248  bool allKnown = false;
249 
250  G4String workingName = name;
251 
252  const std::vector<G4String>& availBases = AvailablePhysLists();
253  const std::vector<G4String>& availExtras = AvailablePhysicsExtensions();
254 
255  G4PhysicsConstructorRegistry* physConstRegistry =
257 
258  const std::vector<G4String>& availPhysCtors =
259  physConstRegistry->AvailablePhysicsConstructors();
260 
261  // find the longest base list that is contained in the user supplied name
262  // and starts at the beginning
263  G4String bestBase = "";
264  allKnown = FindLongestMatch(workingName,"base",availBases,plBase);
265  if ( verb > 2 ) {
266  G4cout << " " << name << ", base known=" << ((allKnown)?"true":"false")
267  << " chosen plBase \"" << plBase << "\"" << G4endl;
268  }
269  if ( ! allKnown ) {
270  // didn't find any matching base physics list
271  // no point of going on to the extensions
272  return allKnown;
273  }
274  // remove base name for working name
275  workingName.erase(0,plBase.size());
276 
277  // now start trying to match up extensions and/or physCtors
278  // each should be preceeded by at "_" (replace) or "+" (register)
279  // but don't freak if it isn't, just assume "_"
280  while ( ! workingName.empty() ) {
281  char c = workingName.data()[0]; // leading character
282  if ( '_' == c || '+' == c ) workingName.erase(0,1); // and remove it
283  G4int replaceExtra = (( c != '+' ) ? doReplace : 0 );
284  G4String extraName = "";
285  G4bool extraKnown = false;
286 
287  extraKnown = FindLongestMatch(workingName,"extNames",availExtras,extraName);
288  if ( extraKnown ) {
289  // physics mapping name is known, but is it actually linked to physics?
290  //const issue// G4String pcname = physicsExtensions[extraName];
291  std::map<G4String,G4String>::const_iterator itr =
292  physicsExtensions.find(extraName);
293  G4String pcname = "";
294  if ( itr != physicsExtensions.end() ) pcname = itr->second;
295  bool realknown = physConstRegistry->IsKnownPhysicsConstructor(pcname);
296  if ( ! realknown ) allKnown = false;
297 #ifdef G4VERBOSE
298  if ( verb > 2 ) {
299  G4cout << " extraName \"" << extraName << "\" maps to physics ctor \""
300  << pcname << "\" which is itself realknown " << realknown
301  << G4endl;
302  }
303 #endif
304  } else {
305  // perhaps it's an explicit physCtor name
306  extraKnown =
307  FindLongestMatch(workingName,"physCtors",availPhysCtors,extraName);
308  if ( extraKnown ) replaceExtra |= isCtorName; // flag it
309  }
310 #ifdef G4VERBOSE
311  if ( verb > 2 ) {
312  G4cout << " physextra " << name << " [" << workingName << "]"
313  <<", extra known " << extraKnown
314  << " chosen extra \"" << extraName << "\""
315  << " replace " << replaceExtra << G4endl;
316  }
317 #endif
318  if ( extraKnown ) {
319  physExt.push_back(extraName);
320  replace.push_back(replaceExtra);
321  // and remove it so we can look for the next bit
322  workingName.erase(0,extraName.size());
323 
324  } else {
325 #ifdef G4VERBOSE
326  if ( verb > 2 ) {
327  G4cout << " workingName \"" << workingName << "\""
328  << " couldn't be found in the extensions list"
329  << G4endl;
330  }
331 #endif
332  allKnown = false;
333  // found a pattern that we can't map
334  return allKnown;
335  }
336  } // workingName not empty
337 
338  return allKnown;
339 }
340 
342  const G4String& searchName,
343  const std::vector<G4String>& validNames,
344  G4String& bestMatch,
345  G4int verb) const
346 {
347  bestMatch = "";
348  bool found = false;
349 
350  size_t n = validNames.size();
351  for (size_t i=0; i<n; ++i) {
352  const G4String& testName = validNames[i];
353  size_t ipos = workingName.find(testName);
354  if ( ipos == 0 ) {
355  if ( testName.size() > bestMatch.size() ) {
356  bestMatch = testName;
357  found = true;
358  if ( verb > 3 ) {
359  G4cout << " " << searchName << " current best guess: "
360  << testName << G4endl;
361  }
362  } else {
363  if ( verb > 3 ) {
364  G4cout << " " << searchName << " match but shorter: "
365  << testName << G4endl;
366  }
367  }
368  } else {
369  if ( verb > 3 ) {
370  G4cout << " " << searchName << " reject: " << testName << G4endl;
371  }
372  }
373  }
374  return found;
375 }
376 
377 
378 const std::vector<G4String>& G4PhysListRegistry::AvailablePhysLists() const
379 {
380  availBasePhysLists.clear();
381  std::map<G4String,G4VBasePhysListStamper*>::const_iterator itr;
382  for ( itr = factories.begin(); itr != factories.end(); ++itr ) {
383  availBasePhysLists.push_back(itr->first);
384  }
385 
386  return availBasePhysLists;
387 }
388 
389 const std::vector<G4String>& G4PhysListRegistry::AvailablePhysicsExtensions() const
390 {
391  availExtensions.clear();
392  std::map<G4String,G4String>::const_iterator itr;
393  for ( itr = physicsExtensions.begin(); itr != physicsExtensions.end(); ++itr ) {
394  availExtensions.push_back(itr->first);
395  }
396 
397  return availExtensions;
398 }
399 
400 const std::vector<G4String>& G4PhysListRegistry::AvailablePhysListsEM() const
401 {
402  // in principle this method could weed out all the extensions that aren't
403  // EM replacements ... but for now just use it as a synonym for
404  // AvailablePhysicsExtensions()
406 }
407 
409 {
410  std::vector<G4String> avail = AvailablePhysLists();
411  G4cout << "Base G4VModularPhysicsLists in G4PhysListRegistry are:"
412  << G4endl;
413  if ( avail.empty() ) G4cout << "... no registered lists" << G4endl;
414  else {
415  size_t n = avail.size();
416  for (size_t i=0; i<n; ++i ) {
417  G4cout << " [" << std::setw(3) << i << "] "
418  << " \"" << avail[i] << "\"" << G4endl;
419  }
420  }
421 
423 
424  std::map<G4String,G4String>::const_iterator itr;
425  G4cout << "Replacement mappings in G4PhysListRegistry are:"
426  << G4endl;
427  for ( itr = physicsExtensions.begin(); itr != physicsExtensions.end(); ++itr ) {
428  bool known = physConstRegistry->IsKnownPhysicsConstructor(itr->second);
429 
430  G4cout << " " << std::setw(10) << itr->first << " => "
431  << std::setw(30) << itr->second << " "
432  << ( (known)?"":"[unregistered physics]")
433  << G4endl;
434  }
435  G4cout << "Use these mapping to extend physics list; append with _EXT or +EXT" << G4endl
436  << " to use ReplacePhysics() (\"_\") or RegisterPhysics() (\"+\")."
437  << G4endl;
438 }