DFNgen  2.0
DFN Model Generator
fractureEstimating.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <algorithm>
3 #include "generatingPoints.h"
4 #include "input.h"
5 #include "fractureEstimating.h"
6 #include "insertShape.h"
7 #include "mathFunctions.h"
8 #include "domain.h"
9 
10 /**********************************************************************/
11 /**************** Sort Families Radii Lists *************************/
16 void sortRadii(std::vector<Shape> &shapeFam) {
17  for (unsigned int i = 0; i < shapeFam.size(); i++) {
18  std::sort(shapeFam[i].radiiList.begin(),
19  shapeFam[i].radiiList.end( ), greaterThan);
20  }
21 }
22 
23 /**********************************************************************/
24 /*** Create Radii Lists for Shape Families When Using NPoly Option ***/
31 void generateRadiiLists_nPolyOption(std::vector<Shape> &shapeFamilies, float *famProb, std::mt19937_64 &generator, Distributions &distributions) {
32 
33  std::cout << "\nBuilding radii lists for nPoly option...\n";
34 
35  if (forceLargeFractures == true) {
36  for (unsigned int i = 0; i < shapeFamilies.size(); i++) {
37  double radius = getLargestFractureRadius(shapeFamilies[i]);
38  shapeFamilies[i].radiiList.push_back(radius);
39  }
40  }
41 
42  for (unsigned int i = 0; i < shapeFamilies.size(); i++) {
43  int amountToAdd;
44  if (forceLargeFractures == true) {
45  amountToAdd = std::ceil(famProb[i] * (nPoly - shapeFamilies.size()));
46  }
47  else {
48  amountToAdd = std::ceil(famProb[i] * nPoly);
49  }
50 
51  addRadii(amountToAdd, i, shapeFamilies[i],
52  generator, distributions);
53  }
54 }
55 
56 
57 /**********************************************************************/
58 /******************** Print Warining to User ************************/
64 void printGeneratingFracturesLessThanHWarning(int famIndex, Shape &shapeFam) {
65  std::cout << "\nWARNING: " << shapeType(shapeFam) << " Family "
66  << getFamilyNumber(famIndex, shapeFam.shapeFamily)
67  << " is attepting to populate fracture radii lists, however "
68  << "many fractures are being generated with radii less than 3*h (Minimum radius). "
69  << "Consider adjusting distribution parameters.\n";
70 }
71 
72 
73 /**********************************************************************/
74 /********* Add Percentage More Radii To Radii Lists *****************/
82 void addRadiiToLists(float percent, std::vector<Shape> &shapeFamilies, std::mt19937_64 &generator, Distributions &distributions) {
83 
84  for (unsigned int i = 0; i < shapeFamilies.size(); i++) {
85  int amountToAdd = std::ceil(shapeFamilies[i].radiiList.size() * percent);
86  addRadii(amountToAdd, i, shapeFamilies[i], generator, distributions);
87  }
88 }
89 
90 
91 /**********************************************************************/
92 /************ Add Radii To Shape Families Radii List ****************/
100 void addRadii(int amountToAdd, int famIdx, Shape &shapeFam, std::mt19937_64 &generator, Distributions &distributions) {
101 
102  int count = 0;
103  double radius;
104  double minRadius = 3*h;
105 
106  std::uniform_real_distribution<double> uniformDist(0,1);
107 
108  switch (shapeFam.distributionType) {
109 
110  case 1: { // Lognormal
111  std::lognormal_distribution<double> logDistribution(shapeFam.mean, shapeFam.sd);
112 
113  for (int k = 0; k < amountToAdd; k++) {
114  count = 0;
115  do {
116  radius = logDistribution(generator);
117  count++;
118  if (count % 1000 == 0) {
119  printGeneratingFracturesLessThanHWarning(famIdx, shapeFam);
120  }
121  } while (radius < minRadius);
122  shapeFam.radiiList.push_back(radius);
123  }
124  break;
125  }
126 
127  case 2: { // Truncated power-law
128  for (int k = 0; k < amountToAdd; k++) {
129  count = 0;
130  do {
131  radius = truncatedPowerLaw(uniformDist(generator),
132  shapeFam.min, shapeFam.max, shapeFam.alpha);
133  count++;
134  if (count % 1000 == 0) {
136  }
137  } while (radius < minRadius);
138  shapeFam.radiiList.push_back(radius);
139  }
140  break;
141  }
142 
143  case 3: { // Exponential
144  for (int k = 0; k < amountToAdd; k++) {
145  count = 0;
146  do {
147  radius = distributions.expDist->getValue(shapeFam.expLambda,
148  shapeFam.minDistInput, shapeFam.maxDistInput);
149  count++;
150  if (count % 1000 == 0) {
152  }
153  } while (radius < minRadius);
154  shapeFam.radiiList.push_back(radius);
155  }
156  break;
157  }
158  }
159 }
160 
161 
162 /**********************************************************************/
163 /******** Estimate Number of Fractures When P32 Option is Used ******/
174 void dryRun(std::vector<Shape> &shapeFamilies, float *shapeProb, std::mt19937_64 &generator, Distributions &distributions) {
175 
176  std::cout << "\nEstimating number of fractures per family for defined fracture intensities (P32)...\n";
177 
178  float domVol = domainSize[0]*domainSize[1]*domainSize[2];
179  int totalFamilies = shapeFamilies.size();
180  int cdfSize = totalFamilies; // This variable shrinks along with CDF when used with fracture intensity (P32) option
181 
182  // Create a copy of the family probablity
183  // Algoithms used in this function modify this array,
184  // we need to keep the original in its original state
185  float *famProbability = new float[totalFamilies];
186  std::copy(shapeProb, shapeProb + totalFamilies, famProbability);
187 
188  // Init uniform dist on [0,1)
189  std::uniform_real_distribution<double> uniformDist(0,1);
190 
191  /****** Convert famProb to CDF *****/
192  float *CDF = createCDF(famProbability, cdfSize);
193 
194  int familyIndex; // Holds index to shape family of fracture being generated
195  unsigned int forceLargeFractCount = 0;
196 
197  while (p32Complete(totalFamilies) == 0) {
198 
199  // Index to CDF array of current family being inserted
200  int cdfIdx;
201  int rejectCounter = 0;
202 
203  Poly newPoly;
204 
205  if ((forceLargeFractCount < shapeFamilies.size()) && forceLargeFractures == true) {
206  double radius = getLargestFractureRadius(shapeFamilies[forceLargeFractCount]);
207  familyIndex = forceLargeFractCount;
208  cdfIdx = cdfIdxFromFamNum(CDF, p32Status, forceLargeFractCount);
209  newPoly = generatePoly_withRadius(radius, shapeFamilies[forceLargeFractCount], generator, distributions, familyIndex);
210  forceLargeFractCount++;
211  }
212  else {
213  // Choose a family based on probabiliyis AND their target p32 completion status
214  // if a family has already met is fracture intinisty req. (p32) dont choose that family anymore
215  // Choose a family based on probabiliyis AND their target p32 completion status
216  // if a family has already met is fracture intinisty reqirement (p32) dont choose that family anymore
217  familyIndex = indexFromProb_and_P32Status(CDF, uniformDist(generator), totalFamilies, cdfSize, cdfIdx);
218  newPoly = generatePoly(shapeFamilies[familyIndex], generator, distributions, familyIndex, false);
219  }
220 
221  // Truncate poly if needed
222  // Returns 1 if poly is outside of domain or truncated to less than 3 vertices
223  bool reject = false;
224  while (domainTruncation(newPoly, domainSize) == 1) {
225  // Poly is completely outside domain, or was truncated to
226  // less than 3 vertices due to vertices being too close together
227  rejectCounter++; // Counter for re-trying a new translation
228 
229  // Test if newPoly has reached its limit of insertion attempts
230  if (rejectCounter >= rejectsPerFracture) {
231  delete[] newPoly.vertices; // Created with new, need to manually deallocate
232  reject = true;
233  break;; // Reject poly, generate new polygon
234  }
235  else { // Retranslate poly and try again, preserving normal, size, and shape
236  reTranslatePoly(newPoly, shapeFamilies[familyIndex], generator);
237  }
238  }
239 
240  if (reject == true) {
241  // Restart while loop
242  // Generate new fracture
243  continue;
244  }
245 
246  // Calculate poly's area
247  newPoly.area = getArea(newPoly);
248 
249  // Update p32 (fracture intensity) per family if using P32 option
250  if (shapeFamilies[familyIndex].layer == 0) {
251  shapeFamilies[familyIndex].currentP32 += newPoly.area*2/domVol;
252  }
253  else {
254  shapeFamilies[familyIndex].currentP32 += newPoly.area*2/layerVol[shapeFamilies[familyIndex].layer-1];
255  }
256 
257  // Save radius for real DFN generation
258  shapeFamilies[familyIndex].radiiList.push_back(newPoly.xradius);
259 
260  // If the last inserted pologon met the p32 reqirement, set that familiy to no longer
261  // insert any more fractures. ajust the CDF and familiy probababilties
262  if (shapeFamilies[familyIndex].currentP32 >= shapeFamilies[familyIndex].p32Target ) {
263 
264  p32Status[familyIndex] = 1; //mark family as having its p32 requirement met
265 
266  // Adjust CDF, PDF, and reduce their size by 1. Keep probabilities proportional.
267  // Remove the completed families element in the CDF and famProb[]
268  // Distribute the removed family probability evenly among the others and rebuild the CDF
269  // familyIndex = index of family's probability
270  // cdfIdx = index of the family's correspongding cdf, (index to elmt to remove)
271  if (cdfSize > 1 ){ // If there are still more families to insert ( cdfSize = 0 means no more families to insert)
272  adjustCDF_and_famProb(CDF, famProbability, cdfSize, cdfIdx);
273  }
274  }
275 
276  // No need to save any polygons,
277  // We are just simulating dfn with no rejections
278  // to get an idea of how many fractures we will
279  // need for each family
280  delete[] newPoly.vertices;
281 
282  } // End while loop for inserting polyons
283 
284  // Reset p32 to 0
285  for (int i = 0; i < totalFamilies; i++) {
286  p32Status[i] = 0;
287  shapeFamilies[i].currentP32 = 0;
288  }
289 }
290 
std::vector< double > radiiList
Definition: structures.h:408
void adjustCDF_and_famProb(float *&CDF, float *&famProbability, int &cdfSize, int idx2Remove)
void dryRun(std::vector< Shape > &shapeFamilies, float *shapeProb, std::mt19937_64 &generator, Distributions &distributions)
float max
Definition: structures.h:502
bool p32Complete(int size)
unsigned int nPoly
Definition: readInput.cpp:15
bool greaterThan(float i, float j)
double getValue(double lambda, double rv)
Definition: expDist.cpp:46
std::string shapeType(struct Shape &shapeFam)
float truncatedPowerLaw(float randomNum, float min, float max, float alpha)
double getArea(struct Poly &poly)
float * createCDF(float *famProb, int size)
float sd
Definition: structures.h:486
double maxDistInput
Definition: structures.h:463
int rejectsPerFracture
Definition: readInput.cpp:439
int getFamilyNumber(int familyIndex, int familyShape)
void addRadiiToLists(float percent, std::vector< Shape > &shapeFamilies, std::mt19937_64 &generator, Distributions &distributions)
int cdfIdxFromFamNum(float *CDF, bool *p32Status, int famIdx)
struct Poly generatePoly_withRadius(double radius, struct Shape &shapeFam, std::mt19937_64 &generator, Distributions &distributions, int familyIndex)
double * vertices
Definition: structures.h:70
bool forceLargeFractures
Definition: readInput.cpp:102
float expLambda
Definition: structures.h:470
float min
Definition: structures.h:499
void generateRadiiLists_nPolyOption(std::vector< Shape > &shapeFamilies, float *famProb, std::mt19937_64 &generator, Distributions &distributions)
float alpha
Definition: structures.h:505
float * famProb
Definition: readInput.cpp:133
short distributionType
Definition: structures.h:396
bool domainTruncation(Poly &newPoly, double *domainSize)
Definition: domain.cpp:19
float mean
Definition: structures.h:482
double xradius
Definition: structures.h:40
void reTranslatePoly(struct Poly &newPoly, struct Shape &shapeFam, std::mt19937_64 &generator)
struct Poly generatePoly(struct Shape &shapeFam, std::mt19937_64 &generator, Distributions &distributions, int familyIndex, bool useList)
Definition: insertShape.cpp:26
void printGeneratingFracturesLessThanHWarning(int famIndex, Shape &shapeFam)
double getLargestFractureRadius(Shape &shapeFam)
bool * p32Status
Definition: readInput.cpp:468
float area
Definition: structures.h:33
short shapeFamily
Definition: structures.h:393
double domainSize[3]
Definition: readInput.cpp:18
ExpDist * expDist
Definition: distributions.h:20
void addRadii(int amountToAdd, int famIdx, Shape &shapeFam, std::mt19937_64 &generator, Distributions &distributions)
int indexFromProb_and_P32Status(float *CDF, double roll, int famSize, int cdfSize, int &cdfIdx)
double h
Definition: readInput.cpp:21
void sortRadii(std::vector< Shape > &shapeFam)
double minDistInput
Definition: structures.h:457
float * layerVol
Definition: readInput.cpp:447