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 // 27 28 #include "G4AttCheck.hh" 29 30 #include "globals.hh" 31 32 #include "G4AttDef.hh" 33 #include "G4AttDefStore.hh" 34 #include "G4AttValue.hh" 35 #include "G4UnitsTable.hh" 36 #include "G4UIcommand.hh" 37 38 G4ThreadLocal G4bool G4AttCheck::fFirst = true; 39 40 G4ThreadLocal std::set<G4String> *G4AttCheck::fUnitCategories = nullptr; 41 42 G4ThreadLocal std::map<G4String,G4String> *G4AttCheck::fStandardUnits = nullptr; 43 44 G4ThreadLocal std::set<G4String> *G4AttCheck::fCategories = nullptr; 45 46 G4ThreadLocal std::set<G4String> *G4AttCheck::fUnits = nullptr; 47 48 G4ThreadLocal std::set<G4String> *G4AttCheck::fValueTypes = nullptr; 49 50 G4AttCheck::G4AttCheck 51 (const std::vector<G4AttValue>* values, 52 const std::map<G4String,G4AttDef>* definitions): 53 fpValues(values), 54 fpDefinitions(definitions) 55 { 56 Init(); 57 58 if (fFirst) { // Initialise static containers. 59 fFirst = false; 60 61 // Legal Unit Category Types... 62 fUnitCategories->insert("Length"); 63 fUnitCategories->insert("Energy"); 64 fUnitCategories->insert("Time"); 65 fUnitCategories->insert("Electric charge"); 66 fUnitCategories->insert("Volumic Mass"); // (Density) 67 68 // Corresponding Standard Units... 69 (*fStandardUnits)["Length"] = "m"; 70 (*fStandardUnits)["Energy"] = "MeV"; 71 (*fStandardUnits)["Time"] = "ns"; 72 (*fStandardUnits)["Electric charge"] = "e+"; 73 (*fStandardUnits)["Volumic Mass"] = "kg/m3"; 74 75 // Legal Categories... 76 fCategories->insert("Bookkeeping"); 77 fCategories->insert("Draw"); 78 fCategories->insert("Physics"); 79 fCategories->insert("PickAction"); 80 fCategories->insert("Association"); 81 82 // Legal units... 83 fUnits->insert(""); 84 fUnits->insert("G4BestUnit"); 85 // ...plus any legal unit symbol ("MeV", "km", etc.)... 86 G4UnitsTable& units = G4UnitDefinition::GetUnitsTable(); 87 for (size_t i = 0; i < units.size(); ++i) { 88 if (fUnitCategories->find(units[i]->GetName()) != 89 fUnitCategories->end()) { 90 //G4cout << units[i]->GetName() << G4endl; 91 G4UnitsContainer& container = units[i]->GetUnitsList(); 92 for (auto & j : container) { 93 //G4cout << container[j]->GetName() << ' ' 94 // << container[j]->GetSymbol() << G4endl; 95 fUnits->insert(j->GetSymbol()); 96 } 97 } 98 } 99 100 // Legal Value Types... 101 fValueTypes->insert("G4String"); 102 fValueTypes->insert("G4int"); 103 fValueTypes->insert("G4double"); 104 fValueTypes->insert("G4ThreeVector"); 105 fValueTypes->insert("G4bool"); 106 } 107 } 108 109 void G4AttCheck::Init() 110 { 111 if (fValueTypes == nullptr) fValueTypes = new std::set<G4String>; 112 if (fUnits == nullptr) fUnits = new std::set<G4String>; 113 if (fCategories == nullptr) fCategories = new std::set<G4String>; 114 if (fStandardUnits == nullptr) fStandardUnits = new std::map<G4String,G4String>; 115 if (fUnitCategories == nullptr) fUnitCategories = new std::set<G4String>; 116 } 117 118 G4bool G4AttCheck::Check(const G4String& leader) const 119 { 120 // Check only. Silent unless error - then G4cerr. Returns error. 121 G4bool error = false; 122 static G4ThreadLocal G4int iError = 0; 123 G4bool print = false; 124 if (iError < 10 || iError%100 == 0) { 125 print = true; 126 } 127 using namespace std; 128 if (fpValues == nullptr) return error; // A null values vector is a valid situation. 129 if (fpDefinitions == nullptr) { 130 ++iError; 131 error = true; 132 if (print) { 133 G4cerr << 134 "\n*******************************************************"; 135 if (!leader.empty()) { 136 G4cerr << '\n' << leader; 137 } 138 G4cerr << 139 "\nG4AttCheck: ERROR " << iError << ": Null definitions pointer" 140 "\n*******************************************************" 141 << G4endl; 142 } 143 return error; 144 } 145 vector<G4AttValue>::const_iterator iValue; 146 for (iValue = fpValues->begin(); iValue != fpValues->end(); ++iValue) { 147 const G4String& valueName = iValue->GetName(); 148 const G4String& value = iValue->GetValue(); 149 // NOLINTNEXTLINE(modernize-use-auto): Explicitly want a const_iterator 150 map<G4String,G4AttDef>::const_iterator iDef = 151 fpDefinitions->find(valueName); 152 if (iDef == fpDefinitions->end()) { 153 ++iError; 154 error = true; 155 if (print) { 156 G4cerr << 157 "\n*******************************************************"; 158 if (!leader.empty()) { 159 G4cerr << '\n' << leader; 160 } 161 G4cerr << 162 "\nG4AttCheck: ERROR " << iError << ": No G4AttDef for G4AttValue \"" 163 << valueName << "\": " << value << 164 "\n*******************************************************" 165 << G4endl; 166 } 167 } else { 168 const G4String& category = iDef->second.GetCategory(); 169 const G4String& extra = iDef->second.GetExtra(); 170 const G4String& valueType = iDef->second.GetValueType(); 171 if (fCategories->find(category) == fCategories->end()) { 172 ++iError; 173 error = true; 174 if (print) { 175 G4cerr << 176 "\n*******************************************************"; 177 if (!leader.empty()) { 178 G4cerr << '\n' << leader; 179 } 180 G4cerr << 181 "\nG4AttCheck: ERROR " << iError << ": Illegal Category Field \"" 182 << category << "\" for G4AttValue \"" 183 << valueName << "\": " << value << 184 "\n Possible Categories:"; 185 set<G4String>::iterator i; 186 for (i = fCategories->begin(); i != fCategories->end(); ++i) { 187 G4cerr << ' ' << *i; 188 } 189 G4cerr << 190 "\n*******************************************************" 191 << G4endl; 192 } 193 } 194 if(category == "Physics" && fUnits->find(extra) == fUnits->end()) { 195 ++iError; 196 error = true; 197 if (print) { 198 G4cerr << 199 "\n*******************************************************"; 200 if (!leader.empty()) { 201 G4cerr << '\n' << leader; 202 } 203 G4cerr << 204 "\nG4AttCheck: ERROR " << iError << ": Illegal Extra field \"" 205 << extra << "\" for G4AttValue \"" 206 << valueName << "\": " << value << 207 "\n Possible Extra fields if Category==\"Physics\":\n "; 208 set<G4String>::iterator i; 209 for (i = fUnits->begin(); i != fUnits->end(); ++i) { 210 G4cerr << ' ' << *i; 211 } 212 G4cerr << 213 "\n*******************************************************" 214 << G4endl; 215 } 216 } 217 if (fValueTypes->find(valueType) == fValueTypes->end()) { 218 ++iError; 219 error = true; 220 if (print) { 221 G4cerr << 222 "\n*******************************************************"; 223 if (!leader.empty()) { 224 G4cerr << '\n' << leader; 225 } 226 G4cerr << 227 "\nG4AttCheck: ERROR " << iError << ": Illegal Value Type field \"" 228 << valueType << "\" for G4AttValue \"" 229 << valueName << "\": " << value << 230 "\n Possible Value Types:"; 231 set<G4String>::iterator i; 232 for (i = fValueTypes->begin(); i != fValueTypes->end(); ++i) { 233 G4cerr << ' ' << *i; 234 } 235 G4cerr << 236 "\n*******************************************************" 237 << G4endl; 238 } 239 } 240 } 241 } 242 return error; 243 } 244 245 std::ostream& operator<< (std::ostream& os, const G4AttCheck& ac) 246 { 247 using namespace std; 248 if (ac.fpDefinitions == nullptr) { 249 os << "G4AttCheck: ERROR: zero definitions pointer." << endl; 250 return os; 251 } 252 G4String storeKey; 253 if (G4AttDefStore::GetStoreKey(ac.fpDefinitions, storeKey)) { 254 os << storeKey << ':' << endl; 255 } 256 if (ac.fpValues == nullptr) { 257 // A null values vector is a valid situation. 258 os << "G4AttCheck: zero values pointer." << endl; 259 return os; 260 } 261 vector<G4AttValue>::const_iterator iValue; 262 for (iValue = ac.fpValues->begin(); iValue != ac.fpValues->end(); ++iValue) { 263 const G4String& valueName = iValue->GetName(); 264 const G4String& value = iValue->GetValue(); 265 // NOLINTNEXTLINE(modernize-use-auto): Explicitly want a const_iterator 266 map<G4String,G4AttDef>::const_iterator iDef = 267 ac.fpDefinitions->find(valueName); 268 G4bool error = false; 269 if (iDef == ac.fpDefinitions->end()) { 270 error = true; 271 os << "G4AttCheck: ERROR: No G4AttDef for G4AttValue \"" 272 << valueName << "\": " << value << endl; 273 } else { 274 const G4String& category = iDef->second.GetCategory(); 275 const G4String& extra = iDef->second.GetExtra(); 276 const G4String& valueType = iDef->second.GetValueType(); 277 if (ac.fCategories->find(category) == ac.fCategories->end()) { 278 error = true; 279 os << 280 "G4AttCheck: ERROR: Illegal Category Field \"" << category 281 << "\" for G4AttValue \"" << valueName << "\": " << value << 282 "\n Possible Categories:"; 283 set<G4String>::iterator i; 284 for (i = ac.fCategories->begin(); i != ac.fCategories->end(); ++i) { 285 os << ' ' << *i; 286 } 287 os << endl; 288 } 289 if(category == "Physics" && ac.fUnits->find(extra) == ac.fUnits->end()) { 290 error = true; 291 os << 292 "G4AttCheck: ERROR: Illegal Extra field \""<< extra 293 << "\" for G4AttValue \"" << valueName << "\": " << value << 294 "\n Possible Extra fields if Category==\"Physics\":\n "; 295 set<G4String>::iterator i; 296 for (i = ac.fUnits->begin(); i != ac.fUnits->end(); ++i) { 297 os << ' ' << *i; 298 } 299 os << endl; 300 } 301 if (ac.fValueTypes->find(valueType) == ac.fValueTypes->end()) { 302 error = true; 303 os << 304 "G4AttCheck: ERROR: Illegal Value Type field \"" << valueType 305 << "\" for G4AttValue \"" << valueName << "\": " << value << 306 "\n Possible Value Types:"; 307 set<G4String>::iterator i; 308 for (i = ac.fValueTypes->begin(); i != ac.fValueTypes->end(); ++i) { 309 os << ' ' << *i; 310 } 311 os << endl; 312 } 313 } 314 if (!error) { 315 os << iDef->second.GetDesc() 316 << " (" << valueName 317 << "): " << value; 318 if (iDef->second.GetCategory() == "Physics" && 319 !iDef->second.GetExtra().empty()) { 320 os << " (" << iDef->second.GetExtra() << ")"; 321 } 322 os << endl; 323 } 324 } 325 return os; 326 } 327 328 void G4AttCheck::AddValuesAndDefs 329 (std::vector<G4AttValue>* standardValues, 330 std::map<G4String,G4AttDef>* standardDefinitions, 331 const G4String& oldName, 332 const G4String& name, 333 const G4String& value, 334 const G4String& extra, 335 const G4String& description) const 336 { 337 // Add new G4AttDeff... 338 standardValues->push_back(G4AttValue(name,value,"")); 339 // Copy original G4AttDef... 340 (*standardDefinitions)[name] = fpDefinitions->find(oldName)->second; 341 // ...and make appropriate changes... 342 (*standardDefinitions)[name].SetName(name); 343 (*standardDefinitions)[name].SetExtra(extra); 344 if (!description.empty()) (*standardDefinitions)[name].SetDesc(description); 345 } 346 347 G4bool G4AttCheck::Standard 348 (std::vector<G4AttValue>* standardValues, 349 std::map<G4String,G4AttDef>* standardDefinitions) const 350 { 351 // Places standard versions in provided vector and map and returns error. 352 // Assumes valid input. Use Check to check. 353 using namespace std; 354 G4bool error = false; 355 vector<G4AttValue>::const_iterator iValue; 356 for (iValue = fpValues->begin(); iValue != fpValues->end(); ++iValue) { 357 const G4String& valueName = iValue->GetName(); 358 const G4String& value = iValue->GetValue(); 359 // NOLINTNEXTLINE(modernize-use-auto): Explicitly want a const_iterator 360 map<G4String,G4AttDef>::const_iterator iDef = 361 fpDefinitions->find(valueName); 362 if (iDef == fpDefinitions->end()) { 363 error = true; 364 } else { 365 const G4String& category = iDef->second.GetCategory(); 366 const G4String& extra = iDef->second.GetExtra(); 367 const G4String& valueType = iDef->second.GetValueType(); 368 if (fCategories->find(category) == fCategories->end() || 369 (category == "Physics" && fUnits->find(extra) == fUnits->end()) || 370 fValueTypes->find(valueType) == fValueTypes->end()) { 371 error = true; 372 } else { 373 if (category != "Physics") { // Simply copy... 374 standardValues->push_back(*iValue); 375 (*standardDefinitions)[valueName] = 376 fpDefinitions->find(valueName)->second; 377 } else { // "Physics"... 378 if (extra.empty()) { // Dimensionless... 379 if (valueType == "G4ThreeVector") { // Split vector into 3... 380 G4ThreeVector internalValue = 381 G4UIcommand::ConvertTo3Vector(value); 382 AddValuesAndDefs 383 (standardValues,standardDefinitions, 384 valueName,valueName+"-X", 385 G4UIcommand::ConvertToString(internalValue.x()),"", 386 fpDefinitions->find(valueName)->second.GetDesc()+"-X"); 387 AddValuesAndDefs 388 (standardValues,standardDefinitions, 389 valueName,valueName+"-Y", 390 G4UIcommand::ConvertToString(internalValue.y()),"", 391 fpDefinitions->find(valueName)->second.GetDesc()+"-Y"); 392 AddValuesAndDefs 393 (standardValues,standardDefinitions, 394 valueName,valueName+"-Z", 395 G4UIcommand::ConvertToString(internalValue.z()),"", 396 fpDefinitions->find(valueName)->second.GetDesc()+"-Z"); 397 } else { // Simply copy... 398 standardValues->push_back(*iValue); 399 (*standardDefinitions)[valueName] = 400 fpDefinitions->find(valueName)->second; 401 } 402 } else { // Dimensioned... 403 G4String valueAndUnit; 404 G4String unit; 405 if (extra == "G4BestUnit") { 406 valueAndUnit = G4StrUtil::strip_copy(value); 407 unit = valueAndUnit.substr(valueAndUnit.rfind(' ')+1); 408 } else { 409 valueAndUnit = G4StrUtil::strip_copy(value + ' ' + extra); 410 unit = extra; 411 } 412 G4String unitCategory = G4UnitDefinition::GetCategory(unit); 413 if (fUnitCategories->find(unitCategory) != fUnitCategories->end()) { 414 G4String standardUnit = (*fStandardUnits)[unitCategory]; 415 G4double valueOfStandardUnit = 416 G4UnitDefinition::GetValueOf(standardUnit); 417 // G4String exstr = iDef->second.GetExtra(); 418 if (valueType == "G4ThreeVector") { // Split vector into 3... 419 G4ThreeVector internalValue = 420 G4UIcommand::ConvertToDimensioned3Vector(valueAndUnit); 421 AddValuesAndDefs 422 (standardValues,standardDefinitions, 423 valueName,valueName+"-X", 424 G4UIcommand::ConvertToString 425 (internalValue.x()/valueOfStandardUnit), 426 standardUnit, 427 fpDefinitions->find(valueName)->second.GetDesc()+"-X"); 428 AddValuesAndDefs 429 (standardValues,standardDefinitions, 430 valueName,valueName+"-Y", 431 G4UIcommand::ConvertToString 432 (internalValue.y()/valueOfStandardUnit), 433 standardUnit, 434 fpDefinitions->find(valueName)->second.GetDesc()+"-Y"); 435 AddValuesAndDefs 436 (standardValues,standardDefinitions, 437 valueName,valueName+"-Z", 438 G4UIcommand::ConvertToString 439 (internalValue.z()/valueOfStandardUnit), 440 standardUnit, 441 fpDefinitions->find(valueName)->second.GetDesc()+"-Z"); 442 } else { 443 G4double internalValue = 444 G4UIcommand::ConvertToDimensionedDouble(valueAndUnit); 445 AddValuesAndDefs 446 (standardValues,standardDefinitions, 447 valueName,valueName, 448 G4UIcommand::ConvertToString 449 (internalValue/valueOfStandardUnit), 450 standardUnit); 451 } 452 } 453 } 454 } 455 } 456 } 457 } 458 if (error) { 459 G4cerr << "G4AttCheck::Standard: Conversion error." << G4endl; 460 } 461 return error; 462 } 463