Geant4  10.02.p02
G4PhysListRegistry.cc
Go to the documentation of this file.
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 // $Id:
28 //
29 // -------------------------------------------------------------------
30 //
31 // GEANT4 Class file
32 //
33 // File name: G4PhysListRegistry
34 //
35 // Author R. Hatcher 2014-10-15
36 //
37 // Modifications: based on G4PhysicsConstructorRegistry
38 //
39 //#define G4VERBOSE 1
40 
41 #include "G4ios.hh"
42 #include <iomanip>
43 #include <algorithm>
44 
45 #include "G4PhysListRegistry.hh"
46 #include "G4VModularPhysicsList.hh"
47 #include "G4PhysListStamper.hh"
49 
51 
53 {
54  if ( 0 == theInstance) {
55  static G4ThreadLocal G4PhysListRegistry *manager_G4MT_TLS_ = 0;
56  if (!manager_G4MT_TLS_) manager_G4MT_TLS_ = new G4PhysListRegistry;
57  G4PhysListRegistry &manager = *manager_G4MT_TLS_;
58  theInstance = &manager;
59  }
60 
61  // common EM overrides
62  theInstance->AddPhysicsExtension("EMV","G4EmStandardPhysics_option1");
63  theInstance->AddPhysicsExtension("EMX","G4EmStandardPhysics_option2");
64  theInstance->AddPhysicsExtension("EMY","G4EmStandardPhysics_option3");
65  theInstance->AddPhysicsExtension("EMZ","G4EmStandardPhysics_option4");
66  theInstance->AddPhysicsExtension("LIV","G4EmLivermorePhysics");
67  theInstance->AddPhysicsExtension("PEN","G4EmPenelopePhysics");
68  // the GS EM extension originally required double underscores
69  // support either one or two as __GS is confusing to users
70  theInstance->AddPhysicsExtension("GS","G4EmStandardPhysicsGS");
71  theInstance->AddPhysicsExtension("_GS","G4EmStandardPhysicsGS");
72 
73  return theInstance;
74 }
75 
77  : verbose(1)
78  , unknownFatal(0)
79  , systemDefault("FTFP_BERT")
80 {
82 }
83 
85 {
86 }
87 
89 {
90  if ( name == "" ) userDefault = systemDefault;
91  else userDefault = name;
92 }
93 
95 {
96  factories[name] = factory;
97 }
98 
100 {
101  // a mapping from short extension names to actual physics process constructors
102  physicsExtensions[name] = procname;
103 }
104 
107 {
108  //
109  //
110  G4String plBase = "";
111  std::vector<G4String> physExt;
112  std::vector<G4int> physReplace;
113  G4bool allKnown =
114  DeconstructPhysListName(name,plBase,physExt,physReplace,verbose);
115 
116  size_t npc = physExt.size();
117  if ( verbose > 0 ) {
118  G4cout << "G4PhysListRegistry::GetModularPhysicsList <"
119  << name << ">"
120  << ", as \"" << plBase << "\" with extensions \"";
121  for ( size_t ipc = 0; ipc < npc; ++ipc )
122  G4cout << ((physReplace[ipc]>0)?"_":"+") << physExt[ipc];
123  G4cout << "\"" << G4endl;
124  }
125 
126  if ( ! allKnown ) {
127  // couldn't match what the user wanted ...
128  G4cout << "### G4PhysListRegistry WARNING: " << name
129  << " is not known" << G4endl << G4endl;
130  if ( ! unknownFatal ) return 0;
131 
133  ED << "The factory for the physicslist ["<< name << "] does not exist!"
134  << G4endl;
135  if ( plBase == "" ) {
136  ED << "Could determine no sensible base physics list" << G4endl;
137  } else {
138  ED << "One or more of the extensions does not exist [ ";
139  for ( size_t ipc = 0; ipc < physExt.size(); ++ipc ) {
140  ED << physExt[ipc] << " ";
141  }
142  ED << "]" << G4endl;
143  }
144  G4Exception("G4PhysListRegistry::GetModularPhysicsList",
145  "PhysicsList001", FatalException, ED);
146  return 0;
147  }
148 
149  // if we want this method "const" then the next line becomes more complex
150  // because there is no const version of [] (which adds an entry if the
151  // key doesn't exist)
152  G4VModularPhysicsList* pl = factories[plBase]->Instantiate(verbose);
153  G4PhysicsConstructorRegistry* pcRegistry =
155  G4int ver = pl->GetVerboseLevel();
156  pl->SetVerboseLevel(0);
157  for ( size_t ipc = 0; ipc < npc; ++ipc ) {
158  // got back a list of short names, need to use the map to get the
159  // full physics constructor name
160  G4String extName = physExt[ipc];
161  G4String pcname = physicsExtensions[extName];
162  // this doesn't have a verbose option ... it should
163  // but G4PhysicsConstructorFactory doesn't support it
164  G4VPhysicsConstructor* pc = pcRegistry->GetPhysicsConstructor(pcname);
165  G4String reporreg = "";
166  if ( physReplace[ipc] > 0 ) {
167  pl->ReplacePhysics(pc);
168  reporreg = "ReplacePhysics ";
169  } else {
170  pl->RegisterPhysics(pc);
171  reporreg = "RegisterPhysics";
172  }
173  if ( verbose > 0 ) G4cout << "<<< " << reporreg << " with " << pcname
174  << " \"" << extName << "\"" << G4endl;
175  }
176  pl->SetVerboseLevel(ver);
177  G4cout << "<<< Reference Physics List " << name << " is built" << G4endl;
178  G4cout << G4endl; // old factory has this
179 
180  return pl;
181 }
182 
185 {
186  //
187  // instantiate PhysList by environment variable "PHYSLIST"
188  // if not set use default
189  G4String name = "";
190  char* path = getenv("PHYSLIST");
191  if (path) {
192  name = G4String(path);
193  } else {
194  name = userDefault;
195  G4cout << "### G4PhysListRegistry WARNING: "
196  << " environment variable PHYSLIST is not defined"
197  << G4endl
198  << " Default Physics Lists " << name
199  << " is instantiated"
200  << G4endl;
201  }
202  return GetModularPhysicsList(name);
203 }
204 
206 {
207  G4String plBase = "";
208  std::vector<G4String> physExt;
209  std::vector<G4int> physReplace;
210  G4bool allKnown = DeconstructPhysListName(name,plBase,physExt,physReplace,1);
211  return allKnown;
212 }
213 
215  G4String& plBase,
216  std::vector<G4String>& physExt,
217  std::vector<G4int>& replace,
218  G4int verb) const
219 {
220  // Take apart a name given to us by the user
221  // this name might be a base PhysList + unknown number of extensions
222  // Extensions preceeded with a "_" should use
223  // ReplacePhysics()
224  // those proceeded with a "+" should use
225  // RegisterPhysics()
226  // the former is in line with previous behaviour, while the second allows
227  // additional flexibility
228  plBase = "";
229  physExt.clear();
230  replace.clear();
231  bool allKnown = false;
232 
233  G4String workingName = name;
234 
235  const std::vector<G4String>& availBases = AvailablePhysLists();
236  const std::vector<G4String>& availExtras = AvailablePhysicsExtensions();
237 
238  G4PhysicsConstructorRegistry* physConstRegistry =
240 
241  // find the longest base list that is contained in the user supplied name
242  // and starts at the beginning
243  size_t nb = availBases.size();
244  for (size_t ib=0; ib<nb; ++ib) {
245  const G4String& testBase = availBases[ib];
246  size_t ipos = workingName.find(testBase);
247  if ( ipos == 0 ) {
248  if ( testBase.size() > plBase.size() ) {
249  plBase = testBase;
250  allKnown = true;
251  if ( verb > 3 ) { G4cout << " physlist current best guess: " << testBase << G4endl; }
252  } else {
253  if ( verb > 3 ) { G4cout << " physlist match but shorter: " << testBase << G4endl; }
254  }
255  } else {
256  if ( verb > 3 ) { G4cout << " physlist reject: " << testBase << G4endl; }
257  }
258  }
259  if ( verb > 2 ) {
260  G4cout << " physlist " << name << ", base known " << allKnown
261  << " chosen plBase \"" << plBase << "\"" << G4endl;
262  }
263  if ( ! allKnown ) {
264  // didn't find any matching base physics list
265  // no point of going on to the extensions
266  return allKnown;
267  }
268  // remove base name for working name
269  workingName.erase(0,plBase.size());
270 
271  // now start trying to match up extensions
272  // each should be preceeded by at "_" (replace) or "+" (register)
273  // but don't freak if it isn't, just assume "_"
274  size_t ne = availExtras.size();
275  while ( ! workingName.empty() ) {
276  char c = workingName.data()[0]; // leading character
277  if ( '_' == c || '+' == c ) workingName.erase(0,1); // and remove it
278  G4int replaceExtra = ( c != '+' );
279  G4String extraName = "";
280  G4bool extraKnown = false;
281  for (size_t ie=0; ie<ne; ++ie) {
282  const G4String& testExtra = availExtras[ie];
283  size_t ipos = workingName.find(testExtra);
284  if ( ipos == 0 ) {
285  if ( testExtra.size() > extraName.size() ) {
286  extraName = testExtra;
287  extraKnown = true;
288 #ifdef G4VERBOSE
289  if ( verb > 3 ) { G4cout << " physextra current best guess: " << testExtra << G4endl; }
290  } else {
291  if ( verb > 3 ) { G4cout << " physextra match but shorter: " << testExtra << G4endl; }
292 #endif
293  }
294  } else {
295 #ifdef G4VERBOSE
296  if ( verb > 3 ) { G4cout << " physextra reject: " << testExtra << G4endl; }
297 #endif
298  }
299  }
300 #ifdef G4VERBOSE
301  if ( verb > 2 ) {
302  G4cout << " physextra " << name << " [" << workingName << "]"
303  <<", extra known " << extraKnown
304  << " chosen extra \"" << extraName << "\""
305  << " replace " << replaceExtra << G4endl;
306  }
307 #endif
308  if ( extraKnown ) {
309  // physics mapping name is known, but is it actually linked to physics?
310  //const issue// G4String pcname = physicsExtensions[extraName];
311  std::map<G4String,G4String>::const_iterator itr =
312  physicsExtensions.find(extraName);
313  G4String pcname = "";
314  if ( itr != physicsExtensions.end() ) pcname = itr->second;
315  bool realknown = physConstRegistry->IsKnownPhysicsConstructor(pcname);
316 #ifdef G4VERBOSE
317  if ( verb > 2 ) {
318  G4cout << " extraName \"" << extraName << "\" maps to physics ctor \""
319  << pcname << "\" which is itself realknown " << realknown
320  << G4endl;
321  }
322 #endif
323  if ( ! realknown ) allKnown = false;
324  physExt.push_back(extraName);
325  replace.push_back(replaceExtra);
326  // and remove it so we can look for the next bit
327  workingName.erase(0,extraName.size());
328  } else {
329  allKnown = false;
330  }
331  } // workingName not empty
332 
333  return allKnown;
334 }
335 
336 const std::vector<G4String>& G4PhysListRegistry::AvailablePhysLists() const
337 {
338  availBasePhysLists.clear();
339  std::map<G4String,G4VBasePhysListStamper*>::const_iterator itr;
340  for ( itr = factories.begin(); itr != factories.end(); ++itr ) {
341  availBasePhysLists.push_back(itr->first);
342  }
343 
344  return availBasePhysLists;
345 }
346 
347 const std::vector<G4String>& G4PhysListRegistry::AvailablePhysicsExtensions() const
348 {
349  availExtensions.clear();
350  std::map<G4String,G4String>::const_iterator itr;
351  for ( itr = physicsExtensions.begin(); itr != physicsExtensions.end(); ++itr ) {
352  availExtensions.push_back(itr->first);
353  }
354 
355  return availExtensions;
356 }
357 
358 const std::vector<G4String>& G4PhysListRegistry::AvailablePhysListsEM() const
359 {
360  // in principle this method could weed out all the extensions that aren't
361  // EM replacements ... but for now just use it as a synonym for
362  // AvailablePhysicsExtensions()
364 }
365 
367 {
368  std::vector<G4String> avail = AvailablePhysLists();
369  G4cout << "Base G4VModularPhysicsLists in G4PhysListRegistry are:"
370  << G4endl;
371  if ( avail.empty() ) G4cout << "... no registered lists" << G4endl;
372  else {
373  size_t n = avail.size();
374  for (size_t i=0; i<n; ++i ) {
375  G4cout << " [" << std::setw(3) << i << "] "
376  << " \"" << avail[i] << "\"" << G4endl;
377  }
378  }
379 
381 
382  std::map<G4String,G4String>::const_iterator itr;
383  G4cout << "Replacement mappings in G4PhysListRegistry are:"
384  << G4endl;
385  for ( itr = physicsExtensions.begin(); itr != physicsExtensions.end(); ++itr ) {
386  bool known = physConstRegistry->IsKnownPhysicsConstructor(itr->second);
387 
388  G4cout << " " << std::setw(10) << itr->first << " => "
389  << std::setw(30) << itr->second << " "
390  << ( (known)?"":"[unregistered physics]")
391  << G4endl;
392  }
393  G4cout << "Use these mapping to extend physics list; append with _EXT or +EXT" << G4endl
394  << " to use ReplacePhysics() (\"_\") or RegisterPhysics() (\"+\")."
395  << G4endl;
396 }
397 
std::vector< G4String > availExtensions
void RegisterPhysics(G4VPhysicsConstructor *)
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
G4String name
Definition: TRTMaterials.hh:40
G4bool IsKnownPhysicsConstructor(const G4String &name)
void AddFactory(G4String name, G4VBasePhysListStamper *)
std::map< G4String, G4VBasePhysListStamper * > factories
#define G4ThreadLocal
Definition: tls.hh:89
int G4int
Definition: G4Types.hh:78
G4String userDefault
throw an exception if unsatisfiable?
G4GLOB_DLL std::ostream G4cout
G4VPhysicsConstructor * GetPhysicsConstructor(const G4String &name)
bool G4bool
Definition: G4Types.hh:79
std::vector< G4String > availBasePhysLists
use this if user hasn't set userDefault or attempts to set the userDefault=""
G4VModularPhysicsList * GetModularPhysicsListFromEnv()
static G4PhysListRegistry * Instance()
const G4int n
void SetVerboseLevel(G4int value)
static const double pc
Definition: G4SIunits.hh:136
void SetUserDefaultPhysList(const G4String &name="")
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
const char * data() const
const std::vector< G4String > & AvailablePhysListsEM() const
void ReplacePhysics(G4VPhysicsConstructor *)
static G4PhysicsConstructorRegistry * Instance()
static G4ThreadLocal G4PhysListRegistry * theInstance
const std::vector< G4String > & AvailablePhysicsExtensions() const
G4bool DeconstructPhysListName(const G4String &name, G4String &plBase, std::vector< G4String > &physExt, std::vector< G4int > &replace, G4int verbose=0) const
void PrintAvailablePhysLists() const
#define G4endl
Definition: G4ios.hh:61
std::map< G4String, G4String > physicsExtensions
G4bool IsReferencePhysList(G4String nam) const
G4String systemDefault
use this if $PHYSLIST isn't set
const std::vector< G4String > & AvailablePhysLists() const
G4VModularPhysicsList * GetModularPhysicsList(const G4String &name)
void AddPhysicsExtension(G4String name, G4String procname)