Program Listing for File xgc_reverse_classification.h

↰ Return to documentation for file (src/pcms/discretization/discretization/xgc_reverse_classification.h)

#ifndef PCMS_DISCRETIZATION_XGC_REVERSE_CLASSIFICATION_H
#define PCMS_DISCRETIZATION_XGC_REVERSE_CLASSIFICATION_H

#include "pcms/configuration.h"
#include "pcms/utility/arrays.h"
#include "pcms/utility/memory_spaces.h"
#include "pcms/utility/types.h"

#include <Kokkos_Core.hpp>
#include <mpi.h>
#include <set>
#include <unordered_map>

#ifdef PCMS_ENABLE_OMEGA_H
#include <Omega_h_mesh.hpp>
#include "pcms/utility/assert.h"
#endif

namespace pcms
{

struct DimID
{
  LO dim;
  LO id;
  bool operator==(const DimID& other) const
  {
    return (dim == other.dim) && (id == other.id);
  }
};

} // namespace pcms

namespace std
{

template <>
struct hash<pcms::DimID>
{
  std::size_t operator()(const pcms::DimID& key) const noexcept
  {
    auto h1 = hash<pcms::LO>{}(key.dim);
    auto h2 = hash<pcms::LO>{}(key.id);
    return h1 ^ (h2 << 1); // hash combine see
                           // https://en.cppreference.com/w/cpp/utility/hash
  }
};

} // namespace std

namespace pcms
{
class ReverseClassificationVertex
{
public:
  // the ordered nature of the set is relied upon to provide the entries for
  // each geometric entity in iteration order (for xgc) where the gids are in
  // ascending order
  using DataMapType = std::unordered_map<DimID, std::set<LO>>;

  void Insert(const DimID& key, Rank1View<LO, HostMemorySpace> data);
  void Insert(const DimID& key, LO data);

  [[nodiscard]] std::vector<LO> Serialize() const;
  void Deserialize(Rank1View<LO, HostMemorySpace> serialized_data);

  [[nodiscard]] bool operator==(const ReverseClassificationVertex& other) const;
  [[nodiscard]] const std::set<LO>* Query(const DimID& geometry) const noexcept;

  [[nodiscard]] DataMapType::iterator begin() noexcept { return data_.begin(); }
  [[nodiscard]] DataMapType::iterator end() noexcept { return data_.end(); }
  [[nodiscard]] DataMapType::const_iterator begin() const noexcept
  {
    return data_.begin();
  }
  [[nodiscard]] DataMapType::const_iterator end() const noexcept
  {
    return data_.end();
  }

  [[nodiscard]] LO GetTotalVerts() const noexcept { return total_verts_; }

  friend std::ostream& operator<<(std::ostream& os,
                                  const ReverseClassificationVertex& v);

private:
  DataMapType data_;
  LO total_verts_{0};
};

ReverseClassificationVertex ReadReverseClassificationVertex(std::string);
ReverseClassificationVertex ReadReverseClassificationVertex(std::istream&);
ReverseClassificationVertex ReadReverseClassificationVertex(std::istream&,
                                                            MPI_Comm,
                                                            int root = 0);
ReverseClassificationVertex ReadReverseClassificationVertex(std::string,
                                                            MPI_Comm,
                                                            int root = 0);

#ifdef PCMS_ENABLE_OMEGA_H

enum class IndexBase
{
  Zero = 0,
  One = 1
};

template <typename T = Omega_h::LO>
[[nodiscard]] ReverseClassificationVertex ConstructRCFromOmegaHMesh(
  Omega_h::Mesh& mesh, std::string numbering = "simNumbering",
  IndexBase index_base = IndexBase::One)
{
  auto class_ids_h = Omega_h::HostRead<Omega_h::ClassId>(
    mesh.get_array<Omega_h::ClassId>(0, "class_id"));
  auto class_dims_h =
    Omega_h::HostRead<Omega_h::I8>(mesh.get_array<Omega_h::I8>(0, "class_dim"));
  auto vert_id = Omega_h::HostRead<T>(mesh.get_array<T>(0, numbering));
  ReverseClassificationVertex rc;
  PCMS_ALWAYS_ASSERT(class_dims_h.size() == class_ids_h.size());
  for (int i = 0; i < class_dims_h.size(); ++i) {
    DimID geom{class_dims_h[i], class_ids_h[i]};
    if (index_base == IndexBase::Zero) {
      rc.Insert(geom, vert_id[i]);
    } else {
      PCMS_ALWAYS_ASSERT(vert_id[i] > 0);
      rc.Insert(geom, vert_id[i] - 1);
    }
  }
  return rc;
}

#endif

} // namespace pcms

#endif // PCMS_DISCRETIZATION_XGC_REVERSE_CLASSIFICATION_H