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 // 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