DFNgen  2.0
DFN Model Generator
clusterGroups.cpp
Go to the documentation of this file.
1 #include <vector>
2 #include <iostream>
3 #include "clusterGroups.h"
4 #include "structures.h"
5 #include "input.h"
6 #include "mathFunctions.h"
7 
8 /* This code goes through all the polygons accepted into the domain and returns the indexes to those polygons
9  which match the users boundary faces option.
10  Isoloated fractures and Polygons with no intersections are removed
11 
12 groupData structure:
13 ***********************
14  groupData keeps information as to how many polygons are in the group or cluster. It also keeps
15  track of the boundary faces which the cluster is in contact with. There is also a valid variable (0 or 1).
16  If a polygon connects two different groups, one of the groups is merged together with the other. The one which
17  nolonger exists has it's valid variable set to 0.
18 
19  The groupData structure array, or vector, is aligned with the group numbers. If you want to know about group 3 for
20  example, you will look at groupData[ (3-1) ], minus 1 because the array starts at 0 while groups start at 1.
21  If valid = 1 in the structure, that group still exists and has not been merged
22 
23 fractGroups structure:
24 *************************
25  fractGroups[] holds the actual pointers/index numbers to the polygon array along with the group number. Unlike
26  groupData[] described above, fractGroups does not stay aligned to group numbers. To keep from copying, deleteing, and
27  re-allocating memory when groups merge together, we simply change the variable groupNum to the new group number.
28 
29  Because of this, there will be multiples of the same group numbers, but with differnt polygons listed. To get all the
30  polygons from a group we must search the fractGroups array for all matching groups
31 */
32 
33 /***********************************************************************************/
34 /********************* Get Matching Fracture Clusters ****************************/
45 std::vector<unsigned int> getCluster(Stats &pstats){
46  // The max number of groups is pstats.nextGroupNum - 1
47  std::vector<unsigned int> matchingGroups;
48  std::vector<unsigned int> finalPolyList;
49 
50 
51 // NOTE: (groupNumber-1) = corresponding groupData structures' index of the arary
52 // similarly, the index of groupData + 1 = groupNumber (due to groupNumber starting at 1, array starting at 0)
53 
54  // Find all matching groups:
55  // Get matching groups from pstats.groupData[]
56  for (unsigned int i = 0; i < pstats.groupData.size(); i++) {
57  // If the data is valid, meaning that group still exists (hasn't been merged to a new group) and
58  // if the group has more than 1 fracture meaning there are intersections and
59  // the cluster matches the reqirements of the user's boundaryFaces option
60  if (ignoreBoundaryFaces == 0) {
61  if (pstats.groupData[i].valid == 1 && pstats.groupData[i].size > 1 && facesMatch(boundaryFaces, pstats.groupData[i].faces)) {
62  matchingGroups.push_back(i+1);//save matching group number
63  }
64  }
65  else { // Get all cluster groups
66  if (pstats.groupData[i].valid == 1 && pstats.groupData[i].size > 1) {
67  matchingGroups.push_back(i+1); // Save matching group number
68  }
69  }
70  }
71 
72  if (keepOnlyLargestCluster == 1 && matchingGroups.size() > 1) {
73  // If only keeping the largest cluster, find group with largest size
74 
75  // Initialize largestGroup
76  unsigned int largestGroup = matchingGroups[0];
77  for (unsigned int i = 0; i < matchingGroups.size(); i++) {
78  // If largest group < current group, the current group is the new largest group
79  if (largestGroup < pstats.groupData[matchingGroups[i]-1].size){
80  largestGroup = matchingGroups[i];
81  }
82  }
83 
84  matchingGroups.clear(); // Clear group numbers
85  matchingGroups.push_back(largestGroup); // Save only the largest group
86  }
87 
88  // Gather the final polygon numbers/indecies.
89  for (unsigned int i = 0; i < matchingGroups.size(); i++){
90  for (unsigned int k = 0; k < pstats.fractGroup.size(); k++){
91  if (matchingGroups[i] == pstats.fractGroup[k].groupNum) {
92  // If the groupNumbers match
93  // copy all poly indecies of matching group
94  for (unsigned int j = 0; j < pstats.fractGroup[k].polyList.size(); j++){
95  finalPolyList.push_back(pstats.fractGroup[k].polyList[j]);
96  }
97  }
98  }
99  }
100  return finalPolyList;
101 }
102 
103 
104 /***********************************************************************************/
105 /******* Test if Boundary Faces Option Match User's Desired Boundary Faces ********/
115 bool facesMatch(bool *facesOption, bool *faces){
116  for (int i = 0; i < 6; i++) {
117  // If the user specified the face, check if faces match
118  if (facesOption[i] == 1){
119  if ((facesOption[i] & faces[i]) == 0) {
120  return 0;
121  }
122  }
123  }
124  return 1;
125 }
126 
127 
128 /******************** Assign New Polygon to a Cluster ****************************/
129 /***********************************************************************************/
137 void assignGroup(Poly &newPoly, Stats &pstats, int newPolyIndex) {
138 
139  newPoly.groupNum = pstats.nextGroupNum;
140  GroupData newGroupData; // Keeps fracture cluster data
141  // Copy newPoly faces info to groupData
142  OR(newGroupData.faces, newPoly.faces);
143  // Incriment groupData's poly count
144  newGroupData.size++;
145  pstats.groupData.push_back(newGroupData); // Save boundary face information to permanent location
146  FractureGroups newGroup; // 'newPoly' had no intersections, put it in a new group
147  newGroup.groupNum = pstats.nextGroupNum; // Assign new group # to newGroup
148  pstats.nextGroupNum++;
149  newGroup.polyList.push_back(newPolyIndex); // Save index (number) of newPoly
150  pstats.fractGroup.push_back(newGroup);
151 
152 
153 }
154 
155 
156 
157 
158 /************************** Update Cluster Groups ********************************/
159 /***********************************************************************************/
192 void updateGroups(Poly &newPoly, std::vector<Poly> &acceptedPoly, std::vector<unsigned int> &encounteredGroups, Stats &pstats, int newPolyIndex) {
193 
194  if (encounteredGroups.size() == 0) {
195  // 'newPoly' didn't encounter more than 1 other group of fractures
196  // Save newPoly to the group structure
197 
198  unsigned int i = 0;
199  // Update boundary face info
200 
201  OR(pstats.groupData[newPoly.groupNum-1].faces, newPoly.faces);
202  // NOTE: Groups start at 1, but array starts at zero hence the groupNum-1 for index
203 
204  // Incriment the groups size for the new polygon
205  pstats.groupData[newPoly.groupNum-1].size++;
206 
207  // Search for group newPoly belongs to and add newPoly to it's list, add to first matching group found
208  while (pstats.fractGroup[i].groupNum != newPoly.groupNum && i != pstats.fractGroup.size()) {
209  i++;
210  }
211  // Error check
212  if (i == pstats.fractGroup.size() && pstats.fractGroup[i].groupNum != newPoly.groupNum ) {
213  std::cout<<"ERROR: Group not found (computationalGeometry.cpp)\n";
214  }
215 
216  // Add newPoly to fracture/cluster group
217  pstats.fractGroup[i].polyList.push_back(newPolyIndex);
218  }
219  else{
220  // Multiple cluter groups were encountered.
221  // Merge the groups (change/update the group numbers)
222  // Search for encountered groups and make them all have the same group numbers
223  // First, add newpoly to correct group
224 
225  int k = 0;
226  while (newPoly.groupNum != pstats.fractGroup[k].groupNum) {
227  k++;
228  }
229 
230  // Add new poly to the group
231  pstats.fractGroup[k].polyList.push_back(newPolyIndex);
232  // Incriment size of group by one for newPoly
233  pstats.groupData[newPoly.groupNum-1].size++;
234  // Add any boundary face data to group fro newPoly
235  OR(pstats.groupData[newPoly.groupNum-1].faces, newPoly.faces);
236 
237  // Need merge groups in encounteredGroups list to newPoly.groupNum
238  for (unsigned int i = 0; i < encounteredGroups.size(); i++) {
239  // Add merging groups size to new group's size
240  if (pstats.groupData[encounteredGroups[i]-1].valid == 1) {
241  pstats.groupData[newPoly.groupNum-1].size += pstats.groupData[encounteredGroups[i]-1].size;
242  // Merge any boundary faces data
243  OR(pstats.groupData[newPoly.groupNum-1].faces, pstats.groupData[encounteredGroups[i]-1].faces);
244  // Mark merged groups group data as invalid
245  pstats.groupData[encounteredGroups[i]-1].valid = 0;
246  }
247 
248  for (unsigned int jj = 0; jj < pstats.fractGroup.size(); jj++) {
249  if (pstats.fractGroup[jj].groupNum == encounteredGroups[i]) {
250  // Change group number to the new group number
251  pstats.fractGroup[jj].groupNum = newPoly.groupNum;
252  // Change polys group number inside the group to the new group num
253  for (unsigned int z = 0; z < pstats.fractGroup[jj].polyList.size(); z++) {
254  acceptedPoly[pstats.fractGroup[jj].polyList[z]].groupNum = newPoly.groupNum;
255  }
256  }
257  }
258  }
259  }
260 }
261 
bool faces[6]
Definition: structures.h:238
unsigned int groupNum
Definition: structures.h:30
std::vector< unsigned int > polyList
Definition: structures.h:212
bool boundaryFaces[6]
Definition: readInput.cpp:52
bool keepOnlyLargestCluster
Definition: readInput.cpp:61
void assignGroup(Poly &newPoly, Stats &pstats, int newPolyIndex)
std::vector< struct FractureGroups > fractGroup
Definition: structures.h:374
unsigned long long int groupNum
Definition: structures.h:210
void updateGroups(Poly &newPoly, std::vector< Poly > &acceptedPoly, std::vector< unsigned int > &encounteredGroups, Stats &pstats, int newPolyIndex)
void OR(bool *dest, bool *src)
Definition: mathFunctions.h:24
std::vector< unsigned int > getCluster(Stats &pstats)
bool facesMatch(bool *facesOption, bool *faces)
std::vector< struct GroupData > groupData
Definition: structures.h:376
unsigned long long int nextGroupNum
Definition: structures.h:336
bool ignoreBoundaryFaces
Definition: readInput.cpp:473
unsigned int size
Definition: structures.h:229
bool faces[6]
Definition: structures.h:84