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