Geant4_10
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 <iostream>
34 
35 #include <CLHEP/Random/Stat.h>
36 #include "Randomize.hh"
37 #include "globals.hh"
38 
39 #include "G4FFGDebuggingMacros.hh"
40 #include "G4FFGDefaultValues.hh"
41 #include "G4FFGEnumerations.hh"
42 #include "G4FPYSamplingOps.hh"
43 #include "G4ShiftedGaussian.hh"
45 
48 {
49  // Set the default verbosity
50  Verbosity_ = G4FFGDefaultValues::Verbosity;
51 
52  // Initialize the class
53  Initialize();
54 }
55 
58 {
59  // Set the default verbosity
61 
62  // Initialize the class
63  Initialize();
64 }
65 
67 Initialize( void )
68 {
70 
71  // Get the pointer to the random number generator
73 
74  // Initialize the data members
76  Mean_ = 0;
77  StdDev_ = 0;
79  GaussianOne_ = 0;
80  GaussianTwo_ = 0;
81  Tolerance_ = 0.000001;
84 
86 }
87 
90  G4double StdDev )
91 {
93 
94  // Determine if the parameters have changed
95  G4bool ParametersChanged = (Mean_ != Mean || StdDev_ != StdDev);
96  if(ParametersChanged == TRUE)
97  {
98  // Set the new values if the parameters have changed
100 
101  Mean_ = Mean;
102  StdDev_ = StdDev;
103  }
104 
105  G4double Sample = SampleGaussian();
106 
108  return Sample;
109 }
110 
113  G4double StdDev,
115 {
117 
118  if(Range == G4FFGEnumerations::ALL)
119  {
120  // Call the overloaded function
121  G4double Sample = G4SampleGaussian(Mean, StdDev);
122 
124  return Sample;
125  }
126 
127  // Determine if the parameters have changed
128  G4bool ParametersChanged = (Mean_ != Mean ||
129  StdDev_ != StdDev);
130  if(ParametersChanged == TRUE)
131  {
132  if(Mean <= 0)
133  {
134  std::ostringstream Temp;
135  Temp << "Mean value of " << Mean << " out of range";
136  G4Exception("G4FPYGaussianOps::G4SampleIntegerGaussian()",
137  Temp.str().c_str(),
138  JustWarning,
139  "A value of '0' will be used instead.");
140 
142  return 0;
143  }
144 
145  // Set the new values if the parameters have changed and then perform
146  // the shift
147  Mean_ = Mean;
148  StdDev_ = StdDev;
149 
151  }
152 
153  // Sample the Gaussian distribution
154  G4double Rand;
155  do
156  {
157  Rand = SampleGaussian();
158  } while(Rand < 0);
159 
161  return Rand;
162 }
163 
166  G4double StdDev )
167 {
169 
170  // Determine if the parameters have changed
171  G4bool ParametersChanged = (Mean_ != Mean || StdDev_ != StdDev);
172  if(ParametersChanged == TRUE)
173  {
174  // Set the new values if the parameters have changed
176 
177  Mean_ = Mean;
178  StdDev_ = StdDev;
179  }
180 
181  // Return the sample integer value
182  G4int Sample = (G4int)(std::floor(SampleGaussian()));
183 
185  return Sample;
186 }
187 
190  G4double StdDev,
192 {
194 
195  if(Range == G4FFGEnumerations::ALL)
196  {
197  // Call the overloaded function
198  G4int Sample = G4SampleIntegerGaussian(Mean, StdDev);
199 
201  return Sample;
202  } else
203  {
204  // ParameterShift() locks up if the mean is less than 1.
205  std::ostringstream Temp;
206  if(Mean < 1)
207  {
208  // Temp << "Mean value of " << Mean << " out of range";
209  // G4Exception("G4FPYGaussianOps::G4SampleIntegerGaussian()",
210  // Temp.str().c_str(),
211  // JustWarning,
212  // "A value of '0' will be used instead.");
213 
214  // return 0;
215  }
216 
217  if(Mean / StdDev < 2)
218  {
219  //Temp << "Non-ideal conditions:\tMean:" << Mean << "\tStdDev: "
220  // << StdDev;
221  //G4Exception("G4FPYGaussianOps::G4SampleIntegerGaussian()",
222  // Temp.str().c_str(),
223  // JustWarning,
224  // "Results not guaranteed: Consider tightening the standard deviation");
225  }
226 
227  // Determine if the parameters have changed
228  G4bool ParametersChanged = (Mean_ != Mean ||
229  StdDev_ != StdDev);
230  if(ParametersChanged == TRUE)
231  {
232  // Set the new values if the parameters have changed and then perform
233  // the shift
234  Mean_ = Mean;
235  StdDev_ = StdDev;
236 
238  }
239 
240  G4int RandInt;
241  // Sample the Gaussian distribution - only non-negative values are
242  // accepted
243  do
244  {
245  RandInt = (G4int)floor(SampleGaussian());
246  } while (RandInt < 0);
247 
249  return RandInt;
250  }
251 }
252 
255 {
257 
258  G4double Sample = RandomEngine_->flat();
259 
261  return Sample;
262 }
263 
266  G4double Upper )
267 {
269 
270  // Calculate the difference
271  G4double Difference = Upper - Lower;
272 
273  // Scale appropriately and return the value
274  G4double Sample = G4SampleUniform() * Difference + Lower;
275 
277  return Sample;
278 }
279 
281 G4SampleWatt( G4int WhatIsotope,
283  G4double WhatEnergy )
284 {
286 
287  // Determine if the parameters are different
288  //TK modified 131108
289  //if(WattConstants_->Product != WhatIsotope
290  if(WattConstants_->Product != WhatIsotope/10
291  || WattConstants_->Cause != WhatCause
292  || WattConstants_->Energy!= WhatEnergy )
293  {
294  // If the parameters are different or have not yet been defined then we
295  // need to re-evaluate the constants
296  //TK modified 131108
297  //WattConstants_->Product = WhatIsotope;
298  WattConstants_->Product = WhatIsotope/10;
299  WattConstants_->Cause = WhatCause;
300  WattConstants_->Energy = WhatEnergy;
301 
303  }
304 
305  G4double X = -std::log(G4SampleUniform());
306  G4double Y = -std::log(G4SampleUniform());
307  while(std::pow(Y - WattConstants_->M*(X + 1), 2)
308  > WattConstants_->B * WattConstants_->L * X)
309  {
310  X = -std::log(G4SampleUniform());
311  Y = -std::log(G4SampleUniform());
312  }
313 
315  return WattConstants_->L * X;
316 }
317 
320 {
322 
324 
326 
328 }
329 
332 {
334 
336  if(ShiftedMean == 0)
337  {
339  return FALSE;
340  }
341 
342  Mean_ = ShiftedMean;
343 
345  return TRUE;
346 }
347 
350 {
352 
353  G4double A, K;
354  A = K = 0;
355  // Use the default values if IsotopeIndex is not reset
356  G4int IsotopeIndex = 0;
357 
359  {
360  // Determine if the isotope requested exists in the lookup tables
361  for(G4int i = 0; SpontaneousWattIsotopesIndex[i] != -1; i++)
362  {
363  if(SpontaneousWattIsotopesIndex[i] ==
365  {
366  IsotopeIndex = i;
367 
368  break;
369  }
370  }
371 
372  // Get A and B
373  A = SpontaneousWattConstants[IsotopeIndex][0];
374  WattConstants_->B = SpontaneousWattConstants[IsotopeIndex][1];
376  {
377  // Determine if the isotope requested exists in the lookup tables
378  for(G4int i = 0; NeutronInducedWattIsotopesIndex[i] != -1; i++)
379  {
380  if(NeutronInducedWattIsotopesIndex[i] == WattConstants_->Product)
381  {
382  IsotopeIndex = i;
383  break;
384  }
385  }
386 
387  // Determine the Watt fission spectrum constants based on the energy of
388  // the incident neutron
389  if(WattConstants_->Energy == G4FFGDefaultValues::ThermalNeutronEnergy)
390  {
391  A = NeutronInducedWattConstants[IsotopeIndex][0][0];
392  WattConstants_->B = NeutronInducedWattConstants[IsotopeIndex][0][1];
393  } else if (WattConstants_->Energy > 14.0 * MeV)
394  {
395  G4Exception("G4FPYSamplingOps::G4SampleWatt()",
396  "Incident neutron energy above 14 MeV requested.",
397  JustWarning,
398  "Using Watt fission constants for 14 Mev.");
399 
400  A = NeutronInducedWattConstants[IsotopeIndex][2][0];
401  WattConstants_->B = NeutronInducedWattConstants[IsotopeIndex][2][1];
402  } else
403  {
404  G4int EnergyIndex = 0;
405  G4double EnergyDifference = 0;
406  G4double RangeDifference, ConstantDifference;
407 
408  for(G4int i = 1; IncidentEnergyBins[i] != -1; i++)
409  {
410  if(WattConstants_->Energy <= IncidentEnergyBins[i])
411  {
412  EnergyIndex = i;
413  EnergyDifference = IncidentEnergyBins[EnergyIndex] - WattConstants_->Energy;
414  if(EnergyDifference != 0)
415  {
416  std::ostringstream Temp;
417  Temp << "Incident neutron energy of ";
418  Temp << WattConstants_->Energy << " MeV is not ";
419  Temp << "explicitly listed in the data tables";
420 // G4Exception("G4FPYSamplingOps::G4SampleWatt()",
421 // Temp.str().c_str(),
422 // JustWarning,
423 // "Using linear interpolation.");
424  }
425  break;
426  }
427  }
428 
429  RangeDifference = IncidentEnergyBins[EnergyIndex] - IncidentEnergyBins[EnergyIndex - 1];
430 
431  // Interpolate the value for 'a'
432  ConstantDifference =
433  NeutronInducedWattConstants[IsotopeIndex][EnergyIndex][0] -
434  NeutronInducedWattConstants[IsotopeIndex]
435  [EnergyIndex - 1][0];
436  A = (EnergyDifference / RangeDifference) * ConstantDifference +
437  NeutronInducedWattConstants[IsotopeIndex]
438  [EnergyIndex - 1][0];
439 
440  // Interpolate the value for 'b'
441  ConstantDifference =
442  NeutronInducedWattConstants[IsotopeIndex][EnergyIndex][1] -
443  NeutronInducedWattConstants[IsotopeIndex]
444  [EnergyIndex - 1][1];
445  WattConstants_->B =
446  (EnergyDifference / RangeDifference) * ConstantDifference +
447  NeutronInducedWattConstants[IsotopeIndex]
448  [EnergyIndex - 1][1];
449  }
450  } else
451  {
452  // Produce an error since an unsupported fission type was requested and
453  // abort the current run
454  G4String Temp = "Watt fission spectra data not available for ";
456  {
457  Temp += "proton induced fission.";
459  {
460  Temp += "gamma induced fission.";
461  } else
462  {
463  Temp += "!Warning! unknown cause.";
464  }
465  G4Exception("G4FPYSamplingOps::G4SampleWatt()",
466  Temp,
468  "Fission events will not be sampled in this run.");
469  }
470 
471  // Calculate the constants
472  K = 1 + (WattConstants_->B / (8.0 * A));
473  WattConstants_->L = (K + std::pow((K * K - 1), 0.5)) / A;
474  WattConstants_->M = A * WattConstants_->L - 1;
475 
477 }
478 
481 {
483 
485  {
487 
489  return GaussianTwo_;
490  }
491 
492  // Define the variables to be used
493  G4double Radius;
494  G4double MappingFactor;
495 
496  // Sample from the unit circle (21.4% rejection probability)
497  do
498  {
499  GaussianOne_ = 2.0 * G4SampleUniform() - 1.0;
500  GaussianTwo_ = 2.0 * G4SampleUniform() - 1.0;
502  } while (Radius > 1.0);
503 
504  // Translate the values to Gaussian space
505  MappingFactor = std::sqrt(-2.0*std::log(Radius)/Radius) * StdDev_;
506  GaussianOne_ = Mean_ + GaussianOne_*MappingFactor;
507  GaussianTwo_ = Mean_ + GaussianTwo_*MappingFactor;
508 
509  // Set the flag that a value is now stored in memory
511 
513  return GaussianOne_;
514 }
515 
518 {
520 
521  // Set the flag that any second value stored is no longer valid
523 
524  // Check if the requested parameters have already been calculated
525  if(CheckAndSetParameters() == TRUE)
526  {
528  return;
529  }
530 
531  // If the requested type is INT, then perform an iterative refinement of the
532  // mean that is going to be sampled
533  if(Type == G4FFGEnumerations::INT)
534  {
535  // Return if the mean is greater than 7 standard deviations away from 0
536  // since there is essentially 0 probability that a sampled number will
537  // be less than 0
538  if(Mean_ > 7 * StdDev_)
539  {
541  return;
542  }
543  // Variables that contain the area and weighted area information for
544  // calculating the statistical mean of the Gaussian distribution when
545  // converted to a step function
546  G4double ErfContainer, AdjustedErfContainer, Container;
547 
548  // Variables that store lower and upper bounds information
549  G4double LowErf, HighErf;
550 
551  // Values for determining the convergence of the solution
552  G4double AdjMean = Mean_;
553  G4double Delta = 1.0;
554  G4bool HalfDelta = false;
555  G4bool ToleranceCheck = false;
556 
557 
558  // Normalization constant for use with erf()
559  const G4double Normalization = StdDev_ * std::sqrt(2.0);
560 
561  // Determine the upper limit of the estimates
562  const G4int UpperLimit = (G4int) std::ceil(Mean_ + 9 * StdDev_);
563 
564  // Calculate the integral of the Gaussian distribution
565 
566  do
567  {
568  // Set the variables
569  ErfContainer = 0;
570  AdjustedErfContainer = 0;
571 
572  // Calculate the area and weighted area
573  for(G4int i = 0; i <= UpperLimit; i++)
574  {
575  // Determine the lower and upper bounds
576  LowErf = ((AdjMean - i) / Normalization);
577  HighErf = ((AdjMean - (i + 1.0)) / Normalization);
578 
579  // Correct the bounds for how they lie on the x-axis with
580  // respect to the mean
581  if(LowErf <= 0)
582  {
583  LowErf *= -1;
584  HighErf *= -1;
585  //Container = (erf(HighErf) - erf(LowErf))/2.0;
586  #if defined WIN32-VC
587  Container = (CLHEP::HepStat::erf(HighErf) - CLHEP::HepStat::erf(LowErf))/2.0;
588  #else
589  Container = (erf(HighErf) - erf(LowErf))/2.0;
590  #endif
591  } else if (HighErf < 0)
592  {
593  HighErf *= -1;
594 
595  //Container = (erf(HighErf) + erf(LowErf))/2.0;
596  #if defined WIN32-VC
597  Container = (CLHEP::HepStat::erf(HighErf) + CLHEP::HepStat::erf(LowErf))/2.0;
598  #else
599  Container = (erf(HighErf) + erf(LowErf))/2.0;
600  #endif
601  } else
602  {
603  //Container = (erf(LowErf) - erf(HighErf))/2.0;
604  #if defined WIN32-VC
605  Container = (CLHEP::HepStat::erf(LowErf) - CLHEP::HepStat::erf(HighErf))/2.0;
606  #else
607  Container = (erf(LowErf) - erf(HighErf))/2.0;
608  #endif
609  }
610 
611  // Add up the weighted area
612  ErfContainer += Container;
613  AdjustedErfContainer += Container * i;
614  }
615 
616  // Calculate the statistical mean
617  Container = AdjustedErfContainer / ErfContainer;
618 
619  // Is it close enough to what we want?
620  ToleranceCheck = (std::fabs(Mean_ - Container) < Tolerance_);
621  if(ToleranceCheck == TRUE)
622  {
623  break;
624  }
625 
626  // Determine the step size
627  if(HalfDelta == TRUE)
628  {
629  Delta /= 2;
630  }
631 
632  // Step in the appropriate direction
633  if(Container > Mean_)
634  {
635  AdjMean -= Delta;
636  } else
637  {
638  HalfDelta = TRUE;
639  AdjMean += Delta;
640  }
641  } while(TRUE);
642 
644  Mean_ = AdjMean;
645  } else if(Mean_ / 7 < StdDev_)
646  {
647  // If the requested type is double, then just re-define the standard
648  // deviation appropriately - chances are approximately 2.56E-12 that
649  // the value will be negative using this sampling scheme
650  StdDev_ = Mean_ / 7;
651  }
652 
654 }
655 
657 {
659 
660  delete ShiftedGaussianValues_;
661  delete WattConstants_;
662 
664 }
G4double G4SampleGaussian(G4double Mean, G4double StdDev)
G4double SampleGaussian(void)
void EvaluateWattConstants(void)
G4double G4SampleWatt(G4int WhatIsotope, G4FFGEnumerations::FissionCause WhatCause, G4double WhatEnergy)
#define G4FFG_SAMPLING_FUNCTIONENTER__
G4double G4SampleUniform(void)
G4double G4FindShiftedMean(G4double RequestedMean, G4double RequestedStdDev)
G4FFGEnumerations::FissionCause Cause
Float_t Y
Definition: plot.C:39
virtual double flat()=0
G4ShiftedGaussian * ShiftedGaussianValues_
int G4int
Definition: G4Types.hh:78
Float_t X
Definition: plot.C:39
static HepRandomEngine * getTheEngine()
Definition: Random.cc:165
WattSpectrumConstants * WattConstants_
void G4SetVerbosity(G4int WhatVerbosity)
bool G4bool
Definition: G4Types.hh:79
void G4InsertShiftedMean(G4double ShiftedMean, G4double RequestedMean, G4double RequestedStdDev)
void ShiftParameters(G4FFGEnumerations::GaussianReturnType Type)
#define FALSE
Definition: globals.hh:52
#define TRUE
Definition: globals.hh:55
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
CLHEP::HepRandomEngine * RandomEngine_
#define G4FFG_FUNCTIONLEAVE__
static double erf(double x)
#define G4FFG_SAMPLING_FUNCTIONLEAVE__
double G4double
Definition: G4Types.hh:76
void G4SetVerbosity(G4int WhatVerbosity)
G4bool CheckAndSetParameters(void)
#define G4FFG_FUNCTIONENTER__
G4bool NextGaussianIsStoredInMemory_
G4int G4SampleIntegerGaussian(G4double Mean, G4double StdDev)