Chi-Tech
chi_ffinter_slice_initialize.cc
Go to the documentation of this file.
1#include "chi_ffinter_slice.h"
2#include "mesh/Cell/cell.h"
3
5
9
10#include "chi_runtime.h"
11#include "chi_log.h"
12
13/**Initializes the data structures necessary for interpolation. This is
14 * independent of the physics and hence is a routine on its own.
15 *
16 * The first step of this initialization is to determine which cells
17 * are intersected by this plane. For polyhedrons this is evaluated
18 * tet-by-tet.
19 *
20 * The second step is find where face-edges are intersected. This will
21 * effectively create intersection polygons.*/
24{
25 Chi::log.Log0Verbose1() << "Initializing slice interpolator.";
26 //================================================== Check grid available
27 if (field_functions_.empty())
28 throw std::logic_error("Unassigned field function in slice "
29 "field function interpolator.");
30
31 const auto& grid =
32 field_functions_.front()->GetSpatialDiscretization().Grid();
33
34 //================================================== Find cells intersecting
35 // plane
36 std::vector<uint64_t> intersecting_cell_indices;
37
38 for (const auto& cell : grid.local_cells)
39 {
40 auto cell_local_index = cell.local_id_;
41
42 if (cell.Type() == chi_mesh::CellType::SLAB)
43 throw std::logic_error("FieldFunctionInterpolationSlice "
44 "does not support 1D cells.");
45 if (cell.Type() == chi_mesh::CellType::POLYGON)
46 intersecting_cell_indices.push_back(cell_local_index);
47 else if (cell.Type() == chi_mesh::CellType::POLYHEDRON)
48 {
49 bool intersects = false;
50
51 size_t num_faces = cell.faces_.size();
52 for (size_t f=0; f<num_faces; f++)
53 {
54 const auto& face = cell.faces_[f];
55
56 size_t num_edges = face.vertex_ids_.size();
57 for (size_t e=0; e<num_edges; e++)
58 {
59 size_t ep1 = (e < (num_edges-1))? e+1 : 0;
60 uint64_t v0_i = face.vertex_ids_[e];
61 uint64_t v1_i = face.vertex_ids_[ep1];
62
63 std::vector<chi_mesh::Vector3> tet_points;
64
65 tet_points.push_back(grid.vertices[v0_i]);
66 tet_points.push_back(grid.vertices[v1_i]);
67 tet_points.push_back(cell.faces_[f].centroid_);
68 tet_points.push_back(cell.centroid_);
69
70 if (CheckPlaneTetIntersect(this->normal_, this->plane_point_, tet_points))
71 {
72 intersecting_cell_indices.push_back(cell_local_index);
73 intersects = true;
74 break;//from for e
75 }
76 }//for e
77 if (intersects) break; //from for f
78 }//for f
79 }
80 else
81 throw std::logic_error("Unsupported cell type in call "
82 "to Slice Initialize.");
83 }//for local cell
84
85 //================================================== Computing cell
86 // intersections
87 for (const uint64_t cell_local_index : intersecting_cell_indices)
88 {
89 const auto& cell = grid.local_cells[cell_local_index];
90
91 if (cell.Type() == chi_mesh::CellType::POLYGON)
92 {
93 FFICellIntersection cell_isds;
94 cell_isds.ref_cell_local_id = cell_local_index;
95
96 //========================================= Loop over vertices
97 for (uint64_t v0gi : cell.vertex_ids_)
98 {
100
101 const auto nudge = 1.0e-4*(grid.vertices[v0gi] - cell.centroid_);
102
103 face_isds.point = grid.vertices[v0gi] - nudge;
104 face_isds.point2d = grid.vertices[v0gi];
105 cell_isds.intersections.push_back(face_isds);
106 }
107
108 //========================================= Set intersection center
109 cell_isds.intersection_centre = cell.centroid_;
110
111 //========================================= Set straight 2D center
112 // This is normally transformed for the 3D case
113 cell_isds.intersection_2d_centre = cell.centroid_;
114
115 //========================================= Same for 2D points
116 size_t num_points = cell_isds.intersections.size();
117 for (size_t p=0; p<num_points; p++)
118 {
119 chi_mesh::Vector3 vref = cell_isds.intersections[p].point - plane_point_;
120
121 cell_isds.intersections[p].point2d = vref;
122 }
123
124 cell_intersections_.push_back(cell_isds);
125 }//polygon
126 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% POLYHEDRON
127 else if (cell.Type() == chi_mesh::CellType::POLYHEDRON)
128 {
129 //========================================= Initialize cell intersection
130 // data structure
131 FFICellIntersection cell_isds;
132 cell_isds.ref_cell_local_id = cell_local_index;
133
134 //========================================= Loop over faces
135 size_t num_faces = cell.faces_.size();
136 for (size_t f=0; f<num_faces; f++)
137 {
138 const auto& face = cell.faces_[f];
139 //================================== Loop over edges
140 size_t num_edges = face.vertex_ids_.size();
141 for (size_t e=0; e<num_edges; e++)
142 {
143 size_t ep1 = (e < (num_edges-1))? e+1 : 0;
144 uint64_t v0gi = face.vertex_ids_[e ]; //global index v0
145 uint64_t v1gi = face.vertex_ids_[ep1]; //global index v1
146
147 const auto& v0 = grid.vertices[v0gi];
148 const auto& v1 = grid.vertices[v1gi];
149
150 chi_mesh::Vertex interstion_point; //Placeholder
151 std::pair<double,double> weights;
152
153 //=========================== Check if intersects plane
155 v0, v1, interstion_point,
156 &weights))
157 {
158 //==================== Check for duplicate
159 bool duplicate_found = false;
160 for (auto& existing_face_isds : cell_isds.intersections)
161 {
162 double dif = (existing_face_isds.point -
163 interstion_point).NormSquare();
164 if (dif < 1.0e-6)
165 {
166 duplicate_found = true;
167 break;
168 }
169 }
170
171 //==================== No duplicate
172 if (!duplicate_found)
173 {
174 FFIFaceEdgeIntersection face_isds;
175
176 face_isds.point = interstion_point;
177 cell_isds.intersections.push_back(face_isds);
178 }
179 }//if intersecting
180 }//for edge
181 }//for face
182
183 //====================================
184
185 //==================================== Computing intersection centre
186 size_t num_points = cell_isds.intersections.size();
187 if (num_points>0)
188 {
189 for (int p=0; p<num_points; p++)
190 {
191 cell_isds.intersection_centre =
192 cell_isds.intersection_centre +
193 cell_isds.intersections[p].point;
194 }
195 cell_isds.intersection_centre =
196 cell_isds.intersection_centre/static_cast<double>(num_points);
197 }
198 else
199 {
200 Chi::log.LogAllWarning() << "No face intersections encountered "
201 "for a cell that is indicated as being "
202 "intersected. Slice FF interp.";
203 }
204
205 //==================================== Computing 2D transforms
207
208 cell_isds.intersection_2d_centre.x = vref.Dot(tangent_);
209 cell_isds.intersection_2d_centre.y = vref.Dot(binorm_);
210 cell_isds.intersection_2d_centre.z = vref.Dot(normal_);
211
212 //==================================== Points
213 std::vector<FFIFaceEdgeIntersection> unsorted_points;
214 for (int p=0; p<num_points; p++)
215 {
216 vref = cell_isds.intersections[p].point - plane_point_;
217
218 cell_isds.intersections[p].point2d.x = vref.Dot(tangent_);
219 cell_isds.intersections[p].point2d.y = vref.Dot(binorm_);
220 cell_isds.intersections[p].point2d.z = vref.Dot(normal_);
221
222 unsorted_points.push_back(cell_isds.intersections[p]);
223 }
224 cell_isds.intersections.clear();
225
226 //==================================== Sort points clockwise
227 //The first point is retrieved from the unused stack.
228 //Subsequent points are only added if they form a
229 //convex line wrt the right hand rule.
230 cell_isds.intersections.push_back(unsorted_points[0]);
231 unsorted_points.erase(unsorted_points.begin());
232
233 while (!unsorted_points.empty())
234 {
235 for (int p=0; p<unsorted_points.size(); p++)
236 {
237 chi_mesh::Vector3 v1 = unsorted_points[p].point2d -
238 cell_isds.intersections.back().point2d;
239
240 bool illegal_value = false;
241 for (int pr=0; pr<unsorted_points.size(); pr++)
242 {
243 if (pr!=p)
244 {
245 chi_mesh::Vector3 vr = unsorted_points[pr].point2d -
246 unsorted_points[p].point2d;
247
248 if (vr.Cross(v1).z < 0.0)
249 {
250 illegal_value = true;
251 break;
252 }
253 }//if not p
254 }//for pr
255
256 if (!illegal_value)
257 {
258 cell_isds.intersections.push_back(unsorted_points[p]);
259 unsorted_points.erase(unsorted_points.begin()+p);
260 break;
261 }
262
263 }//for p
264 }
265 cell_intersections_.push_back(cell_isds);
266 }//polyhedron
267 }//for intersected cell
268
269 //chi::log.Log() << "Finished initializing interpolator.";
270}
static chi::ChiLog & log
Definition: chi_runtime.h:81
LogStream LogAllWarning()
Definition: chi_log.h:238
LogStream Log0Verbose1()
Definition: chi_log.h:234
std::vector< chi_physics::FieldFunctionGridBasedPtr > field_functions_
std::vector< FFICellIntersection > cell_intersections_
bool CheckPlaneTetIntersect(const chi_mesh::Normal &plane_normal, const chi_mesh::Vector3 &plane_point, const std::vector< chi_mesh::Vector3 > &tet_points)
bool CheckPlaneLineIntersect(const chi_mesh::Normal &plane_normal, const chi_mesh::Vector3 &plane_point, const chi_mesh::Vector3 &line_point_0, const chi_mesh::Vector3 &line_point_1, chi_mesh::Vector3 &intersection_point, std::pair< double, double > *weights=nullptr)
chi_mesh::Vector3 intersection_2d_centre
chi_mesh::Vector3 intersection_centre
std::vector< FFIFaceEdgeIntersection > intersections
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.