source: trunk/source/event/src/G4SPSEneDistribution.cc@ 1354

Last change on this file since 1354 was 1347, checked in by garnier, 15 years ago

geant4 tag 9.4

File size: 38.8 KB
RevLine 
[816]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///////////////////////////////////////////////////////////////////////////////
27//
28// MODULE: G4SPSEneDistribution.cc
29//
30// Version: 1.0
31// Date: 5/02/04
32// Author: Fan Lei
33// Organisation: QinetiQ ltd.
34// Customer: ESA/ESTEC
35//
36///////////////////////////////////////////////////////////////////////////////
37//
38// CHANGE HISTORY
39// --------------
40//
41//
42// Version 1.0, 05/02/2004, Fan Lei, Created.
43// Based on the G4GeneralParticleSource class in Geant4 v6.0
44//
45///////////////////////////////////////////////////////////////////////////////
46//
47#include "Randomize.hh"
48//#include <cmath>
49
50#include "G4SPSEneDistribution.hh"
51
[1347]52G4SPSEneDistribution::G4SPSEneDistribution() {
53 //
54 // Initialise all variables
55 particle_energy = 1.0 * MeV;
[816]56
[1347]57 EnergyDisType = "Mono";
58 weight = 1.;
59 MonoEnergy = 1 * MeV;
60 Emin = 0.;
61 Emax = 1.e30;
62 alpha = 0.;
63 biasalpha = 0.;
64 prob_norm = 1.0;
65 Ezero = 0.;
66 SE = 0.;
67 Temp = 0.;
68 grad = 0.;
69 cept = 0.;
70 Biased = false; // not biased
71 EnergySpec = true; // true - energy spectra, false - momentum spectra
72 DiffSpec = true; // true - differential spec, false integral spec
73 IntType = "NULL"; // Interpolation type
74 IPDFEnergyExist = false;
75 IPDFArbExist = false;
[816]76
[1347]77 ArbEmin = 0.;
78 ArbEmax = 1.e30;
[816]79
[1347]80 verbosityLevel = 0;
[816]81
82}
83
[1347]84G4SPSEneDistribution::~G4SPSEneDistribution() {
85}
[816]86
[1347]87void G4SPSEneDistribution::SetEnergyDisType(G4String DisType) {
88 EnergyDisType = DisType;
89 if (EnergyDisType == "User") {
90 UDefEnergyH = IPDFEnergyH = ZeroPhysVector;
91 IPDFEnergyExist = false;
92 } else if (EnergyDisType == "Arb") {
93 ArbEnergyH = IPDFArbEnergyH = ZeroPhysVector;
94 IPDFArbExist = false;
95 } else if (EnergyDisType == "Epn") {
96 UDefEnergyH = IPDFEnergyH = ZeroPhysVector;
97 IPDFEnergyExist = false;
98 EpnEnergyH = ZeroPhysVector;
99 }
[816]100}
101
[1347]102void G4SPSEneDistribution::SetEmin(G4double emi) {
103 Emin = emi;
[816]104}
105
[1347]106void G4SPSEneDistribution::SetEmax(G4double ema) {
107 Emax = ema;
[816]108}
109
[1347]110void G4SPSEneDistribution::SetMonoEnergy(G4double menergy) {
111 MonoEnergy = menergy;
[816]112}
113
[1347]114void G4SPSEneDistribution::SetBeamSigmaInE(G4double e) {
115 SE = e;
[816]116}
[1347]117void G4SPSEneDistribution::SetAlpha(G4double alp) {
118 alpha = alp;
[816]119}
120
[1347]121void G4SPSEneDistribution::SetBiasAlpha(G4double alp) {
122 biasalpha = alp;
123 Biased = true;
[816]124}
125
[1347]126void G4SPSEneDistribution::SetTemp(G4double tem) {
127 Temp = tem;
[816]128}
129
[1347]130void G4SPSEneDistribution::SetEzero(G4double eze) {
131 Ezero = eze;
[816]132}
133
[1347]134void G4SPSEneDistribution::SetGradient(G4double gr) {
135 grad = gr;
[816]136}
137
[1347]138void G4SPSEneDistribution::SetInterCept(G4double c) {
139 cept = c;
[816]140}
141
[1347]142void G4SPSEneDistribution::UserEnergyHisto(G4ThreeVector input) {
143 G4double ehi, val;
144 ehi = input.x();
145 val = input.y();
146 if (verbosityLevel > 1) {
147 G4cout << "In UserEnergyHisto" << G4endl;
148 G4cout << " " << ehi << " " << val << G4endl;
149 }
150 UDefEnergyH.InsertValues(ehi, val);
151 Emax = ehi;
[816]152}
153
[1347]154void G4SPSEneDistribution::ArbEnergyHisto(G4ThreeVector input) {
155 G4double ehi, val;
156 ehi = input.x();
157 val = input.y();
158 if (verbosityLevel > 1) {
159 G4cout << "In ArbEnergyHisto" << G4endl;
160 G4cout << " " << ehi << " " << val << G4endl;
161 }
162 ArbEnergyH.InsertValues(ehi, val);
[816]163}
164
[1347]165void G4SPSEneDistribution::ArbEnergyHistoFile(G4String filename) {
166 std::ifstream infile(filename, std::ios::in);
167 if (!infile)
168 G4Exception("Unable to open the histo ASCII file");
169 G4double ehi, val;
170 while (infile >> ehi >> val) {
171 ArbEnergyH.InsertValues(ehi, val);
172 }
[816]173}
174
[1347]175void G4SPSEneDistribution::EpnEnergyHisto(G4ThreeVector input) {
176 G4double ehi, val;
177 ehi = input.x();
178 val = input.y();
179 if (verbosityLevel > 1) {
180 G4cout << "In EpnEnergyHisto" << G4endl;
181 G4cout << " " << ehi << " " << val << G4endl;
182 }
183 EpnEnergyH.InsertValues(ehi, val);
184 Emax = ehi;
185 Epnflag = true;
186}
[816]187
[1347]188void G4SPSEneDistribution::Calculate() {
189 if (EnergyDisType == "Cdg")
190 CalculateCdgSpectrum();
191 else if (EnergyDisType == "Bbody")
192 CalculateBbodySpectrum();
193}
194
195void G4SPSEneDistribution::CalculateCdgSpectrum() {
196 // This uses the spectrum from The INTEGRAL Mass Model (TIMM)
197 // to generate a Cosmic Diffuse X/gamma ray spectrum.
198 G4double pfact[2] = { 8.5, 112 };
199 G4double spind[2] = { 1.4, 2.3 };
200 G4double ene_line[3] = { 1. * keV, 18. * keV, 1E6 * keV };
201 G4int n_par;
202
203 ene_line[0] = Emin;
204 if (Emin < 18 * keV) {
205 n_par = 2;
206 ene_line[2] = Emax;
207 if (Emax < 18 * keV) {
208 n_par = 1;
209 ene_line[1] = Emax;
210 }
211 } else {
212 n_par = 1;
213 pfact[0] = 112.;
214 spind[0] = 2.3;
215 ene_line[1] = Emax;
[816]216 }
217
[1347]218 // Create a cumulative histogram.
219 CDGhist[0] = 0.;
220 G4double omalpha;
221 G4int i = 0;
222
223 while (i < n_par) {
224 omalpha = 1. - spind[i];
225 CDGhist[i + 1] = CDGhist[i] + (pfact[i] / omalpha) * (std::pow(
226 ene_line[i + 1] / keV, omalpha) - std::pow(ene_line[i] / keV,
227 omalpha));
228 i++;
229 }
230
231 // Normalise histo and divide by 1000 to make MeV.
232 i = 0;
233 while (i < n_par) {
234 CDGhist[i + 1] = CDGhist[i + 1] / CDGhist[n_par];
235 // G4cout << CDGhist[i] << CDGhist[n_par] << G4endl;
236 i++;
237 }
[816]238}
239
[1347]240void G4SPSEneDistribution::CalculateBbodySpectrum() {
241 // create bbody spectrum
242 // Proved very hard to integrate indefinitely, so different
243 // method. User inputs emin, emax and T. These are used to
244 // create a 10,000 bin histogram.
245 // Use photon density spectrum = 2 nu**2/c**2 * (std::exp(h nu/kT)-1)
246 // = 2 E**2/h**2c**2 times the exponential
247 G4double erange = Emax - Emin;
248 G4double steps = erange / 10000.;
249 G4double Bbody_y[10000];
250 G4double k = 8.6181e-11; //Boltzmann const in MeV/K
251 G4double h = 4.1362e-21; // Plancks const in MeV s
252 G4double c = 3e8; // Speed of light
253 G4double h2 = h * h;
254 G4double c2 = c * c;
255 G4int count = 0;
256 G4double sum = 0.;
257 BBHist[0] = 0.;
258 while (count < 10000) {
259 Bbody_x[count] = Emin + G4double(count * steps);
260 Bbody_y[count] = (2. * std::pow(Bbody_x[count], 2.)) / (h2 * c2
261 * (std::exp(Bbody_x[count] / (k * Temp)) - 1.));
262 sum = sum + Bbody_y[count];
263 BBHist[count + 1] = BBHist[count] + Bbody_y[count];
264 count++;
265 }
[816]266
[1347]267 Bbody_x[10000] = Emax;
268 // Normalise cumulative histo.
269 count = 0;
270 while (count < 10001) {
271 BBHist[count] = BBHist[count] / sum;
272 count++;
273 }
[816]274}
275
[1347]276void G4SPSEneDistribution::InputEnergySpectra(G4bool value) {
277 // Allows user to specifiy spectrum is momentum
278 EnergySpec = value; // false if momentum
279 if (verbosityLevel > 1)
280 G4cout << "EnergySpec has value " << EnergySpec << G4endl;
[816]281}
282
[1347]283void G4SPSEneDistribution::InputDifferentialSpectra(G4bool value) {
284 // Allows user to specify integral or differential spectra
285 DiffSpec = value; // true = differential, false = integral
286 if (verbosityLevel > 1)
287 G4cout << "Diffspec has value " << DiffSpec << G4endl;
[816]288}
289
[1347]290void G4SPSEneDistribution::ArbInterpolate(G4String IType) {
291 if (EnergyDisType != "Arb")
292 G4cout << "Error: this is for arbitrary distributions" << G4endl;
293 IntType = IType;
294 ArbEmax = ArbEnergyH.GetMaxLowEdgeEnergy();
295 ArbEmin = ArbEnergyH.GetMinLowEdgeEnergy();
[816]296
[1347]297 // Now interpolate points
298 if (IntType == "Lin")
299 LinearInterpolation();
300 if (IntType == "Log")
301 LogInterpolation();
302 if (IntType == "Exp")
303 ExpInterpolation();
304 if (IntType == "Spline")
305 SplineInterpolation();
[816]306}
307
[1347]308void G4SPSEneDistribution::LinearInterpolation() {
309 // Method to do linear interpolation on the Arb points
310 // Calculate equation of each line segment, max 1024.
311 // Calculate Area under each segment
312 // Create a cumulative array which is then normalised Arb_Cum_Area
[816]313
[1347]314 G4double Area_seg[1024]; // Stores area under each segment
315 G4double sum = 0., Arb_x[1024], Arb_y[1024], Arb_Cum_Area[1024];
316 G4int i, count;
317 G4int maxi = ArbEnergyH.GetVectorLength();
318 for (i = 0; i < maxi; i++) {
319 Arb_x[i] = ArbEnergyH.GetLowEdgeEnergy(size_t(i));
320 Arb_y[i] = ArbEnergyH(size_t(i));
[816]321 }
[1347]322 // Points are now in x,y arrays. If the spectrum is integral it has to be
323 // made differential and if momentum it has to be made energy.
324 if (DiffSpec == false) {
325 // Converts integral point-wise spectra to Differential
326 for (count = 0; count < maxi - 1; count++) {
327 Arb_y[count] = (Arb_y[count] - Arb_y[count + 1])
328 / (Arb_x[count + 1] - Arb_x[count]);
329 }
330 maxi--;
[816]331 }
[1347]332 //
333 if (EnergySpec == false) {
334 // change currently stored values (emin etc) which are actually momenta
335 // to energies.
336 if (particle_definition == NULL)
337 G4cout << "Error: particle not defined" << G4endl;
338 else {
339 // Apply Energy**2 = p**2c**2 + m0**2c**4
340 // p should be entered as E/c i.e. without the division by c
341 // being done - energy equivalent.
342 G4double mass = particle_definition->GetPDGMass();
343 // convert point to energy unit and its value to per energy unit
344 G4double total_energy;
345 for (count = 0; count < maxi; count++) {
346 total_energy = std::sqrt((Arb_x[count] * Arb_x[count]) + (mass
347 * mass)); // total energy
348
349 Arb_y[count] = Arb_y[count] * Arb_x[count] / total_energy;
350 Arb_x[count] = total_energy - mass; // kinetic energy
351 }
352 }
[816]353 }
[1347]354 //
355 i = 1;
356 Arb_grad[0] = 0.;
357 Arb_cept[0] = 0.;
358 Area_seg[0] = 0.;
359 Arb_Cum_Area[0] = 0.;
360 while (i < maxi) {
361 // calc gradient and intercept for each segment
362 Arb_grad[i] = (Arb_y[i] - Arb_y[i - 1]) / (Arb_x[i] - Arb_x[i - 1]);
363 if (verbosityLevel == 2)
364 G4cout << Arb_grad[i] << G4endl;
365 if (Arb_grad[i] > 0.) {
366 if (verbosityLevel == 2)
367 G4cout << "Arb_grad is positive" << G4endl;
368 Arb_cept[i] = Arb_y[i] - (Arb_grad[i] * Arb_x[i]);
369 } else if (Arb_grad[i] < 0.) {
370 if (verbosityLevel == 2)
371 G4cout << "Arb_grad is negative" << G4endl;
372 Arb_cept[i] = Arb_y[i] + (-Arb_grad[i] * Arb_x[i]);
373 } else {
374 if (verbosityLevel == 2)
375 G4cout << "Arb_grad is 0." << G4endl;
376 Arb_cept[i] = Arb_y[i];
377 }
[816]378
[1347]379 Area_seg[i] = ((Arb_grad[i] / 2) * (Arb_x[i] * Arb_x[i] - Arb_x[i - 1]
380 * Arb_x[i - 1]) + Arb_cept[i] * (Arb_x[i] - Arb_x[i - 1]));
381 Arb_Cum_Area[i] = Arb_Cum_Area[i - 1] + Area_seg[i];
382 sum = sum + Area_seg[i];
383 if (verbosityLevel == 2)
384 G4cout << Arb_x[i] << Arb_y[i] << Area_seg[i] << sum << Arb_grad[i]
385 << G4endl;
386 i++;
387 }
[816]388
[1347]389 i = 0;
390 while (i < maxi) {
391 Arb_Cum_Area[i] = Arb_Cum_Area[i] / sum; // normalisation
392 IPDFArbEnergyH.InsertValues(Arb_x[i], Arb_Cum_Area[i]);
393 i++;
394 }
[816]395
[1347]396 // now scale the ArbEnergyH, needed by Probability()
397 ArbEnergyH.ScaleVector(1., 1./sum);
398
399 if (verbosityLevel >= 1) {
400 G4cout << "Leaving LinearInterpolation" << G4endl;
401 ArbEnergyH.DumpValues();
402 IPDFArbEnergyH.DumpValues();
403 }
[816]404}
405
[1347]406void G4SPSEneDistribution::LogInterpolation() {
407 // Interpolation based on Logarithmic equations
408 // Generate equations of line segments
409 // y = Ax**alpha => log y = alpha*logx + logA
410 // Find area under line segments
411 // create normalised, cumulative array Arb_Cum_Area
412 G4double Area_seg[1024]; // Stores area under each segment
413 G4double sum = 0., Arb_x[1024], Arb_y[1024], Arb_Cum_Area[1024];
414 G4int i, count;
415 G4int maxi = ArbEnergyH.GetVectorLength();
416 for (i = 0; i < maxi; i++) {
417 Arb_x[i] = ArbEnergyH.GetLowEdgeEnergy(size_t(i));
418 Arb_y[i] = ArbEnergyH(size_t(i));
419 }
420 // Points are now in x,y arrays. If the spectrum is integral it has to be
421 // made differential and if momentum it has to be made energy.
422 if (DiffSpec == false) {
423 // Converts integral point-wise spectra to Differential
424 for (count = 0; count < maxi - 1; count++) {
425 Arb_y[count] = (Arb_y[count] - Arb_y[count + 1])
426 / (Arb_x[count + 1] - Arb_x[count]);
427 }
428 maxi--;
429 }
430 //
431 if (EnergySpec == false) {
432 // change currently stored values (emin etc) which are actually momenta
433 // to energies.
434 if (particle_definition == NULL)
435 G4cout << "Error: particle not defined" << G4endl;
436 else {
437 // Apply Energy**2 = p**2c**2 + m0**2c**4
438 // p should be entered as E/c i.e. without the division by c
439 // being done - energy equivalent.
440 G4double mass = particle_definition->GetPDGMass();
441 // convert point to energy unit and its value to per energy unit
442 G4double total_energy;
443 for (count = 0; count < maxi; count++) {
444 total_energy = std::sqrt((Arb_x[count] * Arb_x[count]) + (mass
445 * mass)); // total energy
[816]446
[1347]447 Arb_y[count] = Arb_y[count] * Arb_x[count] / total_energy;
448 Arb_x[count] = total_energy - mass; // kinetic energy
449 }
450 }
[816]451 }
[1347]452 //
453 i = 1;
454 Arb_alpha[0] = 0.;
455 Arb_Const[0] = 0.;
456 Area_seg[0] = 0.;
457 Arb_Cum_Area[0] = 0.;
458 if (Arb_x[0] <= 0. || Arb_y[0] <= 0.) {
459 G4cout << "You should not use log interpolation with points <= 0."
460 << G4endl;
461 G4cout << "These will be changed to 1e-20, which may cause problems"
462 << G4endl;
463 if (Arb_x[0] <= 0.)
464 Arb_x[0] = 1e-20;
465 if (Arb_y[0] <= 0.)
466 Arb_y[0] = 1e-20;
467 }
[816]468
[1347]469 G4double alp;
470 while (i < maxi) {
471 // Incase points are negative or zero
472 if (Arb_x[i] <= 0. || Arb_y[i] <= 0.) {
473 G4cout << "You should not use log interpolation with points <= 0."
474 << G4endl;
475 G4cout
476 << "These will be changed to 1e-20, which may cause problems"
477 << G4endl;
478 if (Arb_x[i] <= 0.)
479 Arb_x[i] = 1e-20;
480 if (Arb_y[i] <= 0.)
481 Arb_y[i] = 1e-20;
482 }
483
484 Arb_alpha[i] = (std::log10(Arb_y[i]) - std::log10(Arb_y[i - 1]))
485 / (std::log10(Arb_x[i]) - std::log10(Arb_x[i - 1]));
486 Arb_Const[i] = Arb_y[i] / (std::pow(Arb_x[i], Arb_alpha[i]));
487 alp = Arb_alpha[i] + 1;
488 if (alp == 0.) {
489 Area_seg[i] = Arb_Const[i] * (std::log(Arb_x[i]) - std::log(Arb_x[i - 1]));
490 } else {
491 Area_seg[i] = (Arb_Const[i] / alp) * (std::pow(Arb_x[i], alp)
492 - std::pow(Arb_x[i - 1], alp));
493 }
494 sum = sum + Area_seg[i];
495 Arb_Cum_Area[i] = Arb_Cum_Area[i - 1] + Area_seg[i];
496 if (verbosityLevel == 2)
497 G4cout << Arb_alpha[i] << Arb_Const[i] << Area_seg[i] << G4endl;
498 i++;
499 }
500
501 i = 0;
502 while (i < maxi) {
503 Arb_Cum_Area[i] = Arb_Cum_Area[i] / sum;
504 IPDFArbEnergyH.InsertValues(Arb_x[i], Arb_Cum_Area[i]);
505 i++;
506 }
507
508 // now scale the ArbEnergyH, needed by Probability()
509 ArbEnergyH.ScaleVector(1., 1./sum);
510
511 if (verbosityLevel >= 1)
512 G4cout << "Leaving LogInterpolation " << G4endl;
[816]513}
514
[1347]515void G4SPSEneDistribution::ExpInterpolation() {
516 // Interpolation based on Exponential equations
517 // Generate equations of line segments
518 // y = Ae**-(x/e0) => ln y = -x/e0 + lnA
519 // Find area under line segments
520 // create normalised, cumulative array Arb_Cum_Area
521 G4double Area_seg[1024]; // Stores area under each segment
522 G4double sum = 0., Arb_x[1024], Arb_y[1024], Arb_Cum_Area[1024];
523 G4int i, count;
524 G4int maxi = ArbEnergyH.GetVectorLength();
525 for (i = 0; i < maxi; i++) {
526 Arb_x[i] = ArbEnergyH.GetLowEdgeEnergy(size_t(i));
527 Arb_y[i] = ArbEnergyH(size_t(i));
[816]528 }
[1347]529 // Points are now in x,y arrays. If the spectrum is integral it has to be
530 // made differential and if momentum it has to be made energy.
531 if (DiffSpec == false) {
532 // Converts integral point-wise spectra to Differential
533 for (count = 0; count < maxi - 1; count++) {
534 Arb_y[count] = (Arb_y[count] - Arb_y[count + 1])
535 / (Arb_x[count + 1] - Arb_x[count]);
536 }
537 maxi--;
[816]538 }
[1347]539 //
540 if (EnergySpec == false) {
541 // change currently stored values (emin etc) which are actually momenta
542 // to energies.
543 if (particle_definition == NULL)
544 G4cout << "Error: particle not defined" << G4endl;
545 else {
546 // Apply Energy**2 = p**2c**2 + m0**2c**4
547 // p should be entered as E/c i.e. without the division by c
548 // being done - energy equivalent.
549 G4double mass = particle_definition->GetPDGMass();
550 // convert point to energy unit and its value to per energy unit
551 G4double total_energy;
552 for (count = 0; count < maxi; count++) {
553 total_energy = std::sqrt((Arb_x[count] * Arb_x[count]) + (mass
554 * mass)); // total energy
555
556 Arb_y[count] = Arb_y[count] * Arb_x[count] / total_energy;
557 Arb_x[count] = total_energy - mass; // kinetic energy
558 }
559 }
560 }
561 //
562 i = 1;
563 Arb_ezero[0] = 0.;
564 Arb_Const[0] = 0.;
565 Area_seg[0] = 0.;
566 Arb_Cum_Area[0] = 0.;
567 while (i < maxi) {
568 G4double test = std::log(Arb_y[i]) - std::log(Arb_y[i - 1]);
569 if (test > 0. || test < 0.) {
570 Arb_ezero[i] = -(Arb_x[i] - Arb_x[i - 1]) / (std::log(Arb_y[i])
571 - std::log(Arb_y[i - 1]));
572 Arb_Const[i] = Arb_y[i] / (std::exp(-Arb_x[i] / Arb_ezero[i]));
573 Area_seg[i] = -(Arb_Const[i] * Arb_ezero[i]) * (std::exp(-Arb_x[i]
574 / Arb_ezero[i]) - std::exp(-Arb_x[i - 1] / Arb_ezero[i]));
575 } else {
576 G4cout << "Flat line segment: problem" << G4endl;
577 Arb_ezero[i] = 0.;
578 Arb_Const[i] = 0.;
579 Area_seg[i] = 0.;
580 }
581 sum = sum + Area_seg[i];
582 Arb_Cum_Area[i] = Arb_Cum_Area[i - 1] + Area_seg[i];
583 if (verbosityLevel == 2)
584 G4cout << Arb_ezero[i] << Arb_Const[i] << Area_seg[i] << G4endl;
585 i++;
586 }
587
588 i = 0;
589 while (i < maxi) {
590 Arb_Cum_Area[i] = Arb_Cum_Area[i] / sum;
591 IPDFArbEnergyH.InsertValues(Arb_x[i], Arb_Cum_Area[i]);
592 i++;
593 }
594
595 // now scale the ArbEnergyH, needed by Probability()
596 ArbEnergyH.ScaleVector(1., 1./sum);
597
598 if (verbosityLevel >= 1)
599 G4cout << "Leaving ExpInterpolation " << G4endl;
[816]600}
601
[1347]602void G4SPSEneDistribution::SplineInterpolation() {
603 // Interpolation using Splines.
604 // Create Normalised arrays, make x 0->1 and y hold
605 // the function (Energy)
606 //
607 // Current method based on the above will not work in all cases.
608 // new method is implemented below.
609
610 G4double sum, Arb_x[1024], Arb_y[1024], Arb_Cum_Area[1024];
611 G4int i, count;
[816]612
[1347]613 G4int maxi = ArbEnergyH.GetVectorLength();
614 for (i = 0; i < maxi; i++) {
615 Arb_x[i] = ArbEnergyH.GetLowEdgeEnergy(size_t(i));
616 Arb_y[i] = ArbEnergyH(size_t(i));
617 }
618 // Points are now in x,y arrays. If the spectrum is integral it has to be
619 // made differential and if momentum it has to be made energy.
620 if (DiffSpec == false) {
621 // Converts integral point-wise spectra to Differential
622 for (count = 0; count < maxi - 1; count++) {
623 Arb_y[count] = (Arb_y[count] - Arb_y[count + 1])
624 / (Arb_x[count + 1] - Arb_x[count]);
625 }
626 maxi--;
627 }
628 //
629 if (EnergySpec == false) {
630 // change currently stored values (emin etc) which are actually momenta
631 // to energies.
632 if (particle_definition == NULL)
633 G4cout << "Error: particle not defined" << G4endl;
634 else {
635 // Apply Energy**2 = p**2c**2 + m0**2c**4
636 // p should be entered as E/c i.e. without the division by c
637 // being done - energy equivalent.
638 G4double mass = particle_definition->GetPDGMass();
639 // convert point to energy unit and its value to per energy unit
640 G4double total_energy;
641 for (count = 0; count < maxi; count++) {
642 total_energy = std::sqrt((Arb_x[count] * Arb_x[count]) + (mass
643 * mass)); // total energy
644
645 Arb_y[count] = Arb_y[count] * Arb_x[count] / total_energy;
646 Arb_x[count] = total_energy - mass; // kinetic energy
647 }
648 }
649 }
650
651 //
652 i = 1;
653 Arb_Cum_Area[0] = 0.;
654 sum = 0.;
655 Splinetemp = new G4DataInterpolation(Arb_x, Arb_y, maxi, 0., 0.);
656 G4double ei[101],prob[101];
657 while (i < maxi) {
658 // 100 step per segment for the integration of area
659 G4double de = (Arb_x[i] - Arb_x[i - 1])/100.;
660 G4double area = 0.;
661
662 for (count = 0; count < 101; count++) {
663 ei[count] = Arb_x[i - 1] + de*count ;
664 prob[count] = Splinetemp->CubicSplineInterpolation(ei[count]);
665 if (prob[count] < 0.) {
666 G4cout << "Warning: G4DataInterpolation returns value < 0 " << prob[count] <<" "<<ei[count]<< G4endl;
667 G4Exception(" Please use an alternative method, e.g. Lin, for interpolation");
668 }
669 area += prob[count]*de;
670 }
671 Arb_Cum_Area[i] = Arb_Cum_Area[i - 1] + area;
672 sum += area;
673
674 prob[0] = prob[0]/(area/de);
675 for (count = 1; count < 100; count++)
676 prob[count] = prob[count-1] + prob[count]/(area/de);
677
678 SplineInt[i] = new G4DataInterpolation(prob, ei, 101, 0., 0.);
679 // note i start from 1!
680 i++;
681 }
682 i = 0;
683 while (i < maxi) {
684 Arb_Cum_Area[i] = Arb_Cum_Area[i] / sum; // normalisation
685 IPDFArbEnergyH.InsertValues(Arb_x[i], Arb_Cum_Area[i]);
686 i++;
687 }
688 // now scale the ArbEnergyH, needed by Probability()
689 ArbEnergyH.ScaleVector(1., 1./sum);
690
691 if (verbosityLevel > 0)
692 G4cout << "Leaving SplineInterpolation " << G4endl;
[816]693}
694
[1347]695void G4SPSEneDistribution::GenerateMonoEnergetic() {
696 // Method to generate MonoEnergetic particles.
697 particle_energy = MonoEnergy;
[816]698}
699
[1347]700void G4SPSEneDistribution::GenerateGaussEnergies() {
701 // Method to generate Gaussian particles.
702 particle_energy = G4RandGauss::shoot(MonoEnergy,SE);
703 if (particle_energy < 0) particle_energy = 0.;
[816]704}
705
[1347]706void G4SPSEneDistribution::GenerateLinearEnergies(G4bool bArb = false) {
707 G4double rndm;
708 G4double emaxsq = std::pow(Emax, 2.); //Emax squared
709 G4double eminsq = std::pow(Emin, 2.); //Emin squared
710 G4double intersq = std::pow(cept, 2.); //cept squared
[816]711
[1347]712 if (bArb)
713 rndm = G4UniformRand();
714 else
715 rndm = eneRndm->GenRandEnergy();
[816]716
[1347]717 G4double bracket = ((grad / 2.) * (emaxsq - eminsq) + cept * (Emax - Emin));
718 bracket = bracket * rndm;
719 bracket = bracket + (grad / 2.) * eminsq + cept * Emin;
720 // Now have a quad of form m/2 E**2 + cE - bracket = 0
721 bracket = -bracket;
722 // G4cout << "BRACKET" << bracket << G4endl;
723 if (grad != 0.) {
724 G4double sqbrack = (intersq - 4 * (grad / 2.) * (bracket));
725 // G4cout << "SQBRACK" << sqbrack << G4endl;
726 sqbrack = std::sqrt(sqbrack);
727 G4double root1 = -cept + sqbrack;
728 root1 = root1 / (2. * (grad / 2.));
[816]729
[1347]730 G4double root2 = -cept - sqbrack;
731 root2 = root2 / (2. * (grad / 2.));
[816]732
[1347]733 // G4cout << root1 << " roots " << root2 << G4endl;
734
735 if (root1 > Emin && root1 < Emax)
736 particle_energy = root1;
737 if (root2 > Emin && root2 < Emax)
738 particle_energy = root2;
739 } else if (grad == 0.)
740 // have equation of form cE - bracket =0
741 particle_energy = bracket / cept;
742
743 if (particle_energy < 0.)
744 particle_energy = -particle_energy;
745
746 if (verbosityLevel >= 1)
747 G4cout << "Energy is " << particle_energy << G4endl;
[816]748}
749
[1347]750void G4SPSEneDistribution::GeneratePowEnergies(G4bool bArb = false) {
751 // Method to generate particle energies distributed as
752 // a power-law
[816]753
[1347]754 G4double rndm;
755 G4double emina, emaxa;
[816]756
[1347]757 emina = std::pow(Emin, alpha + 1);
758 emaxa = std::pow(Emax, alpha + 1);
[816]759
[1347]760 if (bArb)
761 rndm = G4UniformRand();
762 else
763 rndm = eneRndm->GenRandEnergy();
764
765 if (alpha != -1.) {
766 particle_energy = ((rndm * (emaxa - emina)) + emina);
767 particle_energy = std::pow(particle_energy, (1. / (alpha + 1.)));
768 } else {
769 particle_energy = (std::log(Emin) + rndm * (std::log(Emax) - std::log(
770 Emin)));
771 particle_energy = std::exp(particle_energy);
772 }
773 if (verbosityLevel >= 1)
774 G4cout << "Energy is " << particle_energy << G4endl;
[816]775}
776
[1347]777void G4SPSEneDistribution::GenerateBiasPowEnergies() {
778 // Method to generate particle energies distributed as
779 // in biased power-law and calculate its weight
[816]780
[1347]781 G4double rndm;
782 G4double emina, emaxa, emin, emax;
783
784 G4double normal = 1. ;
785
786 emin = Emin;
787 emax = Emax;
788 // if (EnergyDisType == "Arb") {
789 // emin = ArbEmin;
790 // emax = ArbEmax;
791 //}
792
793 rndm = eneRndm->GenRandEnergy();
794
795 if (biasalpha != -1.) {
796 emina = std::pow(emin, biasalpha + 1);
797 emaxa = std::pow(emax, biasalpha + 1);
798 particle_energy = ((rndm * (emaxa - emina)) + emina);
799 particle_energy = std::pow(particle_energy, (1. / (biasalpha + 1.)));
800 normal = 1./(1+biasalpha) * (emaxa - emina);
801 } else {
802 particle_energy = (std::log(emin) + rndm * (std::log(emax) - std::log(
803 emin)));
804 particle_energy = std::exp(particle_energy);
805 normal = std::log(emax) - std::log(emin) ;
806 }
807 weight = GetProbability(particle_energy) / (std::pow(particle_energy,biasalpha)/normal);
808
809 if (verbosityLevel >= 1)
810 G4cout << "Energy is " << particle_energy << G4endl;
[816]811}
812
[1347]813void G4SPSEneDistribution::GenerateExpEnergies(G4bool bArb = false) {
814 // Method to generate particle energies distributed according
815 // to an exponential curve.
816 G4double rndm;
[816]817
[1347]818 if (bArb)
819 rndm = G4UniformRand();
820 else
821 rndm = eneRndm->GenRandEnergy();
[816]822
[1347]823 particle_energy = -Ezero * (std::log(rndm * (std::exp(-Emax / Ezero)
824 - std::exp(-Emin / Ezero)) + std::exp(-Emin / Ezero)));
825 if (verbosityLevel >= 1)
826 G4cout << "Energy is " << particle_energy << G4endl;
827}
[816]828
[1347]829void G4SPSEneDistribution::GenerateBremEnergies() {
830 // Method to generate particle energies distributed according
831 // to a Bremstrahlung equation of
832 // form I = const*((kT)**1/2)*E*(e**(-E/kT))
[816]833
[1347]834 G4double rndm;
835 rndm = eneRndm->GenRandEnergy();
836 G4double expmax, expmin, k;
[816]837
[1347]838 k = 8.6181e-11; // Boltzmann's const in MeV/K
839 G4double ksq = std::pow(k, 2.); // k squared
840 G4double Tsq = std::pow(Temp, 2.); // Temp squared
[816]841
[1347]842 expmax = std::exp(-Emax / (k * Temp));
843 expmin = std::exp(-Emin / (k * Temp));
[816]844
[1347]845 // If either expmax or expmin are zero then this will cause problems
846 // Most probably this will be because T is too low or E is too high
[816]847
[1347]848 if (expmax == 0.)
849 G4cout << "*****EXPMAX=0. Choose different E's or Temp" << G4endl;
850 if (expmin == 0.)
851 G4cout << "*****EXPMIN=0. Choose different E's or Temp" << G4endl;
[816]852
[1347]853 G4double tempvar = rndm * ((-k) * Temp * (Emax * expmax - Emin * expmin)
854 - (ksq * Tsq * (expmax - expmin)));
[816]855
[1347]856 G4double bigc = (tempvar - k * Temp * Emin * expmin - ksq * Tsq * expmin)
857 / (-k * Temp);
[816]858
[1347]859 // This gives an equation of form: Ee(-E/kT) + kTe(-E/kT) - C =0
860 // Solve this iteratively, step from Emin to Emax in 1000 steps
861 // and take the best solution.
[816]862
[1347]863 G4double erange = Emax - Emin;
864 G4double steps = erange / 1000.;
865 G4int i;
866 G4double etest, diff, err;
[816]867
[1347]868 err = 100000.;
[816]869
[1347]870 for (i = 1; i < 1000; i++) {
871 etest = Emin + (i - 1) * steps;
[816]872
[1347]873 diff = etest * (std::exp(-etest / (k * Temp))) + k * Temp * (std::exp(
874 -etest / (k * Temp))) - bigc;
[816]875
[1347]876 if (diff < 0.)
877 diff = -diff;
[816]878
[1347]879 if (diff < err) {
880 err = diff;
881 particle_energy = etest;
882 }
883 }
884 if (verbosityLevel >= 1)
885 G4cout << "Energy is " << particle_energy << G4endl;
[816]886}
887
[1347]888void G4SPSEneDistribution::GenerateBbodyEnergies() {
889 // BBody_x holds Energies, and BBHist holds the cumulative histo.
890 // binary search to find correct bin then lin interpolation.
891 // Use the earlier defined histogram + RandGeneral method to generate
892 // random numbers following the histos distribution.
893 G4double rndm;
894 G4int nabove, nbelow = 0, middle;
895 nabove = 10001;
896 rndm = eneRndm->GenRandEnergy();
[816]897
[1347]898 // Binary search to find bin that rndm is in
899 while (nabove - nbelow > 1) {
900 middle = (nabove + nbelow) / 2;
901 if (rndm == BBHist[middle])
902 break;
903 if (rndm < BBHist[middle])
904 nabove = middle;
905 else
906 nbelow = middle;
[816]907 }
908
[1347]909 // Now interpolate in that bin to find the correct output value.
910 G4double x1, x2, y1, y2, m, q;
911 x1 = Bbody_x[nbelow];
912 x2 = Bbody_x[nbelow + 1];
913 y1 = BBHist[nbelow];
914 y2 = BBHist[nbelow + 1];
915 m = (y2 - y1) / (x2 - x1);
916 q = y1 - m * x1;
917
918 particle_energy = (rndm - q) / m;
919
920 if (verbosityLevel >= 1) {
921 G4cout << "Energy is " << particle_energy << G4endl;
[816]922 }
[1347]923}
[816]924
[1347]925void G4SPSEneDistribution::GenerateCdgEnergies() {
926 // Gen random numbers, compare with values in cumhist
927 // to find appropriate part of spectrum and then
928 // generate energy in the usual inversion way.
929 // G4double pfact[2] = {8.5, 112};
930 // G4double spind[2] = {1.4, 2.3};
931 // G4double ene_line[3] = {1., 18., 1E6};
932 G4double rndm, rndm2;
933 G4double ene_line[3];
934 G4double omalpha[2];
935 if (Emin < 18 * keV && Emax < 18 * keV) {
936 omalpha[0] = 1. - 1.4;
937 ene_line[0] = Emin;
938 ene_line[1] = Emax;
[816]939 }
[1347]940 if (Emin < 18 * keV && Emax > 18 * keV) {
941 omalpha[0] = 1. - 1.4;
942 omalpha[1] = 1. - 2.3;
943 ene_line[0] = Emin;
944 ene_line[1] = 18. * keV;
945 ene_line[2] = Emax;
[816]946 }
[1347]947 if (Emin > 18 * keV) {
948 omalpha[0] = 1. - 2.3;
949 ene_line[0] = Emin;
950 ene_line[1] = Emax;
951 }
952 rndm = eneRndm->GenRandEnergy();
953 rndm2 = eneRndm->GenRandEnergy();
954
955 G4int i = 0;
956 while (rndm >= CDGhist[i]) {
957 i++;
958 }
959 // Generate final energy.
960 particle_energy = (std::pow(ene_line[i - 1], omalpha[i - 1]) + (std::pow(
961 ene_line[i], omalpha[i - 1]) - std::pow(ene_line[i - 1], omalpha[i
962 - 1])) * rndm2);
963 particle_energy = std::pow(particle_energy, (1. / omalpha[i - 1]));
964
965 if (verbosityLevel >= 1)
966 G4cout << "Energy is " << particle_energy << G4endl;
[816]967}
968
[1347]969void G4SPSEneDistribution::GenUserHistEnergies() {
970 // Histograms are DIFFERENTIAL.
971 // G4cout << "In GenUserHistEnergies " << G4endl;
972 if (IPDFEnergyExist == false) {
973 G4int ii;
974 G4int maxbin = G4int(UDefEnergyH.GetVectorLength());
975 G4double bins[1024], vals[1024], sum;
976 sum = 0.;
977
978 if ((EnergySpec == false) && (particle_definition == NULL))
979 G4cout << "Error: particle definition is NULL" << G4endl;
980
981 if (maxbin > 1024) {
982 G4cout << "Maxbin > 1024" << G4endl;
983 G4cout << "Setting maxbin to 1024, other bins are lost" << G4endl;
984 }
985
986 if (DiffSpec == false)
987 G4cout << "Histograms are Differential!!! " << G4endl;
988 else {
989 bins[0] = UDefEnergyH.GetLowEdgeEnergy(size_t(0));
990 vals[0] = UDefEnergyH(size_t(0));
991 sum = vals[0];
992 for (ii = 1; ii < maxbin; ii++) {
993 bins[ii] = UDefEnergyH.GetLowEdgeEnergy(size_t(ii));
994 vals[ii] = UDefEnergyH(size_t(ii)) + vals[ii - 1];
995 sum = sum + UDefEnergyH(size_t(ii));
996 }
997 }
998
999 if (EnergySpec == false) {
1000 G4double mass = particle_definition->GetPDGMass();
1001 // multiply the function (vals) up by the bin width
1002 // to make the function counts/s (i.e. get rid of momentum
1003 // dependence).
1004 for (ii = 1; ii < maxbin; ii++) {
1005 vals[ii] = vals[ii] * (bins[ii] - bins[ii - 1]);
1006 }
1007 // Put energy bins into new histo, plus divide by energy bin width
1008 // to make evals counts/s/energy
1009 for (ii = 0; ii < maxbin; ii++) {
1010 bins[ii] = std::sqrt((bins[ii] * bins[ii]) + (mass * mass))
1011 - mass; //kinetic energy
1012 }
1013 for (ii = 1; ii < maxbin; ii++) {
1014 vals[ii] = vals[ii] / (bins[ii] - bins[ii - 1]);
1015 }
1016 sum = vals[maxbin - 1];
1017 vals[0] = 0.;
1018 }
1019 for (ii = 0; ii < maxbin; ii++) {
1020 vals[ii] = vals[ii] / sum;
1021 IPDFEnergyH.InsertValues(bins[ii], vals[ii]);
1022 }
1023
1024 // Make IPDFEnergyExist = true
1025 IPDFEnergyExist = true;
1026 if (verbosityLevel > 1)
1027 IPDFEnergyH.DumpValues();
[816]1028 }
[1347]1029
1030 // IPDF has been create so carry on
1031 G4double rndm = eneRndm->GenRandEnergy();
1032 particle_energy = IPDFEnergyH.GetEnergy(rndm);
1033
1034 if (verbosityLevel >= 1)
1035 G4cout << "Energy is " << particle_energy << G4endl;
1036}
1037
1038void G4SPSEneDistribution::GenArbPointEnergies() {
1039 if (verbosityLevel > 0)
1040 G4cout << "In GenArbPointEnergies" << G4endl;
1041 G4double rndm;
1042 rndm = eneRndm->GenRandEnergy();
1043 // IPDFArbEnergyH.DumpValues();
1044 // Find the Bin
1045 // have x, y, no of points, and cumulative area distribution
1046 G4int nabove, nbelow = 0, middle;
1047 nabove = IPDFArbEnergyH.GetVectorLength();
1048 // G4cout << nabove << G4endl;
1049 // Binary search to find bin that rndm is in
1050 while (nabove - nbelow > 1) {
1051 middle = (nabove + nbelow) / 2;
1052 if (rndm == IPDFArbEnergyH(size_t(middle)))
1053 break;
1054 if (rndm < IPDFArbEnergyH(size_t(middle)))
1055 nabove = middle;
1056 else
1057 nbelow = middle;
1058 }
1059 if (IntType == "Lin") {
1060 Emax = IPDFArbEnergyH.GetLowEdgeEnergy(size_t(nbelow + 1));
[816]1061 Emin = IPDFArbEnergyH.GetLowEdgeEnergy(size_t(nbelow));
[1347]1062 grad = Arb_grad[nbelow + 1];
1063 cept = Arb_cept[nbelow + 1];
[816]1064 // G4cout << rndm << " " << Emax << " " << Emin << " " << grad << " " << cept << G4endl;
1065 GenerateLinearEnergies(true);
[1347]1066 } else if (IntType == "Log") {
1067 Emax = IPDFArbEnergyH.GetLowEdgeEnergy(size_t(nbelow + 1));
[816]1068 Emin = IPDFArbEnergyH.GetLowEdgeEnergy(size_t(nbelow));
[1347]1069 alpha = Arb_alpha[nbelow + 1];
[816]1070 // G4cout << rndm << " " << Emax << " " << Emin << " " << alpha << G4endl;
1071 GeneratePowEnergies(true);
[1347]1072 } else if (IntType == "Exp") {
1073 Emax = IPDFArbEnergyH.GetLowEdgeEnergy(size_t(nbelow + 1));
[816]1074 Emin = IPDFArbEnergyH.GetLowEdgeEnergy(size_t(nbelow));
[1347]1075 Ezero = Arb_ezero[nbelow + 1];
[816]1076 // G4cout << rndm << " " << Emax << " " << Emin << " " << Ezero << G4endl;
1077 GenerateExpEnergies(true);
[1347]1078 } else if (IntType == "Spline") {
1079 Emax = IPDFArbEnergyH.GetLowEdgeEnergy(size_t(nbelow + 1));
1080 Emin = IPDFArbEnergyH.GetLowEdgeEnergy(size_t(nbelow));
1081 particle_energy = -1e100;
1082 rndm = eneRndm->GenRandEnergy();
1083 while (particle_energy < Emin || particle_energy > Emax) {
1084 particle_energy = SplineInt[nbelow+1]->CubicSplineInterpolation(rndm);
1085 rndm = eneRndm->GenRandEnergy();
1086 }
1087 if (verbosityLevel >= 1)
1088 G4cout << "Energy is " << particle_energy << G4endl;
1089 } else
1090 G4cout << "Error: IntType unknown type" << G4endl;
[816]1091}
1092
[1347]1093void G4SPSEneDistribution::GenEpnHistEnergies() {
1094 // G4cout << "In GenEpnHistEnergies " << Epnflag << G4endl;
[816]1095
[1347]1096 // Firstly convert to energy if not already done.
1097 if (Epnflag == true)
1098 // epnflag = true means spectrum is epn, false means e.
[816]1099 {
[1347]1100 // convert to energy by multiplying by A number
1101 ConvertEPNToEnergy();
1102 // EpnEnergyH will be replace by UDefEnergyH.
1103 // UDefEnergyH.DumpValues();
[816]1104 }
[1347]1105
1106 // G4cout << "Creating IPDFEnergy if not already done so" << G4endl;
1107 if (IPDFEnergyExist == false) {
1108 // IPDF has not been created, so create it
1109 G4double bins[1024], vals[1024], sum;
1110 G4int ii;
1111 G4int maxbin = G4int(UDefEnergyH.GetVectorLength());
1112 bins[0] = UDefEnergyH.GetLowEdgeEnergy(size_t(0));
1113 vals[0] = UDefEnergyH(size_t(0));
1114 sum = vals[0];
1115 for (ii = 1; ii < maxbin; ii++) {
1116 bins[ii] = UDefEnergyH.GetLowEdgeEnergy(size_t(ii));
1117 vals[ii] = UDefEnergyH(size_t(ii)) + vals[ii - 1];
1118 sum = sum + UDefEnergyH(size_t(ii));
1119 }
1120
1121 for (ii = 0; ii < maxbin; ii++) {
1122 vals[ii] = vals[ii] / sum;
1123 IPDFEnergyH.InsertValues(bins[ii], vals[ii]);
1124 }
1125 // Make IPDFEpnExist = true
1126 IPDFEnergyExist = true;
[816]1127 }
[1347]1128 // IPDFEnergyH.DumpValues();
1129 // IPDF has been create so carry on
1130 G4double rndm = eneRndm->GenRandEnergy();
1131 particle_energy = IPDFEnergyH.GetEnergy(rndm);
[816]1132
[1347]1133 if (verbosityLevel >= 1)
1134 G4cout << "Energy is " << particle_energy << G4endl;
[816]1135}
1136
[1347]1137void G4SPSEneDistribution::ConvertEPNToEnergy() {
1138 // Use this before particle generation to convert the
1139 // currently stored histogram from energy/nucleon
1140 // to energy.
1141 // G4cout << "In ConvertEpntoEnergy " << G4endl;
1142 if (particle_definition == NULL)
1143 G4cout << "Error: particle not defined" << G4endl;
1144 else {
1145 // Need to multiply histogram by the number of nucleons.
1146 // Baryon Number looks to hold the no. of nucleons.
1147 G4int Bary = particle_definition->GetBaryonNumber();
1148 // G4cout << "Baryon No. " << Bary << G4endl;
1149 // Change values in histogram, Read it out, delete it, re-create it
1150 G4int count, maxcount;
1151 maxcount = G4int(EpnEnergyH.GetVectorLength());
1152 // G4cout << maxcount << G4endl;
1153 G4double ebins[1024], evals[1024];
1154 if (maxcount > 1024) {
1155 G4cout << "Histogram contains more than 1024 bins!" << G4endl;
1156 G4cout << "Those above 1024 will be ignored" << G4endl;
1157 maxcount = 1024;
1158 }
1159 if (maxcount < 1) {
1160 G4cout << "Histogram contains less than 1 bin!" << G4endl;
1161 G4cout << "Redefine the histogram" << G4endl;
1162 return;
1163 }
1164 for (count = 0; count < maxcount; count++) {
1165 // Read out
1166 ebins[count] = EpnEnergyH.GetLowEdgeEnergy(size_t(count));
1167 evals[count] = EpnEnergyH(size_t(count));
1168 }
[816]1169
[1347]1170 // Multiply the channels by the nucleon number to give energies
1171 for (count = 0; count < maxcount; count++) {
1172 ebins[count] = ebins[count] * Bary;
1173 }
[816]1174
[1347]1175 // Set Emin and Emax
1176 Emin = ebins[0];
1177 if (maxcount > 1)
1178 Emax = ebins[maxcount - 1];
1179 else
1180 Emax = ebins[0];
1181 // Put energy bins into new histogram - UDefEnergyH.
1182 for (count = 0; count < maxcount; count++) {
1183 UDefEnergyH.InsertValues(ebins[count], evals[count]);
1184 }
1185 Epnflag = false; //so that you dont repeat this method.
[816]1186 }
1187}
1188
1189//
[1347]1190void G4SPSEneDistribution::ReSetHist(G4String atype) {
1191 if (atype == "energy") {
1192 UDefEnergyH = IPDFEnergyH = ZeroPhysVector;
1193 IPDFEnergyExist = false;
1194 Emin = 0.;
1195 Emax = 1e30;
1196 } else if (atype == "arb") {
1197 ArbEnergyH = IPDFArbEnergyH = ZeroPhysVector;
1198 IPDFArbExist = false;
1199 } else if (atype == "epn") {
1200 UDefEnergyH = IPDFEnergyH = ZeroPhysVector;
1201 IPDFEnergyExist = false;
1202 EpnEnergyH = ZeroPhysVector;
1203 } else {
1204 G4cout << "Error, histtype not accepted " << G4endl;
1205 }
[816]1206}
1207
[1347]1208G4double G4SPSEneDistribution::GenerateOne(G4ParticleDefinition* a) {
1209 particle_definition = a;
1210 particle_energy = -1.;
1211
1212 while ((EnergyDisType == "Arb") ? (particle_energy < ArbEmin
1213 || particle_energy > ArbEmax) : (particle_energy < Emin
1214 || particle_energy > Emax)) {
1215 if (Biased) {
1216 GenerateBiasPowEnergies();
1217 } else {
1218 if (EnergyDisType == "Mono")
1219 GenerateMonoEnergetic();
1220 else if (EnergyDisType == "Lin")
1221 GenerateLinearEnergies();
1222 else if (EnergyDisType == "Pow")
1223 GeneratePowEnergies();
1224 else if (EnergyDisType == "Exp")
1225 GenerateExpEnergies();
1226 else if (EnergyDisType == "Gauss")
1227 GenerateGaussEnergies();
1228 else if (EnergyDisType == "Brem")
1229 GenerateBremEnergies();
1230 else if (EnergyDisType == "Bbody")
1231 GenerateBbodyEnergies();
1232 else if (EnergyDisType == "Cdg")
1233 GenerateCdgEnergies();
1234 else if (EnergyDisType == "User")
1235 GenUserHistEnergies();
1236 else if (EnergyDisType == "Arb")
1237 GenArbPointEnergies();
1238 else if (EnergyDisType == "Epn")
1239 GenEpnHistEnergies();
1240 else
1241 G4cout << "Error: EnergyDisType has unusual value" << G4endl;
1242 }
1243 }
1244 return particle_energy;
[816]1245}
1246
[1347]1247G4double G4SPSEneDistribution::GetProbability(G4double ene) {
1248 G4double prob = 1.;
[816]1249
[1347]1250 if (EnergyDisType == "Lin") {
1251 if (prob_norm == 1.) {
1252 prob_norm = 0.5*grad*Emax*Emax + cept*Emax - 0.5*grad*Emin*Emin - cept*Emin;
1253 }
1254 prob = cept + grad * ene;
1255 prob /= prob_norm;
1256 }
1257 else if (EnergyDisType == "Pow") {
1258 if (prob_norm == 1.) {
1259 if (alpha != -1.) {
1260 G4double emina = std::pow(Emin, alpha + 1);
1261 G4double emaxa = std::pow(Emax, alpha + 1);
1262 prob_norm = 1./(1.+alpha) * (emaxa - emina);
1263 } else {
1264 prob_norm = std::log(Emax) - std::log(Emin) ;
1265 }
1266 }
1267 prob = std::pow(ene, alpha)/prob_norm;
1268 }
1269 else if (EnergyDisType == "Exp"){
1270 if (prob_norm == 1.) {
1271 prob_norm = -Ezero*(std::exp(-Emax/Ezero) - std::exp(Emin/Ezero));
1272 }
1273 prob = std::exp(-ene / Ezero);
1274 prob /= prob_norm;
1275 }
1276 else if (EnergyDisType == "Arb") {
1277 prob = ArbEnergyH.Value(ene);
1278 // prob = ArbEInt->CubicSplineInterpolation(ene);
1279 //G4double deltaY;
1280 //prob = ArbEInt->PolynomInterpolation(ene, deltaY);
1281 if (prob <= 0.) {
1282 //G4cout << " Warning:G4SPSEneDistribution::GetProbability: prob<= 0. "<<prob <<" "<<ene << " " <<deltaY<< G4endl;
1283 G4cout << " Warning:G4SPSEneDistribution::GetProbability: prob<= 0. "<<prob <<" "<<ene << G4endl;
1284 prob = 1e-30;
1285 }
1286 // already normalised
1287 }
1288 else
1289 G4cout << "Error: EnergyDisType not supported" << G4endl;
1290
1291 return prob;
1292}
Note: See TracBrowser for help on using the repository browser.