Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4NuclearLevelManager.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// $Id$
27//
28// -------------------------------------------------------------------
29// GEANT 4 class file
30//
31// CERN, Geneva, Switzerland
32//
33// File name: G4NuclearLevelManager
34//
35// Author: Maria Grazia Pia (pia@genova.infn.it)
36//
37// Creation date: 24 October 1998
38//
39// Modifications:
40//
41// 15 April 1999, Alessandro Brunengo (Alessandro.Brunengo@ge.infn.it)
42// Added half-life, angular momentum, parity, emissioni type
43// reading from experimental data.
44// 02 May 2003, Vladimir Ivanchenko remove rublic copy constructor
45// 06 Oct 2010, M. Kelsey -- Use object storage, not pointers, drop
46// public access to list, simplify list construction
47// -------------------------------------------------------------------
48#include <stdlib.h>
49#include <fstream>
50#include <sstream>
51#include <algorithm>
52
54
55#include "globals.hh"
56#include "G4SystemOfUnits.hh"
57#include "G4NuclearLevel.hh"
58#include "G4ios.hh"
60#include "G4HadTmpUtil.hh"
61/*
62G4NuclearLevelManager::G4NuclearLevelManager():
63 _nucleusA(0), _nucleusZ(0), _fileName(""), _validity(false),
64 _levels(0), _levelEnergy(0), _gammaEnergy(0), _probability(0)
65{ }
66*/
68 _nucleusA(A), _nucleusZ(Z), _fileName(filename), _validity(false),
69 _levels(0), _levelEnergy(0), _gammaEnergy(0), _probability(0)
70{
71 if (A <= 0 || Z <= 0 || Z > A )
72 throw G4HadronicException(__FILE__, __LINE__, "==== G4NuclearLevelManager ==== (Z,A) <0, or Z>A");
73
74 MakeLevels();
75}
76
78{
79 ClearLevels();
80}
81
83{
84 if (A <= 0 || Z <= 0 || Z > A )
85 throw G4HadronicException(__FILE__, __LINE__, "==== G4NuclearLevelManager ==== (Z,A) <0, or Z>A");
86
87 if (_nucleusZ != Z || _nucleusA != A)
88 {
89 _nucleusA = A;
90 _nucleusZ = Z;
91 _fileName = filename;
92 MakeLevels();
93 }
94}
95
97 return (i>=0 && i<NumberOfLevels()) ? (*_levels)[i] : 0;
98}
99
100
101const G4NuclearLevel*
103 G4double eDiffMax) const
104{
105 if (NumberOfLevels() <= 0) return 0;
106
107 G4int iNear = -1;
108
109 //G4cout << "G4NuclearLevelManager::NearestLevel E(MeV)= "
110 // << energy/MeV << " dEmax(MeV)= " << eDiffMax/MeV << G4endl;
111
112 G4double diff = 9999. * GeV;
113 for (unsigned int i=0; i<_levels->size(); i++)
114 {
115 G4double e = GetLevel(i)->Energy();
116 G4double eDiff = std::abs(e - energy);
117 //G4cout << i << ". eDiff(MeV)= " << eDiff/MeV << G4endl;
118 if (eDiff < diff && eDiff <= eDiffMax)
119 {
120 diff = eDiff;
121 iNear = i;
122 }
123 }
124
125 return GetLevel(iNear); // Includes range checking on iNear
126}
127
128
130{
131 return (NumberOfLevels() > 0) ? _levels->front()->Energy() : 9999.*GeV;
132}
133
134
136{
137 return (NumberOfLevels() > 0) ? _levels->back()->Energy() : 0.*GeV;
138}
139
140
142{
143 return (NumberOfLevels() > 0) ? _levels->front() : 0;
144}
145
146
148{
149 return (NumberOfLevels() > 0) ? _levels->back() : 0;
150}
151
152
153G4bool G4NuclearLevelManager::Read(std::ifstream& dataFile)
154{
155 G4bool goodRead = ReadDataLine(dataFile);
156
157 if (goodRead) ProcessDataLine();
158 return goodRead;
159}
160
161// NOTE: Standard stream I/O generates a 45 byte std::string per item!
162
163G4bool G4NuclearLevelManager::ReadDataLine(std::ifstream& dataFile) {
164 /***** DO NOT USE REGULAR STREAM I/O
165 G4bool result = true;
166 if (dataFile >> _levelEnergy)
167 {
168 dataFile >> _gammaEnergy >> _probability >> _polarity >> _halfLife
169 >> _angularMomentum >> _totalCC >> _kCC >> _l1CC >> _l2CC
170 >> _l3CC >> _m1CC >> _m2CC >> _m3CC >> _m4CC >> _m5CC
171 >> _nPlusCC;
172 }
173 else result = false;
174 *****/
175
176 // Each item will return iostream status
177 return (ReadDataItem(dataFile, _levelEnergy) &&
178 ReadDataItem(dataFile, _gammaEnergy) &&
179 ReadDataItem(dataFile, _probability) &&
180 ReadDataItem(dataFile, _polarity) &&
181 ReadDataItem(dataFile, _halfLife) &&
182 ReadDataItem(dataFile, _angularMomentum) &&
183 ReadDataItem(dataFile, _totalCC) &&
184 ReadDataItem(dataFile, _kCC) &&
185 ReadDataItem(dataFile, _l1CC) &&
186 ReadDataItem(dataFile, _l2CC) &&
187 ReadDataItem(dataFile, _l3CC) &&
188 ReadDataItem(dataFile, _m1CC) &&
189 ReadDataItem(dataFile, _m2CC) &&
190 ReadDataItem(dataFile, _m3CC) &&
191 ReadDataItem(dataFile, _m4CC) &&
192 ReadDataItem(dataFile, _m5CC) &&
193 ReadDataItem(dataFile, _nPlusCC) );
194}
195
196G4bool
197G4NuclearLevelManager::ReadDataItem(std::istream& dataFile, G4double& x)
198{
199 G4bool okay = (dataFile >> buffer); // Get next token
200 if (okay) x = strtod(buffer, NULL);
201
202 return okay;
203}
204
205void G4NuclearLevelManager::ProcessDataLine()
206{
207 const G4double minProbability = 1e-8;
208
209 // Assign units for dimensional quantities
210 _levelEnergy *= keV;
211 _gammaEnergy *= keV;
212 _halfLife *= second;
213
214 // The following adjustment is needed to take care of anomalies in
215 // data files, where some transitions show up with relative probability
216 // zero
217 if (_probability < minProbability) _probability = minProbability;
218 // the folowwing is to convert icc probability to accumulative ones
219 _l1CC += _kCC;
220 _l2CC += _l1CC;
221 _l3CC += _l2CC;
222 _m1CC += _l3CC;
223 _m2CC += _m1CC;
224 _m3CC += _m2CC;
225 _m4CC += _m3CC;
226 _m5CC += _m4CC;
227 _nPlusCC += _m5CC;
228
229 if (_nPlusCC!=0) { // Normalize to probabilities
230 _kCC /= _nPlusCC;
231 _l1CC /= _nPlusCC;
232 _l2CC /= _nPlusCC;
233 _l3CC /= _nPlusCC;
234 _m1CC /= _nPlusCC;
235 _m2CC /= _nPlusCC;
236 _m3CC /= _nPlusCC;
237 _m4CC /= _nPlusCC;
238 _m5CC /= _nPlusCC;
239 _nPlusCC /= _nPlusCC;
240 } else { // Total was zero, reset to unity
241 _kCC = 1;
242 _l1CC = 1;
243 _l2CC = 1;
244 _l3CC = 1;
245 _m1CC = 1;
246 _m2CC = 1;
247 _m3CC = 1;
248 _m4CC = 1;
249 _m5CC = 1;
250 _nPlusCC = 1;
251 }
252
253 // G4cout << "Read " << _levelEnergy << " " << _gammaEnergy << " " << _probability << G4endl;
254}
255
256
257void G4NuclearLevelManager::ClearLevels()
258{
259 _validity = false;
260
261 if (NumberOfLevels() > 0) {
262 std::for_each(_levels->begin(), _levels->end(), DeleteLevel());
263 _levels->clear();
264 }
265
266 delete _levels;
267 _levels = 0;
268}
269
270void G4NuclearLevelManager::MakeLevels()
271{
272 _validity = false;
273 if (NumberOfLevels() > 0) ClearLevels(); // Discard existing data
274
275 std::ifstream inFile(_fileName, std::ios::in);
276 if (! inFile)
277 {
278#ifdef GAMMAFILEWARNING
279 if (_nucleusZ > 10) G4cout << " G4NuclearLevelManager: nuclide ("
280 << _nucleusZ << "," << _nucleusA
281 << ") does not have a gamma levels file" << G4endl;
282#endif
283 return;
284 }
285
286 _levels = new G4PtrLevelVector;
287
288 // Read individual gamma data and fill levels for this nucleus
289
290 G4NuclearLevel* thisLevel = 0;
291 G4int nData = 0;
292
293 while (Read(inFile)) {
294 thisLevel = UseLevelOrMakeNew(thisLevel); // May create new pointer
295 AddDataToLevel(thisLevel);
296 nData++; // For debugging purposes
297 }
298
299 FinishLevel(thisLevel); // Final must be completed by hand
300
301 // ---- MGP ---- Don't forget to close the file
302 inFile.close();
303
304 // G4cout << " ==== MakeLevels ===== " << nData << " data read " << G4endl;
305
306 G4PtrSort<G4NuclearLevel>(_levels);
307
308 _validity = true;
309
310 return;
311}
312
314G4NuclearLevelManager::UseLevelOrMakeNew(G4NuclearLevel* level)
315{
316 if (level && _levelEnergy == level->Energy()) return level; // No change
317
318 if (level) FinishLevel(level); // Save what we have up to now
319
320 // G4cout << "Making a new level... " << _levelEnergy << G4endl;
321 return new G4NuclearLevel(_levelEnergy, _halfLife, _angularMomentum);
322}
323
324void G4NuclearLevelManager::AddDataToLevel(G4NuclearLevel* level)
325{
326 if (!level) return; // Sanity check
327
328 level->_energies.push_back(_gammaEnergy);
329 level->_weights.push_back(_probability);
330 level->_polarities.push_back(_polarity);
331 level->_kCC.push_back(_kCC);
332 level->_l1CC.push_back(_l1CC);
333 level->_l2CC.push_back(_l2CC);
334 level->_l3CC.push_back(_l3CC);
335 level->_m1CC.push_back(_m1CC);
336 level->_m2CC.push_back(_m2CC);
337 level->_m3CC.push_back(_m3CC);
338 level->_m4CC.push_back(_m4CC);
339 level->_m5CC.push_back(_m5CC);
340 level->_nPlusCC.push_back(_nPlusCC);
341 level->_totalCC.push_back(_totalCC);
342}
343
344void G4NuclearLevelManager::FinishLevel(G4NuclearLevel* level)
345{
346 if (!level || !_levels) return; // Sanity check
347
348 level->Finalize();
349 _levels->push_back(level);
350}
351
352
354{
355 G4int nLevels = NumberOfLevels();
356
357 G4cout << " ==== G4NuclearLevelManager ==== (" << _nucleusZ << ", " << _nucleusA
358 << ") has " << nLevels << " levels" << G4endl
359 << "Highest level is at energy " << MaxLevelEnergy() << " MeV "
360 << G4endl << "Lowest level is at energy " << MinLevelEnergy()
361 << " MeV " << G4endl;
362
363 for (G4int i=0; i<nLevels; i++)
364 GetLevel(i)->PrintAll();
365}
366
368{
369 _levelEnergy = right._levelEnergy;
370 _gammaEnergy = right._gammaEnergy;
371 _probability = right._probability;
372 _polarity = right._polarity;
373 _halfLife = right._halfLife;
374 _angularMomentum = right._angularMomentum;
375 _kCC = right._kCC;
376 _l1CC = right._l1CC;
377 _l2CC = right._l2CC;
378 _l3CC = right._l3CC;
379 _m1CC = right._m1CC;
380 _m2CC = right._m2CC;
381 _m3CC = right._m3CC;
382 _m4CC = right._m4CC;
383 _m5CC = right._m5CC;
384 _nPlusCC = right._nPlusCC;
385 _totalCC = right._totalCC;
386 _nucleusA = right._nucleusA;
387 _nucleusZ = right._nucleusZ;
388 _fileName = right._fileName;
389 _validity = right._validity;
390
391 if (right._levels != 0)
392 {
393 _levels = new G4PtrLevelVector;
394 G4int n = right._levels->size();
395 G4int i;
396 for (i=0; i<n; ++i)
397 {
398 _levels->push_back(new G4NuclearLevel(*(right.GetLevel(i))));
399 }
400
401 G4PtrSort<G4NuclearLevel>(_levels);
402 }
403 else
404 {
405 _levels = 0;
406 }
407 for (G4int i=0; i<30; ++i) {
408 buffer[i] = right.buffer[i];
409 }
410}
411
std::vector< G4NuclearLevel * > G4PtrLevelVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
const G4NuclearLevel * HighestLevel() const
const G4NuclearLevel * GetLevel(G4int i) const
void SetNucleus(G4int Z, G4int A, const G4String &filename)
G4NuclearLevelManager(G4int Z, G4int A, const G4String &filename)
const G4NuclearLevel * NearestLevel(G4double energy, G4double eDiffMax=9999.*CLHEP::GeV) const
const G4NuclearLevel * LowestLevel() const
void PrintAll() const
G4double Energy() const