Chi-Tech
volmesher_extruder_utils.cc
Go to the documentation of this file.
2
5
6#include "chi_runtime.h"
7#include "chi_log.h"
8
9
10//###################################################################
11/** Creates actual z-levels for the input layer specification.*/
13{
14 //================================================== Create default layers if no
15 // input layers are provided
16 if (input_layers_.empty())
17 {
19 << "VolumeMesherExtruder: No extrusion layers have been specified. "
20 << "A default single layer will be used with height 1.0 and a single "
21 << "subdivision.";
22 double dz = 1.0/default_layer_count;
23 for (int k=0; k<=default_layer_count; k++)
24 {
25 vertex_layers_.push_back(k * dz);
26 }
27 }
28 else
29 {
30 double last_z=0.0;
31 vertex_layers_.push_back(last_z);
32
33 for (const auto& input_layer : input_layers_)
34 {
35 double dz = input_layer.height/input_layer.sub_divisions;
36
37 for (int k=0; k<input_layer.sub_divisions; k++)
38 {
39 last_z += dz;
40 vertex_layers_.push_back(last_z);
41 }
42 }
43 }
44
46 << "VolumeMesherExtruder: Total number of cell layers is "
47 << vertex_layers_.size() - 1;
48}
49
50//###################################################################
51/**Projects a centroid to an extruded equivalent layer.*/
54 const size_t level)
55{
56 double z_location = 0.5 * (vertex_layers_[level] + vertex_layers_[level + 1]);
57
58 auto centroid_projected = centroid;
59 centroid_projected.z = z_location;
60
61 return centroid_projected;
62}
63
64//###################################################################
65/**Computes a cell's partition id based on a centroid.*/
68{
69 int px = options.partition_x;
70 int py = options.partition_y;
71
73 n_gcell.centroid_ = centroid;
74
75 auto xyz_partition_indices = GetCellXYZPartitionID(&n_gcell);
76
77 int nxi = std::get<0>(xyz_partition_indices);
78 int nyi = std::get<1>(xyz_partition_indices);
79 int nzi = std::get<2>(xyz_partition_indices);
80
81 return nzi*px*py + nyi*px + nxi;
82}
83
84
85//###################################################################
86/**Determines if a template cell is in the current partition or a
87 * direct neighbor to the current partition.*/
90 const chi_mesh::Cell& template_cell,
91 const chi_mesh::MeshContinuum& template_continuum,
92 size_t z_level)
93{
94 //======================================== Check if the template cell
95 // is in the current partition
96 {
97 auto& centroid = template_cell.centroid_;
98 auto projected_centroid = ProjectCentroidToLevel(centroid, z_level);
99 int pid = GetCellKBAPartitionIDFromCentroid(projected_centroid);
100 if (pid == Chi::mpi.location_id)
101 return true;
102 }
103
104 const size_t last_z_level = vertex_layers_.size() - 1;
105 const size_t z_level_below = z_level - 1;
106 const size_t z_level_above = z_level + 1;
107
108 //======================================== Build z-levels to search
109 std::vector<size_t> z_levels_to_search;
110 z_levels_to_search.reserve(3);
111
112 z_levels_to_search.push_back(z_level);
113 if (z_level != 0) z_levels_to_search.push_back(z_level_below);
114 if (z_level != (last_z_level-1)) z_levels_to_search.push_back(z_level_above);
115
116 //======================================== Search template cell's
117 // lateral neighbors
118 const auto& vertex_subs =
119 template_unpartitioned_mesh_->GetVertextCellSubscriptions();
120 for (uint64_t vid : template_cell.vertex_ids_)
121 for (uint64_t cid : vertex_subs[vid])
122 {
123 if (cid == template_cell.local_id_) continue;
124
125 auto& candidate_cell =
126 template_continuum.local_cells[cid];
127 auto& cc_centroid = candidate_cell.centroid_;
128
129 for (size_t z : z_levels_to_search)
130 {
131 auto projected_centroid = ProjectCentroidToLevel(cc_centroid, z);
132 int pid = GetCellKBAPartitionIDFromCentroid(projected_centroid);
133 if (pid == Chi::mpi.location_id)
134 return true;
135 }
136 }//for cid
137
138 //======================================== Search template cell's
139 // longitudinal neighbors
140 for (size_t z : z_levels_to_search)
141 {
142 if (z == z_level) continue;
143
144 auto projected_centroid = ProjectCentroidToLevel(template_cell.centroid_, z);
145 int pid = GetCellKBAPartitionIDFromCentroid(projected_centroid);
146 if (pid == Chi::mpi.location_id)
147 return true;
148 }//for z
149
150 return false;
151}
152
153//###################################################################
154/**Makes an extruded cell from a template cell.*/
155std::unique_ptr<chi_mesh::Cell> chi_mesh::VolumeMesherExtruder::
156 MakeExtrudedCell(const chi_mesh::Cell &template_cell,
157 const chi_mesh::MeshContinuum &grid,
158 size_t z_level,
159 uint64_t cell_global_id,
160 int partition_id,
161 size_t num_template_cells)
162{
163 const size_t tc_num_verts = template_cell.vertex_ids_.size();
164
165 //========================================= Determine cell sub-type
166 CellType extruded_subtype;
167 switch (template_cell.SubType())
168 {
169 case CellType::TRIANGLE: extruded_subtype = CellType::WEDGE; break;
170 case CellType::QUADRILATERAL: extruded_subtype = CellType::HEXAHEDRON; break;
171 default: extruded_subtype = CellType::POLYHEDRON;
172 }
173
174 //========================================= Create polyhedron
175 auto cell = std::make_unique<chi_mesh::Cell>(CellType::POLYHEDRON,
176 extruded_subtype);
177 cell->global_id_ = cell_global_id;
178 //cell->local_id set when added to mesh
179 cell->partition_id_ = partition_id;
180 cell->centroid_ = ProjectCentroidToLevel(template_cell.centroid_, z_level);
181
182 //========================================= Populate cell v-indices
183 cell->vertex_ids_.reserve(2 * tc_num_verts);
184 for (auto tc_vid : template_cell.vertex_ids_)
185 cell->vertex_ids_.push_back(tc_vid + z_level * node_z_index_incr_);
186
187 for (auto tc_vid : template_cell.vertex_ids_)
188 cell->vertex_ids_.push_back(tc_vid + (z_level + 1) * node_z_index_incr_);
189
190
191 //========================================= Create side faces
192 for (auto& face : template_cell.faces_)
193 {
194 chi_mesh::CellFace newFace;
195
196 newFace.vertex_ids_.resize(4, -1);
197 newFace.vertex_ids_[0] = face.vertex_ids_[0] + z_level * node_z_index_incr_;
198 newFace.vertex_ids_[1] = face.vertex_ids_[1] + z_level * node_z_index_incr_;
199 newFace.vertex_ids_[2] = face.vertex_ids_[1] + (z_level + 1) * node_z_index_incr_;
200 newFace.vertex_ids_[3] = face.vertex_ids_[0] + (z_level + 1) * node_z_index_incr_;
201
202 //Compute centroid
203 const auto& v0 = grid.vertices[newFace.vertex_ids_[0]];
204 const auto& v1 = grid.vertices[newFace.vertex_ids_[1]];
205 const auto& v2 = grid.vertices[newFace.vertex_ids_[2]];
206 const auto& v3 = grid.vertices[newFace.vertex_ids_[3]];
207
208 chi_mesh::Vertex vfc = (v0+v1+v2+v3)/4.0;
209 newFace.centroid_ = vfc;
210
211 //Compute normal
212 chi_mesh::Vector3 va = v0 - vfc;
213 chi_mesh::Vector3 vb = v1 - vfc;
214
215 chi_mesh::Vector3 vn = va.Cross(vb);
216
217 newFace.normal_ = (vn / vn.Norm());
218
219 //Set neighbor
220 //The side connections have the same connections as the
221 //template cell + the z_level specifiers of the layer.
222 if (face.has_neighbor_)
223 {
224 newFace.neighbor_id_ = face.neighbor_id_ +
225 z_level*num_template_cells;
226 newFace.has_neighbor_ = true;
227 }
228 else
229 newFace.neighbor_id_ = face.neighbor_id_;
230
231 cell->faces_.push_back(newFace);
232 } //for side faces
233
234 //========================================= Create top and bottom faces
235 //=============================== Bottom face
236 {
237 chi_mesh::CellFace newFace;
238 //Vertices
239 auto vfc = chi_mesh::Vertex(0.0,0.0,0.0);
240 newFace.vertex_ids_.reserve(tc_num_verts);
241 for (int tv=(static_cast<int>(tc_num_verts)-1); tv>=0; tv--)
242 {
243 newFace.vertex_ids_.push_back(template_cell.vertex_ids_[tv]
244 + z_level * node_z_index_incr_);
245 const auto& v = grid.vertices[newFace.vertex_ids_.back()];
246 vfc = vfc + v;
247 }
248
249 //Compute centroid
250 vfc = vfc/static_cast<double>(tc_num_verts);
251 newFace.centroid_ = vfc;
252
253 //Compute normal
254 auto va = grid.vertices[newFace.vertex_ids_[0]] - vfc;
255 auto vb = grid.vertices[newFace.vertex_ids_[1]] - vfc;
256
257 auto vn = va.Cross(vb);
258 newFace.normal_ = vn / vn.Norm();
259
260 //Set neighbor
261 if (z_level==0)
262 {
263 newFace.neighbor_id_ = zmin_bndry_id;
264 newFace.has_neighbor_ = false;
265 }
266 else
267 {
268 newFace.neighbor_id_ = template_cell.local_id_ +
269 (z_level-1)*num_template_cells;
270 newFace.has_neighbor_ = true;
271 }
272
273 cell->faces_.push_back(newFace);
274 }
275
276 //=============================== Top face
277 {
278 chi_mesh::CellFace newFace;
279 //Vertices
280 auto vfc = chi_mesh::Vertex(0.0,0.0,0.0);
281 newFace.vertex_ids_.reserve(tc_num_verts);
282 for (auto tc_vid : template_cell.vertex_ids_)
283 {
284 newFace.vertex_ids_.push_back(tc_vid + (z_level + 1) * node_z_index_incr_);
285 const auto& v = grid.vertices[newFace.vertex_ids_.back()];
286 vfc = vfc + v;
287 }
288
289 //Compute centroid
290 vfc = vfc/static_cast<double>(tc_num_verts);
291 newFace.centroid_ = vfc;
292
293 //Compute normal
294 auto va = grid.vertices[newFace.vertex_ids_[0]] - vfc;
295 auto vb = grid.vertices[newFace.vertex_ids_[1]] - vfc;
296
297 auto vn = va.Cross(vb);
298 newFace.normal_ = vn / vn.Norm();
299
300 //Set neighbor
301 if (z_level==(vertex_layers_.size() - 2))
302 {
303 newFace.neighbor_id_ = zmax_bndry_id;
304 newFace.has_neighbor_ = false;
305 }
306 else
307 {
308 newFace.neighbor_id_ = template_cell.local_id_ +
309 (z_level+1)*num_template_cells;
310 newFace.has_neighbor_ = true;
311 }
312
313 cell->faces_.push_back(newFace);
314 }
315
316 return cell;
317}
static chi::ChiLog & log
Definition: chi_runtime.h:81
static chi::MPI_Info & mpi
Definition: chi_runtime.h:78
LogStream Log0Warning()
Definition: chi_log.h:231
LogStream Log(LOG_LVL level=LOG_0)
Definition: chi_log.cc:35
Normal normal_
A list of the vertices.
Definition: cell.h:39
bool has_neighbor_
Flag indicating whether face has a neighbor.
Definition: cell.h:41
uint64_t neighbor_id_
Otherwise contains boundary_id.
Definition: cell.h:42
std::vector< uint64_t > vertex_ids_
Definition: cell.h:38
Vertex centroid_
The face centroid.
Definition: cell.h:40
std::vector< CellFace > faces_
Definition: cell.h:82
CellType SubType() const
Definition: cell.h:99
uint64_t local_id_
Definition: cell.h:76
Vertex centroid_
Definition: cell.h:78
std::vector< uint64_t > vertex_ids_
Definition: cell.h:81
LocalCellHandler local_cells
chi_mesh::Vector3 ProjectCentroidToLevel(const chi_mesh::Vector3 &centroid, size_t level)
bool HasLocalScope(const chi_mesh::Cell &template_cell, const chi_mesh::MeshContinuum &template_continuum, size_t z_level)
int GetCellKBAPartitionIDFromCentroid(chi_mesh::Vector3 &centroid)
std::unique_ptr< chi_mesh::Cell > MakeExtrudedCell(const chi_mesh::Cell &template_cell, const chi_mesh::MeshContinuum &grid, size_t z_level, uint64_t cell_global_id, int partition_id, size_t num_template_cells)
std::vector< MeshLayer > input_layers_
std::vector< double > vertex_layers_
void SetupLayers(int default_layer_count=1)
CellType
Definition: cell.h:12
Vector3 Vertex
Definition: chi_mesh.h:20
Vector3 Cross(const Vector3 &that) const
double z
Element-2.
double Norm() const