DFNgen  2.0
DFN Model Generator
distributions.cpp
Go to the documentation of this file.
1 #include "distributions.h"
2 #include "insertShape.h"
3 #include <float.h>
4 #include <cmath>
5 #include <cstdlib>
6 #include <iostream>
7 
8 /*
9  The Distributions class was created specifically for
10  easy use of a customized exponential distribution
11  which allows users to specify the min and max limit
12  which the distribution function can return.
13  (exponentail distribution function truncated on both sides)
14 
15  The Distributions class was created keeping in mind
16  other distributions may be needed later.
17 
18  Currently, exponential distribution is the only
19  distribution contained in the Distributions class.
20 */
21 
22 /***********************************************************/
23 /******************* Constructor ***************************/
30 Distributions::Distributions(std::mt19937_64 &_generator, std::vector<Shape> &shapeFamilies) {
31  // Maximum double less than 1.0
32  // (0.9999... before being recognized as 1)
34 
35  // Init exponential dist class
36  expDist = new ExpDist(maxInput, _generator);
37 
38  // User input check and exp dist init
39  checkDistributionUserInput(shapeFamilies);
40 }
41 
42 /***********************************************************/
43 /****************** Get Max Digits ***********************/
47  // log(2) / log (10) = 0.301029995663982
48  return std::floor(DBL_MANT_DIG * 0.30102999566398) + 2;
49 }
50 
51 
52 /***********************************************************/
53 /************** Get Max Number Less Than 1.0 **************/
57  char temp[32];
58  int length = getMaxDigits();
59 
60  temp[0] = '.';
61  for (int i = 1; i < length; i++) {
62  temp[i] = '9';
63  }
64  temp[length] = '\0'; // Add NULL char
65 
66  double returnVal = atof(temp);
67  return returnVal;
68 }
69 
70 /********************************************************************************/
71 /*** Initialize and Error Check On User Input for Exponendtail Distribution ***/
95 void Distributions::checkDistributionUserInput(std::vector<Shape> &shapeFamilies) {
96 
97  for (unsigned int i = 0; i < shapeFamilies.size(); i++) {
98  switch (shapeFamilies[i].distributionType) {
99  double input;
100 
101  case 1: // Lognormal
102 
103  break;
104 
105  case 2: // Truncated power-law
106 
107  break;
108 
109  case 3: // Exponential
110 
111  // Check exponential minimum value
112  input = expDist->computeInput(shapeFamilies[i].expMin, shapeFamilies[i].expLambda);
113  if (input >= 1) {
114  std::cout << "\n\nWARNING: The defined minimum value, " << shapeFamilies[i].expMin
115  << ", for " << shapeType(shapeFamilies[i])
116  << " family " << getFamilyNumber(i, shapeFamilies[i].shapeFamily)
117  << " will not be able to be produced by the exponential distribution due to precision issues.\n";
118 
119  std::cout << "The minimum value is too large. The largest value the distribution can "
120  << "produce with current parameters is "
121  << expDist->getMaxValue(shapeFamilies[i].expLambda) << "\n";
122 
123  std::cout << "Please adjust the minimum value, or the mean, and try again.\n";
124  exit(1);
125  }
126  else {
127  shapeFamilies[i].minDistInput = input;
128  }
129 
130  // Check exponential maximum value
131  input = expDist->computeInput(shapeFamilies[i].expMax, shapeFamilies[i].expLambda);
132 
133  if (input >= 1) {
134  std::cout << "\n\nWARNING: The defined maximum value, " << shapeFamilies[i].expMax << ", for "
135  << shapeType(shapeFamilies[i]) << " family " << getFamilyNumber(i, shapeFamilies[i].shapeFamily)
136  << " will not be able to be produced by the exponential distribution due to precision issues.\n";
137 
138  std::cout << "The largest value the distribution can produce with current parameters is "
139  << expDist->getMaxValue(shapeFamilies[i].expLambda) << "\n";
140 
141  std::cout << "Press Enter to automatically adjust this exponential maximum value to "
142  << expDist->getMaxValue(shapeFamilies[i].expLambda) << " (q to Quit)\n";
143 
144  // Prompt user to press enter to continue or q to quit
145  quitOrContinue();
146  double max = expDist->getMaxValue(shapeFamilies[i].expLambda);
147  //check that the max is not less or equal to the min
148  if (max <= shapeFamilies[i].expMin) {
149  std::cout << "ERROR: The maximum exponetnial distribution radius possible for " << shapeType(shapeFamilies[i])
150  << " family " << getFamilyNumber(i, shapeFamilies[i].shapeFamily)
151  << " is less than or equal to the minimum exponential distribution radius.\n";
152  std::cout << "Please adjust the exponential distribution parameters in " << shapeType(shapeFamilies[i])
153  << " family " << getFamilyNumber(i, shapeFamilies[i].shapeFamily) << "\n";
154  exit(1);
155  }
156  }
157 
158  shapeFamilies[i].maxDistInput = input;
159 
160  break; // End case 3
161  }
162  }
163 }
164 
165 
166 /******************************************************/
167 /*************** Quit or Continue *********************/
173  char str[256];
174 
175  do {
176  // Get input
177  std::cin.get(str, 256);
178  std::cin.clear();
179  std::cin.ignore();
180 
181  if ((str[0] == 'q' && str[1] == '\0') || (str[0] == 'Q' && str[1] == '\0')) {
182  exit(1);
183  }
184 
185  if (str[0] != 0) {
186  std::cout << "Invalid input.\n";
187  }
188 
189  } while (str[0] != 0);
190 }
191 
192 /******************************************************/
195  delete expDist;
196 }
197 
double getMaxDecimalForDouble()
std::string shapeType(struct Shape &shapeFam)
void checkDistributionUserInput(std::vector< Shape > &shapeFamilies)
int getFamilyNumber(int familyIndex, int familyShape)
double getMaxValue(double lambda)
Definition: expDist.cpp:115
Distributions(std::mt19937_64 &_generator, std::vector< Shape > &shapeFamilies)
double computeInput(double output, double lambda)
Definition: expDist.cpp:129
ExpDist * expDist
Definition: distributions.h:20