source: trunk/source/processes/electromagnetic/lowenergy/src/G4EMDataSet.cc@ 1201

Last change on this file since 1201 was 1196, checked in by garnier, 16 years ago

update CVS release candidate geant4.9.3.01

File size: 16.4 KB
RevLine 
[819]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//
[1192]27// $Id: G4EMDataSet.cc,v 1.20 2009/09/25 07:41:34 sincerti Exp $
[1196]28// GEANT4 tag $Name: geant4-09-03-cand-01 $
[819]29//
30// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
31//
32// History:
33// -----------
34// 31 Jul 2001 MGP Created
35//
[1192]36// 15 Jul 2009 Nicolas A. Karakatsanis
37//
38// - New Constructor was added when logarithmic data are loaded as well
39// to enhance CPU performance
40//
41// - Destructor was modified accordingly
42//
43// - LoadNonLogData method was created to load only the non-logarithmic data from G4EMLOW
44// dataset. It is essentially performing the data loading operations as in the past.
45//
46// - LoadData method was revised in order to calculate the logarithmic values of the data
47// It retrieves the data values from the G4EMLOW data files but, then, calculates the
48// respective log values and loads them to seperate data structures.
49//
50// - SetLogEnergiesData method was cretaed to set logarithmic values to G4 data vectors.
51// The EM data sets, initialized this way, contain both non-log and log values.
52// These initialized data sets can enhance the computing performance of data interpolation
53// operations
54//
55//
[819]56// -------------------------------------------------------------------
57
58#include "G4EMDataSet.hh"
59#include "G4VDataSetAlgorithm.hh"
60#include <fstream>
61#include <sstream>
[961]62#include "G4Integrator.hh"
63#include "Randomize.hh"
64#include "G4LinInterpolation.hh"
[819]65
[961]66
67G4EMDataSet::G4EMDataSet(G4int Z,
68 G4VDataSetAlgorithm* algo,
69 G4double xUnit,
70 G4double yUnit,
71 G4bool random):
72 z(Z),
73 energies(0),
74 data(0),
[1192]75 log_energies(0),
76 log_data(0),
[961]77 algorithm(algo),
78 unitEnergies(xUnit),
79 unitData(yUnit),
80 pdf(0),
81 randomSet(random)
[819]82{
[961]83 if (algorithm == 0) G4Exception("G4EMDataSet::G4EMDataSet - interpolation == 0");
84 if (randomSet) BuildPdf();
[819]85}
86
[961]87G4EMDataSet::G4EMDataSet(G4int argZ,
88 G4DataVector* dataX,
89 G4DataVector* dataY,
90 G4VDataSetAlgorithm* algo,
91 G4double xUnit,
92 G4double yUnit,
93 G4bool random):
94 z(argZ),
95 energies(dataX),
96 data(dataY),
[1192]97 log_energies(0),
98 log_data(0),
[961]99 algorithm(algo),
100 unitEnergies(xUnit),
101 unitData(yUnit),
102 pdf(0),
103 randomSet(random)
[819]104{
[961]105 if (algorithm == 0) G4Exception("G4EMDataSet::G4EMDataSet - interpolation == 0");
[819]106
[961]107 if ((energies == 0) ^ (data == 0))
108 G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data (zero case)");
[819]109
[961]110 if (energies == 0) return;
[819]111
[961]112 if (energies->size() != data->size())
113 G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data");
114
115 if (randomSet) BuildPdf();
[819]116}
117
[1192]118G4EMDataSet::G4EMDataSet(G4int argZ,
119 G4DataVector* dataX,
120 G4DataVector* dataY,
121 G4DataVector* dataLogX,
122 G4DataVector* dataLogY,
123 G4VDataSetAlgorithm* algo,
124 G4double xUnit,
125 G4double yUnit,
126 G4bool random):
127 z(argZ),
128 energies(dataX),
129 data(dataY),
130 log_energies(dataLogX),
131 log_data(dataLogY),
132 algorithm(algo),
133 unitEnergies(xUnit),
134 unitData(yUnit),
135 pdf(0),
136 randomSet(random)
137{
138 if (algorithm == 0) G4Exception("G4EMDataSet::G4EMDataSet - interpolation == 0");
139
140 if ((energies == 0) ^ (data == 0))
141 G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data (zero case)");
142
143 if (energies == 0) return;
144
145 if (energies->size() != data->size())
146 G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data");
147
148 if ((log_energies == 0) ^ (log_data == 0))
149 G4Exception("G4EMDataSet::G4EMDataSet - different size for log energies and log data (zero case)");
150
151 if (log_energies == 0) return;
152
153 if (log_energies->size() != log_data->size())
154 G4Exception("G4EMDataSet::G4EMDataSet - different size for log energies and log data");
155
156 if (randomSet) BuildPdf();
157}
158
159
[961]160G4EMDataSet::~G4EMDataSet()
[819]161{
[961]162 delete algorithm;
163 if (energies) delete energies;
164 if (data) delete data;
165 if (pdf) delete pdf;
[1192]166 if (log_energies) delete log_energies;
167 if (log_data) delete log_data;
[819]168}
169
[1192]170
[961]171G4double G4EMDataSet::FindValue(G4double energy, G4int /* componentId */) const
172{
173 if (!energies) G4Exception("G4EMDataSet::FindValue - energies == 0");
174 if (energies->empty()) return 0;
175 if (energy <= (*energies)[0]) return (*data)[0];
[819]176
[961]177 size_t i = energies->size()-1;
178 if (energy >= (*energies)[i]) return (*data)[i];
[819]179
[1192]180//Nicolas A. Karakatsanis: Check if the logarithmic data have been loaded to decide
181// which Interpolation-Calculation method will be applied
182 if (log_energies != 0)
183 {
184 return algorithm->Calculate(energy, FindLowerBound(energy), *energies, *data, *log_energies, *log_data);
185 }
186
[961]187 return algorithm->Calculate(energy, FindLowerBound(energy), *energies, *data);
188}
[819]189
190
[961]191void G4EMDataSet::PrintData(void) const
[819]192{
[961]193 if (!energies)
194 {
195 G4cout << "Data not available." << G4endl;
196 }
197 else
198 {
199 size_t size = energies->size();
200 for (size_t i(0); i<size; i++)
201 {
202 G4cout << "Point: " << ((*energies)[i]/unitEnergies)
203 << " - Data value: " << ((*data)[i]/unitData);
204 if (pdf != 0) G4cout << " - PDF : " << (*pdf)[i];
205 G4cout << G4endl;
206 }
207 }
208}
[819]209
210
[961]211void G4EMDataSet::SetEnergiesData(G4DataVector* dataX,
212 G4DataVector* dataY,
213 G4int /* componentId */)
214{
215 if (energies) delete energies;
216 energies = dataX;
[819]217
[961]218 if (data) delete data;
219 data = dataY;
220
221 if ((energies == 0) ^ (data==0))
222 G4Exception("G4EMDataSet::SetEnergiesData - different size for energies and data (zero case)");
[819]223
[961]224 if (energies == 0) return;
[1192]225
226 //G4cout << "Size of energies: " << energies->size() << G4endl << "Size of data: " << data->size() << G4endl;
[961]227 if (energies->size() != data->size())
228 G4Exception("G4EMDataSet::SetEnergiesData - different size for energies and data");
[819]229}
230
[1192]231void G4EMDataSet::SetLogEnergiesData(G4DataVector* dataX,
232 G4DataVector* dataY,
233 G4DataVector* data_logX,
234 G4DataVector* data_logY,
235 G4int /* componentId */)
236{
237//Load of the actual energy and data values
238 if (energies) delete energies;
239 energies = dataX;
240 if (data) delete data;
241 data = dataY;
242
243//Check if data loaded properly from data files
244 if ((energies == 0) ^ (data==0))
245 G4Exception("G4EMDataSet::SetLogEnergiesData - different size for energies and data (zero case)");
246
247 if (energies == 0) return;
248
249 //G4cout << "Size of energies: " << energies->size() << G4endl << "Size of data: " << data->size() << G4endl << G4endl;
250 if (energies->size() != data->size())
251 G4Exception("G4EMDataSet::SetLogEnergiesData - different size for energies and data");
252
253//Load of the logarithmic energy and data values
254 if (log_energies) delete log_energies;
255 log_energies = data_logX;
256 if (log_data) delete log_data;
257 log_data = data_logY;
258
259//Check if logarithmic data loaded properly from data files
260 if ((log_energies == 0) ^ (log_data==0))
261 G4Exception("G4EMDataSet::SetLogEnergiesData - different size for log energies and log data (zero case)");
262
263 if (log_energies == 0) G4cout << "G4EMDataSet::SetLogEnergiesData - log_energies == 0" << G4endl;
264 if (log_energies == 0) return;
265
266 //G4cout << "Size of log energies: " << log_energies->size() << G4endl << "Size of log data: " << log_data->size() << G4endl << G4endl;
267 if (log_energies->size() != log_data->size())
268 G4Exception("G4EMDataSet::SetLogEnergiesData - different size for log energies and log data");
269}
270
271
272
[961]273G4bool G4EMDataSet::LoadData(const G4String& fileName)
274{
[1192]275 // The file is organized into four columns:
276 // 1st column contains the values of energy
277 // 2nd column contains the corresponding data value
278 // The file terminates with the pattern: -1 -1
279 // -2 -2
280
[961]281 G4String fullFileName(FullFileName(fileName));
282 std::ifstream in(fullFileName);
[819]283
[961]284 if (!in.is_open())
285 {
286 G4String message("G4EMDataSet::LoadData - data file \"");
287 message += fullFileName;
288 message += "\" not found";
289 G4Exception(message);
290 }
[819]291
[961]292 G4DataVector* argEnergies=new G4DataVector;
293 G4DataVector* argData=new G4DataVector;
[1192]294 G4DataVector* argLogEnergies=new G4DataVector;
295 G4DataVector* argLogData=new G4DataVector;
[819]296
[961]297 G4double a;
[1192]298 G4int k = 0;
299 G4int nColumns = 2;
[819]300
[961]301 do
302 {
303 in >> a;
[1192]304
305 if (a==0.) a=1e-300;
[819]306
[1192]307 if (a != -1 && a != -2)
[961]308 {
[1192]309 if (k%nColumns == 0)
310 {
311 argEnergies->push_back(a*unitEnergies);
312 argLogEnergies->push_back(std::log10(a)+std::log10(unitEnergies));
313 }
314 else if (k%nColumns == 1)
315 {
316 argData->push_back(a*unitData);
317 argLogData->push_back(std::log10(a)+std::log10(unitData));
318 }
319 k++;
[961]320 }
321 }
322 while (a != -2);
[1192]323
324
325 SetLogEnergiesData(argEnergies, argData, argLogEnergies, argLogData, 0);
326
327 if (randomSet) BuildPdf();
[819]328
[1192]329 return true;
330}
331
332
333G4bool G4EMDataSet::LoadNonLogData(const G4String& fileName)
334{
335 // The file is organized into four columns:
336 // 1st column contains the values of energy
337 // 2nd column contains the corresponding data value
338 // The file terminates with the pattern: -1 -1
339 // -2 -2
340
341 G4String fullFileName(FullFileName(fileName));
342 std::ifstream in(fullFileName);
343 if (!in.is_open())
344 {
345 G4String message("G4EMDataSet::LoadData - data file \"");
346 message += fullFileName;
347 message += "\" not found";
348 G4Exception(message);
349 }
350
351 G4DataVector* argEnergies=new G4DataVector;
352 G4DataVector* argData=new G4DataVector;
353
354 G4double a;
355 G4int k = 0;
356 G4int nColumns = 2;
357
358 do
359 {
360 in >> a;
361
362 if (a != -1 && a != -2)
363 {
364 if (k%nColumns == 0)
365 {
366 argEnergies->push_back(a*unitEnergies);
367 }
368 else if (k%nColumns == 1)
369 {
370 argData->push_back(a*unitData);
371 }
372 k++;
373 }
374 }
375 while (a != -2);
376
[961]377 SetEnergiesData(argEnergies, argData, 0);
[1192]378
[961]379 if (randomSet) BuildPdf();
380
381 return true;
[819]382}
383
[1192]384
385
[961]386G4bool G4EMDataSet::SaveData(const G4String& name) const
387{
388 // The file is organized into two columns:
389 // 1st column is the energy
390 // 2nd column is the corresponding value
391 // The file terminates with the pattern: -1 -1
392 // -2 -2
393
394 G4String fullFileName(FullFileName(name));
395 std::ofstream out(fullFileName);
[819]396
[961]397 if (!out.is_open())
398 {
399 G4String message("G4EMDataSet::SaveData - cannot open \"");
400 message+=fullFileName;
401 message+="\"";
402 G4Exception(message);
403 }
404
405 out.precision(10);
406 out.width(15);
407 out.setf(std::ofstream::left);
408
409 if (energies!=0 && data!=0)
410 {
411 G4DataVector::const_iterator i(energies->begin());
412 G4DataVector::const_iterator endI(energies->end());
413 G4DataVector::const_iterator j(data->begin());
414
415 while (i!=endI)
416 {
417 out.precision(10);
418 out.width(15);
419 out.setf(std::ofstream::left);
420 out << ((*i)/unitEnergies) << ' ';
[819]421
[961]422 out.precision(10);
423 out.width(15);
424 out.setf(std::ofstream::left);
425 out << ((*j)/unitData) << std::endl;
[819]426
[961]427 i++;
428 j++;
429 }
430 }
[819]431
[961]432 out.precision(10);
433 out.width(15);
434 out.setf(std::ofstream::left);
435 out << -1.f << ' ';
[819]436
[961]437 out.precision(10);
438 out.width(15);
439 out.setf(std::ofstream::left);
440 out << -1.f << std::endl;
[819]441
[961]442 out.precision(10);
443 out.width(15);
444 out.setf(std::ofstream::left);
445 out << -2.f << ' ';
[819]446
[961]447 out.precision(10);
448 out.width(15);
449 out.setf(std::ofstream::left);
450 out << -2.f << std::endl;
[819]451
[961]452 return true;
453}
[819]454
[1192]455
456
[961]457size_t G4EMDataSet::FindLowerBound(G4double x) const
[819]458{
[961]459 size_t lowerBound = 0;
460 size_t upperBound(energies->size() - 1);
461
462 while (lowerBound <= upperBound)
463 {
464 size_t midBin((lowerBound + upperBound) / 2);
[819]465
[961]466 if (x < (*energies)[midBin]) upperBound = midBin - 1;
467 else lowerBound = midBin + 1;
468 }
469
470 return upperBound;
471}
[819]472
473
[961]474size_t G4EMDataSet::FindLowerBound(G4double x, G4DataVector* values) const
475{
476 size_t lowerBound = 0;;
477 size_t upperBound(values->size() - 1);
478
479 while (lowerBound <= upperBound)
480 {
481 size_t midBin((lowerBound + upperBound) / 2);
[819]482
[961]483 if (x < (*values)[midBin]) upperBound = midBin - 1;
484 else lowerBound = midBin + 1;
485 }
[819]486
[961]487 return upperBound;
[819]488}
489
490
[961]491G4String G4EMDataSet::FullFileName(const G4String& name) const
[819]492{
[961]493 char* path = getenv("G4LEDATA");
494 if (!path)
495 G4Exception("G4EMDataSet::FullFileName - G4LEDATA environment variable not set");
[819]496
[961]497 std::ostringstream fullFileName;
498 fullFileName << path << '/' << name << z << ".dat";
499
500 return G4String(fullFileName.str().c_str());
501}
[819]502
503
[1192]504
[961]505void G4EMDataSet::BuildPdf()
506{
507 pdf = new G4DataVector;
508 G4Integrator <G4EMDataSet, G4double(G4EMDataSet::*)(G4double)> integrator;
[819]509
[961]510 G4int nData = data->size();
511 pdf->push_back(0.);
[819]512
[961]513 // Integrate the data distribution
514 G4int i;
515 G4double totalSum = 0.;
516 for (i=1; i<nData; i++)
517 {
518 G4double xLow = (*energies)[i-1];
519 G4double xHigh = (*energies)[i];
520 G4double sum = integrator.Legendre96(this, &G4EMDataSet::IntegrationFunction, xLow, xHigh);
521 totalSum = totalSum + sum;
522 pdf->push_back(totalSum);
523 }
[819]524
[961]525 // Normalize to the last bin
526 G4double tot = 0.;
527 if (totalSum > 0.) tot = 1. / totalSum;
528 for (i=1; i<nData; i++)
529 {
530 (*pdf)[i] = (*pdf)[i] * tot;
531 }
[819]532}
533
534
[961]535G4double G4EMDataSet::RandomSelect(G4int /* componentId */) const
536{
537 // Random select a X value according to the cumulative probability distribution
538 // derived from the data
[819]539
[961]540 if (!pdf) G4Exception("G4EMDataSet::RandomSelect - PDF has not been created for this data set");
[819]541
[961]542 G4double value = 0.;
543 G4double x = G4UniformRand();
[819]544
[961]545 // Locate the random value in the X vector based on the PDF
546 size_t bin = FindLowerBound(x,pdf);
[819]547
[961]548 // Interpolate the PDF to calculate the X value:
549 // linear interpolation in the first bin (to avoid problem with 0),
550 // interpolation with associated data set algorithm in other bins
551
552 G4LinInterpolation linearAlgo;
553 if (bin == 0) value = linearAlgo.Calculate(x, bin, *pdf, *energies);
554 else value = algorithm->Calculate(x, bin, *pdf, *energies);
555
556 // G4cout << x << " random bin "<< bin << " - " << value << G4endl;
557 return value;
[819]558}
559
[961]560G4double G4EMDataSet::IntegrationFunction(G4double x)
561{
562 // This function is needed by G4Integrator to calculate the integral of the data distribution
[819]563
[961]564 G4double y = 0;
[819]565
[961]566 // Locate the random value in the X vector based on the PDF
567 size_t bin = FindLowerBound(x);
[819]568
[961]569 // Interpolate to calculate the X value:
570 // linear interpolation in the first bin (to avoid problem with 0),
571 // interpolation with associated algorithm in other bins
[819]572
[961]573 G4LinInterpolation linearAlgo;
[819]574
[961]575 if (bin == 0) y = linearAlgo.Calculate(x, bin, *energies, *data);
576 else y = algorithm->Calculate(x, bin, *energies, *data);
[819]577
[961]578 return y;
[819]579}
[961]580
Note: See TracBrowser for help on using the repository browser.