1 #ifndef OPENMC_LATTICE_H 2 #define OPENMC_LATTICE_H 3 4 #include <cstdint> 5 #include <string> 6 #include <unordered_map> 7 8 #include "hdf5.h" 9 #include "pugixml.hpp" 10 11 #include "openmc/array.h" 12 #include "openmc/constants.h" 13 #include "openmc/memory.h" 14 #include "openmc/position.h" 15 #include "openmc/vector.h" 16 17 namespace openmc { 18 19 //============================================================================== 20 // Module constants 21 //============================================================================== 22 23 constexpr int32_t NO_OUTER_UNIVERSE{-1}; 24 25 enum class LatticeType { 26 rect, hex 27 }; 28 29 //============================================================================== 30 // Global variables 31 //============================================================================== 32 33 class Lattice; 34 35 namespace model { 36 extern std::unordered_map<int32_t, int32_t> lattice_map; 37 extern vector<unique_ptr<Lattice>> lattices; 38 } // namespace model 39 40 //============================================================================== 41 //! \class Lattice 42 //! \brief Abstract type for ordered array of universes. 43 //============================================================================== 44 45 class LatticeIter; 46 class ReverseLatticeIter; 47 48 class Lattice 49 { 50 public: 51 int32_t id_; //!< Universe ID number 52 std::string name_; //!< User-defined name 53 LatticeType type_; 54 vector<int32_t> universes_; //!< Universes filling each lattice tile 55 int32_t outer_ {NO_OUTER_UNIVERSE}; //!< Universe tiled outside the lattice 56 vector<int32_t> offsets_; //!< Distribcell offset table 57 58 explicit Lattice(pugi::xml_node lat_node); 59 ~Lattice()60 virtual ~Lattice() {} 61 62 virtual int32_t const& operator[](array<int, 3> const& i_xyz) = 0; 63 64 virtual LatticeIter begin(); 65 LatticeIter end(); 66 67 virtual ReverseLatticeIter rbegin(); 68 ReverseLatticeIter rend(); 69 70 //! Convert internal universe values from IDs to indices using universe_map. 71 void adjust_indices(); 72 73 //! Allocate offset table for distribcell. allocate_offset_table(int n_maps)74 void allocate_offset_table(int n_maps) 75 {offsets_.resize(n_maps * universes_.size(), C_NONE);} 76 77 //! Populate the distribcell offset tables. 78 int32_t fill_offset_table(int32_t offset, int32_t target_univ_id, int map, 79 std::unordered_map<int32_t, int32_t>& univ_count_memo); 80 81 //! \brief Check lattice indices. 82 //! \param i_xyz[3] The indices for a lattice tile. 83 //! \return true if the given indices fit within the lattice bounds. False 84 //! otherwise. 85 virtual bool are_valid_indices(array<int, 3> const& i_xyz) const = 0; 86 87 //! \brief Find the next lattice surface crossing 88 //! \param r A 3D Cartesian coordinate. 89 //! \param u A 3D Cartesian direction. 90 //! \param i_xyz The indices for a lattice tile. 91 //! \return The distance to the next crossing and an array indicating how the 92 //! lattice indices would change after crossing that boundary. 93 virtual std::pair<double, array<int, 3>> distance( 94 Position r, Direction u, const array<int, 3>& i_xyz) const = 0; 95 96 //! \brief Find the lattice tile indices for a given point. 97 //! \param r A 3D Cartesian coordinate. 98 //! \param u Direction of a particle 99 //! \param result resulting indices to save to 100 virtual void get_indices( 101 Position r, Direction u, array<int, 3>& result) const = 0; 102 103 //! \brief Get coordinates local to a lattice tile. 104 //! \param r A 3D Cartesian coordinate. 105 //! \param i_xyz The indices for a lattice tile. 106 //! \return Local 3D Cartesian coordinates. 107 virtual Position get_local_position( 108 Position r, const array<int, 3>& i_xyz) const = 0; 109 110 //! \brief Check flattened lattice index. 111 //! \param indx The index for a lattice tile. 112 //! \return true if the given index fit within the lattice bounds. False 113 //! otherwise. is_valid_index(int indx)114 virtual bool is_valid_index(int indx) const 115 {return (indx >= 0) && (indx < universes_.size());} 116 117 //! \brief Get the distribcell offset for a lattice tile. 118 //! \param The map index for the target cell. 119 //! \param i_xyz[3] The indices for a lattice tile. 120 //! \return Distribcell offset i.e. the largest instance number for the target 121 //! cell found in the geometry tree under this lattice tile. 122 virtual int32_t& offset(int map, array<int, 3> const& i_xyz) = 0; 123 124 //! \brief Get the distribcell offset for a lattice tile. 125 //! \param The map index for the target cell. 126 //! \param indx The index for a lattice tile. 127 //! \return Distribcell offset i.e. the largest instance number for the target 128 //! cell found in the geometry tree for this lattice index. 129 virtual int32_t offset(int map, int indx) const = 0; 130 131 //! \brief Convert an array index to a useful human-readable string. 132 //! \param indx The index for a lattice tile. 133 //! \return A string representing the lattice tile. 134 virtual std::string index_to_string(int indx) const = 0; 135 136 //! \brief Write lattice information to an HDF5 group. 137 //! \param group_id An HDF5 group id. 138 void to_hdf5(hid_t group_id) const; 139 140 protected: 141 bool is_3d_; //!< Has divisions along the z-axis? 142 143 virtual void to_hdf5_inner(hid_t group_id) const = 0; 144 }; 145 146 //============================================================================== 147 //! An iterator over lattice universes. 148 //============================================================================== 149 150 class LatticeIter 151 { 152 public: 153 int indx_; //!< An index to a Lattice universes or offsets array. 154 LatticeIter(Lattice & lat,int indx)155 LatticeIter(Lattice &lat, int indx) 156 : indx_(indx), lat_(lat) 157 {} 158 159 bool operator==(const LatticeIter &rhs) {return (indx_ == rhs.indx_);} 160 161 bool operator!=(const LatticeIter &rhs) {return !(*this == rhs);} 162 163 int32_t& operator*() {return lat_.universes_[indx_];} 164 165 LatticeIter& operator++() 166 { 167 while (indx_ < lat_.universes_.size()) { 168 ++indx_; 169 if (lat_.is_valid_index(indx_)) return *this; 170 } 171 indx_ = lat_.universes_.size(); 172 return *this; 173 } 174 175 protected: 176 Lattice& lat_; 177 }; 178 179 //============================================================================== 180 //! A reverse iterator over lattice universes. 181 //============================================================================== 182 183 class ReverseLatticeIter : public LatticeIter 184 { 185 public: ReverseLatticeIter(Lattice & lat,int indx)186 ReverseLatticeIter(Lattice &lat, int indx) 187 : LatticeIter {lat, indx} 188 {} 189 190 ReverseLatticeIter& operator++() 191 { 192 while (indx_ > -1) { 193 --indx_; 194 if (lat_.is_valid_index(indx_)) return *this; 195 } 196 indx_ = -1; 197 return *this; 198 } 199 }; 200 201 //============================================================================== 202 203 class RectLattice : public Lattice 204 { 205 public: 206 explicit RectLattice(pugi::xml_node lat_node); 207 208 int32_t const& operator[](array<int, 3> const& i_xyz); 209 210 bool are_valid_indices(array<int, 3> const& i_xyz) const; 211 212 std::pair<double, array<int, 3>> distance( 213 Position r, Direction u, const array<int, 3>& i_xyz) const; 214 215 void get_indices(Position r, Direction u, array<int, 3>& result) const; 216 217 Position get_local_position(Position r, const array<int, 3>& i_xyz) const; 218 219 int32_t& offset(int map, array<int, 3> const& i_xyz); 220 221 int32_t offset(int map, int indx) const; 222 223 std::string index_to_string(int indx) const; 224 225 void to_hdf5_inner(hid_t group_id) const; 226 227 private: 228 array<int, 3> n_cells_; //!< Number of cells along each axis 229 Position lower_left_; //!< Global lower-left corner of the lattice 230 Position pitch_; //!< Lattice tile width along each axis 231 }; 232 233 //============================================================================== 234 235 class HexLattice : public Lattice 236 { 237 public: 238 explicit HexLattice(pugi::xml_node lat_node); 239 240 int32_t const& operator[](array<int, 3> const& i_xyz); 241 242 LatticeIter begin(); 243 244 ReverseLatticeIter rbegin(); 245 246 bool are_valid_indices(array<int, 3> const& i_xyz) const; 247 248 std::pair<double, array<int, 3>> distance( 249 Position r, Direction u, const array<int, 3>& i_xyz) const; 250 251 void get_indices(Position r, Direction u, array<int, 3>& result) const; 252 253 Position get_local_position(Position r, const array<int, 3>& i_xyz) const; 254 255 bool is_valid_index(int indx) const; 256 257 int32_t& offset(int map, array<int, 3> const& i_xyz); 258 259 int32_t offset(int map, int indx) const; 260 261 std::string index_to_string(int indx) const; 262 263 void to_hdf5_inner(hid_t group_id) const; 264 265 private: 266 enum class Orientation { 267 y, //!< Flat side of lattice parallel to y-axis 268 x //!< Flat side of lattice parallel to x-axis 269 }; 270 271 //! Fill universes_ vector for 'y' orientation 272 void fill_lattice_y(const vector<std::string>& univ_words); 273 274 //! Fill universes_ vector for 'x' orientation 275 void fill_lattice_x(const vector<std::string>& univ_words); 276 277 int n_rings_; //!< Number of radial tile positions 278 int n_axial_; //!< Number of axial tile positions 279 Orientation orientation_; //!< Orientation of lattice 280 Position center_; //!< Global center of lattice 281 array<double, 2> pitch_; //!< Lattice tile width and height 282 }; 283 284 //============================================================================== 285 // Non-member functions 286 //============================================================================== 287 288 void read_lattices(pugi::xml_node node); 289 290 } // namespace openmc 291 #endif // OPENMC_LATTICE_H 292