Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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// --------------------------------------------------------------------
58G4NuclideTable::G4NuclideTable()
59 : G4VIsotopeTable("Isomer"),
60 threshold_of_half_life(1000.0*ns),
61 flevelTolerance(1.0*eV)
62{
63 fMessenger = new G4NuclideTableMessenger(this);
64 fIsotopeList = new G4IsotopeList();
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{
188 if ( threshold_of_half_life < minimum_threshold_of_half_life )
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;
233 G4Ions::G4FloatLevelBase flb = StripFloatLevelBase( ionFL );
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
273 minimum_threshold_of_half_life = threshold_of_half_life;
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 {
384 threshold_of_half_life=t;
386 }
387}
388
389// --------------------------------------------------------------------
390G4double G4NuclideTable::StripFloatLevelBase(G4double E, G4int& flbIndex)
391{
392 G4double rem = std::fmod(E/(1.0E-3*eV),10.0);
393 flbIndex = G4int(rem);
394 return E-rem;
395}
396
397// --------------------------------------------------------------------
399G4NuclideTable::StripFloatLevelBase( const G4String& sFLB )
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}
double A(double temperature)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
#define noFloat
Definition: G4Ions.hh:112
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
int G4int
Definition: G4Types.hh:85
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)
static G4double GetTruncationError(G4double eex)
void AddState(G4int, G4int, G4double, G4double, G4int ionJ=0, G4double ionMu=0.0)
static G4NuclideTable * GetInstance()
void SetThresholdOfHalfLife(G4double)
virtual G4IsotopeProperty * GetIsotope(G4int Z, G4int A, G4double E, G4Ions::G4FloatLevelBase flb=G4Ions::G4FloatLevelBase::no_Float)
static G4NuclideTable * GetNuclideTable()
static G4long Truncate(G4double eex)
G4double GetLevelTolerance()
std::vector< G4IsotopeProperty * > G4IsotopeList
static G4double Tolerance()
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