Geant4 11.1.1
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 mean_life_threshold(1.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 (mean_life_threshold < minimum_mean_life_threshold) {
189 // Need to update full list
190 const char* path = G4FindDataDir("G4ENSDFSTATEDATA");
191
192 if (path == nullptr) {
193 G4Exception("G4NuclideTable", "PART70000", FatalException,
194 "G4ENSDFSTATEDATA environment variable must be set");
195 return;
196 }
197
198 std::ifstream ifs;
199 G4String filename(path);
200 filename += "/ENSDFSTATE.dat";
201
202 ifs.open(filename.c_str() );
203 if (!ifs.good() ) {
204 G4Exception("G4NuclideTable", "PART70001", FatalException,
205 "ENSDFSTATE.dat is not found.");
206 return;
207 }
208
209 G4int ionCode = 0;
210 G4int iLevel = 0;
211 G4int ionZ;
212 G4int ionA;
213 G4double ionE;
214 G4String ionFL;
215 G4double ionLife;
216 G4int ionJ;
217 G4double ionMu;
218
219 // Lifetimes read from ENSDFSTATE are mean lives
220 ifs >> ionZ >> ionA >> ionE >> ionFL >> ionLife >> ionJ >> ionMu;
221
222 while (ifs.good() ) // Loop checking, 09.08.2015, K.Kurashige
223 {
224 if (ionCode != 1000*ionZ + ionA ) {
225 iLevel = 0;
226 ionCode = 1000*ionZ + ionA;
227 }
228
229 ionE *= keV;
230 G4Ions::G4FloatLevelBase flb = StripFloatLevelBase(ionFL);
231 ionLife *= ns;
232 ionMu *= (joule/tesla);
233
234 if ((ionE == 0 && flb == G4Ions::G4FloatLevelBase::no_Float) ||
235 (mean_life_threshold <= ionLife &&
236 ionLife < minimum_mean_life_threshold) ) {
237 if (ionE > 0) ++iLevel;
238 if (iLevel > 9) iLevel = 9;
239
240 G4IsotopeProperty* fProperty = new G4IsotopeProperty();
241
242 // Set Isotope Property
243 fProperty->SetAtomicNumber(ionZ);
244 fProperty->SetAtomicMass(ionA);
245 fProperty->SetIsomerLevel(iLevel);
246 fProperty->SetEnergy(ionE);
247 fProperty->SetiSpin(ionJ);
248 fProperty->SetLifeTime(ionLife);
249 fProperty->SetDecayTable(nullptr);
250 fProperty->SetMagneticMoment(ionMu);
251 fProperty->SetFloatLevelBase( flb );
252
253 fIsotopeList->push_back(fProperty);
254
255 auto itf = map_full_list.find(ionCode);
256 if (itf == map_full_list.cend() ) {
257 std::multimap<G4double, G4IsotopeProperty*> aMultiMap;
258 itf = (map_full_list.insert(
259 std::pair<G4int, std::multimap<G4double,
260 G4IsotopeProperty*> > (ionCode, aMultiMap) ) ).first;
261 }
262 itf->second.insert(
263 std::pair<G4double, G4IsotopeProperty*>(ionE, fProperty) );
264 }
265
266 ifs >> ionZ >> ionA >> ionE >> ionFL >> ionLife >> ionJ >> ionMu;
267 } // End while
268
269 minimum_mean_life_threshold = mean_life_threshold;
270 }
271
272 // Clear current map
273 for (auto it = map_pre_load_list.begin(); it != map_pre_load_list.end(); ++it) {
274 it->second.clear();
275 }
276 map_pre_load_list.clear();
277
278 // Build map based on current threshold value
279 for (auto it = map_full_list.cbegin(); it != map_full_list.cend(); ++it) {
280 G4int ionCode = it->first;
281 auto itf = map_pre_load_list.find(ionCode);
282 if (itf == map_pre_load_list.cend() ) {
283 std::multimap<G4double, G4IsotopeProperty*> aMultiMap;
284 itf = (map_pre_load_list.insert(
285 std::pair<G4int, std::multimap<G4double,
286 G4IsotopeProperty*> > (ionCode, aMultiMap) ) ).first;
287 }
288
289 G4int iLevel = 0;
290 for (auto itt = it->second.cbegin(); itt != it->second.cend(); ++itt) {
291 G4double exEnergy = itt->first;
292 G4double meanLife = itt->second->GetLifeTime();
293 if (exEnergy == 0.0 || meanLife > mean_life_threshold) {
294 if (itt->first != 0.0) ++iLevel;
295 if (iLevel > 9) iLevel = 9;
296 itt->second->SetIsomerLevel(iLevel);
297 itf->second.insert(
298 std::pair<G4double, G4IsotopeProperty*>(exEnergy, itt->second) );
299 }
300 }
301 }
302}
303
304// --------------------------------------------------------------------
306 G4double ionLife, G4int ionJ, G4double ionMu )
307{
309 {
310 G4int flbIndex = 0;
311 ionE = StripFloatLevelBase( ionE, flbIndex );
312 AddState(ionZ,ionA,ionE,flbIndex,ionLife,ionJ,ionMu);
313 }
314}
315
316// --------------------------------------------------------------------
318 G4int flbIndex, G4double ionLife, G4int ionJ,
319 G4double ionMu )
320{
322 {
323 if ( fUserDefinedList == nullptr ) fUserDefinedList = new G4IsotopeList();
324
325 G4IsotopeProperty* fProperty = new G4IsotopeProperty();
326
327 // Set Isotope Property
328 fProperty->SetAtomicNumber(ionZ);
329 fProperty->SetAtomicMass(ionA);
330 fProperty->SetIsomerLevel(9);
331 fProperty->SetEnergy(ionE);
332 fProperty->SetiSpin(ionJ);
333 fProperty->SetLifeTime(ionLife);
334 fProperty->SetDecayTable(nullptr);
335 fProperty->SetMagneticMoment(ionMu);
336 fProperty->SetFloatLevelBase(flbIndex);
337
338 fUserDefinedList->push_back(fProperty);
339 fIsotopeList->push_back(fProperty);
340 }
341}
342
343// --------------------------------------------------------------------
346 G4int ionJ, G4double ionMu )
347{
349 {
350 if ( fUserDefinedList == nullptr ) fUserDefinedList = new G4IsotopeList();
351
352 G4IsotopeProperty* fProperty = new G4IsotopeProperty();
353
354 // Set Isotope Property
355 fProperty->SetAtomicNumber(ionZ);
356 fProperty->SetAtomicMass(ionA);
357 fProperty->SetIsomerLevel(9);
358 fProperty->SetEnergy(ionE);
359 fProperty->SetiSpin(ionJ);
360 fProperty->SetLifeTime(ionLife);
361 fProperty->SetDecayTable(0);
362 fProperty->SetMagneticMoment(ionMu);
363 fProperty->SetFloatLevelBase(flb);
364
365 fUserDefinedList->push_back(fProperty);
366 fIsotopeList->push_back(fProperty);
367 }
368}
369
370// --------------------------------------------------------------------
373 mean_life_threshold = t/0.69314718;
375 }
376}
377
378// Set the mean life threshold for nuclides
379// All nuclides with mean lives greater than this value are created
380// for this run
382{
384 {
385 mean_life_threshold = t;
387 }
388}
389
390// --------------------------------------------------------------------
391G4double G4NuclideTable::StripFloatLevelBase(G4double E, G4int& flbIndex)
392{
393 G4double rem = std::fmod(E/(1.0E-3*eV),10.0);
394 flbIndex = G4int(rem);
395 return E-rem;
396}
397
398// --------------------------------------------------------------------
400G4NuclideTable::StripFloatLevelBase( const G4String& sFLB )
401{
402 if ( sFLB.size() < 1 || 2 < sFLB.size() )
403 {
404 G4String text;
405 text += sFLB;
406 text += " is not valid indicator of G4Ions::G4FloatLevelBase.\n";
407 text += "You may use a wrong version of ENSDFSTATE data.\n";
408 text += "Please use G4ENSDFSTATE-2.0 or later.";
409
410 G4Exception( "G4NuclideTable", "PART70002", FatalException, text );
411 }
413 if ( !(sFLB == "-") )
414 {
415 flb = G4Ions::FloatLevelBase( sFLB.back() );
416 }
417 return flb;
418}
const char * G4FindDataDir(const char *)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
#define noFloat
Definition: G4Ions.hh:112
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:110
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)
void SetMeanLifeThreshold(G4double)
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(x)
Definition: xmltok.c:1649