Geant4 11.3.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4FPYSamplingOps.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/*
27 * File: G4FPYSamplingOps.cc
28 * Author: B. Wendt (wendbryc@isu.edu)
29 *
30 * Created on June 30, 2011, 11:10 AM
31 */
32
33#include "G4FPYSamplingOps.hh"
34
36#include "G4FFGDefaultValues.hh"
37#include "G4FFGEnumerations.hh"
38#include "G4Log.hh"
39#include "G4Pow.hh"
40#include "G4ShiftedGaussian.hh"
42#include "Randomize.hh"
43#include "globals.hh"
44
45#include <CLHEP/Random/Stat.h>
46
47#include <iostream>
48
50{
51 // Set the default verbosity
52 Verbosity_ = G4FFGDefaultValues::Verbosity;
53
54 // Initialize the class
55 Initialize();
56}
57
59{
60 // Set the default verbosity
61 Verbosity_ = Verbosity;
62
63 // Initialize the class
64 Initialize();
65}
66
68{
70
71 // Get the pointer to the random number generator
72 // RandomEngine_ = CLHEP::HepRandom::getTheEngine();
73 RandomEngine_ = G4Random::getTheEngine();
74
75 // Initialize the data members
77 Mean_ = 0;
78 StdDev_ = 0;
80 GaussianOne_ = 0;
81 GaussianTwo_ = 0;
82 Tolerance_ = 0.000001;
84 WattConstants_->Product = 0;
85
87}
88
90{
92
93 // Determine if the parameters have changed
94 G4bool ParametersChanged = (Mean_ != Mean || StdDev_ != StdDev);
95 if (static_cast<int>(ParametersChanged) == TRUE) {
96 // Set the new values if the parameters have changed
98
99 Mean_ = Mean;
100 StdDev_ = StdDev;
101 }
102
103 G4double Sample = SampleGaussian();
104
106 return Sample;
107}
108
111{
113
114 if (Range == G4FFGEnumerations::ALL) {
115 // Call the overloaded function
116 G4double Sample = G4SampleGaussian(Mean, StdDev);
117
119 return Sample;
120 }
121
122 // Determine if the parameters have changed
123 G4bool ParametersChanged = (Mean_ != Mean || StdDev_ != StdDev);
124 if (static_cast<int>(ParametersChanged) == TRUE) {
125 if (Mean <= 0) {
126 std::ostringstream Temp;
127 Temp << "Mean value of " << Mean << " out of range";
128 G4Exception("G4FPYGaussianOps::G4SampleIntegerGaussian()", Temp.str().c_str(), JustWarning,
129 "A value of '0' will be used instead.");
130
132 return 0;
133 }
134
135 // Set the new values if the parameters have changed and then perform
136 // the shift
137 Mean_ = Mean;
138 StdDev_ = StdDev;
139
141 }
142
143 // Sample the Gaussian distribution
144 G4double Rand;
145 do {
146 Rand = SampleGaussian();
147 } while (Rand < 0); // Loop checking, 11.05.2015, T. Koi
148
150 return Rand;
151}
152
154{
156
157 // Determine if the parameters have changed
158 G4bool ParametersChanged = (Mean_ != Mean || StdDev_ != StdDev);
159 if (static_cast<int>(ParametersChanged) == TRUE) {
160 // Set the new values if the parameters have changed
162
163 Mean_ = Mean;
164 StdDev_ = StdDev;
165 }
166
167 // Return the sample integer value
168 auto Sample = (G4int)(std::floor(SampleGaussian()));
169
171 return Sample;
172}
173
176{
178
179 if (Range == G4FFGEnumerations::ALL) {
180 // Call the overloaded function
181 G4int Sample = G4SampleIntegerGaussian(Mean, StdDev);
182
184 return Sample;
185 }
186 // ParameterShift() locks up if the mean is less than 1.
187 std::ostringstream Temp;
188 if (Mean < 1) {
189 // Temp << "Mean value of " << Mean << " out of range";
190 // G4Exception("G4FPYGaussianOps::G4SampleIntegerGaussian()",
191 // Temp.str().c_str(),
192 // JustWarning,
193 // "A value of '0' will be used instead.");
194
195 // return 0;
196 }
197
198 if (Mean / StdDev < 2) {
199 // Temp << "Non-ideal conditions:\tMean:" << Mean << "\tStdDev: "
200 // << StdDev;
201 // G4Exception("G4FPYGaussianOps::G4SampleIntegerGaussian()",
202 // Temp.str().c_str(),
203 // JustWarning,
204 // "Results not guaranteed: Consider tightening the standard deviation");
205 }
206
207 // Determine if the parameters have changed
208 G4bool ParametersChanged = (Mean_ != Mean || StdDev_ != StdDev);
209 if (static_cast<int>(ParametersChanged) == TRUE) {
210 // Set the new values if the parameters have changed and then perform
211 // the shift
212 Mean_ = Mean;
213 StdDev_ = StdDev;
214
216 }
217
218 G4int RandInt;
219 // Sample the Gaussian distribution - only non-negative values are
220 // accepted
221 do {
222 RandInt = (G4int)floor(SampleGaussian());
223 } while (RandInt < 0); // Loop checking, 11.05.2015, T. Koi
224
226 return RandInt;
227}
228
238
240{
242
243 // Calculate the difference
244 G4double Difference = Upper - Lower;
245
246 // Scale appropriately and return the value
247 G4double Sample = G4SampleUniform() * Difference + Lower;
248
250 return Sample;
251}
252
255 G4double WhatEnergy)
256{
258
259 // Determine if the parameters are different
260 // TK modified 131108
261 // if(WattConstants_->Product != WhatIsotope
262 if (WattConstants_->Product != WhatIsotope / 10 || WattConstants_->Cause != WhatCause
263 || WattConstants_->Energy != WhatEnergy)
264 {
265 // If the parameters are different or have not yet been defined then we
266 // need to re-evaluate the constants
267 // TK modified 131108
268 // WattConstants_->Product = WhatIsotope;
269 WattConstants_->Product = WhatIsotope / 10;
270 WattConstants_->Cause = WhatCause;
271 WattConstants_->Energy = WhatEnergy;
272
274 }
275
278 G4int icounter = 0;
279 G4int icounter_max = 1024;
280 while (G4Pow::GetInstance()->powN(Y - WattConstants_->M * (X + 1), 2)
281 > WattConstants_->B * WattConstants_->L * X) // Loop checking, 11.05.2015, T. Koi
282 {
283 icounter++;
284 if (icounter > icounter_max) {
285 G4cout << "Loop-counter exceeded the threshold value at " << __LINE__ << "th line of "
286 << __FILE__ << "." << G4endl;
287 break;
288 }
289 X = -G4Log(G4SampleUniform());
290 Y = -G4Log(G4SampleUniform());
291 }
292
294 return WattConstants_->L * X;
295}
296
307
309{
311
312 G4double ShiftedMean = ShiftedGaussianValues_->G4FindShiftedMean(Mean_, StdDev_);
313 if (ShiftedMean == 0) {
315 return FALSE;
316 }
317
318 Mean_ = ShiftedMean;
319
321 return TRUE;
322}
323
325{
327
328 G4double A, K;
329 A = K = 0;
330 // Use the default values if IsotopeIndex is not reset
331 G4int IsotopeIndex = 0;
332
334 // Determine if the isotope requested exists in the lookup tables
335 for (G4int i = 0; SpontaneousWattIsotopesIndex[i] != -1; i++) {
336 if (SpontaneousWattIsotopesIndex[i] == WattConstants_->Product) {
337 IsotopeIndex = i;
338
339 break;
340 }
341 }
342
343 // Get A and B
344 A = SpontaneousWattConstants[IsotopeIndex][0];
345 WattConstants_->B = SpontaneousWattConstants[IsotopeIndex][1];
346 }
348 // Determine if the isotope requested exists in the lookup tables
349 for (G4int i = 0; NeutronInducedWattIsotopesIndex[i] != -1; i++) {
350 if (NeutronInducedWattIsotopesIndex[i] == WattConstants_->Product) {
351 IsotopeIndex = i;
352 break;
353 }
354 }
355
356 // Determine the Watt fission spectrum constants based on the energy of
357 // the incident neutron
358 if (WattConstants_->Energy == G4FFGDefaultValues::ThermalNeutronEnergy) {
359 A = NeutronInducedWattConstants[IsotopeIndex][0][0];
360 WattConstants_->B = NeutronInducedWattConstants[IsotopeIndex][0][1];
361 }
362 else if (WattConstants_->Energy > 14.0 * CLHEP::MeV) {
363 G4Exception("G4FPYSamplingOps::G4SampleWatt()",
364 "Incident neutron energy above 14 MeV requested.", JustWarning,
365 "Using Watt fission constants for 14 Mev.");
366
367 A = NeutronInducedWattConstants[IsotopeIndex][2][0];
368 WattConstants_->B = NeutronInducedWattConstants[IsotopeIndex][2][1];
369 }
370 else {
371 G4int EnergyIndex = 0;
372 G4double EnergyDifference = 0;
373 G4double RangeDifference, ConstantDifference;
374
375 for (G4int i = 1; IncidentEnergyBins[i] != -1; i++) {
376 if (WattConstants_->Energy <= IncidentEnergyBins[i]) {
377 EnergyIndex = i;
378 EnergyDifference = IncidentEnergyBins[EnergyIndex] - WattConstants_->Energy;
379 if (EnergyDifference != 0) {
380 std::ostringstream Temp;
381 Temp << "Incident neutron energy of ";
382 Temp << WattConstants_->Energy << " MeV is not ";
383 Temp << "explicitly listed in the data tables";
384 // G4Exception("G4FPYSamplingOps::G4SampleWatt()",
385 // Temp.str().c_str(),
386 // JustWarning,
387 // "Using linear interpolation.");
388 }
389 break;
390 }
391 }
392
393 RangeDifference = IncidentEnergyBins[EnergyIndex] - IncidentEnergyBins[EnergyIndex - 1];
394
395 // Interpolate the value for 'a'
396 ConstantDifference = NeutronInducedWattConstants[IsotopeIndex][EnergyIndex][0]
397 - NeutronInducedWattConstants[IsotopeIndex][EnergyIndex - 1][0];
398 A = (EnergyDifference / RangeDifference) * ConstantDifference
399 + NeutronInducedWattConstants[IsotopeIndex][EnergyIndex - 1][0];
400
401 // Interpolate the value for 'b'
402 ConstantDifference = NeutronInducedWattConstants[IsotopeIndex][EnergyIndex][1]
403 - NeutronInducedWattConstants[IsotopeIndex][EnergyIndex - 1][1];
404 WattConstants_->B = (EnergyDifference / RangeDifference) * ConstantDifference
405 + NeutronInducedWattConstants[IsotopeIndex][EnergyIndex - 1][1];
406 }
407 }
408 else {
409 // Produce an error since an unsupported fission type was requested and
410 // abort the current run
411 G4String Temp = "Watt fission spectra data not available for ";
413 Temp += "proton induced fission.";
414 }
416 Temp += "gamma induced fission.";
417 }
418 else {
419 Temp += "!Warning! unknown cause.";
420 }
421 G4Exception("G4FPYSamplingOps::G4SampleWatt()", Temp, RunMustBeAborted,
422 "Fission events will not be sampled in this run.");
423 }
424
425 // Calculate the constants
426 K = 1 + (WattConstants_->B / (8.0 * A));
427 WattConstants_->L = (K + G4Pow::GetInstance()->powA((K * K - 1), 0.5)) / A;
428 WattConstants_->M = A * WattConstants_->L - 1;
429
431}
432
434{
436
437 if (static_cast<int>(NextGaussianIsStoredInMemory_) == TRUE) {
439
441 return GaussianTwo_;
442 }
443
444 // Define the variables to be used
445 G4double Radius;
446 G4double MappingFactor;
447
448 // Sample from the unit circle (21.4% rejection probability)
449 do {
450 GaussianOne_ = 2.0 * G4SampleUniform() - 1.0;
451 GaussianTwo_ = 2.0 * G4SampleUniform() - 1.0;
453 } while (Radius > 1.0); // Loop checking, 11.05.2015, T. Koi
454
455 // Translate the values to Gaussian space
456 MappingFactor = std::sqrt(-2.0 * G4Log(Radius) / Radius) * StdDev_;
457 GaussianOne_ = Mean_ + GaussianOne_ * MappingFactor;
458 GaussianTwo_ = Mean_ + GaussianTwo_ * MappingFactor;
459
460 // Set the flag that a value is now stored in memory
462
464 return GaussianOne_;
465}
466
468{
470
471 // Set the flag that any second value stored is no longer valid
473
474 // Check if the requested parameters have already been calculated
475 if (static_cast<int>(CheckAndSetParameters()) == TRUE) {
477 return;
478 }
479
480 // If the requested type is INT, then perform an iterative refinement of the
481 // mean that is going to be sampled
482 if (Type == G4FFGEnumerations::INT) {
483 // Return if the mean is greater than 7 standard deviations away from 0
484 // since there is essentially 0 probability that a sampled number will
485 // be less than 0
486 if (Mean_ > 7 * StdDev_) {
488 return;
489 }
490 // Variables that contain the area and weighted area information for
491 // calculating the statistical mean of the Gaussian distribution when
492 // converted to a step function
493 G4double ErfContainer, AdjustedErfContainer, Container;
494
495 // Variables that store lower and upper bounds information
496 G4double LowErf, HighErf;
497
498 // Values for determining the convergence of the solution
499 G4double AdjMean = Mean_;
500 G4double Delta = 1.0;
501 G4bool HalfDelta = false;
502 G4bool ToleranceCheck = false;
503
504 // Normalization constant for use with erf()
505 const G4double Normalization = StdDev_ * std::sqrt(2.0);
506
507 // Determine the upper limit of the estimates
508 const auto UpperLimit = (G4int)std::ceil(Mean_ + 9 * StdDev_);
509
510 // Calculate the integral of the Gaussian distribution
511
512 G4int icounter = 0;
513 G4int icounter_max = 1024;
514 do {
515 icounter++;
516 if (icounter > icounter_max) {
517 G4cout << "Loop-counter exceeded the threshold value at " << __LINE__ << "th line of "
518 << __FILE__ << "." << G4endl;
519 break;
520 }
521 // Set the variables
522 ErfContainer = 0;
523 AdjustedErfContainer = 0;
524
525 // Calculate the area and weighted area
526 for (G4int i = 0; i <= UpperLimit; i++) {
527 // Determine the lower and upper bounds
528 LowErf = ((AdjMean - i) / Normalization);
529 HighErf = ((AdjMean - (i + 1.0)) / Normalization);
530
531 // Correct the bounds for how they lie on the x-axis with
532 // respect to the mean
533 if (LowErf <= 0) {
534 LowErf *= -1;
535 HighErf *= -1;
536// Container = (erf(HighErf) - erf(LowErf))/2.0;
537#if defined WIN32 - VC
538 Container = (CLHEP::HepStat::erf(HighErf) - CLHEP::HepStat::erf(LowErf)) / 2.0;
539#else
540 Container = (erf(HighErf) - erf(LowErf)) / 2.0;
541#endif
542 }
543 else if (HighErf < 0) {
544 HighErf *= -1;
545
546// Container = (erf(HighErf) + erf(LowErf))/2.0;
547#if defined WIN32 - VC
548 Container = (CLHEP::HepStat::erf(HighErf) + CLHEP::HepStat::erf(LowErf)) / 2.0;
549#else
550 Container = (erf(HighErf) + erf(LowErf)) / 2.0;
551#endif
552 }
553 else {
554// Container = (erf(LowErf) - erf(HighErf))/2.0;
555#if defined WIN32 - VC
556 Container = (CLHEP::HepStat::erf(LowErf) - CLHEP::HepStat::erf(HighErf)) / 2.0;
557#else
558 Container = (erf(LowErf) - erf(HighErf)) / 2.0;
559#endif
560 }
561
562#if defined WIN32 - VC
563 // TK modified to avoid problem caused by QNAN
564 if (Container != Container) Container = 0;
565#endif
566
567 // Add up the weighted area
568 ErfContainer += Container;
569 AdjustedErfContainer += Container * i;
570 }
571
572 // Calculate the statistical mean
573 Container = AdjustedErfContainer / ErfContainer;
574
575 // Is it close enough to what we want?
576 ToleranceCheck = (std::fabs(Mean_ - Container) < Tolerance_);
577 if (static_cast<int>(ToleranceCheck) == TRUE) {
578 break;
579 }
580
581 // Determine the step size
582 if (static_cast<int>(HalfDelta) == TRUE) {
583 Delta /= 2;
584 }
585
586 // Step in the appropriate direction
587 if (Container > Mean_) {
588 AdjMean -= Delta;
589 }
590 else {
591 HalfDelta = TRUE;
592 AdjMean += Delta;
593 }
594 } while (TRUE); // Loop checking, 11.05.2015, T. Koi
595
596 ShiftedGaussianValues_->G4InsertShiftedMean(AdjMean, Mean_, StdDev_);
597 Mean_ = AdjMean;
598 }
599 else if (Mean_ / 7 < StdDev_) {
600 // If the requested type is double, then just re-define the standard
601 // deviation appropriately - chances are approximately 2.56E-12 that
602 // the value will be negative using this sampling scheme
603 StdDev_ = Mean_ / 7;
604 }
605
607}
608
G4double Y(G4double density)
@ JustWarning
@ RunMustBeAborted
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4FFG_FUNCTIONLEAVE__
#define G4FFG_FUNCTIONENTER__
#define G4FFG_SAMPLING_FUNCTIONENTER__
#define G4FFG_SAMPLING_FUNCTIONLEAVE__
G4double G4Log(G4double x)
Definition G4Log.hh:227
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
static double erf(double x)
WattSpectrumConstants * WattConstants_
G4double G4SampleWatt(G4int WhatIsotope, G4FFGEnumerations::FissionCause WhatCause, G4double WhatEnergy)
G4bool NextGaussianIsStoredInMemory_
G4ShiftedGaussian * ShiftedGaussianValues_
CLHEP::HepRandomEngine * RandomEngine_
G4double G4SampleGaussian(G4double Mean, G4double StdDev)
G4int G4SampleIntegerGaussian(G4double Mean, G4double StdDev)
void ShiftParameters(G4FFGEnumerations::GaussianReturnType Type)
void G4SetVerbosity(G4int WhatVerbosity)
static G4Pow * GetInstance()
Definition G4Pow.cc:41
G4double powA(G4double A, G4double y) const
Definition G4Pow.hh:230
#define TRUE
Definition globals.hh:41
#define FALSE
Definition globals.hh:38