Geant4 Cross Reference

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