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

Last change on this file since 1005 was 991, checked in by garnier, 17 years ago

update

File size: 10.3 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//
[961]27// $Id: G4EMDataSet.cc,v 1.18 2008/03/17 13:40:53 pia Exp $
[991]28// GEANT4 tag $Name: geant4-09-02 $
[819]29//
30// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
31//
32// History:
33// -----------
34// 31 Jul 2001 MGP Created
35//
36// -------------------------------------------------------------------
37
38#include "G4EMDataSet.hh"
39#include "G4VDataSetAlgorithm.hh"
40#include <fstream>
41#include <sstream>
[961]42#include "G4Integrator.hh"
43#include "Randomize.hh"
44#include "G4LinInterpolation.hh"
[819]45
[961]46
47G4EMDataSet::G4EMDataSet(G4int Z,
48 G4VDataSetAlgorithm* algo,
49 G4double xUnit,
50 G4double yUnit,
51 G4bool random):
52 z(Z),
53 energies(0),
54 data(0),
55 algorithm(algo),
56 unitEnergies(xUnit),
57 unitData(yUnit),
58 pdf(0),
59 randomSet(random)
[819]60{
[961]61 if (algorithm == 0) G4Exception("G4EMDataSet::G4EMDataSet - interpolation == 0");
62 if (randomSet) BuildPdf();
[819]63}
64
[961]65G4EMDataSet::G4EMDataSet(G4int argZ,
66 G4DataVector* dataX,
67 G4DataVector* dataY,
68 G4VDataSetAlgorithm* algo,
69 G4double xUnit,
70 G4double yUnit,
71 G4bool random):
72 z(argZ),
73 energies(dataX),
74 data(dataY),
75 algorithm(algo),
76 unitEnergies(xUnit),
77 unitData(yUnit),
78 pdf(0),
79 randomSet(random)
[819]80{
[961]81 if (algorithm == 0) G4Exception("G4EMDataSet::G4EMDataSet - interpolation == 0");
[819]82
[961]83 if ((energies == 0) ^ (data == 0))
84 G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data (zero case)");
[819]85
[961]86 if (energies == 0) return;
[819]87
[961]88 if (energies->size() != data->size())
89 G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data");
90
91 if (randomSet) BuildPdf();
[819]92}
93
[961]94G4EMDataSet::~G4EMDataSet()
[819]95{
[961]96 delete algorithm;
97 if (energies) delete energies;
98 if (data) delete data;
99 if (pdf) delete pdf;
[819]100}
101
[961]102G4double G4EMDataSet::FindValue(G4double energy, G4int /* componentId */) const
103{
104 if (!energies) G4Exception("G4EMDataSet::FindValue - energies == 0");
105 if (energies->empty()) return 0;
106 if (energy <= (*energies)[0]) return (*data)[0];
[819]107
[961]108 size_t i = energies->size()-1;
109 if (energy >= (*energies)[i]) return (*data)[i];
[819]110
[961]111 return algorithm->Calculate(energy, FindLowerBound(energy), *energies, *data);
112}
[819]113
114
[961]115void G4EMDataSet::PrintData(void) const
[819]116{
[961]117 if (!energies)
118 {
119 G4cout << "Data not available." << G4endl;
120 }
121 else
122 {
123 size_t size = energies->size();
124 for (size_t i(0); i<size; i++)
125 {
126 G4cout << "Point: " << ((*energies)[i]/unitEnergies)
127 << " - Data value: " << ((*data)[i]/unitData);
128 if (pdf != 0) G4cout << " - PDF : " << (*pdf)[i];
129 G4cout << G4endl;
130 }
131 }
132}
[819]133
134
[961]135void G4EMDataSet::SetEnergiesData(G4DataVector* dataX,
136 G4DataVector* dataY,
137 G4int /* componentId */)
138{
139 if (energies) delete energies;
140 energies = dataX;
[819]141
[961]142 if (data) delete data;
143 data = dataY;
144
145 if ((energies == 0) ^ (data==0))
146 G4Exception("G4EMDataSet::SetEnergiesData - different size for energies and data (zero case)");
[819]147
[961]148 if (energies == 0) return;
149
150 if (energies->size() != data->size())
151 G4Exception("G4EMDataSet::SetEnergiesData - different size for energies and data");
[819]152}
153
[961]154G4bool G4EMDataSet::LoadData(const G4String& fileName)
155{
156 // The file is organized into two columns:
157 // 1st column is the energy
158 // 2nd column is the corresponding value
159 // The file terminates with the pattern: -1 -1
160 // -2 -2
161
162 G4String fullFileName(FullFileName(fileName));
163 std::ifstream in(fullFileName);
[819]164
[961]165 if (!in.is_open())
166 {
167 G4String message("G4EMDataSet::LoadData - data file \"");
168 message += fullFileName;
169 message += "\" not found";
170 G4Exception(message);
171 }
[819]172
[961]173 G4DataVector* argEnergies=new G4DataVector;
174 G4DataVector* argData=new G4DataVector;
[819]175
[961]176 G4double a;
177 bool energyColumn(true);
[819]178
[961]179 do
180 {
181 in >> a;
[819]182
[961]183 if (a!=-1 && a!=-2)
184 {
185 if (energyColumn)
186 argEnergies->push_back(a*unitEnergies);
187 else
188 argData->push_back(a*unitData);
189 energyColumn=(!energyColumn);
190 }
191 }
192 while (a != -2);
[819]193
[961]194 SetEnergiesData(argEnergies, argData, 0);
195 if (randomSet) BuildPdf();
196
197 return true;
[819]198}
199
[961]200G4bool G4EMDataSet::SaveData(const G4String& name) const
201{
202 // The file is organized into two columns:
203 // 1st column is the energy
204 // 2nd column is the corresponding value
205 // The file terminates with the pattern: -1 -1
206 // -2 -2
207
208 G4String fullFileName(FullFileName(name));
209 std::ofstream out(fullFileName);
[819]210
[961]211 if (!out.is_open())
212 {
213 G4String message("G4EMDataSet::SaveData - cannot open \"");
214 message+=fullFileName;
215 message+="\"";
216 G4Exception(message);
217 }
218
219 out.precision(10);
220 out.width(15);
221 out.setf(std::ofstream::left);
222
223 if (energies!=0 && data!=0)
224 {
225 G4DataVector::const_iterator i(energies->begin());
226 G4DataVector::const_iterator endI(energies->end());
227 G4DataVector::const_iterator j(data->begin());
228
229 while (i!=endI)
230 {
231 out.precision(10);
232 out.width(15);
233 out.setf(std::ofstream::left);
234 out << ((*i)/unitEnergies) << ' ';
[819]235
[961]236 out.precision(10);
237 out.width(15);
238 out.setf(std::ofstream::left);
239 out << ((*j)/unitData) << std::endl;
[819]240
[961]241 i++;
242 j++;
243 }
244 }
[819]245
[961]246 out.precision(10);
247 out.width(15);
248 out.setf(std::ofstream::left);
249 out << -1.f << ' ';
[819]250
[961]251 out.precision(10);
252 out.width(15);
253 out.setf(std::ofstream::left);
254 out << -1.f << std::endl;
[819]255
[961]256 out.precision(10);
257 out.width(15);
258 out.setf(std::ofstream::left);
259 out << -2.f << ' ';
[819]260
[961]261 out.precision(10);
262 out.width(15);
263 out.setf(std::ofstream::left);
264 out << -2.f << std::endl;
[819]265
[961]266 return true;
267}
[819]268
[961]269size_t G4EMDataSet::FindLowerBound(G4double x) const
[819]270{
[961]271 size_t lowerBound = 0;
272 size_t upperBound(energies->size() - 1);
273
274 while (lowerBound <= upperBound)
275 {
276 size_t midBin((lowerBound + upperBound) / 2);
[819]277
[961]278 if (x < (*energies)[midBin]) upperBound = midBin - 1;
279 else lowerBound = midBin + 1;
280 }
281
282 return upperBound;
283}
[819]284
285
[961]286size_t G4EMDataSet::FindLowerBound(G4double x, G4DataVector* values) const
287{
288 size_t lowerBound = 0;;
289 size_t upperBound(values->size() - 1);
290
291 while (lowerBound <= upperBound)
292 {
293 size_t midBin((lowerBound + upperBound) / 2);
[819]294
[961]295 if (x < (*values)[midBin]) upperBound = midBin - 1;
296 else lowerBound = midBin + 1;
297 }
[819]298
[961]299 return upperBound;
[819]300}
301
302
[961]303G4String G4EMDataSet::FullFileName(const G4String& name) const
[819]304{
[961]305 char* path = getenv("G4LEDATA");
306 if (!path)
307 G4Exception("G4EMDataSet::FullFileName - G4LEDATA environment variable not set");
[819]308
[961]309 std::ostringstream fullFileName;
310 fullFileName << path << '/' << name << z << ".dat";
311
312 return G4String(fullFileName.str().c_str());
313}
[819]314
315
[961]316void G4EMDataSet::BuildPdf()
317{
318 pdf = new G4DataVector;
319 G4Integrator <G4EMDataSet, G4double(G4EMDataSet::*)(G4double)> integrator;
[819]320
[961]321 G4int nData = data->size();
322 pdf->push_back(0.);
[819]323
[961]324 // Integrate the data distribution
325 G4int i;
326 G4double totalSum = 0.;
327 for (i=1; i<nData; i++)
328 {
329 G4double xLow = (*energies)[i-1];
330 G4double xHigh = (*energies)[i];
331 G4double sum = integrator.Legendre96(this, &G4EMDataSet::IntegrationFunction, xLow, xHigh);
332 totalSum = totalSum + sum;
333 pdf->push_back(totalSum);
334 }
[819]335
[961]336 // Normalize to the last bin
337 G4double tot = 0.;
338 if (totalSum > 0.) tot = 1. / totalSum;
339 for (i=1; i<nData; i++)
340 {
341 (*pdf)[i] = (*pdf)[i] * tot;
342 }
[819]343}
344
345
[961]346G4double G4EMDataSet::RandomSelect(G4int /* componentId */) const
347{
348 // Random select a X value according to the cumulative probability distribution
349 // derived from the data
[819]350
[961]351 if (!pdf) G4Exception("G4EMDataSet::RandomSelect - PDF has not been created for this data set");
[819]352
[961]353 G4double value = 0.;
354 G4double x = G4UniformRand();
[819]355
[961]356 // Locate the random value in the X vector based on the PDF
357 size_t bin = FindLowerBound(x,pdf);
[819]358
[961]359 // Interpolate the PDF to calculate the X value:
360 // linear interpolation in the first bin (to avoid problem with 0),
361 // interpolation with associated data set algorithm in other bins
362
363 G4LinInterpolation linearAlgo;
364 if (bin == 0) value = linearAlgo.Calculate(x, bin, *pdf, *energies);
365 else value = algorithm->Calculate(x, bin, *pdf, *energies);
366
367 // G4cout << x << " random bin "<< bin << " - " << value << G4endl;
368 return value;
[819]369}
370
[961]371G4double G4EMDataSet::IntegrationFunction(G4double x)
372{
373 // This function is needed by G4Integrator to calculate the integral of the data distribution
[819]374
[961]375 G4double y = 0;
[819]376
[961]377 // Locate the random value in the X vector based on the PDF
378 size_t bin = FindLowerBound(x);
[819]379
[961]380 // Interpolate to calculate the X value:
381 // linear interpolation in the first bin (to avoid problem with 0),
382 // interpolation with associated algorithm in other bins
[819]383
[961]384 G4LinInterpolation linearAlgo;
[819]385
[961]386 if (bin == 0) y = linearAlgo.Calculate(x, bin, *energies, *data);
387 else y = algorithm->Calculate(x, bin, *energies, *data);
[819]388
[961]389 return y;
[819]390}
[961]391
Note: See TracBrowser for help on using the repository browser.