Geant4-11
G4NuclideTable.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// G4NuclideTable class implementation
27//
28// Author: T.Koi, SLAC - 10 October 2013
29// --------------------------------------------------------------------
30
31#include "G4NuclideTable.hh"
33
34#include "G4ios.hh"
35#include "G4String.hh"
36#include "globals.hh"
38#include "G4SystemOfUnits.hh"
39
40#include <iomanip>
41#include <fstream>
42#include <sstream>
43
44// --------------------------------------------------------------------
46{
47 static G4NuclideTable instance;
48 return &instance;
49}
50
51// --------------------------------------------------------------------
53{
54 return GetInstance();
55}
56
57// --------------------------------------------------------------------
59 : G4VIsotopeTable("Isomer"),
60 threshold_of_half_life(1000.0*ns),
61 flevelTolerance(1.0*eV)
62{
66}
67
68// --------------------------------------------------------------------
70{
71 for (auto it=map_pre_load_list.begin(); it!=map_pre_load_list.end(); ++it)
72 {
73 it->second.clear();
74 }
75 map_pre_load_list.clear();
76
77 for (auto it=map_full_list.begin(); it!=map_full_list.end(); ++it)
78 {
79 it->second.clear();
80 }
81 map_full_list.clear();
82
83 if (fIsotopeList != nullptr)
84 {
85 for (std::size_t i = 0 ; i<fIsotopeList->size(); ++i)
86 {
87 delete (*fIsotopeList)[i];
88 }
89 fIsotopeList->clear();
90 delete fIsotopeList;
91 fIsotopeList = nullptr;
92 }
93 delete fMessenger;
94}
95
96// --------------------------------------------------------------------
99{
100 G4IsotopeProperty* fProperty = nullptr;
101
102 // At first searching UserDefined
103 if ( fUserDefinedList )
104 {
105 for (auto it=fUserDefinedList->cbegin(); it!=fUserDefinedList->cend(); ++it)
106 {
107 if ( Z == (*it)->GetAtomicNumber() && A == (*it)->GetAtomicMass() )
108 {
109 G4double levelE = (*it)->GetEnergy();
110 if ( levelE - flevelTolerance/2 <= E && E < levelE + flevelTolerance/2 )
111 {
112 if( flb == (*it)->GetFloatLevelBase() ) { return *it; } //found
113 }
114 }
115 }
116 }
117
118 // Searching pre-load
119 // Note: isomer level is properly set only for pre_load_list
120 //
121 G4int ionCode = 1000*Z + A;
122 auto itf = map_pre_load_list.find( ionCode );
123
124 if ( itf != map_pre_load_list.cend() )
125 {
126 auto lower_bound_itr = itf -> second.lower_bound ( E - flevelTolerance/2 );
127 G4double levelE = DBL_MAX;
128
129 while ( lower_bound_itr != itf -> second.cend() )
130 {
131 levelE = lower_bound_itr->first;
132 if ( levelE - flevelTolerance/2 <= E && E < levelE + flevelTolerance/2 )
133 {
134 if ( flb == (lower_bound_itr->second)->GetFloatLevelBase() )
135 {
136 return lower_bound_itr->second; // found
137 }
138 }
139 else
140 {
141 break;
142 }
143 ++lower_bound_itr;
144 }
145 }
146
147 return fProperty; // not found
148}
149
150// --------------------------------------------------------------------
152{
154 return eex - (G4long)(eex/tolerance)*tolerance;
155}
156
157// --------------------------------------------------------------------
159{
161 return round(eex/tolerance)*tolerance;
162}
163
164// --------------------------------------------------------------------
166{
168 return (G4long)(eex/tolerance);
169}
170
171// --------------------------------------------------------------------
173{
175}
176
177// --------------------------------------------------------------------
180{
181 if(lvl==0) return GetIsotope(Z,A,0.0);
182 return nullptr;
183}
184
185// --------------------------------------------------------------------
187{
189 {
190 // Need to update full list
191 char* path = std::getenv("G4ENSDFSTATEDATA");
192
193 if ( path == nullptr )
194 {
195 G4Exception("G4NuclideTable", "PART70000", FatalException,
196 "G4ENSDFSTATEDATA environment variable must be set");
197 return;
198 }
199
200 std::ifstream ifs;
201 G4String filename(path);
202 filename += "/ENSDFSTATE.dat";
203
204 ifs.open( filename.c_str() );
205 if ( !ifs.good() )
206 {
207 G4Exception("G4NuclideTable", "PART70001", FatalException,
208 "ENSDFSTATE.dat is not found.");
209 return;
210 }
211
212 G4int ionCode=0;
213 G4int iLevel=0;
214 G4int ionZ;
215 G4int ionA;
216 G4double ionE;
217 G4String ionFL;
218 G4double ionLife;
219 G4int ionJ;
220 G4double ionMu;
221
222 ifs >> ionZ >> ionA >> ionE >> ionFL >> ionLife >> ionJ >> ionMu;
223
224 while ( ifs.good() ) // Loop checking, 09.08.2015, K.Kurashige
225 {
226 if ( ionCode != 1000*ionZ + ionA )
227 {
228 iLevel = 0;
229 ionCode = 1000*ionZ + ionA;
230 }
231
232 ionE *= keV;
234 ionLife *= ns;
235 ionMu *= (joule/tesla);
236
237 if ( ( ionE == 0 && flb == G4Ions::G4FloatLevelBase::no_Float )
238 || ( threshold_of_half_life <= ionLife*std::log(2.0)
239 && ionLife*std::log(2.0) < minimum_threshold_of_half_life ) )
240 {
241 if ( ionE > 0 ) ++iLevel;
242 if ( iLevel > 9 ) iLevel=9;
243
244 G4IsotopeProperty* fProperty = new G4IsotopeProperty();
245
246 // Set Isotope Property
247 fProperty->SetAtomicNumber(ionZ);
248 fProperty->SetAtomicMass(ionA);
249 fProperty->SetIsomerLevel(iLevel);
250 fProperty->SetEnergy(ionE);
251 fProperty->SetiSpin(ionJ);
252 fProperty->SetLifeTime(ionLife);
253 fProperty->SetDecayTable(nullptr);
254 fProperty->SetMagneticMoment(ionMu);
255 fProperty->SetFloatLevelBase( flb );
256
257 fIsotopeList->push_back(fProperty);
258
259 auto itf = map_full_list.find( ionCode );
260 if ( itf == map_full_list.cend() )
261 {
262 std::multimap<G4double, G4IsotopeProperty*> aMultiMap;
263 itf = ( map_full_list.insert(
264 std::pair< G4int, std::multimap< G4double,
265 G4IsotopeProperty* > > ( ionCode, aMultiMap ) ) ).first;
266 }
267 itf -> second.insert(
268 std::pair< G4double, G4IsotopeProperty* >(ionE, fProperty) );
269 }
270 ifs >> ionZ >> ionA >> ionE >> ionFL >> ionLife >> ionJ >> ionMu;
271 }
272
274
275 }
276
277 // Clear current map
278 for ( auto it=map_pre_load_list.begin(); it!=map_pre_load_list.end(); ++it )
279 {
280 it->second.clear();
281 }
282 map_pre_load_list.clear();
283
284 // Build map based on current threshold value
285 for ( auto it = map_full_list.cbegin(); it != map_full_list.cend(); ++it )
286 {
287 G4int ionCode = it->first;
288 auto itf = map_pre_load_list.find( ionCode );
289 if ( itf == map_pre_load_list.cend() )
290 {
291 std::multimap<G4double, G4IsotopeProperty*> aMultiMap;
292 itf = ( map_pre_load_list.insert(
293 std::pair< G4int, std::multimap< G4double,
294 G4IsotopeProperty* > > (ionCode, aMultiMap) ) ).first;
295 }
296 G4int iLevel = 0;
297 for ( auto itt = it->second.cbegin(); itt != it->second.cend(); ++itt )
298 {
299 G4double exEnergy = itt->first;
300 G4double meanLife = itt->second->GetLifeTime();
301 if ( exEnergy == 0.0 || meanLife*std::log(2.0) > threshold_of_half_life )
302 {
303 if ( itt->first != 0.0 ) ++iLevel;
304 if ( iLevel > 9 ) iLevel=9;
305 itt->second->SetIsomerLevel( iLevel );
306 itf->second.insert(
307 std::pair< G4double, G4IsotopeProperty* >(exEnergy, itt->second) );
308 }
309 }
310 }
311}
312
313// --------------------------------------------------------------------
315 G4double ionLife, G4int ionJ, G4double ionMu )
316{
318 {
319 G4int flbIndex = 0;
320 ionE = StripFloatLevelBase( ionE, flbIndex );
321 AddState(ionZ,ionA,ionE,flbIndex,ionLife,ionJ,ionMu);
322 }
323}
324
325// --------------------------------------------------------------------
327 G4int flbIndex, G4double ionLife, G4int ionJ,
328 G4double ionMu )
329{
331 {
332 if ( fUserDefinedList == nullptr ) fUserDefinedList = new G4IsotopeList();
333
334 G4IsotopeProperty* fProperty = new G4IsotopeProperty();
335
336 // Set Isotope Property
337 fProperty->SetAtomicNumber(ionZ);
338 fProperty->SetAtomicMass(ionA);
339 fProperty->SetIsomerLevel(9);
340 fProperty->SetEnergy(ionE);
341 fProperty->SetiSpin(ionJ);
342 fProperty->SetLifeTime(ionLife);
343 fProperty->SetDecayTable(nullptr);
344 fProperty->SetMagneticMoment(ionMu);
345 fProperty->SetFloatLevelBase(flbIndex);
346
347 fUserDefinedList->push_back(fProperty);
348 fIsotopeList->push_back(fProperty);
349 }
350}
351
352// --------------------------------------------------------------------
355 G4int ionJ, G4double ionMu )
356{
358 {
359 if ( fUserDefinedList == nullptr ) fUserDefinedList = new G4IsotopeList();
360
361 G4IsotopeProperty* fProperty = new G4IsotopeProperty();
362
363 // Set Isotope Property
364 fProperty->SetAtomicNumber(ionZ);
365 fProperty->SetAtomicMass(ionA);
366 fProperty->SetIsomerLevel(9);
367 fProperty->SetEnergy(ionE);
368 fProperty->SetiSpin(ionJ);
369 fProperty->SetLifeTime(ionLife);
370 fProperty->SetDecayTable(0);
371 fProperty->SetMagneticMoment(ionMu);
372 fProperty->SetFloatLevelBase( flb );
373
374 fUserDefinedList->push_back(fProperty);
375 fIsotopeList->push_back(fProperty);
376 }
377}
378
379// --------------------------------------------------------------------
381{
383 {
386 }
387}
388
389// --------------------------------------------------------------------
391{
392 G4double rem = std::fmod(E/(1.0E-3*eV),10.0);
393 flbIndex = G4int(rem);
394 return E-rem;
395}
396
397// --------------------------------------------------------------------
400{
401 if ( sFLB.size() < 1 || 2 < sFLB.size() )
402 {
403 G4String text;
404 text += sFLB;
405 text += " is not valid indicator of G4Ions::G4FloatLevelBase.\n";
406 text += "You may use a wrong version of ENSDFSTATE data.\n";
407 text += "Please use G4ENSDFSTATE-2.0 or later.";
408
409 G4Exception( "G4NuclideTable", "PART70002", FatalException, text );
410 }
412 if ( !(sFLB == "-") )
413 {
414 flb = G4Ions::FloatLevelBase( sFLB.back() );
415 }
416 return flb;
417}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
#define noFloat
Definition: G4Ions.hh:112
static constexpr double joule
Definition: G4SIunits.hh:189
static constexpr double tesla
Definition: G4SIunits.hh:259
static constexpr double second
Definition: G4SIunits.hh:137
static constexpr double keV
Definition: G4SIunits.hh:202
static constexpr double eV
Definition: G4SIunits.hh:201
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
const G4double A[17]
static G4Ions::G4FloatLevelBase FloatLevelBase(char flbChar)
Definition: G4Ions.cc:103
G4FloatLevelBase
Definition: G4Ions.hh:83
void SetAtomicMass(G4int A)
void SetDecayTable(G4DecayTable *table)
void SetFloatLevelBase(G4Ions::G4FloatLevelBase flb)
void SetEnergy(G4double E)
void SetiSpin(G4int J)
void SetAtomicNumber(G4int Z)
void SetIsomerLevel(G4int level)
G4double GetEnergy() const
void SetLifeTime(G4double T)
void SetMagneticMoment(G4double M)
G4double flevelTolerance
std::map< G4int, std::multimap< G4double, G4IsotopeProperty * > > map_full_list
static G4double GetTruncationError(G4double eex)
void AddState(G4int, G4int, G4double, G4double, G4int ionJ=0, G4double ionMu=0.0)
G4IsotopeList * fUserDefinedList
static G4NuclideTable * GetInstance()
std::map< G4int, std::multimap< G4double, G4IsotopeProperty * > > map_pre_load_list
void SetThresholdOfHalfLife(G4double)
G4NuclideTableMessenger * fMessenger
virtual G4IsotopeProperty * GetIsotope(G4int Z, G4int A, G4double E, G4Ions::G4FloatLevelBase flb=G4Ions::G4FloatLevelBase::no_Float)
G4double threshold_of_half_life
G4double minimum_threshold_of_half_life
static G4NuclideTable * GetNuclideTable()
static G4long Truncate(G4double eex)
G4double GetLevelTolerance()
G4IsotopeList * fIsotopeList
std::vector< G4IsotopeProperty * > G4IsotopeList
static G4double Tolerance()
G4double StripFloatLevelBase(G4double E, G4int &flbIndex)
static G4double Round(G4double eex)
virtual G4IsotopeProperty * GetIsotopeByIsoLvl(G4int Z, G4int A, G4int lvl=0)
virtual ~G4NuclideTable()
G4bool IsMasterThread()
Definition: G4Threading.cc:124
#define DBL_MAX
Definition: templates.hh:62
#define ns
Definition: xmlparse.cc:614