#ifndef OPENMC_DISTRIBUTION_SPATIAL_H #define OPENMC_DISTRIBUTION_SPATIAL_H #include "pugixml.hpp" #include "openmc/distribution.h" #include "openmc/mesh.h" #include "openmc/position.h" namespace openmc { //============================================================================== //! Probability density function for points in Euclidean space //============================================================================== class SpatialDistribution { public: virtual ~SpatialDistribution() = default; //! Sample a position from the distribution virtual Position sample(uint64_t* seed) const = 0; static unique_ptr create(pugi::xml_node node); }; //============================================================================== //! Distribution of points specified by independent distributions in x,y,z //============================================================================== class CartesianIndependent : public SpatialDistribution { public: explicit CartesianIndependent(pugi::xml_node node); //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position Position sample(uint64_t* seed) const override; // Observer pointers Distribution* x() const { return x_.get(); } Distribution* y() const { return y_.get(); } Distribution* z() const { return z_.get(); } private: UPtrDist x_; //!< Distribution of x coordinates UPtrDist y_; //!< Distribution of y coordinates UPtrDist z_; //!< Distribution of z coordinates }; //============================================================================== //! Distribution of points specified by cylindrical coordinates r,phi,z //============================================================================== class CylindricalIndependent : public SpatialDistribution { public: explicit CylindricalIndependent(pugi::xml_node node); //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position Position sample(uint64_t* seed) const override; Distribution* r() const { return r_.get(); } Distribution* phi() const { return phi_.get(); } Distribution* z() const { return z_.get(); } Position origin() const { return origin_; } private: UPtrDist r_; //!< Distribution of r coordinates UPtrDist phi_; //!< Distribution of phi coordinates UPtrDist z_; //!< Distribution of z coordinates Position origin_; //!< Cartesian coordinates of the cylinder center }; //============================================================================== //! Distribution of points specified by spherical coordinates r,cos_theta,phi //============================================================================== class SphericalIndependent : public SpatialDistribution { public: explicit SphericalIndependent(pugi::xml_node node); //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position Position sample(uint64_t* seed) const override; Distribution* r() const { return r_.get(); } Distribution* cos_theta() const { return cos_theta_.get(); } Distribution* phi() const { return phi_.get(); } Position origin() const { return origin_; } private: UPtrDist r_; //!< Distribution of r coordinates UPtrDist cos_theta_; //!< Distribution of cos_theta coordinates UPtrDist phi_; //!< Distribution of phi coordinates Position origin_; //!< Cartesian coordinates of the sphere center }; //============================================================================== //! Distribution of points within a mesh //============================================================================== class MeshSpatial : public SpatialDistribution { public: explicit MeshSpatial(pugi::xml_node node); explicit MeshSpatial(int32_t mesh_id, gsl::span strengths); //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position Position sample(uint64_t* seed) const override; //! Sample the mesh for an element and position within that element //! \param seed Pseudorandom number seed pointer //! \return Sampled element index and position within that element std::pair sample_mesh(uint64_t* seed) const; //! For unstructured meshes, ensure that elements are all linear tetrahedra void check_element_types() const; // Accessors const Mesh* mesh() const { return model::meshes.at(mesh_idx_).get(); } int32_t n_sources() const { return this->mesh()->n_bins(); } double total_strength() { return this->elem_idx_dist_.integral(); } private: int32_t mesh_idx_ {C_NONE}; DiscreteIndex elem_idx_dist_; //!< Distribution of //!< mesh element indices }; //============================================================================== //! Uniform distribution of points over a box //============================================================================== class SpatialBox : public SpatialDistribution { public: explicit SpatialBox(pugi::xml_node node, bool fission = false); //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position Position sample(uint64_t* seed) const override; // Properties bool only_fissionable() const { return only_fissionable_; } Position lower_left() const { return lower_left_; } Position upper_right() const { return upper_right_; } private: Position lower_left_; //!< Lower-left coordinates of box Position upper_right_; //!< Upper-right coordinates of box bool only_fissionable_ {false}; //!< Only accept sites in fissionable region? }; //============================================================================== //! Distribution at a single point //============================================================================== class SpatialPoint : public SpatialDistribution { public: SpatialPoint() : r_ {} {}; SpatialPoint(Position r) : r_ {r} {}; explicit SpatialPoint(pugi::xml_node node); //! Sample a position from the distribution //! \param seed Pseudorandom number seed pointer //! \return Sampled position Position sample(uint64_t* seed) const override; Position r() const { return r_; } private: Position r_; //!< Single position at which sites are generated }; using UPtrSpace = unique_ptr; } // namespace openmc #endif // OPENMC_DISTRIBUTION_SPATIAL_H