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 // G4ParticleDefinition class implementation 27 // 28 // Authors: G.Cosmo, 2 December 1995 - Design, based on object model 29 // M.Asai, 29 January 1996 - First implementation 30 // History: 31 // - 1996-2003, H.Kurashige - Revisions 32 // - 11.03.2003, H.Kurashige - Restructuring for Cuts per Region 33 // - 25.01.2013, G.Cosmo, A.Dotti - Introduced thread-safety for MT 34 // - 15.06.2017, K.L.Genser - Added support for MuonicAtom 35 // -------------------------------------------------------------------- 36 37 #include "G4ParticleDefinition.hh" 38 39 #include "G4DecayTable.hh" 40 #include "G4IonTable.hh" 41 #include "G4PDGCodeChecker.hh" 42 #include "G4ParticleTable.hh" 43 #include "G4PhysicalConstants.hh" 44 #include "G4StateManager.hh" 45 #include "G4SystemOfUnits.hh" 46 #include "G4Threading.hh" 47 #include "G4UnitsTable.hh" 48 49 // This new field helps to use the class G4PDefManager. 50 // 51 G4PDefManager G4ParticleDefinition::subInstanceManager; 52 53 // This macro changes the references to fields that are now encapsulated 54 // in the class G4PDefData. 55 // 56 #define G4MT_pmanager \ 57 ((subInstanceManager.offset()[g4particleDefinitionInstanceID]).theProcessManager) 58 #define G4MT_tmanager \ 59 ((subInstanceManager.offset()[g4particleDefinitionInstanceID]).theTrackingManager) 60 61 // -------------------------------------------------------------------- 62 // clang-format off 63 G4ParticleDefinition::G4ParticleDefinition( 64 const G4String& aName, 65 G4double mass, 66 G4double width, 67 G4double charge, 68 G4int iSpin, 69 G4int iParity, 70 G4int iConjugation, 71 G4int iIsospin, 72 G4int iIsospin3, 73 G4int gParity, 74 const G4String& pType, 75 G4int lepton, 76 G4int baryon, 77 G4int encoding, 78 G4bool stable, 79 G4double lifetime, 80 G4DecayTable* decaytable, 81 G4bool shortlived, 82 const G4String& subType, 83 G4int anti_encoding, 84 G4double magneticMoment) 85 86 : theParticleName(aName), 87 thePDGMass(mass), 88 thePDGWidth(width), 89 thePDGCharge(charge), 90 thePDGiSpin(iSpin), 91 thePDGSpin(iSpin*0.5), 92 thePDGiParity(iParity), 93 thePDGiConjugation(iConjugation), 94 thePDGiGParity(gParity), 95 thePDGiIsospin(iIsospin), 96 thePDGiIsospin3(iIsospin3), 97 thePDGIsospin(iIsospin*0.5), 98 thePDGIsospin3(iIsospin3*0.5), 99 thePDGMagneticMoment(magneticMoment), 100 theLeptonNumber(lepton), 101 theBaryonNumber(baryon), 102 theParticleType(pType), 103 theParticleSubType(subType), 104 thePDGEncoding(encoding), 105 theAntiPDGEncoding(-1*encoding), 106 fShortLivedFlag(shortlived), 107 thePDGStable(stable), 108 thePDGLifeTime(lifetime), 109 theDecayTable(decaytable) 110 // clang-format on 111 { 112 static const G4String nucleus("nucleus"); 113 static const G4String muAtom("MuonicAtom"); 114 115 g4particleDefinitionInstanceID = -1; 116 theProcessManagerShadow = nullptr; 117 118 theParticleTable = G4ParticleTable::GetParticleTable(); 119 120 // set verboseLevel equal to ParticleTable 121 verboseLevel = theParticleTable->GetVerboseLevel(); 122 123 if (anti_encoding != 0) theAntiPDGEncoding = anti_encoding; 124 125 // check quark contents 126 if (this->FillQuarkContents() != thePDGEncoding) { 127 #ifdef G4VERBOSE 128 if (verboseLevel > 0) { 129 // Using G4cout expecting that it is available 130 // in construction of static objects 131 G4cout << "Particle " << aName << " has a strange PDGEncoding " << G4endl; 132 } 133 #endif 134 G4Exception("G4ParticleDefintion::G4ParticleDefintion", "PART102", JustWarning, 135 "Strange PDGEncoding "); 136 } 137 138 // check initialization is in Pre_Init state except for ions 139 G4ApplicationState currentState = G4StateManager::GetStateManager()->GetCurrentState(); 140 141 if (!fShortLivedFlag && (theParticleType != nucleus) && (theParticleType != muAtom) 142 && (currentState != G4State_PreInit)) 143 { 144 #ifdef G4VERBOSE 145 if (GetVerboseLevel() > 0) { 146 G4cout << "G4ParticleDefinition (other than ions and shortlived)" 147 << " should be created in Pre_Init state - " << aName << G4endl; 148 } 149 #endif 150 G4Exception("G4ParticleDefintion::G4ParticleDefinition()", "PART101", JustWarning, 151 "G4ParticleDefinition should be created in PreInit state"); 152 } 153 154 if (theParticleTable->GetIonTable()->IsIon(this)) { 155 SetAtomicNumber(G4int(GetPDGCharge() / eplus)); 156 SetAtomicMass(GetBaryonNumber()); 157 } 158 159 if (theParticleTable->GetIonTable()->IsAntiIon(this)) { 160 SetAtomicNumber(std::abs(G4int(GetPDGCharge() / eplus))); 161 SetAtomicMass(std::abs(GetBaryonNumber())); 162 } 163 164 // check name and register this particle into ParticleTable 165 theParticleTable->Insert(this); 166 } 167 168 G4ParticleDefinition::G4ParticleDefinition() 169 { 170 G4Exception("G4ParticleDefinition::G4ParticleDefinition()", "PART001", FatalException, 171 "Illegal call of default constructor for G4ParticleDefinition!"); 172 } 173 174 G4ParticleDefinition::~G4ParticleDefinition() 175 { 176 if (G4ParticleTable::GetParticleTable()->GetReadiness()) { 177 G4StateManager* pStateManager = G4StateManager::GetStateManager(); 178 G4ApplicationState currentState = pStateManager->GetCurrentState(); 179 if (currentState != G4State_PreInit) { 180 G4String msg = "Request of deletion for "; 181 msg += GetParticleName(); 182 msg += " has No effects because readyToUse is true."; 183 G4Exception("G4ParticleDefinition::~G4ParticleDefinition()", "PART117", JustWarning, msg); 184 return; 185 } 186 187 #ifdef G4VERBOSE 188 if (verboseLevel > 0) { 189 G4cout << GetParticleName() << " will be deleted..." << G4endl; 190 } 191 #endif 192 } 193 delete theDecayTable; 194 } 195 196 G4bool G4ParticleDefinition::operator==(const G4ParticleDefinition& right) const 197 { 198 return (this->theParticleName == right.theParticleName); 199 } 200 201 G4bool G4ParticleDefinition::operator!=(const G4ParticleDefinition& right) const 202 { 203 return (this->theParticleName != right.theParticleName); 204 } 205 206 const G4PDefManager& G4ParticleDefinition::GetSubInstanceManager() 207 { 208 // Returns the private data instance manager 209 return subInstanceManager; 210 } 211 212 void G4ParticleDefinition::Clean() 213 { 214 // Clears memory allocated by sub-instance manager 215 subInstanceManager.FreeSlave(); 216 } 217 218 G4ProcessManager* G4ParticleDefinition::GetProcessManager() const 219 { 220 if (g4particleDefinitionInstanceID < 0) return nullptr; 221 return G4MT_pmanager; 222 } 223 224 G4VTrackingManager* G4ParticleDefinition::GetTrackingManager() const 225 { 226 if (g4particleDefinitionInstanceID < 0) return nullptr; 227 return G4MT_tmanager; 228 } 229 230 G4int G4ParticleDefinition::FillQuarkContents() 231 { 232 // Calculate quark and anti-quark contents 233 // Returned value is the PDG encoding for this particle. 234 // It means error if the return value is different from 235 // this->thePDGEncoding 236 237 G4int flavor; 238 for (flavor = 0; flavor < NumberOfQuarkFlavor; ++flavor) { 239 theQuarkContent[flavor] = 0; 240 theAntiQuarkContent[flavor] = 0; 241 } 242 243 G4PDGCodeChecker checker; 244 checker.SetVerboseLevel(verboseLevel); 245 246 G4int temp = checker.CheckPDGCode(thePDGEncoding, theParticleType); 247 248 if (temp != 0) { 249 for (flavor = 0; flavor < NumberOfQuarkFlavor; ++flavor) { 250 theQuarkContent[flavor] = checker.GetQuarkContent(flavor); 251 theAntiQuarkContent[flavor] = checker.GetAntiQuarkContent(flavor); 252 } 253 if ((theParticleType == "meson") || (theParticleType == "baryon")) { 254 // check charge 255 if (!checker.CheckCharge(thePDGCharge)) { 256 temp = 0; 257 G4Exception("G4ParticleDefintion::G4ParticleDefintion", "PART103", JustWarning, 258 "Inconsistent charge against PDG code "); 259 #ifdef G4VERBOSE 260 if (verboseLevel > 0) { 261 G4cout << "G4ParticleDefinition::FillQuarkContents : " 262 << " illegal charge (" << thePDGCharge / eplus << " PDG code=" << thePDGEncoding 263 << G4endl; 264 } 265 #endif 266 } 267 // check spin 268 if (checker.GetSpin() != thePDGiSpin) { 269 temp = 0; 270 G4Exception("G4ParticleDefintion::G4ParticleDefintion", "PART104", JustWarning, 271 "Inconsistent spin against PDG code "); 272 #ifdef G4VERBOSE 273 if (verboseLevel > 0) { 274 G4cout << "G4ParticleDefinition::FillQuarkContents : " 275 << " illegal SPIN (" << thePDGiSpin << "/2" 276 << " PDG code=" << thePDGEncoding << G4endl; 277 } 278 #endif 279 } 280 } 281 } 282 return temp; 283 } 284 285 void G4ParticleDefinition::DumpTable() const 286 { 287 G4cout << G4endl; 288 G4cout << "--- G4ParticleDefinition ---" << G4endl; 289 G4cout << " Particle Name : " << theParticleName << G4endl; 290 G4cout << " PDG particle code : " << thePDGEncoding; 291 G4cout << " [PDG anti-particle code: " << this->GetAntiPDGEncoding() << "]" << G4endl; 292 G4cout << " Mass [GeV/c2] : " << thePDGMass / GeV; 293 G4cout << " Width : " << thePDGWidth / GeV << G4endl; 294 G4cout << " Lifetime [nsec] : " << thePDGLifeTime / ns << G4endl; 295 G4cout << " Charge [e]: " << thePDGCharge / eplus << G4endl; 296 G4cout << " Spin : " << thePDGiSpin << "/2" << G4endl; 297 G4cout << " Parity : " << thePDGiParity << G4endl; 298 G4cout << " Charge conjugation : " << thePDGiConjugation << G4endl; 299 G4cout << " Isospin : (I,Iz): (" << thePDGiIsospin << "/2"; 300 G4cout << " , " << thePDGiIsospin3 << "/2 ) " << G4endl; 301 G4cout << " GParity : " << thePDGiGParity << G4endl; 302 if (thePDGMagneticMoment != 0.0) { 303 G4cout << " MagneticMoment [MeV/T] : " << thePDGMagneticMoment / MeV * tesla << G4endl; 304 } 305 G4cout << " Quark contents (d,u,s,c,b,t) : " << theQuarkContent[0]; 306 G4cout << ", " << theQuarkContent[1]; 307 G4cout << ", " << theQuarkContent[2]; 308 G4cout << ", " << theQuarkContent[3]; 309 G4cout << ", " << theQuarkContent[4]; 310 G4cout << ", " << theQuarkContent[5] << G4endl; 311 G4cout << " AntiQuark contents : " << theAntiQuarkContent[0]; 312 G4cout << ", " << theAntiQuarkContent[1]; 313 G4cout << ", " << theAntiQuarkContent[2]; 314 G4cout << ", " << theAntiQuarkContent[3]; 315 G4cout << ", " << theAntiQuarkContent[4]; 316 G4cout << ", " << theAntiQuarkContent[5] << G4endl; 317 G4cout << " Lepton number : " << theLeptonNumber; 318 G4cout << " Baryon number : " << theBaryonNumber << G4endl; 319 G4cout << " Particle type : " << theParticleType; 320 G4cout << " [" << theParticleSubType << "]" << G4endl; 321 322 if ((theParticleTable->GetIonTable()->IsIon(this)) 323 || (theParticleTable->GetIonTable()->IsAntiIon(this))) 324 { 325 G4cout << " Atomic Number : " << GetAtomicNumber(); 326 G4cout << " Atomic Mass : " << GetAtomicMass() << G4endl; 327 } 328 if (fShortLivedFlag) { 329 G4cout << " ShortLived : ON" << G4endl; 330 } 331 332 if (IsGeneralIon()) { 333 G4double lftm = GetIonLifeTime(); 334 if (lftm < -1000.) { 335 G4cout << " Stable : No data found -- unknown" << G4endl; 336 } 337 else if (lftm < 0.) { 338 G4cout << " Stable : stable" << G4endl; 339 } 340 else { 341 G4cout << " Stable : unstable -- lifetime = " << G4BestUnit(lftm, "Time") 342 << "\n Decay table should be consulted to G4RadioactiveDecayProcess." << G4endl; 343 } 344 } 345 else { 346 if (thePDGStable) { 347 G4cout << " Stable : stable" << G4endl; 348 } 349 else { 350 if (theDecayTable != nullptr) { 351 theDecayTable->DumpInfo(); 352 } 353 else { 354 G4cout << "Decay Table is not defined !!" << G4endl; 355 } 356 } 357 } 358 } 359 360 void G4ParticleDefinition::SetApplyCutsFlag(G4bool flg) 361 { 362 if (theParticleName == "gamma" || theParticleName == "e-" || theParticleName == "e+" 363 || theParticleName == "proton") 364 { 365 fApplyCutsFlag = flg; 366 } 367 else { 368 G4cout << "G4ParticleDefinition::SetApplyCutsFlag() for " << theParticleName << G4endl; 369 G4cout << "becomes obsolete. Production threshold is applied only for " 370 << "gamma, e- ,e+ and proton." << G4endl; 371 } 372 } 373 374 G4double G4ParticleDefinition::CalculateAnomaly() const 375 { 376 G4Exception("G4ParticleDefinition::G4ParticleDefinition", "PART114", JustWarning, 377 "CalculateAnomaly() method will be removed in future releases"); 378 379 // gives the anomaly of magnetic moment for spin 1/2 particles 380 if (thePDGiSpin == 1) { 381 G4double muB = 0.5 * CLHEP::eplus * CLHEP::hbar_Planck / (thePDGMass / CLHEP::c_squared); 382 return 0.5 * std::fabs(thePDGMagneticMoment / muB - 2. * thePDGCharge / CLHEP::eplus); 383 } 384 385 return 0.0; 386 } 387 388 void G4ParticleDefinition::SetParticleDefinitionID(G4int id) 389 { 390 if (id < 0) { 391 g4particleDefinitionInstanceID = subInstanceManager.CreateSubInstance(); 392 G4MT_pmanager = nullptr; 393 } 394 else { 395 if (isGeneralIon || isMuonicAtom) { 396 g4particleDefinitionInstanceID = id; 397 } 398 else { 399 G4ExceptionDescription ed; 400 ed << "ParticleDefinitionID should not be set for the particles <" << theParticleName << ">."; 401 G4Exception("G4ParticleDefintion::SetParticleDefinitionID", "PART10114", FatalException, ed); 402 } 403 } 404 } 405 406 void G4ParticleDefinition::SetProcessManager(G4ProcessManager* aProcessManager) 407 { 408 if (g4particleDefinitionInstanceID < 0 && !isGeneralIon) { 409 if (G4Threading::G4GetThreadId() >= 0) { 410 G4ExceptionDescription ed; 411 ed << "ProcessManager is being set to " << theParticleName 412 << " without proper initialization of TLS pointer vector.\n" 413 << "This operation is thread-unsafe."; 414 G4Exception("G4ParticleDefintion::SetProcessManager", "PART10116", JustWarning, ed); 415 } 416 SetParticleDefinitionID(); 417 } 418 G4MT_pmanager = aProcessManager; 419 } 420 421 void G4ParticleDefinition::SetTrackingManager(G4VTrackingManager* aTrackingManager) 422 { 423 if (g4particleDefinitionInstanceID < 0 && !isGeneralIon) { 424 if (G4Threading::G4GetThreadId() >= 0) { 425 G4ExceptionDescription ed; 426 ed << "TrackingManager is being set to " << theParticleName 427 << " without proper initialization of TLS pointer vector.\n" 428 << "This operation is thread-unsafe."; 429 G4Exception("G4ParticleDefintion::SetTrackingManager", "PART10118", JustWarning, ed); 430 } 431 SetParticleDefinitionID(); 432 } 433 G4MT_tmanager = aTrackingManager; 434 } 435