Program Listing for File mesh.h

↰ Return to documentation for file (framework/mesh/mesh/mesh.h)

// SPDX-FileCopyrightText: 2024 The OpenSn Authors <https://open-sn.github.io/opensn/>
// SPDX-License-Identifier: MIT

#pragma once

#include "framework/mesh/mesh/cell.h"
#include "framework/data_types/ndarray.h"
#include "framework/math/geometry.h"
#include <memory>
#include <array>
#include <map>
#include <cstddef>

namespace opensn
{
class GridFaceHistogram;
class MeshGenerator;
class LogicalVolume;

constexpr std::string_view
ToString(CoordinateSystemType type) noexcept
{
  switch (type)
  {
    case CoordinateSystemType::UNDEFINED:
      return "UNDEFINED";
    case CoordinateSystemType::CARTESIAN:
      return "CARTESIAN";
    case CoordinateSystemType::CYLINDRICAL:
      return "CYLINDRICAL";
    case CoordinateSystemType::SPHERICAL:
      return "SPHERICAL";
    default:
      return "UNKNOWN";
  }
}

enum MeshType : int
{
  ORTHOGONAL,
  UNSTRUCTURED
};

constexpr std::string_view
ToString(MeshType type) noexcept
{
  switch (type)
  {
    case ORTHOGONAL:
      return "UNDEFINED";
    case UNSTRUCTURED:
      return "CARTESIAN";
    default:
      return "UNKNOWN";
  }
}

enum BoundaryID : int
{
  XMIN = 0,
  XMAX = 1,
  YMIN = 2,
  YMAX = 3,
  ZMIN = 4,
  ZMAX = 5
};

struct OrthoMeshAttributes
{
  size_t Nx = 0;
  size_t Ny = 0;
  size_t Nz = 0;
};

/// Encapsulates all the necessary information required to fully define a computational domain.
class Mesh
{
  using GlobalVertexIDMap = std::map<uint64_t, Vector3>;

public:
  Mesh();

  unsigned int GetDimension() const { return dim_; }
  void SetDimension(const unsigned int dim) { dim_ = dim; }

  MeshType GetType() const { return mesh_type_; }
  void SetType(const MeshType type) { mesh_type_ = type; }

  CoordinateSystemType GetCoordinateSystem() const { return coord_sys_; }
  void SetCoordinateSystem(const CoordinateSystemType coord_sys) { coord_sys_ = coord_sys; }

  GeometryType GetGeometryType() const;

  bool Extruded() const { return extruded_; }
  void SetExtruded(const bool extruded) { extruded_ = extruded; }

  /// Gets and orthogonal mesh interface object.
  std::array<size_t, 3> GetIJKInfo() const;
  void SetOrthoAttributes(const OrthoMeshAttributes& attrs) { ortho_attributes_ = attrs; }

  void SetGlobalVertexCount(const uint64_t count) { global_vertex_count_ = count; }
  uint64_t GetGlobalVertexCount() const { return global_vertex_count_; }

  /// Get vertex using global vertex ID
  Vector3& GlobalVertex(const uint64_t global_id) { return global_vertex_id_map_.at(global_id); }

  /// Get vertex using global vertex ID
  const Vector3& GlobalVertex(const uint64_t global_id) const
  {
    return global_vertex_id_map_.at(global_id);
  }

  /// Add global vertex providing global ID and location in 3D space
  void AddGlobalVertex(const uint64_t global_id, const Vector3& pos)
  {
    global_vertex_id_map_.insert(std::make_pair(global_id, pos));
  }

  int GetNumPartitions() const { return num_partitions_; }
  size_t GetGlobalNumberOfCells() const;

  std::map<std::string, uint64_t>& GetBoundaryNameMap() { return boundary_name_map_; }
  const std::map<std::string, uint64_t>& GetBoundaryNameMap() const { return boundary_name_map_; }

  std::map<uint64_t, std::string>& GetBoundaryIDMap() { return boundary_id_map_; }
  const std::map<uint64_t, std::string>& GetBoundaryIDMap() const { return boundary_id_map_; }
  /// Returns the unique boundary ids present in the problem.
  std::vector<uint64_t> GetUniqueBoundaryIDs() const;

  /// Compute the geometric data for the cells and faces in the mesh.
  void ComputeGeometricInfo();

  /// Method to be called if cells and nodes have been transferred to another grid.
  void ClearCellReferences();

  /**
   * Makes a boundary id given a name. If the boundary name already exists, the associated
   * boundary id will be returned. Other the id will be set to one more than the maximum boundary
   * id.
   */
  uint64_t MakeBoundaryID(const std::string& boundary_name) const;

  /**
   * Associate boundary name with a boundary ID
   *
   * \param id Boundary ID
   * \param name Boundary name to associate with ``id``
   */
  void SetBoundaryName(std::uint64_t id, const std::string& name);

  /// Defines the standard x/y/z min/max boundaries.
  void SetOrthogonalBoundaries();

  /// Returns the the total number of ghost cells
  size_t GhostCellCount() const { return global_cell_id_to_nonlocal_id_map_.size(); }

  /**
   * Adds a new cell to the appropriate category (local or ghost).
   * @param new_cell The cell to add.
   */
  void AddGlobalCell(std::shared_ptr<Cell> new_cell);

  /// Returns a reference to a cell given its global cell index.
  Cell& GetGlobalCell(uint64_t cell_global_index);

  /// Returns a const reference to a cell given its global cell index.
  const Cell& GetGlobalCell(uint64_t cell_global_index) const;

  /**
   * Returns the cell global ids of all ghost cells. These are cells that neighbors to this
   * partition's cells but are on a different partition.
   */
  std::vector<uint64_t> GetGhostGlobalIDs() const;

  /**
   * Returns the local storage address of a ghost cell. If the ghost is not truly a ghost then -1 is
   * returned, but is wasteful and therefore the user of this function should implement code to
   * prevent it.
   */
  uint64_t GetGhostLocalID(uint64_t cell_global_index) const;

  /**
   * Populates a face histogram.
   *
   * \param master_tolerance Multiple histograms will only be attempted
   * if the ratio of the maximum dofs-per-face to the average dofs-per-face
   * is greater than this value. Default 1.2.
   *
   * \param slave_tolerance While traversing a sorted list of dofs-per-face,
   * a new bin will only be generated when the ratio of the listed dofs-per-face
   * to a running bin average exceeds this value. Defualt 1.1.
   *
   * The function populates face_categories which is a structure containing
   * pairs. Pair.first is the max dofs-per-face for the category and Pair.second
   * is the number of faces in this category.
   */
  std::shared_ptr<GridFaceHistogram> MakeGridFaceHistogram(double master_tolerance = 100.0,
                                                           double slave_tolerance = 1.1) const;

  std::size_t GetLocalCellCount() const;

  const Cell& GetLocalCell(uint64_t id) const;
  Cell& GetLocalCell(uint64_t id);

  std::vector<std::shared_ptr<Cell>>& GetLocalCells();
  const std::vector<std::shared_ptr<Cell>>& GetLocalCells() const;

  /// Returns whether the cell with the given global id is locally owned.
  bool IsCellLocal(uint64_t global_id) const noexcept
  {
    return global_cell_id_to_local_id_map_.contains(global_id);
  }

  /**
   * Given a global id of a cell, returns the local id if the cell is local, otherwise throws
   * an out_of_range error.
   */
  size_t MapCellGlobalID2LocalID(uint64_t global_id) const;

  /// Creates a mapping of the current face local ids to the adjacent face's local ids.
  void FindAssociatedVertices(const CellFace& cur_face, std::vector<short>& dof_mapping) const;
  /// Creates a mapping of the current face local ids to the adjacent cell's local ids.
  void FindAssociatedCellVertices(const CellFace& cur_face, std::vector<short>& dof_mapping) const;

  /// Counts the number of cells within a logical volume across all partitions.
  size_t CountCellsInLogicalVolume(const LogicalVolume& log_vol) const;

  /// Checks whether a point is within a cell.
  bool CheckPointInsideCell(const Cell& cell, const Vector3& point) const;
  /// Checks whether a point is within a cell face.
  bool CheckPointInsideCellFace(const Cell& cell, size_t face_i, const Vector3& point) const;

  /// Provides a mapping from cell ijk indices to global ids.
  NDArray<uint64_t, 3> MakeIJKToGlobalIDMapping() const;

  /**
   * Determines the bounding box size of each cell and returns it as a list of 3-component vectors,
   * one Vector3 for each cell.
   */
  std::vector<Vector3> MakeCellOrthoSizes() const;

  /// Returns the bounding box corners for the locally owned cells.
  std::pair<Vector3, Vector3> GetLocalBoundingBox() const;

  /// Sets block ids for all cells to the specified block id.
  void SetUniformBlockID(unsigned int blk_id);

  /// Sets block IDs using a logical volume.
  void SetBlockIDFromLogicalVolume(const LogicalVolume& log_vol, unsigned int blk_id, bool sense);

  /// Assign all boundary faces to a single name
  void SetUniformBoundaryID(const std::string& boundary_name);

  /// Sets boundary ids using a logical volume.
  void SetBoundaryIDFromLogicalVolume(const LogicalVolume& log_vol,
                                      const std::string& boundary_name,
                                      bool sense = true);

  /// Computes the centroid from nodes specified by the given list.
  Vector3 ComputeCentroidFromListOfNodes(const std::vector<uint64_t>& list) const;

  /**
   * Get the face vertices of a tetrahedron contained within the given face and
   * side of a polyhedron.
   */
  std::array<std::array<Vector3, 3>, 4>
  GetTetrahedralFaceVertices(const Cell& cell, const CellFace& face, size_t side) const;

  /// Compute volume per block IDs
  std::map<unsigned int, double> ComputeVolumePerBlockID() const;

private:
  /// Spatial dimension
  unsigned int dim_;
  MeshType mesh_type_;
  CoordinateSystemType coord_sys_;
  bool extruded_;
  OrthoMeshAttributes ortho_attributes_;
  std::map<uint64_t, std::string> boundary_id_map_;
  std::map<std::string, uint64_t> boundary_name_map_;
  int num_partitions_;
  uint64_t global_vertex_count_;

  ///
  GlobalVertexIDMap global_vertex_id_map_;
  /// Locally owned cells
  std::vector<std::shared_ptr<Cell>> local_cells_;
  /// Locally stored ghost cells
  std::vector<std::shared_ptr<Cell>> ghost_cells_;

  std::map<uint64_t, uint64_t> global_cell_id_to_local_id_map_;
  /// Global to ghost ID map
  std::map<uint64_t, uint64_t> global_cell_id_to_nonlocal_id_map_;

public:
  /// Returns a new instance of the spatial discretization.
  static std::shared_ptr<Mesh> New() { return std::make_shared<Mesh>(); }

  /// Returns the spatial dimensionality of the cell.
  static int GetCellDimension(const Cell& cell);

  /**
   * Given the current cell, cell A, and its adjacent cell, cell B, with cell B adjacent to
   * A at the `f`-th face of cell A. Will determine the `af`-th index of the face on cell B
   * that interface with the `f`-th face of cell A.
   */
  static size_t MapCellFace(const Cell& cur_cell, const Cell& adj_cell, unsigned int f);
};

} // namespace opensn