Skip to content

Commit

Permalink
Account for integral of underlying distributions when sampling Mixture (
Browse files Browse the repository at this point in the history
  • Loading branch information
paulromano authored Aug 31, 2023
1 parent eea5223 commit c93feed
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 13 deletions.
17 changes: 15 additions & 2 deletions include/openmc/distribution.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ class Distribution {
public:
virtual ~Distribution() = default;
virtual double sample(uint64_t* seed) const = 0;

//! Return integral of distribution
//! \return Integral of distribution
virtual double integral() const { return 1.0; };
};

using UPtrDist = unique_ptr<Distribution>;
Expand Down Expand Up @@ -51,11 +55,13 @@ class DiscreteIndex {
// Properties
const vector<double>& prob() const { return prob_; }
const vector<size_t>& alias() const { return alias_; }
double integral() const { return integral_; }

private:
vector<double> prob_; //!< Probability of accepting the uniformly sampled bin,
//!< mapped to alias method table
vector<size_t> alias_; //!< Alias table
double integral_; //!< Integral of distribution

//! Normalize distribution so that probabilities sum to unity
void normalize();
Expand All @@ -78,6 +84,8 @@ class Discrete : public Distribution {
//! \return Sampled value
double sample(uint64_t* seed) const override;

double integral() const override { return di_.integral(); };

// Properties
const vector<double>& x() const { return x_; }
const vector<double>& prob() const { return di_.prob(); }
Expand Down Expand Up @@ -219,17 +227,19 @@ class Tabular : public Distribution {
//! \return Sampled value
double sample(uint64_t* seed) const override;

// x property
// properties
vector<double>& x() { return x_; }
const vector<double>& x() const { return x_; }
const vector<double>& p() const { return p_; }
Interpolation interp() const { return interp_; }
double integral() const override { return integral_; };

private:
vector<double> x_; //!< tabulated independent variable
vector<double> p_; //!< tabulated probability density
vector<double> c_; //!< cumulative distribution at tabulated values
Interpolation interp_; //!< interpolation rule
double integral_; //!< Integral of distribution

//! Initialize tabulated probability density function
//! \param x Array of values for independent variable
Expand Down Expand Up @@ -272,12 +282,15 @@ class Mixture : public Distribution {
//! \return Sampled value
double sample(uint64_t* seed) const override;

double integral() const override { return integral_; }

private:
// Storrage for probability + distribution
using DistPair = std::pair<double, UPtrDist>;

vector<DistPair>
distribution_; //!< sub-distributions + cummulative probabilities
distribution_; //!< sub-distributions + cummulative probabilities
double integral_; //!< integral of distribution
};

} // namespace openmc
Expand Down
29 changes: 18 additions & 11 deletions src/distribution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,12 @@ size_t DiscreteIndex::sample(uint64_t* seed) const

void DiscreteIndex::normalize()
{
// Renormalize density function so that it sums to unity
double norm = std::accumulate(prob_.begin(), prob_.end(), 0.0);
// Renormalize density function so that it sums to unity. Note that we save
// the integral of the distribution so that if it is used as part of another
// distribution (e.g., Mixture), we know its relative strength.
integral_ = std::accumulate(prob_.begin(), prob_.end(), 0.0);
for (auto& p_i : prob_) {
p_i /= norm;
p_i /= integral_;
}
}

Expand Down Expand Up @@ -300,10 +302,13 @@ void Tabular::init(
}
}

// Normalize density and distribution functions
// Normalize density and distribution functions. Note that we save the
// integral of the distribution so that if it is used as part of another
// distribution (e.g., Mixture), we know its relative strength.
integral_ = c_[n - 1];
for (int i = 0; i < n; ++i) {
p_[i] = p_[i] / c_[n - 1];
c_[i] = c_[i] / c_[n - 1];
p_[i] = p_[i] / integral_;
c_[i] = c_[i] / integral_;
}
}

Expand Down Expand Up @@ -379,12 +384,14 @@ Mixture::Mixture(pugi::xml_node node)
if (!pair.child("dist"))
fatal_error("Mixture pair element does not have a distribution.");

// cummulative sum of probybilities
cumsum += std::stod(pair.attribute("probability").value());
// cummulative sum of probabilities
double p = std::stod(pair.attribute("probability").value());

// Save cummulative probybility and distrubution
distribution_.push_back(
std::make_pair(cumsum, distribution_from_xml(pair.child("dist"))));
// Save cummulative probability and distribution
auto dist = distribution_from_xml(pair.child("dist"));
cumsum += p * dist->integral();

distribution_.push_back(std::make_pair(cumsum, std::move(dist)));
}

// Normalize cummulative probabilities to 1
Expand Down

0 comments on commit c93feed

Please sign in to comment.