Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/particles/management/src/G4IonTable.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /particles/management/src/G4IonTable.cc (Version 11.3.0) and /particles/management/src/G4IonTable.cc (Version 11.2.2)


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