Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4IonTable class implementation << 27 // 26 // 28 // Author: H.Kurashige, 27 June 1998 << 27 // $Id: G4IonTable.cc,v 1.65 2010/10/16 06:04:51 kurasige Exp $ 29 // ------------------------------------------- << 28 // GEANT4 tag $Name: geant4-09-04 $ >> 29 // >> 30 // >> 31 // -------------------------------------------------------------- >> 32 // GEANT 4 class implementation file >> 33 // >> 34 // History: first implementation, based on object model of >> 35 // 27 June 1998 H.Kurashige >> 36 // --------------------------------------------------------------- >> 37 // modified GetIon 02 Aug., 98 H.Kurashige >> 38 // added Remove() 06 Nov.,98 H.Kurashige >> 39 // use G4NucleiPropoerties to get nuceli Mass 17 Nov.,98 H.Kurashige >> 40 // use G4GenericIon for process List >> 41 // modify fomula of Ion mass 09 Dec., 98 H.Kurashige >> 42 // ----- >> 43 // Modified GetIon methods 17 Aug. 99 H.Kurashige >> 44 // New design using G4VIsotopeTable 5 Oct. 99 H.Kurashige >> 45 // Modified Element Name for Z>103 06 Apr. 01 H.Kurashige >> 46 // Remove test of cuts in SetCuts 16 Jan 03 V.Ivanchenko 30 47 31 #include "G4IonTable.hh" 48 #include "G4IonTable.hh" 32 << 33 #include "G4AutoDelete.hh" << 34 #include "G4HyperNucleiProperties.hh" << 35 #include "G4Ions.hh" << 36 #include "G4IsotopeProperty.hh" << 37 #include "G4MuonicAtom.hh" << 38 #include "G4MuonicAtomHelper.hh" << 39 #include "G4NucleiProperties.hh" << 40 #include "G4NuclideTable.hh" << 41 #include "G4ParticleTable.hh" 49 #include "G4ParticleTable.hh" 42 #include "G4PhysicalConstants.hh" << 43 #include "G4StateManager.hh" 50 #include "G4StateManager.hh" 44 #include "G4SystemOfUnits.hh" << 51 #include "G4Ions.hh" 45 #include "G4Threading.hh" << 46 #include "G4UImanager.hh" 52 #include "G4UImanager.hh" >> 53 #include "G4NucleiProperties.hh" >> 54 #include "G4HyperNucleiProperties.hh" >> 55 >> 56 #include "G4IsotopeProperty.hh" 47 #include "G4VIsotopeTable.hh" 57 #include "G4VIsotopeTable.hh" >> 58 48 #include "G4ios.hh" 59 #include "G4ios.hh" >> 60 #include <iostream> >> 61 #include <iomanip> 49 62 50 #include <algorithm> << 51 #include <iomanip> << 52 #include <iostream> << 53 #include <sstream> 63 #include <sstream> 54 #include <vector> << 55 64 56 // It is very important for multithreaded Gean << 57 // particle table pointer and the ion table po << 58 // each worker thread hold its own copy of the << 59 // ion list. This implementation is equivalent << 60 // private. The two shadow ponters are used by << 61 // content from the master thread. << 62 // << 63 G4ThreadLocal G4IonTable::G4IonList* G4IonTabl << 64 G4ThreadLocal std::vector<G4VIsotopeTable*>* G << 65 G4IonTable::G4IonList* G4IonTable::fIonListSha << 66 std::vector<G4VIsotopeTable*>* G4IonTable::fIs << 67 << 68 namespace lightions << 69 { << 70 static const G4ParticleDefinition* p_proton = << 71 static const G4ParticleDefinition* p_deuteron << 72 static const G4ParticleDefinition* p_triton = << 73 static const G4ParticleDefinition* p_alpha = n << 74 static const G4ParticleDefinition* p_He3 = nul << 75 void Init() << 76 { << 77 if (p_proton != nullptr) return; << 78 p_proton = G4ParticleTable::GetParticleTable << 79 p_deuteron = G4ParticleTable::GetParticleTab << 80 p_triton = G4ParticleTable::GetParticleTable << 81 p_alpha = G4ParticleTable::GetParticleTable( << 82 p_He3 = G4ParticleTable::GetParticleTable()- << 83 } << 84 } // namespace lightions << 85 << 86 namespace antilightions << 87 { << 88 static const G4ParticleDefinition* p_proton = << 89 static const G4ParticleDefinition* p_deuteron << 90 static const G4ParticleDefinition* p_triton = << 91 static const G4ParticleDefinition* p_alpha = n << 92 static const G4ParticleDefinition* p_He3 = nul << 93 void Init() << 94 { << 95 if (p_proton != nullptr) return; << 96 p_proton = G4ParticleTable::GetParticleTable << 97 p_deuteron = G4ParticleTable::GetParticleTab << 98 p_triton = G4ParticleTable::GetParticleTable << 99 p_alpha = G4ParticleTable::GetParticleTable( << 100 p_He3 = G4ParticleTable::GetParticleTable()- << 101 } << 102 } // namespace antilightions << 103 << 104 #ifdef G4MULTITHREADED << 105 G4Mutex G4IonTable::ionTableMutex = G4MUTEX_IN << 106 #endif << 107 << 108 // ------------------------------------------- << 109 65 >> 66 //////////////////// 110 G4IonTable::G4IonTable() 67 G4IonTable::G4IonTable() 111 { 68 { 112 fIonList = new G4IonList(); 69 fIonList = new G4IonList(); 113 << 114 // Set up the shadow pointer used by worker << 115 // << 116 if (fIonListShadow == nullptr) { << 117 fIonListShadow = fIonList; << 118 } << 119 << 120 fIsotopeTableList = new std::vector<G4VIsoto 70 fIsotopeTableList = new std::vector<G4VIsotopeTable*>; 121 << 122 // Set up the shadow pointer used by worker << 123 // << 124 if (fIsotopeTableListShadow == nullptr) { << 125 fIsotopeTableListShadow = fIsotopeTableLis << 126 } << 127 << 128 PrepareNuclideTable(); << 129 RegisterIsotopeTable(pNuclideTable); << 130 } 71 } 131 72 >> 73 //////////////////// 132 G4IonTable::~G4IonTable() 74 G4IonTable::~G4IonTable() 133 { 75 { 134 // delete IsotopeTable if existing << 76 // delete IsotopeTable if exists 135 if (fIsotopeTableList != nullptr) { << 77 if (fIsotopeTableList != 0) { 136 for (const auto fIsotopeTable : *fIsotopeT << 78 for (size_t i = 0; i< fIsotopeTableList->size(); ++i) { 137 if (fIsotopeTable != G4NuclideTable::Get << 79 G4VIsotopeTable* fIsotopeTable= (*fIsotopeTableList)[i]; 138 delete fIsotopeTable; << 80 delete fIsotopeTable; 139 } << 140 } 81 } 141 fIsotopeTableList->clear(); 82 fIsotopeTableList->clear(); 142 delete fIsotopeTableList; 83 delete fIsotopeTableList; 143 } 84 } 144 fIsotopeTableList = nullptr; << 85 fIsotopeTableList =0; 145 86 146 if (fIonList == nullptr) return; << 147 87 148 // remove all contents in the Ion List << 88 if (fIonList ==0) return; 149 // No need to delete here because all partic << 89 // remove all contents in the Ion List >> 90 // No need to delete here because all particles are dynamic objects 150 fIonList->clear(); 91 fIonList->clear(); 151 delete fIonList; << 152 fIonList = nullptr; << 153 } << 154 92 155 G4IonTable* G4IonTable::GetIonTable() << 93 delete fIonList; 156 { << 94 fIonList =0; 157 return G4ParticleTable::GetParticleTable()-> << 158 } 95 } 159 96 160 // Used by each worker thread to copy the cont << 161 void G4IonTable::WorkerG4IonTable() << 162 { << 163 if (fIonList == nullptr) { << 164 fIonList = new G4IonList(); << 165 } << 166 else { << 167 fIonList->clear(); << 168 } << 169 << 170 for (const auto& it : *fIonListShadow) { << 171 fIonList->insert(it); << 172 } << 173 << 174 // Do not copy Isotope Table to Worker threa << 175 // << 176 if (fIsotopeTableList == nullptr) { << 177 fIsotopeTableList = new std::vector<G4VIso << 178 for (const auto i : *fIsotopeTableListShad << 179 fIsotopeTableList->push_back(i); << 180 } << 181 } << 182 } << 183 97 184 void G4IonTable::InitializeLightIons() << 98 //////////////////// >> 99 // -- CreateIon method ------ >> 100 //////////////////// >> 101 G4ParticleDefinition* G4IonTable::CreateIon(G4int Z, G4int A, >> 102 G4double E, G4int J) 185 { 103 { 186 lightions::Init(); << 104 G4ParticleDefinition* ion=0; 187 antilightions::Init(); << 188 } << 189 105 190 void G4IonTable::DestroyWorkerG4IonTable() << 106 // check whether the cuurent state is not "PreInit" 191 { << 107 // to make sure that GenericIon has processes 192 // delete IsotopeTable if existing << 108 G4ApplicationState currentState = G4StateManager::GetStateManager()->GetCurrentState(); 193 if (fIsotopeTableList != nullptr) { << 109 if (currentState == G4State_PreInit){ 194 for (auto fIsotopeTable : *fIsotopeTableLi << 110 #ifdef G4VERBOSE 195 if (fIsotopeTable != G4NuclideTable::Get << 111 if (GetVerboseLevel()>1) { 196 delete fIsotopeTable; << 112 G4cerr << "G4IonTable::CreateIon() : can not create ion of " 197 } << 113 << " Z =" << Z << " A = " << A >> 114 << " because the current state is PreInit !!" << G4endl; 198 } 115 } 199 fIsotopeTableList->clear(); << 116 #endif 200 delete fIsotopeTableList; << 117 G4Exception( "G4IonTable::CreateIon()","Illegal operation", 201 } << 118 JustWarning, "Can not create ions in PreInit state"); 202 fIsotopeTableList = nullptr; << 119 return 0; 203 << 204 if (fIonList == nullptr) return; << 205 << 206 // remove all contents in the Ion List << 207 // No need to delete here because all partic << 208 fIonList->clear(); << 209 delete fIonList; << 210 fIonList = nullptr; << 211 } << 212 << 213 G4ParticleDefinition* G4IonTable::CreateIon(G4 << 214 G4 << 215 { << 216 G4ParticleDefinition* ion = nullptr; << 217 << 218 // check whether GenericIon has processes << 219 G4ParticleDefinition* genericIon = G4Particl << 220 G4ProcessManager* pman = nullptr; << 221 if (genericIon != nullptr) { << 222 pman = genericIon->GetProcessManager(); << 223 } 120 } 224 if ((genericIon == nullptr) || (genericIon-> << 121 >> 122 // get ion name >> 123 G4String name = GetIonName(Z, A, E); >> 124 if ( name(0) == '?') { 225 #ifdef G4VERBOSE 125 #ifdef G4VERBOSE 226 if (GetVerboseLevel() > 1) { << 126 if (GetVerboseLevel()>0) { 227 G4cout << "G4IonTable::CreateIon() : can << 127 G4cerr << "G4IonTable::CreateIon() : can not create ions " 228 << " Z =" << Z << " A = " << A < << 128 << " Z =" << Z << " A = " << A << G4endl; 229 } 129 } 230 #endif 130 #endif 231 G4Exception("G4IonTable::CreateIon()", "PA << 131 return 0; 232 "Can not create ions because G << 132 } 233 return nullptr; << 234 } << 235 133 236 G4double life = 0.0; << 134 G4double life = -1.0; 237 G4DecayTable* decayTable = nullptr; << 135 G4DecayTable* decayTable =0; 238 G4bool stable = true; 136 G4bool stable = true; 239 G4double mu = 0.0; 137 G4double mu = 0.0; 240 G4double Eex = 0.0; << 138 241 G4int lvl = 0; << 139 const G4IsotopeProperty* fProperty = FindIsotope(Z, A, E, J); 242 G4int J = 0; << 140 if (fProperty !=0 ){ 243 << 141 E = fProperty->GetEnergy(); 244 const G4IsotopeProperty* fProperty = FindIso << 142 J = fProperty->GetiSpin(); 245 if (fProperty != nullptr) { << 246 Eex = fProperty->GetEnergy(); << 247 lvl = fProperty->GetIsomerLevel(); << 248 J = fProperty->GetiSpin(); << 249 life = fProperty->GetLifeTime(); 143 life = fProperty->GetLifeTime(); 250 mu = fProperty->GetMagneticMoment(); << 144 mu = fProperty->GetMagneticMoment(); 251 decayTable = fProperty->GetDecayTable(); 145 decayTable = fProperty->GetDecayTable(); 252 stable = (life <= 0.) || (decayTable == nu << 253 lvl = fProperty->GetIsomerLevel(); << 254 if (lvl < 0) lvl = 9; << 255 } 146 } 256 else { << 147 stable = life <= 0.; 257 #ifdef G4VERBOSE << 148 G4double mass = GetNucleusMass(Z, A)+ E; 258 if (GetVerboseLevel() > 1) { << 149 G4double charge = G4double(Z)*eplus; 259 G4ExceptionDescription ed; << 150 260 ed << "G4IonTable::CreateIon(): G4Isotop << 151 G4int encoding = GetNucleusEncoding(Z,A,E,J); 261 << " Z = " << Z << " A = " << A << " << 262 if (flb != G4Ions::G4FloatLevelBase::no_ << 263 ed << " FloatingLevel +" << G4Ions::Fl << 264 } << 265 ed << ".\n" << 266 << " Physics quantities such as life << 267 G4Exception("G4IonTable::CreateIon()", " << 268 } << 269 #endif << 270 // excitation energy << 271 Eex = E; << 272 // lvl is assigned to 9 temporarily << 273 if (Eex > 0.0) lvl = 9; << 274 } << 275 << 276 // Eex = G4NuclideTable::Round(Eex); << 277 if (Eex == 0.0) lvl = 0; << 278 // ion name << 279 G4String name = ""; << 280 /////////////if (lvl<9) name = GetIonName(Z, << 281 if (lvl == 0 && flb == G4Ions::G4FloatLevelB << 282 name = GetIonName(Z, A, lvl); << 283 else << 284 name = GetIonName(Z, A, Eex, flb); << 285 << 286 // PDG encoding << 287 G4int encoding = GetNucleusEncoding(Z, A, E, << 288 << 289 // PDG mass << 290 G4double mass = GetNucleusMass(Z, A) + Eex; << 291 << 292 // PDG charge is set to one of nucleus << 293 G4double charge = G4double(Z) * eplus; << 294 152 295 // create an ion 153 // create an ion 296 // spin, parity, isospin values are fixed << 154 // spin, parity, isospin values are fixed 297 << 298 // Request lock for particle table accesses. << 299 // this critical region. << 300 // 155 // 301 // clang-format off << 302 ion = new G4Ions( name, mass, 156 ion = new G4Ions( name, mass, 0.0*MeV, charge, 303 J, +1, << 157 J, +1, 0, 304 0, 0, << 158 0, 0, 0, 305 "nucleus", 0, << 159 "nucleus", 0, A, encoding, 306 stable, life, << 160 stable, life, decayTable, false, 307 "generic", 0, << 161 "generic", 0, 308 Eex, lvl << 162 E ); 309 // clang-format on << 310 << 311 // Release lock for particle table accesses. << 312 // << 313 ion->SetPDGMagneticMoment(mu); 163 ion->SetPDGMagneticMoment(mu); 314 static_cast<G4Ions*>(ion)->SetFloatLevelBase << 315 164 316 // No Anti particle registered << 165 //No Anti particle registered 317 ion->SetAntiPDGEncoding(0); 166 ion->SetAntiPDGEncoding(0); 318 << 167 319 #ifdef G4VERBOSE 168 #ifdef G4VERBOSE 320 if (GetVerboseLevel() > 1) { << 169 if (GetVerboseLevel()>1) { 321 G4cout << "G4IonTable::CreateIon() : creat << 170 G4cout << "G4IonTable::CreateIon() : create ion of " << name 322 << " encoding=" << encoding; << 171 << " " << Z << ", " << A 323 if (E > 0.0) { << 172 << " encoding=" << encoding << G4endl; 324 G4cout << " IsomerLVL=" << lvl << " exci << 173 } 325 } << 326 G4cout << G4endl; << 327 } << 328 #endif 174 #endif 329 << 175 330 // Add process manager to the ion 176 // Add process manager to the ion 331 AddProcessManager(ion); << 177 AddProcessManager(name); 332 << 178 333 #ifdef G4MULTITHREADED << 334 // Fill decay channels if this method is inv << 335 if (G4Threading::IsWorkerThread()) { << 336 if (!stable && (decayTable != nullptr)) { << 337 G4int nCh = decayTable->entries(); << 338 for (G4int iCh = 0; iCh < nCh; ++iCh) { << 339 decayTable->GetDecayChannel(iCh)->GetD << 340 } << 341 } << 342 } << 343 #endif << 344 << 345 return ion; 179 return ion; 346 } 180 } 347 181 348 G4ParticleDefinition* G4IonTable::CreateIon(G4 << 349 G4 << 350 { << 351 if (LL == 0) return CreateIon(Z, A, E, flb); << 352 182 >> 183 //////////////////// >> 184 G4ParticleDefinition* G4IonTable::CreateIon(G4int Z, G4int A, G4int L, >> 185 G4double E, G4int J) >> 186 { >> 187 if (L==0) return CreateIon(A,Z,E,J); >> 188 353 // create hyper nucleus 189 // create hyper nucleus 354 G4ParticleDefinition* ion = nullptr; << 190 G4ParticleDefinition* ion=0; 355 191 356 // check whether GenericIon has processes << 192 // check whether the cuurent state is not "PreInit" 357 G4ParticleDefinition* genericIon = G4Particl << 193 // to make sure that GenericIon has processes 358 G4ProcessManager* pman = nullptr; << 194 G4ApplicationState currentState = G4StateManager::GetStateManager()->GetCurrentState(); 359 if (genericIon != nullptr) pman = genericIon << 195 if (currentState == G4State_PreInit){ 360 if ((genericIon == nullptr) || (genericIon-> << 361 #ifdef G4VERBOSE 196 #ifdef G4VERBOSE 362 if (GetVerboseLevel() > 1) { << 197 if (GetVerboseLevel()>1) { 363 G4cout << "G4IonTable::CreateIon() : can << 198 G4cerr << "G4IonTable::CreateIon() : can not create ion of " 364 << " Z =" << Z << " A = " << A < << 199 << " Z =" << Z << " A = " << A << " L = " <<L >> 200 << " because the current state is PreInit !!" << G4endl; 365 } 201 } 366 #endif 202 #endif 367 G4Exception("G4IonTable::CreateIon()", "PA << 203 G4Exception( "G4IonTable::CreateIon()","Illegal operation", 368 "Can not create ions because G << 204 JustWarning, "Can not create ions in PreInit state"); 369 return nullptr; << 205 return 0; 370 } 206 } >> 207 >> 208 // get ion name >> 209 G4String name = GetIonName(Z, A, L, E); >> 210 if ( name(L) == '?') { >> 211 #ifdef G4VERBOSE >> 212 if (GetVerboseLevel()>0) { >> 213 G4cerr << "G4IonTable::CreateIon() : can not create ions " >> 214 << " Z =" << Z << " A = " << A << " L = " << L << G4endl; >> 215 } >> 216 #endif >> 217 return 0; >> 218 } 371 219 372 G4int J = 0; << 220 G4double life = -1.0; 373 G4double life = 0.0; << 221 G4DecayTable* decayTable =0; 374 G4DecayTable* decayTable = nullptr; << 375 G4bool stable = true; 222 G4bool stable = true; 376 << 223 G4double mu = 0.0; 377 // excitation energy << 224 G4double mass = GetNucleusMass(Z, A, L)+ E; 378 // G4double Eex = G4NuclideTable::Round(E); << 225 G4double charge = G4double(Z)*eplus; 379 G4double Eex = E; << 226 380 G4double mass = GetNucleusMass(Z, A, LL) + E << 227 G4int encoding = GetNucleusEncoding(Z,A,L,E,J); 381 G4int lvl = 0; << 382 // lvl is assigned to 9 temporarily << 383 if (Eex > 0.0) lvl = 9; << 384 << 385 // PDG encoding << 386 G4int encoding = GetNucleusEncoding(Z, A, LL << 387 << 388 // PDG charge is set to one of nucleus << 389 G4double charge = G4double(Z) * eplus; << 390 228 391 // create an ion 229 // create an ion 392 // spin, parity, isospin values are fixed << 230 // spin, parity, isospin values are fixed 393 // 231 // 394 // get ion name << 395 G4String name = GetIonName(Z, A, LL, Eex, fl << 396 << 397 // clang-format off << 398 ion = new G4Ions( name, mass, 232 ion = new G4Ions( name, mass, 0.0*MeV, charge, 399 J, +1, << 233 J, +1, 0, 400 0, 0, << 234 0, 0, 0, 401 "nucleus", 0, << 235 "nucleus", 0, A, encoding, 402 stable, life, << 236 stable, life, decayTable, false, 403 "generic", 0, << 237 "generic", 0, 404 Eex, lvl << 238 E ); 405 // clang-format on << 406 << 407 // Release lock for particle table accesses << 408 << 409 G4double mu = 0.0; // magnetic moment << 410 ion->SetPDGMagneticMoment(mu); 239 ion->SetPDGMagneticMoment(mu); 411 static_cast<G4Ions*>(ion)->SetFloatLevelBase << 412 240 413 // No Anti particle registered << 241 //No Anti particle registered 414 ion->SetAntiPDGEncoding(0); 242 ion->SetAntiPDGEncoding(0); 415 << 243 416 #ifdef G4VERBOSE 244 #ifdef G4VERBOSE 417 if (GetVerboseLevel() > 1) { << 245 if (GetVerboseLevel()>1) { 418 G4cout << "G4IonTable::CreateIon() : creat << 246 G4cout << "G4IonTable::CreateIon() : create hyper ion of " << name 419 << ", " << LL << " encoding=" << en << 247 << " encoding=" << encoding << G4endl; 420 if (E > 0.0) { << 248 } 421 G4cout << " IsomerLVL=" << lvl << " exci << 422 } << 423 G4cout << G4endl; << 424 } << 425 #endif 249 #endif 426 << 250 427 // Add process manager to the ion 251 // Add process manager to the ion 428 AddProcessManager(ion); << 252 AddProcessManager(name); 429 << 253 430 return ion; 254 return ion; 431 } 255 } 432 256 433 G4ParticleDefinition* G4IonTable::CreateIon(G4 << 257 //////////////////// 434 { << 258 // -- GetIon methods ------ 435 // always create an ion for any lvl << 259 //////////////////// 436 return CreateIon(Z, A, 0.0, G4Ions::FloatLev << 260 G4ParticleDefinition* G4IonTable::GetIon(G4int Z, G4int A, G4int , G4int ) 437 } << 438 << 439 G4ParticleDefinition* G4IonTable::CreateIon(G4 << 440 { 261 { 441 return (LL == 0) ? CreateIon(Z, A, 0.0, G4Io << 262 return GetIon(Z, A); 442 : CreateIon(Z, A, LL, 0.0, << 443 } 263 } 444 264 445 G4ParticleDefinition* G4IonTable::GetIon(G4int << 265 //////////////////// >> 266 G4ParticleDefinition* G4IonTable::GetIon(G4int Z, G4int A, G4int J) 446 { 267 { 447 return GetIon(Z, A, 0.0, G4Ions::G4FloatLeve << 268 return GetIon( Z, A, 0.0, J); 448 } 269 } 449 270 450 G4ParticleDefinition* G4IonTable::GetIon(G4int << 271 //////////////////// >> 272 G4ParticleDefinition* G4IonTable::GetIon(G4int encoding) 451 { 273 { 452 return (LL == 0) ? GetIon(Z, A, 0.0, G4Ions: << 274 G4int Z, A, L, J; 453 : GetIon(Z, A, LL, 0.0, G4I << 275 G4double E; >> 276 if (!GetNucleusByEncoding(encoding,Z,A,L,E,J) ){ >> 277 #ifdef G4VERBOSE >> 278 if (GetVerboseLevel()>0) { >> 279 G4cerr << "G4IonTable::GetIon() : illegal encoding" >> 280 << " CODE:" << encoding << G4endl; >> 281 } >> 282 #endif >> 283 G4Exception( "G4IonTable::GetIon()","Illegal operation", >> 284 JustWarning, "illegal encoding"); >> 285 return 0; >> 286 } >> 287 // Only ground state is supported >> 288 return GetIon( Z, A, L, 0.0, J); 454 } 289 } 455 290 >> 291 //////////////////// 456 G4ParticleDefinition* G4IonTable::GetIon(G4int 292 G4ParticleDefinition* G4IonTable::GetIon(G4int Z, G4int A, G4double E, G4int J) 457 { 293 { 458 return GetIon(Z, A, E, G4Ions::G4FloatLevelB << 294 if ( (A<1) || (Z<=0) || (J<0) || (E<0.0) || (A>999) ) { 459 } << 460 << 461 G4ParticleDefinition* G4IonTable::GetIon(G4int << 462 { << 463 return GetIon(Z, A, E, G4Ions::FloatLevelBas << 464 } << 465 << 466 G4ParticleDefinition* G4IonTable::GetIon(G4int << 467 G4int << 468 { << 469 if ((A < 1) || (Z <= 0) || (E < 0.0) || (A > << 470 #ifdef G4VERBOSE 295 #ifdef G4VERBOSE 471 if (GetVerboseLevel() > 0) { << 296 if (GetVerboseLevel()>0) { 472 G4cout << "G4IonTable::GetIon() : illega << 297 G4cerr << "G4IonTable::GetIon() : illegal atomic number/mass" 473 << " Z =" << Z << " A = " << A < << 298 << " Z =" << Z << " A = " << A << " E = " << E/keV << G4endl; 474 } 299 } 475 #endif 300 #endif 476 return nullptr; << 301 return 0; 477 } << 302 } 478 auto flb1 = flb; << 479 << 480 // Search ions with A, Z << 481 G4ParticleDefinition* ion = FindIon(Z, A, E, << 482 303 483 // find out ground state floating level << 304 // Search ions with A, Z 484 if (ion == nullptr && E == 0.0) { << 305 G4ParticleDefinition* ion = FindIon(Z,A,E,J); 485 const G4IsotopeProperty* fProperty = FindI << 486 if (nullptr != fProperty) { << 487 flb1 = fProperty->GetFloatLevelBase(); << 488 if (flb != flb1) { << 489 ion = FindIon(Z, A, E, flb1, J); << 490 } << 491 } << 492 } << 493 306 494 // create ion 307 // create ion 495 #ifdef G4MULTITHREADED << 308 if (ion == 0) { 496 if (ion == nullptr) { << 309 ion = CreateIon(Z, A, E, J); 497 if (G4Threading::IsWorkerThread()) { << 498 G4MUTEXLOCK(&G4IonTable::ionTableMutex); << 499 ion = FindIonInMaster(Z, A, E, flb1, J); << 500 if (ion == nullptr) ion = CreateIon(Z, A << 501 InsertWorker(ion); << 502 G4MUTEXUNLOCK(&G4IonTable::ionTableMutex << 503 } << 504 else { << 505 ion = CreateIon(Z, A, E, flb1); << 506 } << 507 } 310 } 508 #else << 509 if (ion == nullptr) ion = CreateIon(Z, A, E, << 510 #endif << 511 311 512 return ion; << 312 return ion; 513 } << 514 << 515 G4ParticleDefinition* G4IonTable::GetIon(G4int << 516 { << 517 return GetIon(Z, A, LL, E, G4Ions::G4FloatLe << 518 } << 519 << 520 G4ParticleDefinition* G4IonTable::GetIon(G4int << 521 G4int << 522 { << 523 return GetIon(Z, A, LL, E, G4Ions::FloatLeve << 524 } 313 } 525 314 526 G4ParticleDefinition* G4IonTable::GetIon(G4int << 315 //////////////////// 527 G4Ion << 316 G4ParticleDefinition* G4IonTable::GetIon(G4int Z, G4int A, G4int L, G4double E, G4int J) 528 { 317 { 529 if (LL == 0) return GetIon(Z, A, E, flb, J); << 318 if (L==0) return GetIon(Z,A,E,J); 530 319 531 if (A < 2 || Z < 0 || Z > A - LL || LL > A | << 320 if (A < 2 || Z < 0 || Z > A-L || L>A || A>999 ) { 532 #ifdef G4VERBOSE 321 #ifdef G4VERBOSE 533 if (GetVerboseLevel() > 0) { << 322 if (GetVerboseLevel()>0) { 534 G4cout << "G4IonTable::GetIon() : illega << 323 G4cerr << "G4IonTable::GetIon() : illegal atomic number/mass" 535 << " Z =" << Z << " A = " << A < << 324 << " Z =" << Z << " A = " << A << " L = " << L >> 325 <<" E = " << E/keV << G4endl; 536 } 326 } 537 #endif 327 #endif 538 return nullptr; << 328 return 0; 539 } << 329 } else if( A==2 ) { 540 if (A == 2) { << 541 #ifdef G4VERBOSE 330 #ifdef G4VERBOSE 542 if (GetVerboseLevel() > 0) { << 331 if (GetVerboseLevel()>0) { 543 G4cout << "G4IonTable::GetIon() : No bou << 332 G4cerr << "G4IonTable::GetIon() : No boud state for " 544 << " Z =" << Z << " A = " << A < << 333 << " Z =" << Z << " A = " << A << " L = " << L >> 334 << " E = " << E/keV << G4endl; 545 } 335 } 546 #endif 336 #endif 547 return nullptr; << 337 return 0; 548 } << 338 } 549 339 550 // Search ions with A, Z << 340 // Search ions with A, Z 551 G4ParticleDefinition* ion = FindIon(Z, A, LL << 341 G4ParticleDefinition* ion = FindIon(Z,A,L,E,J); 552 342 553 // create ion 343 // create ion 554 #ifdef G4MULTITHREADED << 344 if (ion == 0) { 555 if (ion == nullptr) { << 345 ion = CreateIon(Z, A, L, E, J); 556 if (G4Threading::IsWorkerThread()) { << 557 G4MUTEXLOCK(&G4IonTable::ionTableMutex); << 558 ion = FindIonInMaster(Z, A, LL, E, flb, << 559 if (ion == nullptr) ion = CreateIon(Z, A << 560 InsertWorker(ion); << 561 G4MUTEXUNLOCK(&G4IonTable::ionTableMutex << 562 } << 563 else { << 564 ion = CreateIon(Z, A, LL, E, flb); << 565 } << 566 } 346 } 567 #else << 568 if (ion == nullptr) ion = CreateIon(Z, A, LL << 569 #endif << 570 347 571 return ion; << 348 return ion; 572 } << 573 << 574 G4ParticleDefinition* G4IonTable::GetIon(G4int << 575 { << 576 G4int Z, A, LL, IsoLvl; << 577 G4double E; << 578 if (!GetNucleusByEncoding(encoding, Z, A, LL << 579 #ifdef G4VERBOSE << 580 if (GetVerboseLevel() > 0) { << 581 G4cout << "G4IonTable::GetIon() : illega << 582 << " CODE:" << encoding << G4endl << 583 } << 584 #endif << 585 G4Exception("G4IonTable::GetIon()", "PART1 << 586 return nullptr; << 587 } << 588 return GetIon(Z, A, LL, IsoLvl); << 589 } 349 } 590 350 >> 351 //////////////////// 591 G4ParticleDefinition* G4IonTable::FindIon(G4in 352 G4ParticleDefinition* G4IonTable::FindIon(G4int Z, G4int A, G4double E, G4int J) 592 { 353 { 593 return FindIon(Z, A, E, G4Ions::G4FloatLevel << 354 const G4double EnergyTorelance = 0.1 * keV; 594 } << 595 << 596 G4ParticleDefinition* G4IonTable::FindIon(G4in << 597 { << 598 return FindIon(Z, A, E, G4Ions::FloatLevelBa << 599 } << 600 355 601 G4ParticleDefinition* G4IonTable::FindIon(G4in << 356 if ( (A<1) || (Z<=0) || (J<0) || (E<0.0) || (A>999) ) { 602 G4Io << 603 { << 604 if ((A < 1) || (Z <= 0) || (J < 0) || (E < 0 << 605 #ifdef G4VERBOSE 357 #ifdef G4VERBOSE 606 if (GetVerboseLevel() > 0) { << 358 if (GetVerboseLevel()>0) { 607 G4cout << "G4IonTable::FindIon(): illega << 359 G4cerr << "G4IonTable::FindIon() : illegal atomic number/mass or excitation level " 608 << " or excitation level:" << G4e << 360 << " Z =" << Z << " A = " << A << " E = " << E/keV << G4endl; 609 << " E = " << E / keV << G4endl; << 610 } 361 } 611 #endif 362 #endif 612 G4Exception("G4IonTable::FindIon()", "PART << 363 G4Exception( "G4IonTable::FindIon()","Illegal operation", 613 return nullptr; << 364 JustWarning, "illegal atomic number/mass"); >> 365 return 0; 614 } 366 } 615 // Search ions with A, Z ,E 367 // Search ions with A, Z ,E 616 // !! J is omitted now !! 368 // !! J is omitted now !! 617 const G4ParticleDefinition* ion = nullptr; << 369 const G4ParticleDefinition* ion=0; 618 G4bool isFound = false; 370 G4bool isFound = false; 619 371 620 // check if light ion << 372 // -- loop over all particles in Ion table 621 ion = GetLightIon(Z, A); << 373 G4int encoding=GetNucleusEncoding(Z, A, 0); 622 if (ion != nullptr && E == 0.0) { << 374 G4IonList::iterator i = fIonList->find(encoding); 623 // light ion << 375 for( ;i != fIonList->end() ; i++) { 624 isFound = true; << 376 ion = i->second; 625 } << 377 if ( ( ion->GetAtomicNumber() != Z) || (ion->GetAtomicMass()!=A) ) break; 626 else { << 378 627 // -- loop over all particles in Ion table << 379 // excitation level 628 G4int encoding = GetNucleusEncoding(Z, A); << 380 G4double anExcitaionEnergy = ((const G4Ions*)(ion))->GetExcitationEnergy(); 629 const G4ParticleDefinition* ion1 = nullptr << 381 if ( ( std::fabs(E - anExcitaionEnergy ) < EnergyTorelance ) ) { 630 for (auto i = fIonList->find(encoding); i << 631 ion = i->second; << 632 if ((ion->GetAtomicNumber() != Z) || (io << 633 // excitation level << 634 G4double anExcitaionEnergy = ((const G4I << 635 << 636 if (std::fabs(E - anExcitaionEnergy) < p << 637 if (nullptr == ion1) ion1 = ion; << 638 if (((const G4Ions*)(ion))->GetFloatLe << 639 isFound = true; << 640 break; << 641 } << 642 } << 643 } << 644 // rerun search on ground level without ch << 645 if (!isFound && E == 0.0 && nullptr != ion << 646 isFound = true; 382 isFound = true; 647 ion = ion1; << 383 break; 648 } 384 } 649 } 385 } 650 386 651 if (isFound) { << 387 if ( isFound ){ 652 return const_cast<G4ParticleDefinition*>(i 388 return const_cast<G4ParticleDefinition*>(ion); >> 389 } else { >> 390 return 0; 653 } 391 } 654 << 655 return nullptr; << 656 } 392 } 657 393 658 G4ParticleDefinition* G4IonTable::FindIon(G4in << 659 { << 660 return (LL == 0) ? FindIon(Z, A, E, G4Ions:: << 661 : FindIon(Z, A, LL, E, G4Io << 662 } << 663 394 664 G4ParticleDefinition* G4IonTable::FindIon(G4in << 395 //////////////////// 665 G4in << 396 G4ParticleDefinition* G4IonTable::FindIon(G4int Z, G4int A, G4int L, G4double E, G4int J) 666 { 397 { 667 return FindIon(Z, A, LL, E, G4Ions::FloatLev << 398 if (L==0) return FindIon(Z,A,E,J); 668 } << 399 >> 400 const G4double EnergyTorelance = 0.1 * keV; 669 401 670 G4ParticleDefinition* G4IonTable::FindIon(G4in << 402 if (A < 2 || Z < 0 || Z > A-L || L>A || A>999 ) { 671 G4Io << 672 { << 673 if (LL == 0) return FindIon(Z, A, E, flb, J) << 674 << 675 if (A < 2 || Z < 0 || Z > A - LL || LL > A | << 676 #ifdef G4VERBOSE 403 #ifdef G4VERBOSE 677 if (GetVerboseLevel() > 0) { << 404 if (GetVerboseLevel()>0) { 678 G4cout << "G4IonTable::FindIon(): illega << 405 G4cerr << "G4IonTable::FindIon() : illegal atomic number/mass or excitation level " 679 << " or excitation level:" << G4e << 406 << " Z =" << Z << " A = " << A << " L = " << L 680 << " E = " << E / keV << G4endl; << 407 <<" E = " << E/keV << G4endl; 681 } << 408 } 682 #endif 409 #endif 683 G4Exception("G4IonTable::FindIon()", "PART << 410 G4Exception( "G4IonTable::FindIon()","Illegal operation", 684 return nullptr; << 411 JustWarning, "illegal atomic number/mass"); >> 412 return 0; 685 } 413 } 686 // Search ions with A, Z ,E 414 // Search ions with A, Z ,E 687 // !! J is omitted now !! 415 // !! J is omitted now !! 688 const G4ParticleDefinition* ion = nullptr; << 416 const G4ParticleDefinition* ion=0; 689 G4bool isFound = false; 417 G4bool isFound = false; 690 418 691 // -- loop over all particles in Ion table 419 // -- loop over all particles in Ion table 692 G4int encoding = GetNucleusEncoding(Z, A, LL << 420 G4int encoding=GetNucleusEncoding(Z, A, L); 693 for (auto i = fIonList->find(encoding); i != << 421 G4IonList::iterator i = fIonList->find(encoding); >> 422 for( ;i != fIonList->end() ; i++) { 694 ion = i->second; 423 ion = i->second; 695 if ((ion->GetAtomicNumber() != Z) || (ion- << 424 if ( ( ion->GetAtomicNumber() != Z) || (ion->GetAtomicMass()!=A) ) break; 696 if (ion->GetQuarkContent(3) != LL) break; << 425 if( ion->GetQuarkContent(3) != L) break; 697 // excitation level << 426 >> 427 // excitation level 698 G4double anExcitaionEnergy = ((const G4Ion 428 G4double anExcitaionEnergy = ((const G4Ions*)(ion))->GetExcitationEnergy(); 699 if (std::fabs(E - anExcitaionEnergy) < pNu << 429 700 if (((const G4Ions*)(ion))->GetFloatLeve << 430 if ( ( std::fabs(E - anExcitaionEnergy ) < EnergyTorelance ) ) { 701 isFound = true; << 431 isFound = true; 702 break; << 432 break; 703 } << 704 } 433 } 705 } 434 } 706 435 707 if (isFound) { << 436 if ( isFound ){ 708 return const_cast<G4ParticleDefinition*>(i 437 return const_cast<G4ParticleDefinition*>(ion); >> 438 } else { >> 439 return 0; 709 } 440 } 710 << 711 return nullptr; << 712 } 441 } 713 442 714 G4ParticleDefinition* G4IonTable::FindIon(G4in << 715 { << 716 return FindIon(Z, A, 0.0, G4Ions::FloatLevel << 717 } << 718 << 719 G4ParticleDefinition* G4IonTable::FindIon(G4in << 720 { << 721 return (LL == 0) ? FindIon(Z, A, 0.0, G4Ions << 722 : FindIon(Z, A, LL, 0.0, G4 << 723 } << 724 443 725 G4int G4IonTable::GetNucleusEncoding(G4int Z, << 444 ///////////////// >> 445 G4int G4IonTable::GetNucleusEncoding(G4int Z, G4int A, G4double E, G4int ) 726 { 446 { 727 // PDG code for Ions 447 // PDG code for Ions 728 // Nuclear codes are given as 10-digit numbe 448 // Nuclear codes are given as 10-digit numbers +-100ZZZAAAI. 729 // For a nucleus consisting of np protons an << 449 //For a nucleus consisting of np protons and nn neutrons 730 // A = np + nn and Z = np. 450 // A = np + nn and Z = np. 731 // I gives the isomer level, with I = 0 corr << 451 // I gives the isomer level, with I = 0 corresponding 732 // to the ground state and I >0 to excitatio 452 // to the ground state and I >0 to excitations 733 << 453 734 if (Z == 1 && A == 1 && E == 0.0) return 221 << 454 //!!! I = 1 is assigned fo all excitation states !!! 735 << 455 const G4double EnergyTorelance = 0.1 * keV; >> 456 if ( Z==1 && A==1 && E< EnergyTorelance ) { >> 457 //proton >> 458 return 2212; >> 459 } >> 460 736 G4int encoding = 1000000000; 461 G4int encoding = 1000000000; 737 encoding += Z * 10000; 462 encoding += Z * 10000; 738 encoding += A * 10; << 463 encoding += A *10; 739 if (lvl > 0 && lvl < 10) << 464 if (E>0.0) encoding += 1; 740 encoding += lvl; // isomer level << 465 741 else if (E > 0.0) << 742 encoding += 9; // isomer level << 743 << 744 return encoding; 466 return encoding; 745 } 467 } 746 468 747 G4int G4IonTable::GetNucleusEncoding(G4int Z, << 469 ///////////////// >> 470 G4int G4IonTable::GetNucleusEncoding(G4int Z, G4int A, G4int L, >> 471 G4double E, G4int ) 748 { 472 { 749 // Get PDG code for Hyper-Nucleus Ions << 473 // get PDG code for Hyper-Nucleus Ions 750 // Nuclear codes are given as 10-digit numbe 474 // Nuclear codes are given as 10-digit numbers +-10LZZZAAAI. 751 // For a nucleus consisting of np protons an << 475 //For a nucleus consisting of np protons and nn neutrons 752 // A = np + nn +nlambda and Z = np. 476 // A = np + nn +nlambda and Z = np. 753 // LL = nlambda << 477 // L = nlambda 754 // I gives the isomer level, with I = 0 corr << 478 // I gives the isomer level, with I = 0 corresponding 755 // to the ground state and I >0 to excitatio 479 // to the ground state and I >0 to excitations >> 480 // >> 481 //!!! I = 1 is assigned fo all excitation states in Geant4 756 482 757 G4int encoding = GetNucleusEncoding(Z, A, E, << 483 G4int encoding = 1000000000; 758 if (LL == 0) return encoding; << 484 encoding += L* 10000000; 759 encoding += LL * 10000000; << 485 encoding += Z * 10000; 760 if (Z == 1 && A == 1 && E == 0.0) encoding = << 486 encoding += A *10; 761 << 487 if (E>0.0) encoding += 1; >> 488 762 return encoding; 489 return encoding; 763 } 490 } 764 491 765 G4bool G4IonTable::GetNucleusByEncoding(G4int << 492 /////////////// >> 493 G4bool G4IonTable::GetNucleusByEncoding(G4int encoding, >> 494 G4int &Z, G4int &A, >> 495 G4double &E, G4int &J) 766 { 496 { 767 if (encoding <= 0) return false; // anti pa << 497 if (encoding <= 0) { 768 << 498 // anti particle 769 if (encoding == 2212) // proton << 499 return false; 770 { << 500 } >> 501 if (encoding == 2212) { >> 502 // proton 771 Z = 1; 503 Z = 1; 772 A = 1; 504 A = 1; 773 E = 0.0; << 505 E=0.0; 774 lvl = 0; << 506 J=0; 775 return true; 507 return true; 776 } 508 } 777 509 >> 510 if (encoding % 10 != 0) { >> 511 //!!!not supported for excitation states !!! >> 512 return false; >> 513 } >> 514 778 encoding -= 1000000000; 515 encoding -= 1000000000; 779 Z = encoding / 10000; << 516 Z = encoding/10000; 780 encoding -= 10000 * Z; << 517 encoding -= 10000*Z; 781 A = encoding / 10; << 518 A = encoding/10; 782 lvl = encoding % 10; << 519 >> 520 E=0.0; >> 521 J=0; >> 522 783 return true; 523 return true; 784 } 524 } 785 << 525 /////////////// 786 G4bool G4IonTable::GetNucleusByEncoding(G4int << 526 G4bool G4IonTable::GetNucleusByEncoding(G4int encoding, 787 G4int& << 527 G4int &Z, G4int &A, >> 528 G4int &L, >> 529 G4double &E, G4int &J) 788 { 530 { 789 if (encoding <= 0) return false; // anti pa << 531 if (encoding <= 0) { 790 << 532 // anti particle 791 if (encoding == 3122) // Lambda << 533 return false; 792 { << 793 Z = 1; << 794 A = 1; << 795 LL = 1; << 796 E = 0.0; << 797 lvl = 0; << 798 return true; << 799 } 534 } 800 << 801 if (encoding % 10 != 0) { 535 if (encoding % 10 != 0) { 802 // !!!not supported for excitation states << 536 //!!!not supported for excitation states !!! 803 return false; 537 return false; 804 } 538 } 805 if (encoding < 1000000000) { 539 if (encoding < 1000000000) { 806 // anti particle << 540 // anti particle 807 return false; 541 return false; 808 } 542 } 809 543 810 encoding -= 1000000000; 544 encoding -= 1000000000; 811 LL = encoding / 10000000; << 545 L = encoding/10000000; 812 encoding -= 10000000 * LL; << 546 encoding -= 10000000*L; 813 Z = encoding / 10000; << 547 Z = encoding/10000; 814 encoding -= 10000 * Z; << 548 encoding -= 10000*Z; 815 A = encoding / 10; << 549 A = encoding/10; 816 lvl = encoding % 10; << 550 >> 551 E=0.0; >> 552 J=0; >> 553 817 return true; 554 return true; 818 } 555 } 819 << 556 ///////////////// 820 G4String G4IonTable::GetIonName(G4int Z, G4int << 557 const G4String& G4IonTable::GetIonName(G4int Z, G4int A, G4double E) const 821 G4Ions::G4Floa << 822 { 558 { 823 G4String name = GetIonName(Z, A, 0); << 559 static G4String name; 824 << 560 name =""; 825 // Excited energy or floating level << 561 if ( (0< Z) && (Z <=numberOfElements) ) { 826 if (E > 0 || flb != G4Ions::G4FloatLevelBase << 562 name = elementName[Z-1]; 827 std::ostringstream os; << 563 } else if (Z > numberOfElements) { 828 os.setf(std::ios::fixed); << 564 std::ostringstream os1; 829 os.precision(3); << 565 os1.setf(std::ios::fixed); 830 // Excited nucleus << 566 os1 << Z ; 831 os << '[' << E / keV; << 567 name = "E" + os1.str() + "-"; 832 if (flb != G4Ions::G4FloatLevelBase::no_Fl << 568 } else { 833 os << G4Ions::FloatLevelBaseChar(flb); << 569 name = "?"; 834 } << 570 return name; 835 os << ']'; << 836 name += os.str(); << 837 } 571 } 838 << 839 return name; << 840 } << 841 << 842 G4String G4IonTable::GetIonName(G4int Z, G4int << 843 G4Ions::G4Floa << 844 { << 845 if (LL == 0) return GetIonName(Z, A, E, flb) << 846 G4String name = ""; << 847 for (G4int i = 0; i < LL; ++i) { << 848 name += "L"; << 849 } << 850 name += GetIonName(Z, A, E, flb); << 851 return name; << 852 } << 853 << 854 G4String G4IonTable::GetIonName(G4int Z, G4int << 855 { << 856 std::ostringstream os; 572 std::ostringstream os; 857 << 573 os.setf(std::ios::fixed); 858 // Atomic number << 574 os << A << '[' << std::setprecision(1) << E/keV << ']'; 859 if ((0 < Z) && (Z <= numberOfElements)) { << 575 name += os.str(); 860 os << elementName[Z - 1]; << 861 } << 862 else { << 863 os << "E" << Z << "-"; << 864 } << 865 // Atomic Mass << 866 os << A; << 867 << 868 if (lvl > 0) { << 869 // Isomer level for Excited nucelus << 870 os << '[' << lvl << ']'; << 871 } << 872 G4String name = os.str(); << 873 return name; 576 return name; 874 } 577 } 875 578 876 G4String G4IonTable::GetIonName(G4int Z, G4int << 579 ///////////////// >> 580 const G4String& G4IonTable::GetIonName(G4int Z, G4int A, G4int L, G4double E) const 877 { 581 { 878 if (LL == 0) return GetIonName(Z, A, lvl); << 582 if (L==0) return GetIonName(Z, A, E); 879 G4String name = ""; << 583 static G4String name; 880 for (G4int i = 0; i < LL; ++i) { << 584 name =""; 881 name += "L"; << 585 for (int i =0; i<L; i++){ >> 586 name +="L"; 882 } 587 } 883 name += GetIonName(Z, A, lvl); << 588 name += GetIonName(Z, A, E); 884 return name; 589 return name; 885 } 590 } 886 591 >> 592 ///////////////// 887 G4bool G4IonTable::IsIon(const G4ParticleDefin 593 G4bool G4IonTable::IsIon(const G4ParticleDefinition* particle) 888 { 594 { 889 // Return true if the particle is ion << 595 // return true if the particle is ion 890 static const G4String nucleus("nucleus"); << 891 static const G4String proton("proton"); << 892 596 893 // Neutron is not ion << 597 static G4String nucleus("nucleus"); 894 if ((particle->GetAtomicMass() > 0) && (part << 598 static G4String proton("proton"); 895 return particle->GetBaryonNumber() > 0; << 599 >> 600 // neutron is not ion >> 601 if ((particle->GetAtomicMass()>0) && >> 602 (particle->GetAtomicNumber()>0) ){ >> 603 if (particle->GetBaryonNumber()>0) return true; >> 604 else return false; 896 } 605 } 897 606 898 // Particles derived from G4Ions << 607 >> 608 // particles derived from G4Ions 899 if (particle->GetParticleType() == nucleus) 609 if (particle->GetParticleType() == nucleus) return true; 900 610 901 // Proton (Hydrogen nucleus) << 611 // proton (Hydrogen nucleus) 902 if (particle->GetParticleName() == proton) r 612 if (particle->GetParticleName() == proton) return true; 903 613 904 return false; 614 return false; 905 } 615 } 906 616 >> 617 ///////////////// 907 G4bool G4IonTable::IsAntiIon(const G4ParticleD 618 G4bool G4IonTable::IsAntiIon(const G4ParticleDefinition* particle) 908 { 619 { 909 // Return true if the particle is ion << 620 // return true if the particle is ion 910 static const G4String anti_nucleus("anti_nuc << 621 911 static const G4String anti_proton("anti_prot << 622 static G4String anti_nucleus("anti_nucleus"); >> 623 static G4String anti_proton("anti_proton"); 912 624 913 // Anti_neutron is not ion << 625 // anti_neutron is not ion 914 if ((particle->GetAtomicMass() > 0) && (part << 626 if ((particle->GetAtomicMass()>0) && 915 return particle->GetBaryonNumber() < 0; << 627 (particle->GetAtomicNumber()>0) ){ >> 628 if (particle->GetBaryonNumber()<0) return true; >> 629 else return false; 916 } 630 } 917 631 918 // Particles derived from G4Ions << 632 // particles derived from G4Ions 919 if (particle->GetParticleType() == anti_nucl 633 if (particle->GetParticleType() == anti_nucleus) return true; 920 634 921 // Anti_proton (Anti_Hydrogen nucleus) << 635 // anti_proton (Anti_Hydrogen nucleus) 922 if (particle->GetParticleName() == anti_prot 636 if (particle->GetParticleName() == anti_proton) return true; 923 637 924 return false; 638 return false; 925 } 639 } 926 640 >> 641 ///////////////// >> 642 #include <algorithm> >> 643 927 G4bool G4IonTable::IsLightIon(const G4Particle 644 G4bool G4IonTable::IsLightIon(const G4ParticleDefinition* particle) const 928 { 645 { 929 static const std::string names[] = {"proton" << 646 static const std::string names[] = { "proton", "alpha", "deuteron", >> 647 "triton", "He3"}; 930 648 931 // Return true if the particle is pre-define << 649 // return true if the particle is pre-defined ion 932 return std::find(names, names + 5, (particle << 650 return std::find(names, names+5, particle->GetParticleName())!=names+5; 933 } << 651 } 934 652 935 G4bool G4IonTable::IsLightAntiIon(const G4Part 653 G4bool G4IonTable::IsLightAntiIon(const G4ParticleDefinition* particle) const 936 { 654 { 937 static const std::string names[] = {"anti_pr << 655 static const std::string names[] = { "anti_proton", "anti_alpha", "anti_deuteron", 938 "anti_He << 656 "anti_triton", "anti_He3"}; 939 657 940 // Return true if the particle is pre-define << 658 // return true if the particle is pre-defined ion 941 return std::find(names, names + 5, (particle << 659 return std::find(names, names+5, particle->GetParticleName())!=names+5; 942 } << 660 } 943 661 >> 662 ///////////////// 944 G4ParticleDefinition* G4IonTable::GetLightIon( 663 G4ParticleDefinition* G4IonTable::GetLightIon(G4int Z, G4int A) const 945 { 664 { 946 // Returns pointer to pre-defined ions << 665 // returns pointer to pre-defined ions 947 const G4ParticleDefinition* ion = nullptr; << 666 static G4bool isInitialized = false; 948 if ((Z <= 2)) { << 667 static const G4ParticleDefinition* p_proton=0; 949 #ifndef G4MULTITHREADED << 668 static const G4ParticleDefinition* p_deuteron=0; 950 // In sequential use lazy-initialization << 669 static const G4ParticleDefinition* p_triton=0; 951 lightions::Init(); << 670 static const G4ParticleDefinition* p_alpha=0; 952 #endif << 671 static const G4ParticleDefinition* p_He3=0; 953 if ((Z == 1) && (A == 1)) { << 672 954 ion = lightions::p_proton; << 673 if (!isInitialized) { 955 } << 674 p_proton = G4ParticleTable::GetParticleTable()->FindParticle("proton"); // proton 956 else if ((Z == 1) && (A == 2)) { << 675 p_deuteron = G4ParticleTable::GetParticleTable()->FindParticle("deuteron"); // deuteron 957 ion = lightions::p_deuteron; << 676 p_triton = G4ParticleTable::GetParticleTable()->FindParticle("triton"); // tritoon 958 } << 677 p_alpha = G4ParticleTable::GetParticleTable()->FindParticle("alpha"); // alpha 959 else if ((Z == 1) && (A == 3)) { << 678 p_He3 = G4ParticleTable::GetParticleTable()->FindParticle("He3"); // He3 960 ion = lightions::p_triton; << 679 isInitialized = true; 961 } << 680 } 962 else if ((Z == 2) && (A == 4)) { << 681 963 ion = lightions::p_alpha; << 682 const G4ParticleDefinition* ion=0; 964 } << 683 if ( (Z<=2) ) { 965 else if ((Z == 2) && (A == 3)) { << 684 if ( (Z==1)&&(A==1) ) { 966 ion = lightions::p_He3; << 685 ion = p_proton; >> 686 } else if ( (Z==1)&&(A==2) ) { >> 687 ion = p_deuteron; >> 688 } else if ( (Z==1)&&(A==3) ) { >> 689 ion = p_triton; >> 690 } else if ( (Z==2)&&(A==4) ) { >> 691 ion = p_alpha; >> 692 } else if ( (Z==2)&&(A==3) ) { >> 693 ion = p_He3; 967 } 694 } 968 } 695 } 969 return const_cast<G4ParticleDefinition*>(ion 696 return const_cast<G4ParticleDefinition*>(ion); 970 } 697 } 971 698 >> 699 ///////////////// 972 G4ParticleDefinition* G4IonTable::GetLightAnti 700 G4ParticleDefinition* G4IonTable::GetLightAntiIon(G4int Z, G4int A) const 973 { 701 { 974 // Returns pointer to pre-defined ions << 702 // returns pointer to pre-defined ions 975 const G4ParticleDefinition* ion = nullptr; << 703 static G4bool isInitialized = false; 976 if ((Z <= 2)) { << 704 static const G4ParticleDefinition* p_proton=0; 977 #ifndef G4MULTITHREADED << 705 static const G4ParticleDefinition* p_deuteron=0; 978 // In sequential use lazy-initialization << 706 static const G4ParticleDefinition* p_triton=0; 979 antilightions::Init(); << 707 static const G4ParticleDefinition* p_alpha=0; 980 #endif << 708 static const G4ParticleDefinition* p_He3=0; 981 if ((Z == 1) && (A == 1)) { << 709 982 ion = antilightions::p_proton; << 710 if (!isInitialized) { 983 } << 711 p_proton = G4ParticleTable::GetParticleTable()->FindParticle("anti_proton"); // proton 984 else if ((Z == 1) && (A == 2)) { << 712 p_deuteron = G4ParticleTable::GetParticleTable()->FindParticle("anti_deuteron"); // deuteron 985 ion = antilightions::p_deuteron; << 713 p_triton = G4ParticleTable::GetParticleTable()->FindParticle("anti_triton"); // tritoon 986 } << 714 p_alpha = G4ParticleTable::GetParticleTable()->FindParticle("anti_alpha"); // alpha 987 else if ((Z == 1) && (A == 3)) { << 715 p_He3 = G4ParticleTable::GetParticleTable()->FindParticle("anti_He3"); // He3 988 ion = antilightions::p_triton; << 716 isInitialized = true; 989 } << 717 } 990 else if ((Z == 2) && (A == 4)) { << 718 991 ion = antilightions::p_alpha; << 719 const G4ParticleDefinition* ion=0; 992 } << 720 if ( (Z<=2) ) { 993 else if ((Z == 2) && (A == 3)) { << 721 if ( (Z==1)&&(A==1) ) { 994 ion = antilightions::p_He3; << 722 ion = p_proton; >> 723 } else if ( (Z==1)&&(A==2) ) { >> 724 ion = p_deuteron; >> 725 } else if ( (Z==1)&&(A==3) ) { >> 726 ion = p_triton; >> 727 } else if ( (Z==2)&&(A==4) ) { >> 728 ion = p_alpha; >> 729 } else if ( (Z==2)&&(A==3) ) { >> 730 ion = p_He3; 995 } 731 } 996 } 732 } 997 return const_cast<G4ParticleDefinition*>(ion 733 return const_cast<G4ParticleDefinition*>(ion); 998 } 734 } 999 735 1000 G4double G4IonTable::GetNucleusMass(G4int Z, << 736 >> 737 ///////////////// >> 738 // -- GetNucleusMass/GetIonMass --- >> 739 ///////////////// >> 740 G4double G4IonTable::GetNucleusMass(G4int Z, G4int A, G4int L) const 1001 { 741 { 1002 if ((A < 1) || (Z < 0) || (LL < 0) || (lvl << 742 if ( (A<1) || (Z<0) || (L<0) ){ 1003 #ifdef G4VERBOSE 743 #ifdef G4VERBOSE 1004 if (GetVerboseLevel() > 0) { << 744 if (GetVerboseLevel()>0) { 1005 G4cout << "G4IonTable::GetNucleusMass() << 745 G4cerr << "G4IonTable::GetNucleusMass() : illegal atomic number/mass " 1006 << " Z =" << Z << " A = " << A << 746 << " Z =" << Z << " A = " << A << G4endl; 1007 } 747 } 1008 #endif 748 #endif 1009 G4Exception("G4IonTable::GetNucleusMass() << 749 G4Exception( "G4IonTable::GetNucleusMass()","Illegal operation", 1010 "illegal atomic number/mass") << 750 EventMustBeAborted, "illegal atomic number/mass"); 1011 return -1.0; 751 return -1.0; 1012 } 752 } 1013 753 1014 G4double mass; 754 G4double mass; 1015 if (LL == 0) { << 755 if (L == 0) { 1016 // calculate nucleus mass 756 // calculate nucleus mass 1017 const G4ParticleDefinition* ion = GetLigh << 757 const G4ParticleDefinition* ion=GetLightIon(Z, A); 1018 << 758 1019 if (ion != nullptr) { << 759 if (ion!=0) { 1020 mass = ion->GetPDGMass(); 760 mass = ion->GetPDGMass(); 1021 } << 761 } else { 1022 else { << 762 // use G4NucleiProperties::GetNuclearMass 1023 // Use G4NucleiProperties::GetNuclearMa << 1024 mass = G4NucleiProperties::GetNuclearMa 763 mass = G4NucleiProperties::GetNuclearMass(A, Z); 1025 } 764 } 1026 765 1027 // Isomer << 766 } else { 1028 if (lvl > 0) { << 767 mass = G4HyperNucleiProperties::GetNuclearMass(A, Z, L); 1029 // -- loop over all particles in Ion ta << 1030 G4int encoding = GetNucleusEncoding(Z, << 1031 G4bool isFound = false; << 1032 for (auto i = fIonList->find(encoding); << 1033 ion = i->second; << 1034 if ((ion->GetAtomicNumber() != Z) || << 1035 // Excitation level << 1036 if (((const G4Ions*)(ion))->GetIsomer << 1037 isFound = true; << 1038 break; << 1039 } << 1040 } << 1041 if (isFound) { << 1042 // Return existing isomer mass << 1043 mass = ion->GetPDGMass(); << 1044 } << 1045 else { << 1046 // Find isomer from IsotopeTable << 1047 const G4IsotopeProperty* fProperty = << 1048 if (fProperty != nullptr) mass += fPr << 1049 } << 1050 } << 1051 } << 1052 else { << 1053 mass = G4HyperNucleiProperties::GetNuclea << 1054 } 768 } 1055 return mass; 769 return mass; 1056 } 770 } 1057 771 1058 G4double G4IonTable::GetIsomerMass(G4int Z, G << 772 ////////////////// >> 773 G4double G4IonTable::GetIonMass(G4int Z, G4int A, G4int L) const 1059 { 774 { 1060 return GetNucleusMass(Z, A, 0, lvl); << 775 return GetNucleusMass(Z,A,L); 1061 } 776 } 1062 777 1063 G4double G4IonTable::GetIonMass(G4int Z, G4in << 1064 { << 1065 return GetNucleusMass(Z, A, LL, lvl); << 1066 } << 1067 << 1068 void G4IonTable::clear() << 1069 { << 1070 if (G4ParticleTable::GetParticleTable()->Ge << 1071 G4Exception("G4IonTable::clear()", "PART1 << 1072 "No effects because readyToUs << 1073 return; << 1074 } << 1075 << 1076 #ifdef G4VERBOSE << 1077 if (GetVerboseLevel() > 2) { << 1078 G4cout << "G4IonTable::Clear() : number o << 1079 G4cout << fIonList->size() << G4endl; << 1080 } << 1081 #endif << 1082 fIonList->clear(); << 1083 } << 1084 778 >> 779 ///////////////// >> 780 // -- Methods for handling conatiner --- >> 781 ///////////////// 1085 void G4IonTable::Insert(const G4ParticleDefin 782 void G4IonTable::Insert(const G4ParticleDefinition* particle) 1086 { 783 { 1087 if (!IsIon(particle)) return; 784 if (!IsIon(particle)) return; 1088 if (Contains(particle)) return; 785 if (Contains(particle)) return; 1089 << 786 1090 G4int Z = particle->GetAtomicNumber(); 787 G4int Z = particle->GetAtomicNumber(); 1091 G4int A = particle->GetAtomicMass(); << 788 G4int A = particle->GetAtomicMass(); 1092 G4int LL = particle->GetQuarkContent(3); / << 789 G4int L = particle->GetQuarkContent(3); //strangeness 1093 G4int encoding = GetNucleusEncoding(Z, A, L << 790 G4int encoding=GetNucleusEncoding(Z, A, L); 1094 791 1095 // Register the ion with its encoding of th << 792 fIonList->insert( std::pair<const G4int, const G4ParticleDefinition*>(encoding, particle) ); 1096 fIonListShadow->insert(std::pair<const G4in << 1097 } << 1098 << 1099 void G4IonTable::InsertWorker(const G4Particl << 1100 { << 1101 if (particle == nullptr) return; << 1102 793 1103 G4int Z = particle->GetAtomicNumber(); << 1104 G4int A = particle->GetAtomicMass(); << 1105 G4int LL = particle->GetQuarkContent(3); / << 1106 G4int encoding = GetNucleusEncoding(Z, A, L << 1107 G4bool found = false; << 1108 if (encoding != 0) { << 1109 for (auto i = fIonList->find(encoding); i << 1110 if (particle == i->second) { << 1111 found = true; << 1112 break; << 1113 } << 1114 } << 1115 } << 1116 if (found) return; << 1117 << 1118 // Register the ion with its encoding of th << 1119 fIonList->insert(std::pair<const G4int, con << 1120 } 794 } 1121 795 >> 796 ///////////////// 1122 void G4IonTable::Remove(const G4ParticleDefin 797 void G4IonTable::Remove(const G4ParticleDefinition* particle) 1123 { 798 { 1124 if (particle == nullptr) return; << 1125 #ifdef G4MULTITHREADED << 1126 if (G4Threading::IsWorkerThread()) { << 1127 G4ExceptionDescription ed; << 1128 ed << "Request of removing " << particle- << 1129 << " is ignored as it is invoked from << 1130 G4Exception("G4IonTable::Remove()", "PART << 1131 return; << 1132 } << 1133 #endif << 1134 if (G4ParticleTable::GetParticleTable()->Ge << 1135 G4StateManager* pStateManager = G4StateMa << 1136 G4ApplicationState currentState = pStateM << 1137 if (currentState != G4State_PreInit) { << 1138 G4String msg = "Request of removing "; << 1139 msg += particle->GetParticleName(); << 1140 msg += " has No effects other than Pre_ << 1141 G4Exception("G4IonTable::Remove()", "PA << 1142 return; << 1143 } << 1144 << 1145 #ifdef G4VERBOSE << 1146 if (GetVerboseLevel() > 0) { << 1147 G4cout << particle->GetParticleName() < << 1148 } << 1149 #endif << 1150 } << 1151 << 1152 if (IsIon(particle)) { 799 if (IsIon(particle)) { 1153 G4int Z = particle->GetAtomicNumber(); 800 G4int Z = particle->GetAtomicNumber(); 1154 G4int A = particle->GetAtomicMass(); << 801 G4int A = particle->GetAtomicMass(); 1155 G4int LL = particle->GetQuarkContent(3); << 802 G4int L = particle->GetQuarkContent(3); //strangeness 1156 G4int encoding = GetNucleusEncoding(Z, A, << 803 G4int encoding=GetNucleusEncoding(Z, A, L); 1157 if (encoding != 0) { << 804 if (encoding !=0 ) { 1158 for (auto i = fIonListShadow->find(enco << 805 G4IonList::iterator i = fIonList->find(encoding); 1159 if (particle == i->second) { << 806 for( ;i != fIonList->end() ; i++) { 1160 fIonListShadow->erase(i); << 807 if (particle == i->second) { 1161 break; << 808 fIonList->erase(i); 1162 } << 809 break; >> 810 } 1163 } 811 } 1164 } 812 } 1165 } << 813 } else { 1166 else { << 1167 #ifdef G4VERBOSE 814 #ifdef G4VERBOSE 1168 if (GetVerboseLevel() > 1) { << 815 if (GetVerboseLevel()>1) { 1169 G4cout << "G4IonTable::Remove :" << par << 816 G4cerr << "G4IonTable::Remove :" << particle->GetParticleName() >> 817 << " is not ions" << G4endl; 1170 } 818 } 1171 #endif 819 #endif 1172 } 820 } >> 821 1173 } 822 } 1174 823 1175 void G4IonTable::DumpTable(const G4String& pa << 824 >> 825 >> 826 ///////////////// >> 827 // -- Dump Information >> 828 ///////////////// >> 829 void G4IonTable::DumpTable(const G4String &particle_name) const 1176 { 830 { 1177 const G4ParticleDefinition* ion; 831 const G4ParticleDefinition* ion; 1178 for (const auto& idx : *fIonList) { << 832 G4IonList::iterator idx; 1179 ion = idx.second; << 833 for (idx = fIonList->begin(); idx!= fIonList->end(); ++idx) { 1180 if ((particle_name == "ALL") || (particle << 834 ion = idx->second; >> 835 if (( particle_name == "ALL" ) || (particle_name == "all")){ 1181 ion->DumpTable(); 836 ion->DumpTable(); 1182 } << 837 } else if ( particle_name == ion->GetParticleName() ) { 1183 else if (particle_name == ion->GetParticl << 1184 ion->DumpTable(); 838 ion->DumpTable(); 1185 } 839 } 1186 } 840 } 1187 } 841 } 1188 842 1189 // ------------------------------------------ << 843 ///////////////// 1190 // << 844 const G4String G4IonTable::elementName[] = { 1191 // clang-format off << 1192 const G4String G4IonTable::elementName[] = << 1193 { << 1194 "H", 845 "H", "He", 1195 "Li", "Be", 846 "Li", "Be", "B", "C", "N", "O", "F", "Ne", 1196 "Na", "Mg", 847 "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", 1197 "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe 848 "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", 1198 "Rb", "Sr", "Y", "Zr", "Nb", "Mo","Tc", "Ru 849 "Rb", "Sr", "Y", "Zr", "Nb", "Mo","Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", 1199 "Cs", "Ba", 850 "Cs", "Ba", 1200 "La", "Ce", "Pr", "Nd", "Pm", " 851 "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", 1201 "Hf", "Ta", "W", "Re", "Os 852 "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", 1202 "Fr", "Ra", 853 "Fr", "Ra", 1203 "Ac", "Th", "Pa", "U", "Np", " 854 "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr", 1204 "Rf", "Db", "Sg", "Bh", "Hs", " << 855 "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", >> 856 "Uub", "Uut", "Uuq","Uup","Uuh","Uus","Uuo" 1205 }; 857 }; 1206 // clang-format on << 1207 858 >> 859 >> 860 ///////////////// 1208 G4int G4IonTable::GetVerboseLevel() const 861 G4int G4IonTable::GetVerboseLevel() const 1209 { 862 { 1210 return G4ParticleTable::GetParticleTable()- 863 return G4ParticleTable::GetParticleTable()->GetVerboseLevel(); 1211 } 864 } 1212 865 1213 void G4IonTable::AddProcessManager(G4Particle << 866 ///////////////// >> 867 void G4IonTable::AddProcessManager(const G4String& name) 1214 { 868 { 1215 if (ion->IsGeneralIon()) { << 869 // create command string for addProcManager 1216 // Check whether GenericIon has processes << 870 std::ostringstream osAdd; 1217 G4ParticleDefinition* genericIon = G4Part << 871 osAdd << "/run/particle/addProcManager "<< name; 1218 << 872 G4String cmdAdd = osAdd.str(); 1219 G4ProcessManager* pman = nullptr; << 1220 if (genericIon != nullptr) pman = generic << 1221 if ((genericIon == nullptr) || (genericIo << 1222 { << 1223 G4String msg = "G4IonTable::AddProcessM << 1224 msg += ion->GetParticleName(); << 1225 msg += "\n because GenericIon is not av << 1226 G4Exception("G4IonTable::AddProcessMana << 1227 return; << 1228 } << 1229 << 1230 ion->SetParticleDefinitionID(genericIon-> << 1231 } << 1232 else { << 1233 // Is this a MuonicAtom ? << 1234 auto muatom = dynamic_cast<G4MuonicAtom*> << 1235 873 1236 if (muatom != nullptr) { << 874 // set /control/verbose 0 1237 #ifdef G4VERBOSE << 875 G4int tempVerboseLevel = G4UImanager::GetUIpointer()->GetVerboseLevel(); 1238 if (GetVerboseLevel() > 1) { << 876 G4UImanager::GetUIpointer()->SetVerboseLevel(0); 1239 G4cout << "G4IonTable::AddProcessMana << 1240 << "MuonicAtom dynamic_cast su << 1241 } << 1242 #endif << 1243 // Check whether GenericMuonicAtom has << 1244 G4ParticleDefinition* genericMA = G4Par << 1245 877 1246 G4ProcessManager* pman = nullptr; << 878 // issue /run/particle/addProcManage 1247 if (genericMA != nullptr) pman = generi << 879 G4UImanager::GetUIpointer()->ApplyCommand(cmdAdd); 1248 if ((genericMA == nullptr) || (genericM << 1249 { << 1250 G4String msg = "G4IonTable::AddProces << 1251 msg += ion->GetParticleName(); << 1252 msg += "\n because GenericMuonicAtom << 1253 G4Exception("G4IonTable::AddProcessMa << 1254 return; << 1255 } << 1256 880 1257 ion->SetParticleDefinitionID(genericMA- << 881 // retreive /control/verbose 1258 } << 882 G4UImanager::GetUIpointer()->SetVerboseLevel(tempVerboseLevel); 1259 else { << 1260 G4String msg = "G4IonTable::AddProcessM << 1261 msg += ion->GetParticleName(); << 1262 msg += "\n because of unsupported parti << 1263 G4Exception("G4IonTable::AddProcessMana << 1264 return; << 1265 } << 1266 } << 1267 return; << 1268 } 883 } 1269 884 1270 void G4IonTable::RegisterIsotopeTable(G4VIsot << 885 #include <vector> >> 886 >> 887 //////////////////// >> 888 void G4IonTable::RegisterIsotopeTable(G4VIsotopeTable* table) 1271 { 889 { 1272 // check duplication << 1273 G4String name = table->GetName(); << 1274 for (const auto fIsotopeTable : *fIsotopeTa << 1275 if (name == fIsotopeTable->GetName()) ret << 1276 } << 1277 // register << 1278 fIsotopeTableList->push_back(table); 890 fIsotopeTableList->push_back(table); 1279 } 891 } 1280 892 1281 G4VIsotopeTable* G4IonTable::GetIsotopeTable( << 893 //////////////////// >> 894 G4VIsotopeTable* G4IonTable::GetIsotopeTable(size_t index) const 1282 { 895 { 1283 G4VIsotopeTable* fIsotopeTable = nullptr; << 896 G4VIsotopeTable* fIsotopeTable=0; 1284 if (index < fIsotopeTableList->size()) { << 897 if ( index < fIsotopeTableList->size() ) { 1285 fIsotopeTable = (*fIsotopeTableList)[inde << 898 fIsotopeTable = (*fIsotopeTableList)[index]; 1286 } << 899 } 1287 return fIsotopeTable; << 900 return fIsotopeTable; 1288 } 901 } 1289 902 1290 G4IsotopeProperty* G4IonTable::FindIsotope(G4 << 1291 G4 << 1292 { << 1293 if (fIsotopeTableList == nullptr) return nu << 1294 if (fIsotopeTableList->empty()) return null << 1295 << 1296 G4IsotopeProperty* property = nullptr; << 1297 903 1298 for (std::size_t i = 0; i < fIsotopeTableLi << 904 //////////////////// 1299 G4VIsotopeTable* fIsotopeTable = (*fIsoto << 905 G4IsotopeProperty* G4IonTable::FindIsotope(G4int Z, G4int A, G4double E, G4int ) 1300 property = fIsotopeTable->GetIsotope(Z, A << 906 { 1301 if (property != nullptr) break; << 907 if (fIsotopeTableList ==0) return 0; >> 908 if (fIsotopeTableList->size()==0) return 0; >> 909 >> 910 // ask IsotopeTable >> 911 G4IsotopeProperty* property =0; >> 912 >> 913 // iterate >> 914 for (size_t i = 0; i< fIsotopeTableList->size(); ++i) { >> 915 G4VIsotopeTable* fIsotopeTable= (*fIsotopeTableList)[i]; >> 916 G4IsotopeProperty* tmp = fIsotopeTable->GetIsotope(Z,A,E); >> 917 if ( tmp !=0) { >> 918 >> 919 #ifdef G4VERBOSE >> 920 if (GetVerboseLevel()>1) { >> 921 G4cout << "G4IonTable::FindIsotope:"; >> 922 G4cout << " Z: " << Z; >> 923 G4cout << " A: " << A; >> 924 G4cout << " E: " << E; >> 925 G4cout << G4endl; >> 926 tmp->DumpInfo(); >> 927 } >> 928 #endif >> 929 if (property !=0) { >> 930 // overwrite spin/magnetic moment/decay table if not defined >> 931 if( property->GetiSpin() ==0) { >> 932 property->SetiSpin( tmp->GetiSpin() ); >> 933 } >> 934 if( property->GetMagneticMoment() <= 0.0) { >> 935 property->SetMagneticMoment( tmp->GetMagneticMoment() ); >> 936 } >> 937 if( property->GetLifeTime() <= 0.0) { >> 938 property->SetLifeTime( tmp->GetLifeTime() ); >> 939 if ( (property->GetLifeTime() > 0.0) >> 940 && (property->GetDecayTable() ==0 ) ) { >> 941 property->SetDecayTable( tmp->GetDecayTable() ); >> 942 tmp->SetDecayTable( 0 ); >> 943 } >> 944 } >> 945 } else { >> 946 property = tmp; >> 947 } >> 948 } 1302 } 949 } 1303 << 950 1304 return property; 951 return property; 1305 } 952 } 1306 953 1307 G4IsotopeProperty* G4IonTable::FindIsotope(G4 << 1308 { << 1309 if (fIsotopeTableList == nullptr) return nu << 1310 if (fIsotopeTableList->empty()) return null << 1311 << 1312 G4IsotopeProperty* property = nullptr; << 1313 << 1314 // iterate << 1315 for (std::size_t i = 0; i < fIsotopeTableLi << 1316 G4VIsotopeTable* fIsotopeTable = (*fIsoto << 1317 property = fIsotopeTable->GetIsotope(Z, A << 1318 if (property != nullptr) break; << 1319 } << 1320 << 1321 return property; << 1322 } << 1323 954 >> 955 //////////////////// 1324 void G4IonTable::CreateAllIon() 956 void G4IonTable::CreateAllIon() 1325 { 957 { 1326 PreloadNuclide(); << 958 G4int Z; 1327 } << 959 G4int A; 1328 << 960 G4double E=0.0; 1329 void G4IonTable::CreateAllIsomer() << 961 G4int J=0; 1330 { << 962 1331 PreloadNuclide(); << 963 for (Z=1; Z<=120; Z++) { 1332 } << 964 for (A=Z;A<999 && A<Z*3+10; A++) { 1333 << 965 if (G4NucleiProperties::IsInStableTable(A,Z)){ 1334 void G4IonTable::PrepareNuclideTable() << 966 GetIon(Z,A,E,J); 1335 { << 967 } 1336 if (pNuclideTable == nullptr) pNuclideTable << 968 } 1337 } << 1338 << 1339 void G4IonTable::PreloadNuclide() << 1340 { << 1341 if (isIsomerCreated || !G4Threading::IsMult << 1342 << 1343 pNuclideTable->GenerateNuclide(); << 1344 << 1345 for (std::size_t i = 0; i != pNuclideTable- << 1346 const G4IsotopeProperty* fProperty = pNuc << 1347 G4int Z = fProperty->GetAtomicNumber(); << 1348 G4int A = fProperty->GetAtomicMass(); << 1349 G4double Eex = fProperty->GetEnergy(); << 1350 GetIon(Z, A, Eex); << 1351 } 969 } 1352 << 1353 isIsomerCreated = true; << 1354 } 970 } 1355 971 >> 972 //////////////////// 1356 G4ParticleDefinition* G4IonTable::GetParticle 973 G4ParticleDefinition* G4IonTable::GetParticle(G4int index) const 1357 { 974 { 1358 if ((index >= 0) && (index < Entries())) { << 975 if ( (index >=0) && (index < Entries()) ) { 1359 auto idx = fIonList->cbegin(); << 976 G4IonList::iterator idx = fIonList->begin(); 1360 G4int counter = 0; 977 G4int counter = 0; 1361 while (idx != fIonList->cend()) // Loop << 978 while( idx != fIonList->end() ){ 1362 { << 979 if ( counter == index ) { 1363 if (counter == index) { << 980 return const_cast<G4ParticleDefinition*>(idx->second); 1364 return const_cast<G4ParticleDefinitio << 1365 } 981 } 1366 ++counter; << 982 counter++; 1367 ++idx; << 983 idx++; 1368 } 984 } 1369 } << 985 } 1370 #ifdef G4VERBOSE 986 #ifdef G4VERBOSE 1371 if (GetVerboseLevel() > 1) { << 987 if (GetVerboseLevel()>1){ 1372 G4cout << " G4IonTable::GetParticle" << 988 G4cerr << " G4IonTable::GetParticle" 1373 << " invalid index (=" << index << << 989 << " invalid index (=" << index << ")" 1374 << " entries = " << Entries() << G << 990 << " entries = " << Entries() << G4endl; 1375 } 991 } 1376 #endif 992 #endif 1377 return nullptr; << 993 return 0; 1378 } 994 } 1379 995 1380 G4bool G4IonTable::Contains(const G4ParticleD << 1381 { << 1382 if (!IsIon(particle)) return false; << 1383 << 1384 G4int Z = particle->GetAtomicNumber(); << 1385 G4int A = particle->GetAtomicMass(); << 1386 G4int LL = particle->GetQuarkContent(3); / << 1387 G4int encoding = GetNucleusEncoding(Z, A, L << 1388 G4bool found = false; << 1389 if (encoding != 0) { << 1390 for (auto i = fIonListShadow->find(encodi << 1391 if (particle == i->second) { << 1392 found = true; << 1393 break; << 1394 } << 1395 } << 1396 } << 1397 return found; << 1398 } << 1399 << 1400 G4int G4IonTable::Entries() const << 1401 { << 1402 return (G4int)fIonList->size(); << 1403 } << 1404 << 1405 G4int G4IonTable::size() const << 1406 { << 1407 return (G4int)fIonList->size(); << 1408 } << 1409 << 1410 G4ParticleDefinition* G4IonTable::FindIonInMa << 1411 << 1412 { << 1413 // Search ions with A, Z ,E << 1414 // !! J is omitted now !! << 1415 const G4ParticleDefinition* ion = nullptr; << 1416 G4bool isFound = false; << 1417 << 1418 // -- loop over all particles in Ion table << 1419 G4int encoding = GetNucleusEncoding(Z, A); << 1420 for (auto i = fIonListShadow->find(encoding << 1421 ion = i->second; << 1422 if ((ion->GetAtomicNumber() != Z) || (ion << 1423 // excitation level << 1424 G4double anExcitaionEnergy = ((const G4Io << 1425 if (std::fabs(E - anExcitaionEnergy) < pN << 1426 if (((const G4Ions*)(ion))->GetFloatLev << 1427 isFound = true; << 1428 break; << 1429 } << 1430 } << 1431 } << 1432 << 1433 if (isFound) { << 1434 return const_cast<G4ParticleDefinition*>( << 1435 } << 1436 << 1437 return nullptr; << 1438 } << 1439 << 1440 G4ParticleDefinition* G4IonTable::FindIonInMa << 1441 << 1442 { << 1443 if (LL == 0) return FindIon(Z, A, E, flb, J << 1444 << 1445 // Search ions with A, Z ,E << 1446 // !! J is omitted now !! << 1447 const G4ParticleDefinition* ion = nullptr; << 1448 G4bool isFound = false; << 1449 << 1450 // -- loop over all particles in Ion table << 1451 G4int encoding = GetNucleusEncoding(Z, A, L << 1452 for (auto i = fIonListShadow->find(encoding << 1453 ion = i->second; << 1454 if ((ion->GetAtomicNumber() != Z) || (ion << 1455 if (ion->GetQuarkContent(3) != LL) break; << 1456 // Excitation level << 1457 G4double anExcitaionEnergy = ((const G4Io << 1458 if (std::fabs(E - anExcitaionEnergy) < pN << 1459 if (((const G4Ions*)(ion))->GetFloatLev << 1460 isFound = true; << 1461 break; << 1462 } << 1463 } << 1464 } << 1465 << 1466 if (isFound) { << 1467 return const_cast<G4ParticleDefinition*>( << 1468 } << 1469 << 1470 return nullptr; << 1471 } << 1472 << 1473 G4ParticleDefinition* G4IonTable::FindIonInMa << 1474 { << 1475 // Search ions with A, Z ,E << 1476 // !! J is omitted now !! << 1477 const G4ParticleDefinition* ion = nullptr; << 1478 G4bool isFound = false; << 1479 << 1480 // -- loop over all particles in Ion table << 1481 G4int encoding = GetNucleusEncoding(Z, A); << 1482 for (auto i = fIonListShadow->find(encoding << 1483 ion = i->second; << 1484 if ((ion->GetAtomicNumber() != Z) || (ion << 1485 // Excitation level << 1486 if (((const G4Ions*)(ion))->GetIsomerLeve << 1487 isFound = true; << 1488 break; << 1489 } << 1490 } << 1491 << 1492 if (isFound) { << 1493 return const_cast<G4ParticleDefinition*>( << 1494 } << 1495 << 1496 return nullptr; << 1497 } << 1498 << 1499 G4ParticleDefinition* G4IonTable::FindIonInMa << 1500 { << 1501 if (LL == 0) return FindIon(Z, A, lvl); << 1502 << 1503 // Search ions with A, Z ,E, lvl << 1504 const G4ParticleDefinition* ion = nullptr; << 1505 G4bool isFound = false; << 1506 << 1507 // -- loop over all particles in Ion table << 1508 G4int encoding = GetNucleusEncoding(Z, A, L << 1509 for (auto i = fIonListShadow->find(encoding << 1510 ion = i->second; << 1511 if ((ion->GetAtomicNumber() != Z) || (ion << 1512 if (ion->GetQuarkContent(3) != LL) break; << 1513 // excitation level << 1514 if (((const G4Ions*)(ion))->GetIsomerLeve << 1515 isFound = true; << 1516 break; << 1517 } << 1518 } << 1519 << 1520 if (isFound) { << 1521 return const_cast<G4ParticleDefinition*>( << 1522 } << 1523 << 1524 return nullptr; << 1525 } << 1526 << 1527 G4double G4IonTable::GetLifeTime(const G4Part << 1528 { << 1529 if ((particle->IsGeneralIon()) && (pNuclide << 1530 G4Exception("G4IonTable::GetLifeTime()", << 1531 "Method is invoked before G4I << 1532 return 0.; << 1533 } << 1534 return particle->GetPDGLifeTime(); << 1535 } << 1536 << 1537 G4double G4IonTable::GetLifeTime(G4int Z, G4i << 1538 { << 1539 return GetLifeTime(Z, A, E, G4Ions::FloatLe << 1540 } << 1541 << 1542 G4double G4IonTable::GetLifeTime(G4int Z, G4i << 1543 { << 1544 G4double life = -1001.0; << 1545 const G4IsotopeProperty* fProperty = FindIs << 1546 if (fProperty != nullptr) life = fProperty- << 1547 return life; << 1548 } << 1549 996 1550 G4ParticleDefinition* G4IonTable::GetMuonicAt << 1551 { << 1552 if (base == nullptr || !IsIon(base)) { << 1553 G4Exception("G4IonTable::GetMuonicAtom()" << 1554 "Constructor argument is not << 1555 return nullptr; << 1556 } << 1557 997 1558 // We're assuming here that we get a base t << 1559 // constructed and unexcited ... strip exci << 1560 // isomers from the encoding << 1561 998 1562 auto const Z = base->GetAtomicNumber(); << 1563 auto const A = base->GetAtomicMass(); << 1564 auto const baseenc = GetNucleusEncoding(Z, << 1565 auto const encoding = baseenc + 1000000000; << 1566 999 1567 // We have to do all the MT manipulations m << 1568 // convenience functions assume a G4Ions wi << 1569 // they recalculate the encoding from parti << 1570 // than using the carried member function v << 1571 // do operations on the base ion, rather th << 1572 // G4MuonicAtom << 1573 1000 1574 auto i = fIonList->find(encoding); << 1575 if (i != fIonList->cend()) { << 1576 return const_cast<G4ParticleDefinition*>( << 1577 } << 1578 // not in threadlocal list; check global li << 1579 #ifdef G4MULTITHREADED << 1580 if (G4Threading::IsWorkerThread()) { << 1581 G4MUTEXLOCK(&G4IonTable::ionTableMutex); << 1582 i = fIonListShadow->find(encoding); << 1583 auto end = fIonListShadow->cend(); << 1584 G4MUTEXUNLOCK(&G4IonTable::ionTableMutex) << 1585 if (i != end) { << 1586 // we found it, stuff it into the threa << 1587 fIonList->insert(*i); << 1588 // and then return it ... << 1589 return const_cast<G4ParticleDefinition* << 1590 } << 1591 } << 1592 #endif << 1593 1001 1594 // not found in either list; create and pot << 1595 auto const name = "Mu" + GetIonName(Z, A); << 1596 1002 1597 G4MuonicAtom* muatom = G4MuonicAtomHelper:: << 1598 1003 1599 // Not sure this is doing the right thing.. << 1600 AddProcessManager(muatom); << 1601 1004 1602 // Now, we have to push the muatom into the << 1603 // first, recheck global list, in case anot << 1604 // before us and created this same muatom << 1605 << 1606 #ifdef G4MULTITHREADED << 1607 if (G4Threading::IsWorkerThread()) { << 1608 G4MUTEXLOCK(&G4IonTable::ionTableMutex); << 1609 // first, we need to make sure it hasn't << 1610 // other thread << 1611 auto j = fIonListShadow->find(encoding); << 1612 if (j != fIonListShadow->cend()) { << 1613 // oops ... someone else built a copy w << 1614 // cleanup our instantiation, and take << 1615 // the global list << 1616 delete muatom; << 1617 muatom = const_cast<G4MuonicAtom*>(stat << 1618 } << 1619 else { << 1620 // otherwise, push onto the global list << 1621 fIonListShadow->insert(std::make_pair(e << 1622 } << 1623 G4MUTEXUNLOCK(&G4IonTable::ionTableMutex) << 1624 } << 1625 #endif << 1626 // in either case, push onto the the thread << 1627 fIonList->insert(std::make_pair(encoding, m << 1628 << 1629 return muatom; << 1630 } << 1631 1005 1632 G4ParticleDefinition* G4IonTable::GetMuonicAt << 1633 { << 1634 // Need the cast because we need a G4Ions* << 1635 // function, but GetIon returns a G4Particl << 1636 auto base = static_cast<G4Ions const*>(GetI << 1637 return GetMuonicAtom(base); << 1638 } << 1639 1006