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