Geant4 11.2.2
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"
32
35#include "G4String.hh"
36#include "G4SystemOfUnits.hh"
37#include "G4ios.hh"
38#include "globals.hh"
39
40#include <fstream>
41#include <iomanip>
42#include <sstream>
43
45{
46 static G4NuclideTable instance;
47 return &instance;
48}
49
54
55G4NuclideTable::G4NuclideTable()
56 : G4VIsotopeTable("Isomer"), mean_life_threshold(1.0 * ns), flevelTolerance(1.0 * eV)
57{
58 fMessenger = new G4NuclideTableMessenger(this);
59 fIsotopeList = new G4IsotopeList();
61}
62
64{
65 for (auto& it : map_pre_load_list) {
66 it.second.clear();
67 }
68 map_pre_load_list.clear();
69
70 for (auto& it : map_full_list) {
71 it.second.clear();
72 }
73 map_full_list.clear();
74
75 if (fIsotopeList != nullptr) {
76 for (const auto& i : *fIsotopeList) {
77 delete i;
78 }
79 fIsotopeList->clear();
80 delete fIsotopeList;
81 fIsotopeList = nullptr;
82 }
83 delete fMessenger;
84}
85
88{
89 G4IsotopeProperty* fProperty = nullptr;
90
91 // At first searching UserDefined
92 if (fUserDefinedList != nullptr) {
93 for (const auto it : *fUserDefinedList) {
94 if (Z == it->GetAtomicNumber() && A == it->GetAtomicMass()) {
95 G4double levelE = it->GetEnergy();
96 if (levelE - flevelTolerance / 2 <= E && E < levelE + flevelTolerance / 2) {
97 if (flb == it->GetFloatLevelBase()) {
98 return it;
99 } // found
100 }
101 }
102 }
103 }
104
105 // Searching pre-load
106 // Note: isomer level is properly set only for pre_load_list
107 //
108 G4int ionCode = 1000 * Z + A;
109 auto itf = map_pre_load_list.find(ionCode);
110
111 if (itf != map_pre_load_list.cend()) {
112 auto lower_bound_itr = itf->second.lower_bound(E - flevelTolerance / 2);
113 G4double levelE = DBL_MAX;
114
115 while (lower_bound_itr != itf->second.cend()) {
116 levelE = lower_bound_itr->first;
117 if (levelE - flevelTolerance / 2 <= E && E < levelE + flevelTolerance / 2) {
118 if (flb == (lower_bound_itr->second)->GetFloatLevelBase() || E == 0.0) {
119 return lower_bound_itr->second; // found
120 }
121 }
122 else {
123 break;
124 }
125 ++lower_bound_itr;
126 }
127 }
128
129 return fProperty; // not found
130}
131
133{
135 return eex - (G4long)(eex / tolerance) * tolerance;
136}
137
139{
141 return round(eex / tolerance) * tolerance;
142}
143
145{
147 return (G4long)(eex / tolerance);
148}
149
154
156{
157 if (lvl == 0) return GetIsotope(Z, A, 0.0);
158 return nullptr;
159}
160
162{
163 if (mean_life_threshold < minimum_mean_life_threshold) {
164 // Need to update full list
165 const char* path = G4FindDataDir("G4ENSDFSTATEDATA");
166
167 if (path == nullptr) {
168 G4Exception("G4NuclideTable", "PART70000", FatalException,
169 "G4ENSDFSTATEDATA environment variable must be set");
170 return;
171 }
172
173 std::ifstream ifs;
174 G4String filename(path);
175 filename += "/ENSDFSTATE.dat";
176
177 ifs.open(filename.c_str());
178 if (!ifs.good()) {
179 G4Exception("G4NuclideTable", "PART70001", FatalException, "ENSDFSTATE.dat is not found.");
180 return;
181 }
182
183 G4int ionCode = 0;
184 G4int iLevel = 0;
185 G4int ionZ;
186 G4int ionA;
187 G4double ionE;
188 G4String ionFL;
189 G4double ionLife;
190 G4int ionJ;
191 G4double ionMu;
192
193 // Lifetimes read from ENSDFSTATE are mean lives
194 ifs >> ionZ >> ionA >> ionE >> ionFL >> ionLife >> ionJ >> ionMu;
195
196 while (ifs.good()) // Loop checking, 09.08.2015, K.Kurashige
197 {
198 if (ionCode != 1000 * ionZ + ionA) {
199 iLevel = 0;
200 ionCode = 1000 * ionZ + ionA;
201 }
202
203 ionE *= keV;
204 G4Ions::G4FloatLevelBase flb = StripFloatLevelBase(ionFL);
205 ionLife *= ns;
206 ionMu *= (joule / tesla);
207
208 if ((ionE == 0 && flb == G4Ions::G4FloatLevelBase::no_Float)
209 || (mean_life_threshold <= ionLife && ionLife < minimum_mean_life_threshold))
210 {
211 if (ionE > 0) ++iLevel;
212 if (iLevel > 9) iLevel = 9;
213
214 auto fProperty = new G4IsotopeProperty();
215
216 // Set Isotope Property
217 fProperty->SetAtomicNumber(ionZ);
218 fProperty->SetAtomicMass(ionA);
219 fProperty->SetIsomerLevel(iLevel);
220 fProperty->SetEnergy(ionE);
221 fProperty->SetiSpin(ionJ);
222 fProperty->SetLifeTime(ionLife);
223 fProperty->SetDecayTable(nullptr);
224 fProperty->SetMagneticMoment(ionMu);
225 fProperty->SetFloatLevelBase(flb);
226
227 fIsotopeList->push_back(fProperty);
228
229 auto itf = map_full_list.find(ionCode);
230 if (itf == map_full_list.cend()) {
231 std::multimap<G4double, G4IsotopeProperty*> aMultiMap;
232 itf = (map_full_list.insert(std::pair<G4int, std::multimap<G4double, G4IsotopeProperty*>>(
233 ionCode, aMultiMap)))
234 .first;
235 }
236 itf->second.insert(std::pair<G4double, G4IsotopeProperty*>(ionE, fProperty));
237 }
238
239 ifs >> ionZ >> ionA >> ionE >> ionFL >> ionLife >> ionJ >> ionMu;
240 } // End while
241
242 minimum_mean_life_threshold = mean_life_threshold;
243 }
244
245 // Clear current map
246 for (auto& it : map_pre_load_list) {
247 it.second.clear();
248 }
249 map_pre_load_list.clear();
250
251 // Build map based on current threshold value
252 for (const auto& it : map_full_list) {
253 G4int ionCode = it.first;
254 auto itf = map_pre_load_list.find(ionCode);
255 if (itf == map_pre_load_list.cend()) {
256 std::multimap<G4double, G4IsotopeProperty*> aMultiMap;
257 itf = (map_pre_load_list.insert(
258 std::pair<G4int, std::multimap<G4double, G4IsotopeProperty*>>(ionCode, aMultiMap)))
259 .first;
260 }
261
262 G4int iLevel = 0;
263 for (const auto& itt : it.second) {
264 G4double exEnergy = itt.first;
265 G4double meanLife = itt.second->GetLifeTime();
266 if (exEnergy == 0.0 || meanLife > mean_life_threshold) {
267 if (itt.first != 0.0) ++iLevel;
268 if (iLevel > 9) iLevel = 9;
269 itt.second->SetIsomerLevel(iLevel);
270 itf->second.insert(std::pair<G4double, G4IsotopeProperty*>(exEnergy, itt.second));
271 }
272 }
273 }
274}
275
276void G4NuclideTable::AddState(G4int ionZ, G4int ionA, G4double ionE, G4double ionLife, G4int ionJ,
277 G4double ionMu)
278{
280 G4int flbIndex = 0;
281 ionE = StripFloatLevelBase(ionE, flbIndex);
282 AddState(ionZ, ionA, ionE, flbIndex, ionLife, ionJ, ionMu);
283 }
284}
285
286void G4NuclideTable::AddState(G4int ionZ, G4int ionA, G4double ionE, G4int flbIndex,
287 G4double ionLife, G4int ionJ, G4double ionMu)
288{
290 if (fUserDefinedList == nullptr) fUserDefinedList = new G4IsotopeList();
291
292 auto fProperty = new G4IsotopeProperty();
293
294 // Set Isotope Property
295 fProperty->SetAtomicNumber(ionZ);
296 fProperty->SetAtomicMass(ionA);
297 fProperty->SetIsomerLevel(9);
298 fProperty->SetEnergy(ionE);
299 fProperty->SetiSpin(ionJ);
300 fProperty->SetLifeTime(ionLife);
301 fProperty->SetDecayTable(nullptr);
302 fProperty->SetMagneticMoment(ionMu);
303 fProperty->SetFloatLevelBase(flbIndex);
304
305 fUserDefinedList->push_back(fProperty);
306 fIsotopeList->push_back(fProperty);
307 }
308}
309
311 G4double ionLife, G4int ionJ, G4double ionMu)
312{
314 if (fUserDefinedList == nullptr) fUserDefinedList = new G4IsotopeList();
315
316 auto fProperty = new G4IsotopeProperty();
317
318 // Set Isotope Property
319 fProperty->SetAtomicNumber(ionZ);
320 fProperty->SetAtomicMass(ionA);
321 fProperty->SetIsomerLevel(9);
322 fProperty->SetEnergy(ionE);
323 fProperty->SetiSpin(ionJ);
324 fProperty->SetLifeTime(ionLife);
325 fProperty->SetDecayTable(nullptr);
326 fProperty->SetMagneticMoment(ionMu);
327 fProperty->SetFloatLevelBase(flb);
328
329 fUserDefinedList->push_back(fProperty);
330 fIsotopeList->push_back(fProperty);
331 }
332}
333
335{
337 mean_life_threshold = t / 0.69314718;
339 }
340}
341
342// Set the mean life threshold for nuclides
343// All nuclides with mean lives greater than this value are created
344// for this run
346{
348 mean_life_threshold = t;
350 }
351}
352
353G4double G4NuclideTable::StripFloatLevelBase(G4double E, G4int& flbIndex)
354{
355 G4double rem = std::fmod(E / (1.0E-3 * eV), 10.0);
356 flbIndex = G4int(rem);
357 return E - rem;
358}
359
360G4Ions::G4FloatLevelBase G4NuclideTable::StripFloatLevelBase(const G4String& sFLB)
361{
362 if (sFLB.empty() || 2 < sFLB.size()) {
363 G4String text;
364 text += sFLB;
365 text += " is not valid indicator of G4Ions::G4FloatLevelBase.\n";
366 text += "You may use a wrong version of ENSDFSTATE data.\n";
367 text += "Please use G4ENSDFSTATE-2.0 or later.";
368
369 G4Exception("G4NuclideTable", "PART70002", FatalException, text);
370 }
372 if (!(sFLB == "-")) {
373 flb = G4Ions::FloatLevelBase(sFLB.back());
374 }
375 return flb;
376}
const char * G4FindDataDir(const char *)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define noFloat
Definition G4Ions.hh:119
double G4double
Definition G4Types.hh:83
long G4long
Definition G4Types.hh:87
int G4int
Definition G4Types.hh:85
const G4double A[17]
static G4Ions::G4FloatLevelBase FloatLevelBase(char flbChar)
Definition G4Ions.cc:107
G4FloatLevelBase
Definition G4Ions.hh:80
G4IsotopeProperty * GetIsotope(G4int Z, G4int A, G4double E, G4Ions::G4FloatLevelBase flb=G4Ions::G4FloatLevelBase::no_Float) override
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)
~G4NuclideTable() override
static G4NuclideTable * GetNuclideTable()
static G4long Truncate(G4double eex)
G4double GetLevelTolerance()
std::vector< G4IsotopeProperty * > G4IsotopeList
static G4double Tolerance()
static G4double Round(G4double eex)
G4IsotopeProperty * GetIsotopeByIsoLvl(G4int Z, G4int A, G4int lvl=0) override
G4bool IsMasterThread()
#define DBL_MAX
Definition templates.hh:62
#define ns(x)
Definition xmltok.c:1649