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