DFNgen  2.0
DFN Model Generator
mathFunctions.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <numeric>
3 #include <algorithm>
4 #include "mathFunctions.h"
5 #include <math.h>
6 #include "structures.h"
7 #include "vectorFunctions.h"
8 #include <iomanip>
9 
10 /****************************************************************************/
11 /****************************************************************************/
19 double sumDeviation(const double *v, int n){
20  double mean = 0, sumDeviation = 0;
21  int i;
22  for(i = 0; i < n; i++) {
23  mean += v[i];
24  }
25  mean=mean/n;
26 
27  for(i = 0; i < n; i++) {
28  double temp = v[i] - mean;
29  sumDeviation += temp * temp;
30  }
31  return sumDeviation;
32 }
33 
34 /******************************************************************/
35 /************* Sum deviaiton array X 3 **************************/
46 double *sumDevAry3(double *v) {
47  double *result = new double[3];
48  const double x[4] = {v[0], v[3], v[6], v[9]};
49  const double y[4] = {v[1], v[4], v[7], v[10]};
50  const double z[4] = {v[2], v[5], v[8], v[11]};
51 
52  result[0] = sumDeviation(x, 4);
53  result[1] = sumDeviation(y, 4);
54  result[2] = sumDeviation(z, 4);
55 
56  return result; // MUST DELETE RETURN MANUALLY
57 }
58 
59 /******************************************************************/
60 /******************* Get Max Element's Index ********************/
68 int maxElmtIdx(double *v, int n) {
69  double max = v[0]; // Initialize
70  int i;
71  int idx = 0;
72  for (i = 1; i < n; i++) {
73  if (max < v[i] ) {
74  max = v[i];
75  idx = i;
76  }
77  }
78  return idx;
79 }
80 
81 /******************************************************************/
82 /******************** Sort Array Indices ************************/
88 int* sortedIndex(const double *v, int n) {
89 
90  // Initialize original index locations
91  int *idx = new int[n];
92  std::iota(idx, idx+n, 0);
93 
94  // Sort indexes based on comparing values in v
95  std::sort(idx, idx+n, [v](size_t i1, size_t i2) {return v[i1] < v[i2];});
96 
97  return idx;
98 }
99 
100 /******************************************************************/
101 /******************** Get Poly's Area ***************************/
110 double getArea(struct Poly &poly){
111 
112  if (poly.numberOfNodes == 3) { //area = 1/2 mag of xProd
113  double v1[3] = {poly.vertices[3]-poly.vertices[0], poly.vertices[4]-poly.vertices[1], poly.vertices[5]-poly.vertices[2]};
114  double v2[3] = {poly.vertices[6]-poly.vertices[0], poly.vertices[7]-poly.vertices[1], poly.vertices[8]-poly.vertices[2]};
115  double *xProd = crossProduct(v1, v2);
116  double area = .5 * magnitude(xProd[0], xProd[1], xProd[2]);
117 
118  delete[] xProd;
119  return area;
120  }
121 
122  else { // More than 3 vertices
123  double polyArea = 0; // For summing area over trianlges of polygon
124 
125  // Get coordinate within polygon
126  double insidePt[3];
127  int idxAcross = poly.numberOfNodes / 2 * 3;
128  insidePt[0] = poly.vertices[0] + (.5 * (poly.vertices[idxAcross] - poly.vertices[0])); //x
129  insidePt[1] = poly.vertices[1] + (.5 * (poly.vertices[idxAcross+1] - poly.vertices[1])); //y
130  insidePt[2] = poly.vertices[2] + (.5 * (poly.vertices[idxAcross+2] - poly.vertices[2])); //z
131 
132 
133 
134  for (int i = 0; i<poly.numberOfNodes-1; i++){
135  int idx = i*3;
136  double v1[3] = {poly.vertices[idx]-insidePt[0], poly.vertices[idx+1]-insidePt[1], poly.vertices[idx+2]-insidePt[2]};
137  double v2[3] = {poly.vertices[idx+3]-insidePt[0], poly.vertices[idx+4]-insidePt[1], poly.vertices[idx+5]-insidePt[2]};
138  double *xProd = crossProduct(v1, v2);
139  double area = .5 * magnitude(xProd[0], xProd[1], xProd[2]);
140  delete[] xProd;
141  polyArea += area; // Accumulate area
142  }
143  // Last portion of polygon, insidePt to first vertice and insidePt to last vertice
144  int last = 3*(poly.numberOfNodes-1);
145  double v1[3] = {poly.vertices[0]-insidePt[0], poly.vertices[1]-insidePt[1], poly.vertices[2]-insidePt[2]};
146  double v2[3] = {poly.vertices[last]-insidePt[0], poly.vertices[last+1]-insidePt[1], poly.vertices[last+2]-insidePt[2]};
147  double *xProd = crossProduct(v1, v2);
148  double area = .5 * magnitude(xProd[0], xProd[1], xProd[2]);
149  delete[] xProd;
150  polyArea += area; // Accumulate area
151 
152  return polyArea;
153  }
154 }
155 
156 
157 /******************************************************************/
158 /************* Index from Probability ***************************/
166 int indexFromProb(float *CDF, double roll, int size){
167 
168  for (int i = 0; i < size; i++){
169  if (roll <= CDF[i]){
170  return i;
171  }
172  }
173  return size - 1;
174 }
175 
176 
177 /****************************************************************************/
178 /****** Choose Family Randomly Based On P32 and CDF ***********************/
187 int indexFromProb_and_P32Status(float *CDF, double roll, int famSize, int cdfSize, int &cdfIdx) {
188  // The p32Status bool array stays 1 to 1 with the number of total families.
189  // The p32Status array with element = 1 means that family has reached its p32 requirement.
190  // The CDF contains an amount of elements equal to the number of families which has not met its intensity requirement.
191  // To get the correct familyShape[] index from cdf, me must ignore any families their p32 requirement alrady met
192 
193  // Index we hit based on random roll,
194  cdfIdx = indexFromProb(CDF, roll, cdfSize);
195  // If cdfIndex = 2 (thrid element including 0)
196  // we need to find the families with p32Status still 0, and choose the thrid one
197  // this family will be used to create the next polygon
198  int count = 0; // Count of families encountered with p32Status = 0
199  for (int i = 0; i < famSize; i++) {
200 
201  if (cdfIdx == count && p32Status[i] == 0){
202  return i; // Returns family index we need to build poly with.
203  }
204  else if (p32Status[i] == 0) {
205  count++; // Count number of 0's ( number of families not having met their p32 req. )
206  }
207  }
208 
209  std::cout << "ERROR: see indexFromProb_and_P32Status(), funct did not return anything\n";
210  return famSize - 1;
211 }
212 
213 
214 /****************************************************************************/
215 /****** Choose Family Randomly Based On P32 and CDF ***********************/
221 int cdfIdxFromFamNum(float *CDF, bool *p32Status, int famIdx) {
222 
223  int idx = -1;
224  // The CDF array only contains elements for families who have not
225  // met their P32 requirenment (p32 option)
226  // If Npoly option is being used, the CDF array and shape familyies array
227  // are aligned and 1:1
228 
229  // Check how many 0's (p32's not complete) before the given family index
230  // This gives the index in the CDF array for the given family
231  for (int i = famIdx; i >= 0; i--) {
232  if (p32Status[i] == 0) {
233  idx++;
234  }
235  }
236  return idx;
237 }
238 
239 /******************************************************************/
240 /************************ Create CDF *****************************/
244 float *createCDF(float *famProb, int size) {
245  // Convert famProb to CDF
246  float *CDF = new float[size];
247  CDF[0] = famProb[0];
248  for (int i=1; i<size; i++){
249  CDF[i] = CDF[i-1] + famProb[i];
250  }
251 
252  if ((CDF[size-1] < 0.999) || (CDF[size-1] > 1.001)) {
253  std::cout << "\nWARNING: Familiy probabilities (famProb in input file) do not sum to 1 \nsum = "
254  << std::setprecision(17) << CDF[size-1] << "\nPlease check input file.\n\n";
255  }
256 
257  return CDF;
258 }
259 
260 /**************************************************************************************/
261 /**************************************************************************************/
269 void adjustCDF_and_famProb(float *&CDF, float *&famProbability, int &cdfSize, int idx2Remove) {
270 
271  cdfSize--;
272  float *newProbs = new float[cdfSize];
273 
274  // Adjust probabilities, remove element while keeping the rest of probabilities in proportion
275  // Take probability of the familiy being removed, and divide it equally among remaining probabilities
276  float addToRemainingElmts = famProbability[idx2Remove]/cdfSize; // Distribute removed probability among leftore famillies probabilities
277  // cdfIdx is index to that families cdf index AND familily probability index
278  int idx = 0;
279 
280  for (int i = 0; i < cdfSize+1; i++) { // cdfSize+1 becuase of cdfSize-- at the beginning of function. This
281  // makes the loop cover the all probabilities in the ary before one is removed
282  // and distributed to the rest
283  if (i != idx2Remove) {
284  newProbs[idx] = famProbability[i] + addToRemainingElmts;
285  idx++;
286  }
287  }
288 
289  delete[] famProbability; // Delete old prob array
290  famProbability = newProbs; // Assign famProbability array to new probabilities array
291 
292  delete[] CDF; // Delete old CDF array
293  CDF = createCDF(famProbability, cdfSize); // Create new CDF array
294 }
295 
296 
T magnitude(T x, T y, T z)
void adjustCDF_and_famProb(float *&CDF, float *&famProbability, int &cdfSize, int idx2Remove)
int * sortedIndex(const double *v, int n)
int numberOfNodes
Definition: structures.h:14
double getArea(struct Poly &poly)
float * createCDF(float *famProb, int size)
int cdfIdxFromFamNum(float *CDF, bool *p32Status, int famIdx)
int maxElmtIdx(double *v, int n)
double * vertices
Definition: structures.h:70
float * famProb
Definition: readInput.cpp:133
int indexFromProb(float *CDF, double roll, int size)
double sumDeviation(const double *v, int n)
bool * p32Status
Definition: readInput.cpp:468
float area
Definition: structures.h:33
int indexFromProb_and_P32Status(float *CDF, double roll, int famSize, int cdfSize, int &cdfIdx)
T * crossProduct(const T *v1, const T *v2)
double * sumDevAry3(double *v)