Chi-Tech
MeshGenerator_02_utils.cc
Go to the documentation of this file.
1#include "MeshGenerator.h"
2
3namespace chi_mesh
4{
5
6// ###################################################################
7/**Broadcasts PIDs to other locations.*/
8void MeshGenerator::BroadcastPIDs(std::vector<int64_t>& cell_pids,
9 int root,
10 MPI_Comm communicator)
11{
12 size_t data_count = Chi::mpi.location_id == root ? cell_pids.size() : 0;
13
14 //======================================== Broadcast data_count to all
15 // locations
16 MPI_Bcast(&data_count, // buffer [IN/OUT]
17 1, // count
18 MPI_UINT64_T, // data type
19 root, // root
20 communicator); // communicator
21
22 if (Chi::mpi.location_id != root) cell_pids.assign(data_count, 0);
23
24 //======================================== Broadcast partitioning to all
25 // locations
26 MPI_Bcast(cell_pids.data(), // buffer [IN/OUT]
27 static_cast<int>(data_count), // count
28 MPI_LONG_LONG_INT, // data type
29 root, // root
30 communicator); // communicator
31}
32
33// ###################################################################
34/**Determines if a cells needs to be included as a ghost or as a local cell.*/
36 int location_id,
38 uint64_t cell_global_id,
39 const std::vector<std::set<uint64_t>>& vertex_subscriptions,
40 const std::vector<int64_t>& cell_partition_ids) const
41{
42 if (replicated_) return true;
43 // First determine if the cell is a local cell
44 int cell_pid = static_cast<int>(cell_partition_ids[cell_global_id]);
45 if (cell_pid == location_id) return true;
46
47 // Now determine if the cell is a ghost cell
48 for (uint64_t vid : lwcell.vertex_ids)
49 for (uint64_t cid : vertex_subscriptions[vid])
50 {
51 if (cid == cell_global_id) continue;
52 int adj_pid = static_cast<int>(cell_partition_ids[cid]);
53 if (adj_pid == location_id) return true;
54 }
55
56 return false;
57}
58
59// ###################################################################
60/**Converts a light-weight cell to a real cell.*/
61std::unique_ptr<chi_mesh::Cell>
64 uint64_t global_id,
65 uint64_t partition_id,
66 const VertexListHelper& vertices)
67{
68 auto cell =
69 std::make_unique<chi_mesh::Cell>(raw_cell.type, raw_cell.sub_type);
70 cell->centroid_ = raw_cell.centroid;
71 cell->global_id_ = global_id;
72 cell->partition_id_ = partition_id;
73 cell->material_id_ = raw_cell.material_id;
74
75 cell->vertex_ids_ = raw_cell.vertex_ids;
76
77 size_t face_counter = 0;
78 for (auto& raw_face : raw_cell.faces)
79 {
80 chi_mesh::CellFace newFace;
81
82 newFace.has_neighbor_ = raw_face.has_neighbor;
83 newFace.neighbor_id_ = raw_face.neighbor;
84
85 newFace.vertex_ids_ = raw_face.vertex_ids;
86 auto vfc = chi_mesh::Vertex(0.0, 0.0, 0.0);
87 for (auto fvid : newFace.vertex_ids_)
88 vfc = vfc + vertices.at(fvid);
89 newFace.centroid_ = vfc / static_cast<double>(newFace.vertex_ids_.size());
90
91 if (cell->Type() == CellType::SLAB)
92 {
93 // A slab face is very easy. If it is the first face
94 // the normal is -khat. If it is the second face then
95 // it is +khat.
96 if (face_counter == 0)
97 newFace.normal_ = chi_mesh::Vector3(0.0, 0.0, -1.0);
98 else
99 newFace.normal_ = chi_mesh::Vector3(0.0, 0.0, 1.0);
100 }
101 else if (cell->Type() == CellType::POLYGON)
102 {
103 // A polygon face is just a line so we can just grab
104 // the first vertex and form a vector with the face
105 // centroid. The normal is then just khat
106 // cross-product with this vector.
107 uint64_t fvid = newFace.vertex_ids_[0];
108 auto vec_vvc = vertices.at(fvid) - newFace.centroid_;
109
110 newFace.normal_ = chi_mesh::Vector3(0.0, 0.0, 1.0).Cross(vec_vvc);
111 newFace.normal_.Normalize();
112 }
113 else if (cell->Type() == CellType::POLYHEDRON)
114 {
115 // A face of a polyhedron can itself be a polygon
116 // which can be multifaceted. Here we need the
117 // average normal over all the facets computed
118 // using an area-weighted average.
119 const size_t num_face_verts = newFace.vertex_ids_.size();
120 double total_area = 0.0;
121 for (size_t fv = 0; fv < num_face_verts; ++fv)
122 {
123 size_t fvp1 = (fv < (num_face_verts - 1)) ? fv + 1 : 0;
124
125 uint64_t fvid_m = newFace.vertex_ids_[fv];
126 uint64_t fvid_p = newFace.vertex_ids_[fvp1];
127
128 auto leg_m = vertices.at(fvid_m) - newFace.centroid_;
129 auto leg_p = vertices.at(fvid_p) - newFace.centroid_;
130
131 auto vn = leg_m.Cross(leg_p);
132
133 double area = 0.5 * vn.Norm();
134 total_area += area;
135
136 newFace.normal_ = newFace.normal_ + area * vn.Normalized();
137 }
138 newFace.normal_ = newFace.normal_ / total_area;
139 newFace.normal_.Normalize();
140 }
141 ++face_counter;
142
143 cell->faces_.push_back(newFace);
144 }
145
146 return cell;
147}
148
149} // namespace chi_mesh
static chi::MPI_Info & mpi
Definition: chi_runtime.h:78
const int & location_id
Current process rank.
Definition: mpi_info.h:26
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
bool CellHasLocalScope(int location_id, const chi_mesh::UnpartitionedMesh::LightWeightCell &lwcell, uint64_t cell_global_id, const std::vector< std::set< uint64_t > > &vertex_subscriptions, const std::vector< int64_t > &cell_partition_ids) const
static void BroadcastPIDs(std::vector< int64_t > &cell_pids, int root, MPI_Comm communicator)
static std::unique_ptr< chi_mesh::Cell > SetupCell(const UnpartitionedMesh::LightWeightCell &raw_cell, uint64_t global_id, uint64_t partition_id, const VertexListHelper &vertices)
VectorN< 3 > Vector3
Vector3 Vertex
Definition: chi_mesh.h:20
virtual const chi_mesh::Vertex & at(uint64_t vid) const =0
Vector3 Cross(const Vector3 &that) const
Vector3 Normalized() const
double Norm() const