Chi-Tech
cell.cc
Go to the documentation of this file.
1#include "cell.h"
3
5
6#include "chi_runtime.h"
7#include "chi_log.h"
8#include "chi_mpi.h"
9
10//###################################################################
11/**Provides the text name associated with a cell type.*/
12std::string chi_mesh::CellTypeName(const CellType type)
13{
14 switch (type)
15 {
16 case CellType::GHOST: return "GHOST";
17 case CellType::SLAB: return "SLAB";
18// case CellType::SPHERICAL_SHELL: return "SPHERICAL_SHELL";
19// case CellType::CYLINDRICAL_ANNULUS: return "CYLINDRICAL_ANNULUS";
20 case CellType::TRIANGLE: return "TRIANGLE";
21 case CellType::QUADRILATERAL: return "QUADRILATERAL";
22
23 case CellType::POLYGON: return "POLYGON";
24 case CellType::TETRAHEDRON: return "TETRAHEDRON";
25 case CellType::HEXAHEDRON: return "HEXAHEDRON";
26 case CellType::WEDGE: return "WEDGE";
27 case CellType::PYRAMID: return "PYRAMID";
28 case CellType::POLYHEDRON: return "POLYHEDRON";
29
30 case CellType::POINT: return "POINT";
31 }
32
33 return "NONE";
34}
35
36//###################################################################
37/**Copy constructor*/
39 cell_type_(other.cell_type_),
40 cell_sub_type_(other.cell_sub_type_),
41 global_id_(other.global_id_),
42 local_id_(other.local_id_),
43 partition_id_(other.partition_id_),
44 centroid_(other.centroid_),
45 material_id_(other.material_id_),
46 vertex_ids_(other.vertex_ids_),
47 faces_(other.faces_)
48{
49}
50
51//###################################################################
52/**Move constructor*/
53chi_mesh::Cell::Cell(Cell &&other) noexcept :
54 cell_type_(other.cell_type_),
55 cell_sub_type_(other.cell_sub_type_),
56 global_id_(other.global_id_),
57 local_id_(other.local_id_),
58 partition_id_(other.partition_id_),
59 centroid_(other.centroid_),
60 material_id_(other.material_id_),
61 vertex_ids_(std::move(other.vertex_ids_)),
62 faces_(std::move(other.faces_))
63{
64}
65
66
67//###################################################################
68/**Copy operator.*/
70{
71 global_id_ = other.global_id_;
72 local_id_ = other.local_id_;
73 partition_id_ = other.partition_id_;
74 centroid_ = other.centroid_;
75 material_id_ = other.material_id_;
76 vertex_ids_ = other.vertex_ids_;
77 faces_ = other.faces_;
78
79 return *this;
80}
81
82
83//###################################################################
84/**Determines the neighbor's partition and whether its local or not.*/
87{
88 if (not has_neighbor_) return false;
89 if (Chi::mpi.process_count == 1) return true;
90
91 auto& adj_cell = grid.cells[neighbor_id_];
92
93 return (adj_cell.partition_id_ == static_cast<uint64_t>(Chi::mpi.location_id));
94}
95
96//###################################################################
97/**Determines the neighbor's partition.*/
100{
101 if (not has_neighbor_) return -1;
102 if (Chi::mpi.process_count == 1) return 0;
103
104 auto& adj_cell = grid.cells[neighbor_id_];
105
106 return static_cast<int>(adj_cell.partition_id_);
107}
108
109//###################################################################
110/**Determines the neighbor's local id.*/
113{
114 if (not has_neighbor_) return -1;
115 if (Chi::mpi.process_count == 1) return neighbor_id_; //cause global_ids=local_ids
116
117 auto& adj_cell = grid.cells[neighbor_id_];
118
119 if (adj_cell.partition_id_ != Chi::mpi.location_id)
120 throw std::logic_error("Cell local ID requested from a non-local cell.");
121
122 return adj_cell.local_id_;
123}
124
125//###################################################################
126/**Determines the neighbor's associated face.*/
129{
130 const auto& cur_face = *this; //just for readability
131 //======================================== Check index validity
132 if (not cur_face.has_neighbor_)
133 {
134 std::stringstream outstr;
135 outstr
136 << "Invalid cell index encountered in call to "
137 << "CellFace::GetNeighborAssociatedFace. Index points "
138 << "to a boundary";
139 throw std::logic_error(outstr.str());
140 }
141
142 const auto& adj_cell = grid.cells[cur_face.neighbor_id_];
143
144 int associated_face = -1;
145 std::set<uint64_t> cfvids(cur_face.vertex_ids_.begin(),
146 cur_face.vertex_ids_.end()); //cur_face vertex ids
147
148 //======================================== Loop over adj cell faces
149 int af=-1;
150 for (const auto& adj_face : adj_cell.faces_)
151 {
152 ++af;
153 std::set<uint64_t> afvids(adj_face.vertex_ids_.begin(),
154 adj_face.vertex_ids_.end()); //adj_face vertex ids
155
156 if (afvids == cfvids) {associated_face = af; break;}
157 }
158
159 //======================================== Check associated face validity
160 if (associated_face<0)
161 {
162 std::stringstream outstr;
163 outstr
164 << "Could not find associated face in call to "
165 << "CellFace::GetNeighborAssociatedFace.\n"
166 << "Reference face with centroid at: "
167 << cur_face.centroid_.PrintS() << "\n"
168 << "Adjacent cell: " << adj_cell.global_id_ << "\n";
169 for (size_t afi=0; afi < adj_cell.faces_.size(); afi++)
170 {
171 outstr
172 << "Adjacent cell face " << afi << " centroid "
173 << adj_cell.faces_[afi].centroid_.PrintS();
174 }
175 throw std::runtime_error(outstr.str());
176 }
177
178 return associated_face;
179}
180
181//###################################################################
182/**Computes the face area.*/
184{
185 if (vertex_ids_.size() <= 1)
186 return 1.0;
187 else if (vertex_ids_.size() == 2)
188 {
189 const auto& v0 = grid.vertices[vertex_ids_[0]];
190 const auto& v1 = grid.vertices[vertex_ids_[1]];
191
192 return (v1 - v0).Norm();
193 }
194 else
195 {
196 double area = 0.0;
197 auto& v2 = centroid_;
198 const auto num_verts = vertex_ids_.size();
199 for (uint64_t v=0; v<num_verts; ++v)
200 {
201 uint64_t vid0 = vertex_ids_[v];
202 uint64_t vid1 = (v < (num_verts-1)) ? vertex_ids_[v + 1] : vertex_ids_[0];
203
204 const auto& v0 = grid.vertices[vid0];
205 const auto& v1 = grid.vertices[vid1];
206
207 auto v01 = v1-v0;
208 auto v02 = v2-v0;
209
211 J.SetColJVec(0,v01);
212 J.SetColJVec(1,v02);
213 J.SetColJVec(2,chi_mesh::Vector3(1.0,1.0,1.0));
214
215 area += 0.5*std::fabs(J.Det());
216 }
217
218 return area;
219 }
220
221}
222
223//###################################################################
224/**Serializes a face into a vector of bytes.*/
226{
228
229 raw.Write<size_t>(vertex_ids_.size());
230 for (uint64_t vid : vertex_ids_)
231 raw.Write<uint64_t>(vid);
232
233 raw.Write<chi_mesh::Vector3>(normal_);
234 raw.Write<chi_mesh::Vector3>(centroid_);
235 raw.Write<bool>(has_neighbor_);
236 raw.Write<uint64_t>(neighbor_id_);
237
238 return raw;
239}
240
241//###################################################################
242/**Deserializes a face from a set of raw data*/
245 size_t& address)
246{
247
248 CellFace face;
249
250 const size_t num_face_verts = raw.Read<size_t>(address, &address);
251 face.vertex_ids_.reserve(num_face_verts);
252 for (size_t fv=0; fv<num_face_verts; ++fv)
253 face.vertex_ids_.push_back(raw.Read<uint64_t>(address, &address));
254
255 face.normal_ = raw.Read<chi_mesh::Vector3>(address, &address);
256 face.centroid_ = raw.Read<chi_mesh::Vector3>(address, &address);
257 face.has_neighbor_ = raw.Read<bool> (address, &address);
258 face.neighbor_id_ = raw.Read<uint64_t> (address, &address);
259
260 return face;
261}
262
263
264//###################################################################
265/**Provides string information of the face.*/
267{
268 std::stringstream outstr;
269
270 outstr << "num_vertex_ids: " << vertex_ids_.size() << "\n";
271 {
272 size_t counter=0;
273 for (uint64_t vid : vertex_ids_)
274 outstr << "vid" << counter++ << ": " << vid << "\n";
275 }
276
277 outstr << "normal: " << normal_.PrintS() << "\n";
278 outstr << "centroid: " << centroid_.PrintS() << "\n";
279 outstr << "has_neighbor: " << has_neighbor_ << "\n";
280 outstr << "neighbor_id: " << neighbor_id_ << "\n";
281
282 return outstr.str();
283}
284
285
286//###################################################################
287/**Recomputes the face centroid assuming the mesh vertices
288 * have been transformed.*/
291{
292 centroid_ = chi_mesh::Vector3(0, 0, 0);
293 for (uint64_t vid : vertex_ids_)
294 centroid_ += grid.vertices[vid];
295 centroid_ /= static_cast<double>(vertex_ids_.size());
296}
297
298
299//###################################################################
300/**Serializes a cell into a vector of bytes.*/
302{
304
305 raw.Write<uint64_t>(global_id_);
306 raw.Write<uint64_t>(local_id_);
307 raw.Write<uint64_t>(partition_id_);
308 raw.Write<chi_mesh::Vector3>(centroid_);
309 raw.Write<int>(material_id_);
310
311 raw.Write<CellType>(cell_type_);
312 raw.Write<CellType>(cell_sub_type_);
313
314 raw.Write<size_t>(vertex_ids_.size());
315 for (uint64_t vid : vertex_ids_)
316 raw.Write<uint64_t>(vid);
317
318 raw.Write<size_t>(faces_.size());
319 for (const auto& face : faces_)
320 raw.Append(face.Serialize());
321
322 return raw;
323}
324
325//###################################################################
326/**Deserializes a cell from a vector of bytes.*/
329 size_t& address)
330{
331 typedef chi_mesh::Vector3 Vec3;
332 auto cell_global_id = raw.Read<uint64_t>(address, &address);
333 auto cell_local_id = raw.Read<uint64_t>(address, &address);
334 auto cell_prttn_id = raw.Read<uint64_t>(address, &address);
335 auto cell_centroid = raw.Read<Vec3> (address, &address);
336 auto cell_matrl_id = raw.Read<int> (address, &address);
337
338 auto cell_type = raw.Read<CellType>(address, &address);
339 auto cell_sub_type = raw.Read<CellType>(address, &address);
340
341 Cell cell(cell_type, cell_sub_type);
342 cell.global_id_ = cell_global_id;
343 cell.local_id_ = cell_local_id;
344 cell.partition_id_ = cell_prttn_id;
345 cell.centroid_ = cell_centroid;
346 cell.material_id_ = cell_matrl_id;
347
348 auto num_vertex_ids = raw.Read<size_t>(address, &address);
349 cell.vertex_ids_.reserve(num_vertex_ids);
350 for (size_t v=0; v<num_vertex_ids; ++v)
351 cell.vertex_ids_.push_back(raw.Read<uint64_t>(address, &address));
352
353 auto num_faces = raw.Read<size_t>(address, &address);
354 cell.faces_.reserve(num_faces);
355 for (size_t f=0; f<num_faces; ++f)
356 cell.faces_.push_back(chi_mesh::CellFace::DeSerialize(raw, address));
357
358 return cell;
359}
360
361
362//###################################################################
363/**Provides string information of the cell.*/
364std::string chi_mesh::Cell::ToString() const
365{
366 std::stringstream outstr;
367
368 outstr << "cell_type: " << CellTypeName(cell_type_) << "\n";
369 outstr << "cell_sub_type: " << CellTypeName(cell_sub_type_) << "\n";
370 outstr << "global_id: " << global_id_ << "\n";
371 outstr << "local_id: " << local_id_ << "\n";
372 outstr << "partition_id: " << partition_id_ << "\n";
373 outstr << "centroid: " << centroid_.PrintS() << "\n";
374 outstr << "material_id: " << material_id_ << "\n";
375
376 outstr << "num_vertex_ids: " << vertex_ids_.size() << "\n";
377 {
378 size_t counter=0;
379 for (uint64_t vid : vertex_ids_)
380 outstr << "vid" << counter++ << ": " << vid << "\n";
381 }
382
383 {
384 outstr << "num_faces: " << faces_.size() << "\n";
385 size_t f=0;
386 for (const auto& face : faces_)
387 outstr << "Face " << f++ << ":\n" << face.ToString();
388 }
389
390 return outstr.str();
391}
392
393//###################################################################
394/**Recomputes the cell centroid and all face centroids assuming
395 * the mesh vertices have been transformed.*/
398{
399 const auto k_hat = Vector3(0,0,1);
400
401 centroid_ = chi_mesh::Vector3(0, 0, 0);
402 for (uint64_t vid : vertex_ids_)
403 centroid_ += grid.vertices[vid];
404 centroid_ /= static_cast<double>(vertex_ids_.size());
405
406 for (auto& face : faces_)
407 {
408 face.RecomputeCentroid(grid);
409
410 if (cell_type_ == CellType::POLYGON)
411 {
412 const auto v0 = grid.vertices[face.vertex_ids_[0]];
413 const auto v1 = grid.vertices[face.vertex_ids_[1]];
414
415 const auto v01 = v1 - v0;
416
417 face.normal_ = v01.Cross(k_hat).Normalized();
418 }
419 else if (cell_type_ == CellType::POLYHEDRON)
420 {
421 // A face of a polyhedron can itself be a polygon
422 // which can be multifaceted. Here we need the
423 // average normal over all the facets computed
424 // using an area-weighted average.
425 const size_t num_face_verts = face.vertex_ids_.size();
426 double total_area = 0.0;
427 auto weighted_normal = Vector3(0,0,0);
428 for (size_t fv=0; fv<num_face_verts; ++fv)
429 {
430 size_t fvp1 = (fv < (num_face_verts-1))? fv+1 : 0;
431
432 uint64_t fvid_m = face.vertex_ids_[fv ];
433 uint64_t fvid_p = face.vertex_ids_[fvp1];
434
435 auto leg_m = grid.vertices[fvid_m] - face.centroid_;
436 auto leg_p = grid.vertices[fvid_p] - face.centroid_;
437
438 auto vn = leg_m.Cross(leg_p);
439
440 double area = 0.5*vn.Norm();
441 total_area += area;
442
443 weighted_normal = weighted_normal + area*vn.Normalized();
444 }
445 weighted_normal = weighted_normal/total_area;
446
447 face.normal_ = weighted_normal.Normalized();
448 }
449 }
450}
static chi::MPI_Info & mpi
Definition: chi_runtime.h:78
const int & location_id
Current process rank.
Definition: mpi_info.h:26
void Append(const ByteArray &other_raw)
Definition: byte_array.h:99
void Write(const T &value)
Definition: byte_array.h:34
int GetNeighborPartitionID(const chi_mesh::MeshContinuum &grid) const
Definition: cell.cc:99
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
chi_data_types::ByteArray Serialize() const
Definition: cell.cc:225
std::vector< uint64_t > vertex_ids_
Definition: cell.h:38
void RecomputeCentroid(const chi_mesh::MeshContinuum &grid)
Definition: cell.cc:290
bool IsNeighborLocal(const chi_mesh::MeshContinuum &grid) const
Definition: cell.cc:86
double ComputeFaceArea(const chi_mesh::MeshContinuum &grid) const
Definition: cell.cc:183
Vertex centroid_
The face centroid.
Definition: cell.h:40
static CellFace DeSerialize(const chi_data_types::ByteArray &raw, size_t &address)
Definition: cell.cc:244
uint64_t GetNeighborLocalID(const chi_mesh::MeshContinuum &grid) const
Definition: cell.cc:112
int GetNeighborAssociatedFace(const chi_mesh::MeshContinuum &grid) const
Definition: cell.cc:128
std::string ToString() const
Definition: cell.cc:266
Cell(const Cell &other)
Definition: cell.cc:38
std::vector< CellFace > faces_
Definition: cell.h:82
static Cell DeSerialize(const chi_data_types::ByteArray &raw, size_t &address)
Definition: cell.cc:328
void RecomputeCentroidsAndNormals(const chi_mesh::MeshContinuum &grid)
Definition: cell.cc:397
Cell & operator=(const Cell &other)
Definition: cell.cc:69
std::string ToString() const
Definition: cell.cc:364
chi_data_types::ByteArray Serialize() const
Definition: cell.cc:301
uint64_t local_id_
Definition: cell.h:76
int material_id_
Definition: cell.h:79
uint64_t partition_id_
Definition: cell.h:77
uint64_t global_id_
Definition: cell.h:75
Vertex centroid_
Definition: cell.h:78
std::vector< uint64_t > vertex_ids_
Definition: cell.h:81
GlobalCellHandler cells
VectorN< 3 > Vector3
CellType
Definition: cell.h:12
std::string CellTypeName(CellType type)
Definition: cell.cc:12
void SetColJVec(int j, Vector3 vec)
double Det(int row=0)