#ifndef OPENMC_TALLIES_TALLY_H #define OPENMC_TALLIES_TALLY_H #include "openmc/constants.h" #include "openmc/memory.h" // for unique_ptr #include "openmc/span.h" #include "openmc/tallies/filter.h" #include "openmc/tallies/trigger.h" #include "openmc/vector.h" #include "openmc/tensor.h" #include "pugixml.hpp" #include #include namespace openmc { //============================================================================== //! A user-specified flux-weighted (or current) measurement. //============================================================================== class Tally { public: //---------------------------------------------------------------------------- // Constructors, destructors, factory functions explicit Tally(int32_t id); explicit Tally(pugi::xml_node node); ~Tally(); static Tally* create(int32_t id = -1); //---------------------------------------------------------------------------- // Accessors void set_id(int32_t id); int id() const { return id_; } void set_active(bool active) { active_ = active; } void set_multiply_density(bool value) { multiply_density_ = value; } void set_writable(bool writable) { writable_ = writable; } void set_scores(pugi::xml_node node); void set_scores(const vector& scores); std::vector scores() const; int32_t n_scores() const { return scores_.size(); } void set_nuclides(pugi::xml_node node); void set_nuclides(const vector& nuclides); const tensor::Tensor& results() const { return results_; } //! returns vector of indices corresponding to the tally this is called on const vector& filters() const { return filters_; } //! returns a vector of filter types for the tally std::vector filter_types() const; //! returns a mapping of filter types to index into the tally's filters std::unordered_map filter_indices() const; //! \brief Returns the tally filter at index i int32_t filters(int i) const { return filters_[i]; } //! \brief Return a const pointer to a filter instance based on type. Always //! returns the first matching filter type template const T* get_filter() const { const T* out; for (auto filter_idx : filters_) { if ((out = dynamic_cast(model::tally_filters[filter_idx].get()))) return out; } return nullptr; } template const T* get_filter(int idx) const { if (const T* out = dynamic_cast(model::tally_filters[filters_.at(idx)])) return out; return nullptr; } //! \brief Check if this tally has a specified type of filter bool has_filter(FilterType filter_type) const; void set_filters(span filters); //! Given already-set filters, set the stride lengths void set_strides(); int64_t strides(int i) const { return strides_[i]; } int64_t n_filter_bins() const { return n_filter_bins_; } bool multiply_density() const { return multiply_density_; } bool writable() const { return writable_; } bool higher_moments() const { return higher_moments_; } //---------------------------------------------------------------------------- // Other methods. void add_filter(Filter* filter); void init_triggers(pugi::xml_node node); void init_results(); void reset(); void accumulate(); //! return the index of a score specified by name int score_index(const std::string& score) const; //! Tally results reshaped according to filter sizes tensor::Tensor get_reshaped_data() const; //! A string representing the i-th score on this tally std::string score_name(int score_idx) const; //! A string representing the i-th nuclide on this tally std::string nuclide_name(int nuclide_idx) const; //---------------------------------------------------------------------------- // Major public data members. int id_ {C_NONE}; //!< User-defined identifier std::string name_; //!< User-defined name TallyType type_ {TallyType::VOLUME}; //!< e.g. volume, surface current //! Event type that contributes to this tally TallyEstimator estimator_ {TallyEstimator::TRACKLENGTH}; //! Whether this tally is currently being updated bool active_ {false}; //! Number of realizations int n_realizations_ {0}; vector scores_; //!< Filter integrands (e.g. flux, fission) //! Index of each nuclide to be tallied. -1 indicates total material. vector nuclides_ {-1}; //! Results for each bin -- the first dimension of the array is for the //! combination of filters (e.g. specific cell, specific energy group, etc.) //! and the second dimension of the array is for scores (e.g. flux, total //! reaction rate, fission reaction rate, etc.) tensor::Tensor results_; //! True if this tally should be written to statepoint files bool writable_ {true}; //---------------------------------------------------------------------------- // Miscellaneous public members. // We need to have quick access to some filters. The following gives indices // for various filters that could be in the tally or C_NONE if they are not // present. int energyout_filter_ {C_NONE}; int delayedgroup_filter_ {C_NONE}; vector triggers_; int deriv_ {C_NONE}; //!< Index of a TallyDerivative object for diff tallies. private: //---------------------------------------------------------------------------- // Private data. vector filters_; //!< Filter indices in global filters array //! Index strides assigned to each filter to support 1D indexing. vector strides_; int64_t n_filter_bins_ {0}; //! Whether to multiply by atom density for reaction rates bool multiply_density_ {true}; //! Whether to accumulate higher moments (third and fourth) bool higher_moments_ {false}; int64_t index_; }; //============================================================================== // Global variable declarations //============================================================================== namespace model { extern std::unordered_map tally_map; extern vector> tallies; extern vector active_tallies; extern vector active_analog_tallies; extern vector active_tracklength_tallies; extern vector active_timed_tracklength_tallies; extern vector active_collision_tallies; extern vector active_meshsurf_tallies; extern vector active_surface_tallies; extern vector active_pulse_height_tallies; extern vector pulse_height_cells; extern vector time_grid; } // namespace model namespace simulation { //! Global tallies (such as k-effective estimators) extern tensor::StaticTensor2D global_tallies; //! Number of realizations for global tallies extern "C" int32_t n_realizations; } // namespace simulation extern double global_tally_absorption; extern double global_tally_collision; extern double global_tally_tracklength; extern double global_tally_leakage; //============================================================================== // Non-member functions //============================================================================== //! Read tally specification from tallies.xml void read_tallies_xml(); //! Read tally specification from an XML node //! \param[in] root node of tallies XML element void read_tallies_xml(pugi::xml_node root); //! \brief Accumulate the sum of the contributions from each history within the //! batch to a new random variable void accumulate_tallies(); //! Determine distance to next time boundary // //! \param time Current time of particle //! \param speed Speed of particle //! \return Distance to next time boundary (or INFTY if none) double distance_to_time_boundary(double time, double speed); //! Determine which tallies should be active void setup_active_tallies(); #ifdef OPENMC_MPI //! Collect all tally results onto master process void reduce_tally_results(); #endif void free_memory_tally(); } // namespace openmc #endif // OPENMC_TALLIES_TALLY_H