32std::shared_ptr<chi_mesh::GridFaceHistogram>
34 double slave_tolerance)
const
36 std::vector<std::pair<size_t, size_t>> face_categories_list;
38 std::vector<size_t> face_size_histogram;
40 for (
const auto& face : cell.faces_)
41 face_size_histogram.push_back(face.vertex_ids_.size());
43 std::stable_sort(face_size_histogram.begin(), face_size_histogram.end());
46 size_t total_face_dofs_count = 0;
47 for (
auto face_size : face_size_histogram)
48 total_face_dofs_count += face_size;
51 size_t smallest_face = face_size_histogram.front();
52 size_t largest_face = face_size_histogram.back();
53 size_t total_num_faces = face_size_histogram.size();
54 double average_dofs_per_face =
55 (double)total_face_dofs_count / (
double)total_num_faces;
57 std::stringstream outstr;
58 outstr <<
"\nSmallest face = " << smallest_face;
59 outstr <<
"\nLargest face = " << largest_face;
60 outstr <<
"\nTotal face dofs = " << total_face_dofs_count;
61 outstr <<
"\nTotal faces = " << face_size_histogram.size();
62 outstr <<
"\nAverage dofs/face = " << average_dofs_per_face;
63 outstr <<
"\nMax to avg ratio = "
64 << (double)largest_face / average_dofs_per_face;
68 size_t last_bin_num_faces = total_num_faces;
69 if (((
double)largest_face / average_dofs_per_face) > master_tolerance)
72 <<
"The ratio of max face dofs to average face dofs "
73 <<
"is larger than " << master_tolerance
74 <<
", therefore a binned histogram "
75 <<
"will be constructed.";
78 size_t running_total_face_dofs = 0;
79 size_t running_face_count = 0;
80 size_t running_face_size = face_size_histogram[0];
82 double running_average = (double)face_size_histogram[0];
84 for (
size_t f = 0; f < total_num_faces; ++f)
86 if (((
double)face_size_histogram[f] / running_average) > slave_tolerance)
88 face_categories_list.emplace_back(running_face_size,
90 running_total_face_dofs = 0;
91 running_face_count = 0;
94 running_face_size = face_size_histogram[f];
95 running_total_face_dofs += face_size_histogram[f];
98 (double)running_total_face_dofs /
double(running_face_count);
99 last_bin_num_faces = running_face_count;
102 face_categories_list.emplace_back(largest_face, last_bin_num_faces);
105 outstr.str(std::string());
106 outstr <<
"A total of " << face_categories_list.size()
107 <<
" bins were created:\n";
109 size_t bin_counter = -1;
110 for (
auto bins : face_categories_list)
112 outstr <<
"Bin " << ++bin_counter <<
": " << bins.second
113 <<
" faces with max face dofs " << bins.first <<
"\n";
118 return std::make_shared<GridFaceHistogram>(face_categories_list);
126 auto native_index = global_cell_id_to_local_id_map_.find(cell_global_index);
128 if (native_index != global_cell_id_to_local_id_map_.end())
return true;
156 throw std::logic_error(
"chi_mesh::MeshContinuum::GetCellDimension: "
157 "Dimension mapping unavailable for cell type.");
170 "Invalid cell index encountered in call to "
171 "MeshContinuum::FindAssociatedVertices. Index "
172 "points to a boundary");
178 const auto& adj_face = adj_cell.faces_[associated_face];
184 for (
auto afvid : adj_face.vertex_ids_)
188 dof_mapping.push_back((
short)afv);
198 <<
"Face DOF mapping failed in call to "
199 <<
"MeshContinuum::FindAssociatedVertices. Could not find a matching"
214 "Invalid cell index encountered in call to "
215 "MeshContinuum::FindAssociatedVertices. Index "
216 "points to a boundary");
226 for (
auto acvid : adj_cell.vertex_ids_)
230 dof_mapping.push_back(acv);
240 <<
"Face DOF mapping failed in call to "
241 <<
"MeshContinuum::FindAssociatedVertices. Could not find a matching"
258 const auto& ccface = cur_cell.
faces_[f];
259 std::set<uint64_t> ccface_vids;
260 for (
auto vid : ccface.vertex_ids_)
261 ccface_vids.insert(vid);
264 bool map_found =
false;
265 for (
size_t af = 0; af < adj_cell.
faces_.size(); af++)
267 const auto& acface = adj_cell.
faces_[af];
269 std::set<uint64_t> acface_vids;
270 for (
auto vid : acface.vertex_ids_)
271 acface_vids.insert(vid);
273 if (acface_vids == ccface_vids)
282 throw std::logic_error(
283 "chi_mesh::MeshContinuum::MapCellFace: Mapping failure.");
294 return global_cell_id_to_local_id_map_.at(global_id);
300 const std::vector<uint64_t>& list)
const
308 for (
auto node_id : list)
309 centroid = centroid + vertices[node_id];
311 return centroid / double(list.size());
320 size_t local_count = 0;
321 for (
const auto& cell : local_cells)
322 if (log_vol.
Inside(cell.centroid_)) ++local_count;
324 size_t global_count = 0;
326 MPI_Allreduce(&local_count,
329 MPI_UNSIGNED_LONG_LONG,
341 const auto& grid_ref = *
this;
344 [](
const Vec3& point,
const Vec3& v0,
const Vec3& v1,
const Vec3& v2)
346 const auto& v01 = v1 - v0;
347 const auto& v02 = v2 - v0;
350 const auto c = (v0 + v1 + v2) / 3.0;
352 const auto pc = point - c;
354 if (pc.Dot(n) > 0.0)
return true;
362 const auto& v0 = grid_ref.vertices[cell.
vertex_ids_[0]];
363 const auto& v1 = grid_ref.vertices[cell.
vertex_ids_[1]];
365 const auto v01 = v1 - v0;
366 const auto v0p = point - v0;
368 const double v0p_dot_v01 = v0p.
Dot(v01);
370 if (not(v0p_dot_v01 >= 0 and v0p_dot_v01 < v01.Norm())) inside =
false;
375 for (
const auto& face : cell.
faces_)
377 const auto& vcp = point - face.centroid_;
379 if (vcp.Dot(face.normal_) > 0)
392 for (
const auto& face : cell.
faces_)
394 const auto& vfc = face.centroid_;
396 const size_t num_sides = face.vertex_ids_.size();
397 for (
size_t s = 0; s < num_sides; ++s)
399 const size_t sp1 = (s < (num_sides - 1)) ? s + 1 : 0;
400 const auto& v0 = grid_ref.vertices[face.vertex_ids_[s]];
401 const auto& v1 = vfc;
402 const auto& v2 = grid_ref.vertices[face.vertex_ids_[sp1]];
403 const auto& v3 = vcc;
405 typedef std::tuple<Vec3, Vec3, Vec3> TetFace;
407 std::vector<TetFace> tet_faces;
408 tet_faces.emplace_back(v0, v1, v2);
409 tet_faces.emplace_back(v0, v2, v3);
410 tet_faces.emplace_back(v1, v3, v2);
411 tet_faces.emplace_back(v0, v3, v1);
413 bool inside_tet =
true;
414 for (
const auto& tet_face : tet_faces)
416 if (not InsideTet(point,
417 std::get<0>(tet_face),
418 std::get<1>(tet_face),
419 std::get<2>(tet_face)))
435 throw std::logic_error(
"chi_mesh::MeshContinuum::CheckPointInsideCell: "
436 "Unsupported cell-type encountered.");
445 const std::string fname =
"GetIJKInfo";
447 throw std::logic_error(fname +
" can only be run on orthogonal meshes.");
449 return {ortho_attributes.Nx, ortho_attributes.Ny, ortho_attributes.Nz};
457 const std::string fname =
"MakeIJKToGlobalIDMapping";
459 throw std::logic_error(fname +
" can only be run on orthogonal meshes.");
461 const auto ijk_info = this->GetIJKInfo();
462 const auto Nx =
static_cast<int64_t
>(ijk_info[0]);
463 const auto Ny =
static_cast<int64_t
>(ijk_info[1]);
464 const auto Nz =
static_cast<int64_t
>(ijk_info[2]);
467 for (
int i = 0; i < Nx; ++i)
468 for (
int j = 0; j < Ny; ++j)
469 for (
int k = 0; k < Nz; ++k)
470 m_ijk_to_i(i, j, k) =
471 static_cast<uint64_t
>(m_ijk_to_i.MapNDtoLin(i, j, k));
479std::vector<chi_mesh::Vector3>
482 std::vector<chi_mesh::Vector3> cell_ortho_sizes(local_cells.size());
483 for (
const auto& cell : local_cells)
488 for (
const auto vid : cell.vertex_ids_)
490 const auto& vertex = vertices[vid];
491 vmin.
x = std::min(vertex.x, vmin.
x);
492 vmin.
y = std::min(vertex.y, vmin.
y);
493 vmin.
z = std::min(vertex.z, vmin.
z);
495 vmax.
x = std::max(vertex.x, vmax.
x);
496 vmax.
y = std::max(vertex.y, vmax.
y);
497 vmax.
z = std::max(vertex.z, vmax.
z);
500 cell_ortho_sizes[cell.local_id_] = vmax - vmin;
503 return cell_ortho_sizes;
513 if (boundary_id_map_.empty())
return 0;
515 for (
const auto& [
id, name] : boundary_id_map_)
516 if (boundary_name == name)
return id;
519 for (
const auto& [
id, name] : boundary_id_map_)
520 max_id = std::max(
id, max_id);
525std::pair<chi_mesh::Vector3, chi_mesh::Vector3>
535 std::min(xyz_A.
y, xyz_B.y),
536 std::min(xyz_A.
z, xyz_B.z));
542 std::max(xyz_A.
y, xyz_B.y),
543 std::max(xyz_A.
z, xyz_B.z));
546 bool initialized =
false;
547 for (
const auto& cell : local_cells)
549 for (
const uint64_t vid : cell.vertex_ids_)
551 const auto& vertex = vertices[vid];
558 xyz_min = Vec3Min(xyz_min, vertex);
559 xyz_max = Vec3Max(xyz_max, vertex);
562 return {xyz_min, xyz_max};
#define ChiLogicalErrorIf(condition, message)
static void Exit(int error_code)
static chi::MPI_Info & mpi
LogStream LogAllVerbose2()
bool has_neighbor_
Flag indicating whether face has a neighbor.
uint64_t neighbor_id_
Otherwise contains boundary_id.
std::vector< uint64_t > vertex_ids_
Vertex centroid_
The face centroid.
int GetNeighborAssociatedFace(const chi_mesh::MeshContinuum &grid) const
std::vector< CellFace > faces_
std::vector< uint64_t > vertex_ids_
virtual bool Inside(const chi_mesh::Vector3 &point) const
bool CheckPointInsideCell(const chi_mesh::Cell &cell, const chi_mesh::Vector3 &point) const
chi_mesh::Vector3 ComputeCentroidFromListOfNodes(const std::vector< uint64_t > &list) const
std::shared_ptr< GridFaceHistogram > MakeGridFaceHistogram(double master_tolerance=100.0, double slave_tolerance=1.1) const
LocalCellHandler local_cells
void FindAssociatedCellVertices(const chi_mesh::CellFace &cur_face, std::vector< short > &dof_mapping) const
std::array< size_t, 3 > GetIJKInfo() const
std::vector< chi_mesh::Vector3 > MakeCellOrthoSizes() const
chi_data_types::NDArray< uint64_t > MakeIJKToGlobalIDMapping() const
static int GetCellDimension(const chi_mesh::Cell &cell)
bool IsCellLocal(uint64_t cell_global_index) const
std::pair< chi_mesh::Vector3, chi_mesh::Vector3 > GetLocalBoundingBox() const
uint64_t MakeBoundaryID(const std::string &boundary_name) const
size_t MapCellGlobalID2LocalID(uint64_t global_id) const
static size_t MapCellFace(const chi_mesh::Cell &cur_cell, const chi_mesh::Cell &adj_cell, unsigned int f)
size_t CountCellsInLogicalVolume(const chi_mesh::LogicalVolume &log_vol) const
void FindAssociatedVertices(const chi_mesh::CellFace &cur_face, std::vector< short > &dof_mapping) const
std::string PrintS() const
Vector3 Cross(const Vector3 &that) const
Vector3 Normalized() const
Vector3 Dot(const chi_mesh::TensorRank2Dim3 &that) const