Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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 ([email protected])
36//
37// Creation date: 24 October 1998
38//
39// Modifications:
40//
41// 15 April 1999, Alessandro Brunengo ([email protected])
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