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