Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
53 #include "G4NuclearLevelManager.hh"
54 
55 #include "globals.hh"
56 #include "G4SystemOfUnits.hh"
57 #include "G4NuclearLevel.hh"
58 #include "G4ios.hh"
59 #include "G4HadronicException.hh"
60 #include "G4HadTmpUtil.hh"
61 /*
62 G4NuclearLevelManager::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 
101 const 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 
153 G4bool 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 
163 G4bool 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 
196 G4bool
197 G4NuclearLevelManager::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 
205 void 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 
257 void 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 
270 void 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 
314 G4NuclearLevelManager::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 
324 void 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 
344 void 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