Chi-Tech
unpartmesh_00d_vtk_copies.cc
Go to the documentation of this file.
2
3#include <vtkUnstructuredGrid.h>
4#include <vtkAppendFilter.h>
5
6#include <vtkCellData.h>
7#include <vtkPointData.h>
8
9#include "chi_runtime.h"
10#include "chi_log.h"
11
12// ###################################################################
13/**Copies the vtk data structures to the current object's internal
14 * data.*/
16 vtkUnstructuredGrid& ugrid, const double scale, int dimension_to_copy)
17{
18 const std::string fname =
19 "chi_mesh::UnpartitionedMesh::CopyUGridCellsAndPoints";
20 typedef chi_mesh::Vector3 Vec3;
21 typedef Vec3* Vec3Ptr;
22 typedef LightWeightCell* CellPtr;
23
24 const vtkIdType total_cell_count = ugrid.GetNumberOfCells();
25 const vtkIdType total_point_count = ugrid.GetNumberOfPoints();
26
27 bool has_cell_gids = ugrid.GetCellData()->GetGlobalIds();
28 bool has_pnts_gids = ugrid.GetPointData()->GetGlobalIds();
29 bool has_global_ids = has_cell_gids and has_pnts_gids;
30
31 const auto& block_id_array_name = mesh_options_.material_id_fieldname;
32
33 if (not ugrid.GetCellData()->GetArray(block_id_array_name.c_str()))
34 throw std::logic_error(fname + ": grid has no \"" + block_id_array_name +
35 "\" array.");
36
37 auto block_id_array = vtkIntArray::SafeDownCast(
38 ugrid.GetCellData()->GetArray(block_id_array_name.c_str()));
39
40 ChiLogicalErrorIf(not block_id_array,
41 "Failed to cast BlockID array to vtkInt");
42
43 if (has_global_ids)
44 {
45 std::vector<CellPtr> cells(total_cell_count, nullptr);
46 std::vector<Vec3Ptr> vertices(total_point_count, nullptr);
47
48 auto cell_gids_ptr = ugrid.GetCellData()->GetGlobalIds();
49 auto pnts_gids_ptr = ugrid.GetPointData()->GetGlobalIds();
50
51 auto cell_gids = vtkIdTypeArray::SafeDownCast(cell_gids_ptr);
52 auto pnts_gids = vtkIdTypeArray::SafeDownCast(pnts_gids_ptr);
53
54 //=========================================== Determine id offset
55 // We do this because some mesh formats (like ExodusII)
56 // are indexed with a 1 base instead of 0
57 int cid_offset = 0, pid_offset = 0;
58 {
59 vtkIdType min_cid = total_point_count; // Minimum cell-id
60 vtkIdType min_pid = total_point_count; // Minimum point-id
61
62 for (vtkIdType c = 0; c < total_cell_count; ++c)
63 min_cid = std::min(min_cid, cell_gids->GetValue(c));
64
65 for (vtkIdType p = 0; p < total_point_count; ++p)
66 min_pid = std::min(min_pid, pnts_gids->GetValue(p));
67
68 cid_offset -= static_cast<int>(min_cid);
69 pid_offset -= static_cast<int>(min_pid);
70 } // build offset
71
72 //=========================================== Build node map
73 std::vector<vtkIdType> node_map(total_point_count, 0);
74 for (vtkIdType p = 0; p < total_point_count; ++p)
75 node_map[p] = pnts_gids->GetValue(p) + pid_offset;
76
77 //=========================================== Load cells
78 for (vtkIdType c = 0; c < total_cell_count; ++c)
79 {
80 auto vtk_cell = ugrid.GetCell(static_cast<vtkIdType>(c));
81 auto vtk_celldim = vtk_cell->GetCellDimension();
82 const vtkIdType cell_gid = cell_gids->GetValue(c) + cid_offset;
83
84 if (vtk_celldim != dimension_to_copy) continue;
85
86 CellPtr raw_cell;
87 if (vtk_celldim == 3) raw_cell = CreateCellFromVTKPolyhedron(vtk_cell);
88 else if (vtk_celldim == 2)
89 raw_cell = CreateCellFromVTKPolygon(vtk_cell);
90 else if (vtk_celldim == 1)
91 raw_cell = CreateCellFromVTKLine(vtk_cell);
92 else if (vtk_celldim == 0)
93 raw_cell = CreateCellFromVTKVertex(vtk_cell);
94 else
95 throw std::logic_error(fname + ": Unsupported cell dimension ." +
96 std::to_string(vtk_celldim));
97
98 // Map the cell vertex-ids
99 for (uint64_t& vid : raw_cell->vertex_ids)
100 vid = node_map[vid];
101
102 // Map face vertex-ids
103 for (auto& face : raw_cell->faces)
104 for (uint64_t& vid : face.vertex_ids)
105 vid = node_map[vid];
106
107 raw_cell->material_id = block_id_array->GetValue(c);
108
109 cells[cell_gid] = raw_cell;
110 } // for cell c
111
112 //=========================================== Load points
113 for (vtkIdType p = 0; p < total_point_count; ++p)
114 {
115 auto point = ugrid.GetPoint(static_cast<vtkIdType>(p));
116 const vtkIdType point_gid = pnts_gids->GetValue(p) + pid_offset;
117
118 auto vertex = new Vec3(point[0], point[1], point[2]);
119
120 *vertex *= scale;
121
122 vertices.at(point_gid) = vertex;
123 } // for point p
124
125 //=========================================== Check all cells assigned
126 for (vtkIdType c = 0; c < total_cell_count; ++c)
127 if (cells[c] == nullptr)
128 throw std::logic_error(fname + ": Cell pointer not assigned ");
129
130 //=========================================== Check all points assigned
131 for (vtkIdType p = 0; p < total_point_count; ++p)
132 if (vertices[p] == nullptr)
133 throw std::logic_error(fname + ": Vertex pointer not assigned");
134
135 raw_cells_ = cells;
136 vertices_.reserve(total_point_count);
137 for (auto& vertex_ptr : vertices)
138 vertices_.push_back(*vertex_ptr);
139 } // If global-ids available
140 else
141 {
142 //======================================== Push cells
143 for (vtkIdType c = 0; c < total_cell_count; ++c)
144 {
145 auto vtk_cell = ugrid.GetCell(static_cast<vtkIdType>(c));
146 auto vtk_celldim = vtk_cell->GetCellDimension();
147
148 if (vtk_celldim != dimension_to_copy) continue;
149
150 if (vtk_celldim == 3)
151 raw_cells_.push_back(CreateCellFromVTKPolyhedron(vtk_cell));
152 else if (vtk_celldim == 2)
153 raw_cells_.push_back(CreateCellFromVTKPolygon(vtk_cell));
154 else if (vtk_celldim == 1)
155 raw_cells_.push_back(CreateCellFromVTKLine(vtk_cell));
156 else if (vtk_celldim == 0)
157 raw_cells_.push_back(CreateCellFromVTKVertex(vtk_cell));
158 else
159 throw std::logic_error(fname + ": Unsupported cell dimension.");
160
161 raw_cells_.back()->material_id = block_id_array->GetValue(c);
162 } // for c
163
164 //======================================== Push points
165 for (size_t p = 0; p < total_point_count; ++p)
166 {
167 auto point = ugrid.GetPoint(static_cast<vtkIdType>(p));
168
169 Vec3 vertex(point[0], point[1], point[2]);
170
171 vertex *= scale;
172
173 vertices_.emplace_back(point[0], point[1], point[2]);
174 }
175 } // if no global-ids
176
177 //================================================== Determine bound box
178 for (size_t p = 0; p < total_point_count; ++p)
179 {
180 const auto& vertex = vertices_[p];
181 if (not bound_box_)
182 bound_box_ = std::shared_ptr<BoundBox>(new BoundBox{
183 vertex.x, vertex.x, vertex.y, vertex.y, vertex.z, vertex.z});
184
185 bound_box_->xmin = std::min(bound_box_->xmin, vertex.x);
186 bound_box_->xmax = std::max(bound_box_->xmax, vertex.x);
187 bound_box_->ymin = std::min(bound_box_->ymin, vertex.y);
188 bound_box_->ymax = std::max(bound_box_->ymax, vertex.y);
189 bound_box_->zmin = std::min(bound_box_->zmin, vertex.z);
190 bound_box_->zmax = std::max(bound_box_->zmax, vertex.z);
191 }
192
193 Chi::log.Log() << fname + ": Done";
194}
195
196// ###################################################################
197/**Set material-ids from list.*/
199 const std::vector<int>& material_ids)
200{
201 const size_t total_cell_count = raw_cells_.size();
202
203 for (size_t c = 0; c < total_cell_count; ++c)
204 raw_cells_[c]->material_id = material_ids[c];
205}
206
207// ###################################################################
208/**Set boundary-ids from boundary grid_blocks.*/
210 std::vector<vtkUGridPtrAndName>& bndry_grid_blocks)
211{
212 const double EPSILON = 1.0e-12;
213 //======================================== Build boundary faces
214 std::vector<LightWeightFace*> bndry_faces;
215 for (auto& cell_ptr : raw_cells_)
216 for (auto& face : cell_ptr->faces)
217 if (not face.has_neighbor) bndry_faces.push_back(&face);
218
219 Chi::log.Log() << "Number of boundary faces: " << bndry_faces.size();
220
221 //======================================== Build boundary vertex ids
222 std::set<uint64_t> bndry_vids_set;
223 for (const auto& face_ptr : bndry_faces)
224 for (const auto vid : face_ptr->vertex_ids)
225 bndry_vids_set.insert(vid);
226
227 //======================================== Process each boundary block
228 uint64_t bndry_id = 0;
229 for (const auto& ugrid_name : bndry_grid_blocks)
230 {
231 auto ugrid = ugrid_name.first;
232
233 mesh_options_.boundary_id_map[bndry_id] = ugrid_name.second;
234
235 //================================= Build vertex map
236 bool mapping_failed = false;
237 std::vector<size_t> vertex_map(ugrid->GetNumberOfPoints(), 0);
238 for (size_t p = 0; p < ugrid->GetNumberOfPoints(); ++p)
239 {
240 chi_mesh::Vector3 point;
241 ugrid->GetPoint(static_cast<vtkIdType>(p), &point.x);
242
243 bool map_found = false;
244 for (const auto vid : bndry_vids_set)
245 if ((point - vertices_[vid]).NormSquare() < EPSILON)
246 {
247 vertex_map[p] = vid;
248 map_found = true;
249 break;
250 }
251
252 if (not map_found)
253 {
255 << "chi_mesh::UnpartitionedMesh::"
256 "SetBoundaryIDsFromBlocks: Failed to map a vertex. " +
257 point.PrintStr() + " for boundary " + ugrid_name.second +
258 " therefore the boundary assignment was skipped.";
259 mapping_failed = true;
260 break;
261 }
262 } // for point in boundary block
263
264 if (mapping_failed) continue;
265
266 //================================= Build vertex subscriptions
267 std::map<uint64_t, std::set<size_t>> vertex_face_subs;
268 for (size_t f = 0; f < bndry_faces.size(); ++f)
269 for (const auto vid : bndry_faces[f]->vertex_ids)
270 vertex_face_subs[vid].insert(f);
271
272 //================================= Process each cell in bndry block
273 size_t num_faces_boundarified = 0;
274 auto& bndry_block = ugrid_name.first;
275 size_t num_bndry_block_cells = bndry_block->GetNumberOfCells();
276 for (size_t bc = 0; bc < num_bndry_block_cells; ++bc)
277 {
278 auto bndry_cell = bndry_block->GetCell(static_cast<vtkIdType>(bc));
279
280 //========================== Build list of face candidates
281 // and vertex set
282 std::set<size_t> face_ids_short_list;
283 std::set<uint64_t> bndry_cell_id_set;
284 size_t num_points = bndry_cell->GetNumberOfPoints();
285 for (size_t p = 0; p < num_points; ++p)
286 {
287 auto point_id = bndry_cell->GetPointId(static_cast<int>(p));
288 bndry_cell_id_set.insert(vertex_map[point_id]);
289 for (size_t face_id : vertex_face_subs[vertex_map[point_id]])
290 face_ids_short_list.insert(face_id);
291 } // for point p
292
293 for (size_t face_id : face_ids_short_list)
294 {
295 auto& face = bndry_faces[face_id];
296 const auto& face_vids = face->vertex_ids;
297 std::set<uint64_t> face_id_set(face_vids.begin(), face_vids.end());
298
299 if (face_id_set == bndry_cell_id_set)
300 {
301 face->neighbor = bndry_id;
302 ++num_faces_boundarified;
303 }
304 } // for face_id
305 } // for boundary cell bc
306
307 Chi::log.Log() << "UnpartitionedMesh: assigned " << num_faces_boundarified
308 << " to boundary id " << bndry_id << " with name "
309 << ugrid_name.second;
310
311 ++bndry_id;
312 } // for boundary_block
313}
#define ChiLogicalErrorIf(condition, message)
static chi::ChiLog & log
Definition: chi_runtime.h:81
LogStream Log0Warning()
Definition: chi_log.h:231
LogStream Log(LOG_LVL level=LOG_0)
Definition: chi_log.cc:35
static LightWeightCell * CreateCellFromVTKLine(vtkCell *vtk_cell)
void CopyUGridCellsAndPoints(vtkUnstructuredGrid &ugrid, double scale, int dimension_to_copy)
static LightWeightCell * CreateCellFromVTKVertex(vtkCell *vtk_cell)
void SetMaterialIDsFromList(const std::vector< int > &material_ids)
std::vector< chi_mesh::Vertex > vertices_
void SetBoundaryIDsFromBlocks(std::vector< vtkUGridPtrAndName > &bndry_grid_blocks)
static LightWeightCell * CreateCellFromVTKPolygon(vtkCell *vtk_cell)
std::vector< LightWeightCell * > raw_cells_
static LightWeightCell * CreateCellFromVTKPolyhedron(vtkCell *vtk_cell)
std::shared_ptr< BoundBox > bound_box_
std::string PrintStr() const
double x
Element-0.