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