OpenMC/include/openmc/cell.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

494 lines
18 KiB
C
Raw Permalink Normal View History

2018-08-08 13:54:33 -05:00
#ifndef OPENMC_CELL_H
#define OPENMC_CELL_H
#include <cstdint>
2019-12-12 07:30:41 -06:00
#include <functional> // for hash
#include <limits>
#include <string>
2018-05-27 13:38:16 -04:00
#include <unordered_map>
#include <unordered_set>
#include "hdf5.h"
2018-06-20 10:56:28 -05:00
#include "pugixml.hpp"
#include "openmc/bounding_box.h"
2018-08-27 17:07:22 -04:00
#include "openmc/constants.h"
#include "openmc/memory.h" // for unique_ptr
#include "openmc/neighbor_list.h"
#include "openmc/position.h"
2019-02-15 11:42:49 -06:00
#include "openmc/surface.h"
#include "openmc/universe.h"
#include "openmc/vector.h"
namespace openmc {
2018-05-11 17:20:25 -04:00
//==============================================================================
// Constants
//==============================================================================
enum class Fill { MATERIAL, UNIVERSE, LATTICE };
2018-05-11 17:20:25 -04:00
2018-08-20 23:42:51 -04:00
constexpr int32_t OP_LEFT_PAREN {std::numeric_limits<int32_t>::max()};
constexpr int32_t OP_RIGHT_PAREN {std::numeric_limits<int32_t>::max() - 1};
constexpr int32_t OP_COMPLEMENT {std::numeric_limits<int32_t>::max() - 2};
constexpr int32_t OP_INTERSECTION {std::numeric_limits<int32_t>::max() - 3};
constexpr int32_t OP_UNION {std::numeric_limits<int32_t>::max() - 4};
//==============================================================================
// Global variables
//==============================================================================
class Cell;
2024-01-16 10:35:57 -06:00
class GeometryState;
class ParentCell;
2020-05-14 22:49:13 -05:00
class CellInstance;
class Universe;
class UniversePartitioner;
namespace model {
extern std::unordered_map<int32_t, int32_t> cell_map;
extern vector<unique_ptr<Cell>> cells;
} // namespace model
//==============================================================================
2022-09-08 11:24:08 -05:00
class Region {
public:
2022-09-25 22:05:22 -04:00
//----------------------------------------------------------------------------
// Constructors
2022-09-08 11:24:08 -05:00
Region() {}
2022-11-04 13:26:13 -05:00
explicit Region(std::string region_spec, int32_t cell_id);
2022-09-08 11:24:08 -05:00
2022-09-25 22:05:22 -04:00
//----------------------------------------------------------------------------
// Methods
//! \brief Determine if a cell contains the particle at a given location.
//!
//! The bounds of the cell are determined by a logical expression involving
//! surface half-spaces. The expression used is given in infix notation
//!
//! The function is split into two cases, one for simple cells (those
//! involving only the intersection of half-spaces) and one for complex cells.
//! Both cases use short circuiting; however, in the case fo complex cells,
//! the complexity increases with the binary operators involved.
//! \param r The 3D Cartesian coordinate to check.
//! \param u A direction used to "break ties" the coordinates are very
//! close to a surface.
//! \param on_surface The signed index of a surface that the coordinate is
//! known to be on. This index takes precedence over surface sense
//! calculations.
bool contains(Position r, Direction u, int32_t on_surface) const;
//! Find the oncoming boundary of this cell.
2022-09-25 22:05:22 -04:00
std::pair<double, int32_t> distance(
2024-01-16 10:35:57 -06:00
Position r, Direction u, int32_t on_surface) const;
//! Get the BoundingBox for this cell.
2022-09-25 22:05:22 -04:00
BoundingBox bounding_box(int32_t cell_id) const;
//! Get the CSG expression as a string
2022-09-25 22:05:22 -04:00
std::string str() const;
//! Get a vector containing all the surfaces in the region expression
2022-09-25 22:05:22 -04:00
vector<int32_t> surfaces() const;
2022-09-08 11:24:08 -05:00
2022-09-25 22:05:22 -04:00
//----------------------------------------------------------------------------
// Accessors
//! Get Boolean of if the cell is simple or not
2022-09-25 22:05:22 -04:00
bool is_simple() const { return simple_; }
2022-09-08 11:24:08 -05:00
private:
2022-09-25 22:05:22 -04:00
//----------------------------------------------------------------------------
// Private Methods
//! Get a vector of the region expression in postfix notation
2022-09-25 22:05:22 -04:00
vector<int32_t> generate_postfix(int32_t cell_id) const;
//! Determine if a particle is inside the cell for a simple cell (only
//! intersection operators)
2022-09-25 22:05:22 -04:00
bool contains_simple(Position r, Direction u, int32_t on_surface) const;
//! Determine if a particle is inside the cell for a complex cell.
//!
//! Uses the comobination of half-spaces and binary operators to determine
//! if short circuiting can be used. Short cicuiting uses the relative and
//! absolute depth of parentheses in the expression.
2022-09-25 22:05:22 -04:00
bool contains_complex(Position r, Direction u, int32_t on_surface) const;
//! BoundingBox if the paritcle is in a simple cell.
2022-09-25 22:05:22 -04:00
BoundingBox bounding_box_simple() const;
//! BoundingBox if the particle is in a complex cell.
2022-09-25 22:05:22 -04:00
BoundingBox bounding_box_complex(vector<int32_t> postfix) const;
//! Enforce precedence between intersections and unions
void enforce_precedence();
//! Add parenthesis to enforce precedence
void add_parentheses(int64_t start);
//! Remove complement operators from the expression
2022-09-25 22:05:22 -04:00
void remove_complement_ops();
//! Remove complement operators by using DeMorgan's laws
2022-09-08 11:24:08 -05:00
void apply_demorgan(
vector<int32_t>::iterator start, vector<int32_t>::iterator stop);
2022-09-25 22:05:22 -04:00
//----------------------------------------------------------------------------
// Private Data
2022-09-08 11:24:08 -05:00
//! Definition of spatial region as Boolean expression of half-spaces
// TODO: Should this be a vector of some other type
2022-09-25 22:05:22 -04:00
vector<int32_t> expression_;
2022-09-08 11:24:08 -05:00
bool simple_; //!< Does the region contain only intersections?
};
//==============================================================================
// XML parsing helpers for <cell> nodes
//==============================================================================
//! Parse material IDs from a <cell> XML node.
//! \param node XML node containing a "material" attribute or child element
//! \param cell_id Cell ID used in error messages
//! \return Vector of material IDs (MATERIAL_VOID for "void")
vector<int32_t> parse_cell_material_xml(pugi::xml_node node, int32_t cell_id);
//! Parse temperatures in [K] from a <cell> XML node.
//! Validates that all values are non-negative and the list is non-empty.
//! \param node XML node containing a "temperature" attribute or child element
//! \param cell_id Cell ID used in error messages
//! \return Vector of temperatures in [K]
vector<double> parse_cell_temperature_xml(pugi::xml_node node, int32_t cell_id);
//! Parse densities in [g/cm³] from a <cell> XML node.
//! Validates that all values are positive and the list is non-empty.
//! \param node XML node containing a "density" attribute or child element
//! \param cell_id Cell ID used in error messages
//! \return Vector of densities in [g/cm³]
vector<double> parse_cell_density_xml(pugi::xml_node node, int32_t cell_id);
//==============================================================================
2019-07-08 14:07:40 -05:00
class Cell {
public:
2019-07-08 14:07:40 -05:00
//----------------------------------------------------------------------------
// Constructors, destructors, factory functions
explicit Cell(pugi::xml_node cell_node);
Cell() {};
virtual ~Cell() = default;
//----------------------------------------------------------------------------
// Methods
//! \brief Determine if a cell contains the particle at a given location.
//!
//! The bounds of the cell are detemined by a logical expression involving
//! surface half-spaces. At initialization, the expression was converted
//! to RPN notation.
//!
//! The function is split into two cases, one for simple cells (those
//! involving only the intersection of half-spaces) and one for complex cells.
//! Simple cells can be evaluated with short circuit evaluation, i.e., as soon
//! as we know that one half-space is not satisfied, we can exit. This
//! provides a performance benefit for the common case. In
//! contains_complex, we evaluate the RPN expression using a stack, similar to
//! how a RPN calculator would work.
//! \param r The 3D Cartesian coordinate to check.
//! \param u A direction used to "break ties" the coordinates are very
//! close to a surface.
//! \param on_surface The signed index of a surface that the coordinate is
//! known to be on. This index takes precedence over surface sense
//! calculations.
virtual bool contains(Position r, Direction u, int32_t on_surface) const = 0;
//! Find the oncoming boundary of this cell.
virtual std::pair<double, int32_t> distance(
2024-01-16 10:35:57 -06:00
Position r, Direction u, int32_t on_surface, GeometryState* p) const = 0;
2019-07-08 14:07:40 -05:00
//! Write all information needed to reconstruct the cell to an HDF5 group.
//! \param group_id An HDF5 group id.
2021-06-25 07:21:33 -05:00
void to_hdf5(hid_t group_id) const;
2020-07-19 22:34:20 -05:00
virtual void to_hdf5_inner(hid_t group_id) const = 0;
2019-07-08 14:07:40 -05:00
//! Export physical properties to HDF5
//! \param[in] group HDF5 group to read from
void export_properties_hdf5(hid_t group) const;
//! Import physical properties from HDF5
//! \param[in] group HDF5 group to write to
void import_properties_hdf5(hid_t group);
2019-07-08 14:07:40 -05:00
//! Get the BoundingBox for this cell.
virtual BoundingBox bounding_box() const = 0;
2022-09-25 22:05:22 -04:00
//! Get a vector of surfaces in the cell
virtual vector<int32_t> surfaces() const { return vector<int32_t>(); }
2022-09-25 22:05:22 -04:00
//! Check if the cell region expression is simple
virtual bool is_simple() const { return true; }
2022-09-25 22:05:22 -04:00
2019-07-08 14:07:40 -05:00
//----------------------------------------------------------------------------
// Accessors
//! Get the temperature of a cell instance
//! \param[in] instance Instance index. If -1 is given, the temperature for
//! the first instance is returned.
//! \return Temperature in [K]
double temperature(int32_t instance = -1) const;
//! Get the density multiplier of a cell instance
//! \param[in] instance Instance index. If -1 is given, the density multiplier
//! for the first instance is returned.
//! \return Density multiplier
double density_mult(int32_t instance = -1) const;
//! Get the density of a cell instance in g/cm3
//! \param[in] instance Instance index. If -1 is given, the density
//! for the first instance is returned.
//! \return Density in [g/cm3]
double density(int32_t instance = -1) const;
2019-07-08 14:07:40 -05:00
//! Set the temperature of a cell instance
//! \param[in] T Temperature in [K]
//! \param[in] instance Instance index. If -1 is given, the temperature for
//! all instances is set.
2020-05-19 13:51:38 -05:00
//! \param[in] set_contained If this cell is not filled with a material,
//! collect all contained cells with material fills and set their
//! temperatures.
void set_temperature(
double T, int32_t instance = -1, bool set_contained = false);
2019-07-08 14:07:40 -05:00
//! Set the density of a cell instance
//! \param[in] density Density [g/cm3]
//! \param[in] instance Instance index. If -1 is given, the density
//! for all instances is set.
//! \param[in] set_contained If this cell is not filled with a material,
//! collect all contained cells with material fills and set their
//! densities.
void set_density(
double density, int32_t instance = -1, bool set_contained = false);
int32_t n_instances() const;
//! Set the rotation matrix of a cell instance
//! \param[in] rot The rotation matrix of length 3 or 9
void set_rotation(const vector<double>& rot);
2019-07-18 12:19:13 -05:00
//! Get the name of a cell
//! \return Cell name
const std::string& name() const { return name_; };
2019-07-18 12:19:13 -05:00
//! Set the temperature of a cell instance
//! \param[in] name Cell name
2019-07-18 12:25:53 -05:00
void set_name(const std::string& name) { name_ = name; };
2019-07-18 12:19:13 -05:00
2020-05-14 13:44:12 -05:00
//! Get all cell instances contained by this cell
//! \param[in] instance Instance of the cell for which to get contained cells
2021-08-25 07:32:12 -05:00
//! (default instance is zero)
//! \param[in] hint positional hint for determining the parent cells
2021-08-25 07:32:12 -05:00
//! \return Map with cell indexes as keys and
//! instances as values
std::unordered_map<int32_t, vector<int32_t>> get_contained_cells(
int32_t instance = 0, Position* hint = nullptr) const;
//! Determine the material index corresponding to a specific cell instance,
//! taking into account presence of distribcell material
//! \param[in] instance of the cell
//! \return material index
int32_t material(int32_t instance) const
{
// If distributed materials are used, then each instance has its own
// material definition. If distributed materials are not used, then
// all instances used the same material stored at material_[0]. The
// presence of distributed materials is inferred from the size of
// the material_ vector being greater than one.
if (material_.size() > 1) {
return material_[instance];
} else {
return material_[0];
}
}
//! Determine the temperature index corresponding to a specific cell instance,
//! taking into account presence of distribcell temperature
//! \param[in] instance of the cell
//! \return temperature index
double sqrtkT(int32_t instance) const
{
// If distributed materials are used, then each instance has its own
// temperature definition. If distributed materials are not used, then
// all instances used the same temperature stored at sqrtkT_[0]. The
// presence of distributed materials is inferred from the size of
// the sqrtkT_ vector being greater than one.
if (sqrtkT_.size() > 1) {
return sqrtkT_[instance];
} else {
return sqrtkT_[0];
}
}
protected:
//! Determine the path to this cell instance in the geometry hierarchy
//! \param[in] instance of the cell to find parent cells for
//! \param[in] r position used to do a fast search for parent cells
//! \return parent cells
vector<ParentCell> find_parent_cells(
int32_t instance, const Position& r) const;
//! Determine the path to this cell instance in the geometry hierarchy
//! \param[in] instance of the cell to find parent cells for
//! \param[in] p particle used to do a fast search for parent cells
//! \return parent cells
2024-01-16 10:35:57 -06:00
vector<ParentCell> find_parent_cells(
int32_t instance, GeometryState& p) const;
//! Determine the path to this cell instance in the geometry hierarchy
//! \param[in] instance of the cell to find parent cells for
//! \return parent cells
vector<ParentCell> exhaustive_find_parent_cells(int32_t instance) const;
//! Inner function for retrieving contained cells
void get_contained_cells_inner(
std::unordered_map<int32_t, vector<int32_t>>& contained_cells,
vector<ParentCell>& parent_cells) const;
2020-05-14 13:44:12 -05:00
public:
2019-07-08 14:07:40 -05:00
//----------------------------------------------------------------------------
// Data members
int32_t id_; //!< Unique ID
std::string name_; //!< User-defined name
Fill type_; //!< Material, universe, or lattice
int32_t universe_; //!< Universe # this cell is in
int32_t fill_; //!< Universe # filling this cell
2018-08-19 18:39:28 -04:00
//! \brief Index corresponding to this cell in distribcell arrays
int distribcell_index_ {C_NONE};
2018-08-19 18:39:28 -04:00
//! \brief Material(s) within this cell.
2018-05-27 13:38:16 -04:00
//!
2018-08-19 14:57:28 -04:00
//! May be multiple materials for distribcell.
vector<int32_t> material_;
2018-05-11 17:20:25 -04:00
2018-08-19 14:57:28 -04:00
//! \brief Temperature(s) within this cell.
//!
//! The stored values are actually sqrt(k_Boltzmann * T) for each temperature
//! T. The units are sqrt(eV).
vector<double> sqrtkT_;
2018-08-19 14:57:28 -04:00
//! \brief Unitless density multiplier(s) within this cell.
vector<double> density_mult_;
2018-11-24 09:29:24 -05:00
//! \brief Neighboring cells in the same universe.
2018-12-18 15:02:07 -05:00
NeighborList neighbors_;
2018-11-24 09:29:24 -05:00
Position translation_ {0, 0, 0}; //!< Translation vector for filled universe
//! \brief Rotational tranfsormation of the filled universe.
//
//! The vector is empty if there is no rotation. Otherwise, the first 9 values
//! give the rotation matrix in row-major order. When the user specifies
//! rotation angles about the x-, y- and z- axes in degrees, these values are
//! also present at the end of the vector, making it of length 12.
vector<double> rotation_;
vector<int32_t> offset_; //!< Distribcell offset table
// Right now, either CSG or DAGMC cells are used.
virtual GeometryType geom_type() const = 0;
};
2020-05-14 13:44:12 -05:00
struct CellInstanceItem {
int32_t index {-1}; //! Index into global cells array
int lattice_indx {-1}; //! Flat index value of the lattice cell
};
2018-12-15 15:34:00 -05:00
//==============================================================================
class CSGCell : public Cell {
public:
2022-09-25 22:05:22 -04:00
//----------------------------------------------------------------------------
// Constructors
CSGCell() = default;
explicit CSGCell(pugi::xml_node cell_node);
2022-09-25 22:05:22 -04:00
//----------------------------------------------------------------------------
// Methods
vector<int32_t> surfaces() const override { return region_.surfaces(); }
2018-02-04 21:11:12 -05:00
2024-01-16 10:35:57 -06:00
std::pair<double, int32_t> distance(Position r, Direction u,
int32_t on_surface, GeometryState* p) const override
2022-09-25 22:05:22 -04:00
{
2024-01-16 10:35:57 -06:00
return region_.distance(r, u, on_surface);
2022-09-25 22:05:22 -04:00
}
2018-02-04 17:44:04 -05:00
2022-09-25 22:05:22 -04:00
bool contains(Position r, Direction u, int32_t on_surface) const override
{
return region_.contains(r, u, on_surface);
}
2022-09-25 22:05:22 -04:00
BoundingBox bounding_box() const override
{
return region_.bounding_box(id_);
}
2022-09-25 22:05:22 -04:00
void to_hdf5_inner(hid_t group_id) const override;
2022-09-25 22:05:22 -04:00
bool is_simple() const override { return region_.is_simple(); }
virtual GeometryType geom_type() const override { return GeometryType::CSG; }
2022-09-25 22:05:22 -04:00
protected:
//! Returns the beginning position of a parenthesis block (immediately before
//! two surface tokens) in the RPN given a starting position at the end of
//! that block (immediately after two surface tokens)
2019-09-13 13:45:18 -05:00
//! \param start Starting position of the search
//! \param rpn The rpn being searched
static vector<int32_t>::iterator find_left_parenthesis(
vector<int32_t>::iterator start, const vector<int32_t>& rpn);
2022-09-08 11:24:08 -05:00
private:
Region region_;
2018-02-04 17:44:04 -05:00
};
//==============================================================================
2019-12-12 07:30:41 -06:00
//! Define an instance of a particular cell
//==============================================================================
//! Stores information used to identify a unique cell in the model
2019-12-12 07:30:41 -06:00
struct CellInstance {
//! Check for equality
bool operator==(const CellInstance& other) const
{
return index_cell == other.index_cell && instance == other.instance;
}
int64_t index_cell;
int64_t instance;
2019-12-12 07:30:41 -06:00
};
//! Structure necessary for inserting CellInstance into hashed STL data
//! structures
struct CellInstanceHash {
std::size_t operator()(const CellInstance& k) const
2019-12-12 07:30:41 -06:00
{
return 4096 * k.index_cell + k.instance;
2019-12-12 07:30:41 -06:00
}
};
//==============================================================================
// Non-member functions
//==============================================================================
2019-02-15 06:35:59 -06:00
void read_cells(pugi::xml_node node);
//! Add cells to universes
void populate_universes();
} // namespace openmc
2018-08-08 13:54:33 -05:00
#endif // OPENMC_CELL_H