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