Cloned SEACAS for EXODUS library with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
6.8 KiB

2 years ago
// Copyright(C) 2021, 2022 National Technology & Engineering Solutions
// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
// NTESS, the U.S. Government retains certain rights in this software.
//
// See packages/seacas/LICENSE for details
#pragma once
//
// `Cell`:
// -- for each location:
// -- i,j location (could be calculated, but easier if entry knows it...)
// -- reference to unit_cell region
// -- global node offset for node ids (over all ranks if parallel)
// -- local node offset for node ids (for this rank only if parallel)
// -- global element block offsets for element ids for each element block (over all ranks if
// parallel)
// -- local element block offsets for element ids for each element block (for this rank only
// if parallel)
// -- offX, offY -- coordinate offsets for nodes (can be calculated?)
// -- rank (for parallel -- which rank does this entry exist on)
//
#include <array>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "UnitCell.h"
//! \file
// Each entry in grid will have the following information:
enum class Axis { X, Y, Z };
enum class Mode { GLOBAL, PROCESSOR };
enum class Loc { C = 0, BL, B, BR, L, R, TL, T, TR };
class Cell
{
public:
Cell() = default;
Cell(const Cell &) = default;
std::pair<double, double> get_coordinate_range(enum Axis) const;
void initialize(size_t i, size_t j, std::shared_ptr<UnitCell> unit_cell);
//! Provide access to the UnitCell that this cell uses.
std::shared_ptr<UnitCell> unit() const { return m_unitCell; }
//! Provide access to the Ioss::Region in the unit_cell that this cell uses.
std::shared_ptr<Ioss::Region> region() const { return m_unitCell->m_region; }
//! True if this cell has a neighbor to its "left" (lower i)
bool has_neighbor_i() const { return m_i > 0; }
//! True if this cell has a neighbor "below it" (lower j)
bool has_neighbor_j() const { return m_j > 0; }
//! Return neighbor information for each possible direction.
//! This is only valid after `grid.decompose()` has been called
bool has_neighbor(enum Loc loc) const { return m_ranks[(int)loc] != -1; }
//! True if this cell has a processor boundary to the specified direction
//! Note that cell cannot compute this, but is "told" this during decomposition
//! of the owning `Grid`
//! There is a processor boundary if the rank of the cell at that location is
//! different than the rank of this cell...
bool processor_boundary(enum Loc loc) const
{
return m_ranks[(int)loc] >= 0 && (m_ranks[(int)Loc::C] != m_ranks[(int)loc]);
}
//! Number of nodes that will be added to global node count when this cell is added to
//! grid -- accounts for coincident nodes if this cell has neighbor(s)
size_t added_node_count(enum Mode mode, bool equivalence_nodes) const;
//! Number of nodes that this cell adds to the processor boundary node count.
//! Assumes that cells are processed in "order", so accounts for corner nodes
//! shared with another cell...
//! Note that a node shared by more than one processor (e.g. a corner node) counts
//! for each processor it is shared with.
size_t processor_boundary_node_count() const;
template <typename INT>
void populate_node_communication_map(const std::vector<INT> &node_map, std::vector<INT> &nodes,
std::vector<INT> &procs) const;
//! Returns a `std::array<int,9>` which categorizes whether the cells at each location are on the
//! same rank as `rank`. A value of `1` means the cell at that location is on the same rank; a
//! value of `0` means it is on a different rank. Used to determine which nodes have already been
//! accounted for on this rank and which this cell will add to the processor-local count.
std::array<int, 9> categorize_processor_boundary_nodes(int rank) const;
//! The mpi rank that this cell, or the neighboring cells, will be on in a parallel run.
int rank(enum Loc loc) const { return m_ranks[(int)loc]; }
//! The mpi rank that this cell will be on in a parallel run.
void set_rank(enum Loc loc, int my_rank) { m_ranks[(int)loc] = my_rank; }
//! Create a vector of `node_count` length which has the following values:
//! * 0: Node that is not shared with any "lower" neighbors.
//! * 1: Node on `min_I` face
//! * 2: Node on `min_J` face
//! * 3: Node on `min_I-min_J` line
//! If `mode == PROCESSOR`, then modify due to processor boundaries...
std::vector<int> categorize_nodes(enum Mode mode) const;
template <typename INT>
std::vector<INT> generate_node_map(Mode mode, bool equivalance_nodes, INT /*dummy*/) const;
template <typename INT>
void populate_neighbor(Loc location, const std::vector<INT> &map, const Cell &neighbor) const;
//! A vector containing the global node ids of the nodes on the `min_I` face of this
//! unit cell. These nodes were generated by the "left" (lower i) neighbor.
//! Once this cell uses this information, it can clear out the vector.
mutable std::vector<int64_t> min_I_nodes;
//! A vector containing the global node ids of the nodes on the `min_J` face of this
//! unit cell. These nodes were generated by the "below" (lower j neighbor.
//! Once this cell uses this information, it can clear out the vector.
mutable std::vector<int64_t> min_J_nodes;
//! The `i` location of this entry in the grid
size_t m_i{0};
//! The `j` location of this entry in the grid
size_t m_j{0};
int64_t m_globalNodeIdOffset{0};
int64_t m_localNodeIdOffset{0};
//! The offset into the commincation node output array for this cell in the file associated with
//! the rank that this cell is on. Set by handle_communications() in Grid.C.
mutable size_t m_communicationNodeOffset{0};
//! The number of node/proc pairs that this cell adds to the communication node map.
mutable size_t m_communicationNodeCount{0};
std::map<std::string, size_t> m_globalElementIdOffset;
std::map<std::string, size_t> m_localElementIdOffset;
//! For each surface/sideset, this is the offset into the output element/face lists
//! for this cells data. 0-based. Indexed by surface name.
std::map<std::string, size_t> m_localSurfaceOffset;
//! The offset that must be added to the `x` coordinates of the
//! UnitCell to place it in the correct global location of the
//! output mesh
double m_offX{0.0};
//! The offset that must be added to the `y` coordinates of the
//! UnitCell to place it in the correct global location of the
//! output mesh
double m_offY{0.0};
private:
//! The UnitCell that occupies this location in the grid / latice
std::shared_ptr<UnitCell> m_unitCell;
//! The MPI ranks of all surrounding cells in order:
//! 6 7 8 TL T TR
//! 4 0 5 L C R
//! 1 2 3 BL B BR
std::array<int, 9> m_ranks{{0, -1, -1, -1, -1, -1, -1, -1, -1}};
};