Chi-Tech
chi_surfacemesh_meshstats.cc
Go to the documentation of this file.
1#include "chi_surfacemesh.h"
2
4
5#include "chi_runtime.h"
6#include "chi_log.h"
7
8#include <algorithm>
9
10//###################################################################
11/**Checks for cyclic dependencies in this mesh.
12 * Transport type sweeps have a step where the inter-cell dependency
13 * is acyclically sorted. This step is repeated here.*/
15{
16 double tolerance = 1.0e-8;
17 double dvarphi = 2.0*M_PI/num_angles;
18 chi_mesh::Vector3 khat(0.0, 0.0, 1.0);
19
20
21 //================================================== Loop over angles
22 for (int a=0; a<num_angles; a++)
23 {
24 double varphi = 0.5*dvarphi + a*dvarphi;
25
27 omega.x = cos(varphi);
28 omega.y = sin(varphi);
29 omega.z = 0.0;
30
31 //================================= Add all polyfaces to graph
33 size_t num_loc_cells = poly_faces_.size();
34 for (size_t c=0; c<num_loc_cells; c++)
35 G.AddVertex();
36
37 //================================= Now construct dependencies
38 for (size_t c=0; c<num_loc_cells; c++)
39 {
41
42 size_t num_edges = face->edges.size();
43 for (size_t e=0; e<num_edges; e++)
44 {
45 int v0i = face->edges[e][0];
46 int v1i = face->edges[e][1];
47
48 chi_mesh::Vector3 v01 = vertices_[v1i] - vertices_[v0i];
49 chi_mesh::Vector3 n = v01.Cross(khat); n= n / n.Norm();
50
51 double mu = omega.Dot(n);
52 int neighbor = face->edges[e][2];
53 if ( (mu > (0.0 + tolerance)) and (neighbor >= 0))
54 {
55// boost::add_edge(c,neighbor,G);
56 G.AddEdge(c,neighbor);
57 }//if outgoing
58 }//for edge
59 }//for cell
60
61 //================================================== Generic topological
62 // sorting
63// typedef boost::graph_traits<CHI_D_GRAPH>::vertex_descriptor gVertex;
64//
65// boost::property_map<CHI_D_GRAPH, boost::vertex_index_t>::type
66// index_map = get(boost::vertex_index, G);
67//
68// std::vector<gVertex> sorted_list;
69// try{
70// boost::topological_sort(G,std::back_inserter(sorted_list));
71// }
72// catch (const boost::bad_graph& exc)
73// {
74// chi::log.LogAllError()
75// << "Function CheckCyclicDependencies. Detected cyclic depency.";
76// chi::Exit(EXIT_FAILURE);
77// }
78
79 auto topological_order = G.GenerateTopologicalSort();
80 if (topological_order.empty())
81 {
83 << "Function CheckCyclicDependencies. Detected cyclic depency.";
84 Chi::Exit(EXIT_FAILURE);
85 }
86
87 //================================= Cleanup
88 G.Clear();
89 }//for angles
90
92
94 << "Cyclic dependency check complete. No cycles or "
95 << "bad mesh elements were detected";
96}
97
98//###################################################################
99/**Gets simple mesh statistics.
100 */
102{
103 std::vector<double> areas;
104 std::vector<double> histo_bins;
105 std::vector<int> histo;
106
107 int num_negative_areas = 0;
108
109
110 //============================================= Compute areas for
111 // each polyface
112 size_t num_loc_cells = poly_faces_.size();
113 areas.resize(num_loc_cells);
114 double max_area = 0.0;
115 for (size_t c=0; c<num_loc_cells; c++)
116 {
117 chi_mesh::PolyFace* face = poly_faces_[c];
118
119 size_t num_edges = face->edges.size();
120 double area = 0.0;
121 for (size_t e=0; e<num_edges; e++)
122 {
123 int v0i = face->edges[e][0];
124 int v1i = face->edges[e][1];
125
126 chi_mesh::Vector3 v01 = vertices_[v1i] - vertices_[v0i];
127 chi_mesh::Vector3 v02 = face->face_centroid - vertices_[v0i];
128
129 //This is essentially the combine of the triangle for each side
130
131 area += 0.5*(v01.x*v02.y - v01.y*v02.x);
132 }//for edge
133
134 areas[c] = area;
135 if (area > max_area)
136 max_area = area;
137
138 if (area <= 0.0)
139 num_negative_areas += 1;
140 }//for cell
141
142 //============================================= Sort the areas
143 std::sort(areas.begin(),areas.end(),std::greater<double>());
144
145 //============================================= Compute histogram bins
146 histo_bins.resize(10);
147 histo.resize(10,0);
148 histo_bins[0] = max_area*1.05;
149 for (int i=1;i<10; i++)
150 histo_bins[i] = histo_bins[i-1]/2.0;
151
152 //============================================= Polulate histogram
153 for (auto area : areas)
154 {
155 int home_bin = 9;
156 for (int i=0;i<10; i++)
157 {
158
159 if (area <= histo_bins[i])
160 home_bin = i;
161
162 }//check bins
163
164 histo[home_bin] += 1;
165 }//for areas
166
167
168 std::stringstream output;
169 for (int i=0;i<10; i++)
170 {
171 char buff[100];
172 snprintf(buff,100,"%11.3e",histo_bins[i]);
173
174 output << "Areas < " << buff << " = " << histo[i] << "\n";
175 }
176 output << "Number of negative or zero faces = " << num_negative_areas;
177
178 Chi::log.Log() << output.str();
179
180}
181
182
183//###################################################################
184/**Computes load balancing parameters from a set of predictive cuts.
185 * Does not actually perform these cuts.*/
187 std::vector<double> &x_cuts,
188 std::vector<double> &y_cuts)
189{
190 Chi::log.Log() << "X-cuts to be logged: " << x_cuts.size();
191// for (auto& val : x_cuts)
192// chi::log.Log() << val;
193//
194 Chi::log.Log() << "Y-cuts to be logged: " << y_cuts.size();
195// for (auto& val : y_cuts)
196// chi::log.Log() << val;
197
198 //======================================== Sort faces into bins
199 size_t I = x_cuts.size();
200 size_t J = y_cuts.size();
201
202 std::vector<std::vector<int>> IJ_bins(I+1,std::vector<int>(J+1,0));
203
204 for (auto& poly_face : poly_faces_)
205 {
206 int ref_i = 0;
207 int ref_j = 0;
208 for (size_t i=0; i<I; ++i)
209 {
210 if (poly_face->face_centroid.x >= x_cuts[i])
211 ref_i = i+1;
212 }//for i
213 for (size_t j=0; j<J; ++j)
214 {
215 if (poly_face->face_centroid.y >= y_cuts[j])
216 ref_j = j+1;
217 }//for j
218
219 IJ_bins[ref_i][ref_j] += 1;
220 }//for face
221
222 //======================================== Determine average and max
223 int max_bin_size = 0;
224 int tot_bin_size = 0;
225 int i_max = 0, j_max = 0;
226
227 for (int i=0; i<(I+1); ++i)
228 {
229 for (int j=0; j<(J+1); ++j)
230 {
231 if (IJ_bins[i][j] > max_bin_size)
232 {
233 max_bin_size = IJ_bins[i][j];
234 i_max = i;
235 j_max = j;
236 }
237 tot_bin_size += IJ_bins[i][j];
238 }
239 }
240
241 double average = tot_bin_size/((double)(I+1)*(J+1));
242
243 Chi::log.Log() << "Average faces per set: " << average;
244 Chi::log.Log()
245 << "Maximum faces per set: " << max_bin_size
246 << " at (i,j)= ( " << i_max << " , " << j_max << " )";
247
248 if (i_max == I) Chi::log.Log() << "X greater than " << x_cuts[i_max-1];
249 else if (i_max == 0)
250 Chi::log.Log() << "X less than " << x_cuts[0];
251 else
252 Chi::log.Log()
253 << "X greater than " << x_cuts[i_max-1]
254 << " and less than " << x_cuts[i_max];
255
256 if (j_max == J) Chi::log.Log() << "Y greater than " << y_cuts[j_max-1];
257 else if (j_max == 0)
258 Chi::log.Log() << "Y less than " << y_cuts[0];
259 else
260 Chi::log.Log()
261 << "Y greater than " << y_cuts[j_max-1]
262 << " and less than " << y_cuts[j_max];
263
264 Chi::log.Log()
265 << "Max-to-average ratio: " << max_bin_size/average;
266
267
268}
static void Exit(int error_code)
Definition: chi_runtime.cc:342
static chi::ChiLog & log
Definition: chi_runtime.h:81
LogStream LogAllError()
Definition: chi_log.h:239
LogStream Log(LOG_LVL level=LOG_0)
Definition: chi_log.cc:35
std::vector< size_t > GenerateTopologicalSort()
void AddVertex(size_t id, void *context=nullptr)
bool AddEdge(size_t from, size_t to, double weight=1.0)
void ComputeLoadBalancing(std::vector< double > &x_cuts, std::vector< double > &y_cuts)
void CheckCyclicDependencies(int num_angles)
std::vector< chi_mesh::PolyFace * > poly_faces_
Polygonal faces.
std::vector< chi_mesh::Vertex > vertices_
std::vector< int * > edges
Definition: chi_meshface.h:92
chi_mesh::Vertex face_centroid
Definition: chi_meshface.h:96
double x
Element-0.
Vector3 Cross(const Vector3 &that) const
Vector3 Dot(const chi_mesh::TensorRank2Dim3 &that) const
double y
Element-1.
double z
Element-2.
double Norm() const