Cleanup from self-review.

This commit is contained in:
Patrick Shriwise 2019-10-08 13:53:22 -05:00
parent f251822b9f
commit 919c19c909
4 changed files with 35 additions and 31 deletions

View file

@ -31,8 +31,8 @@ public:
std::array<double, 2> volume; //!< Mean/standard deviation of volume
std::vector<int> nuclides; //!< Index of nuclides
std::vector<double> atoms; //!< Number of atoms for each nuclide
std::vector<double> uncertainty; //!< Uncertainty on number of atoms
int iterations;
std::vector<double> uncertainty; //!< Uncertainty on number of atoms
int iterations; //!< Number of iterations needed to obtain the results
}; // Results for a single domain
// Constructors

View file

@ -32,7 +32,6 @@ class VolumeCalculation(object):
Upper-right coordinates of bounding box used to sample points. If this
argument is not supplied, an attempt is made to automatically determine
a bounding box.
Attributes
----------
@ -59,10 +58,10 @@ class VolumeCalculation(object):
Dictionary mapping unique IDs of domains to estimated volumes in cm^3.
threshold : float
Threshold for the maxmimum standard deviation of volumes.
iterations : int
Number of iterations over samples (for calculations with a trigger).
trigger_type : {'variance', 'std_dev', 'rel_err'}
Value type used to halt volume calculation
iterations : int
Number of iterations over samples (for calculations with a trigger).
"""
def __init__(self, domains, samples, lower_left=None, upper_right=None):
@ -83,7 +82,7 @@ class VolumeCalculation(object):
self.ids = [d.id for d in domains]
self.samples = samples
if lower_left is not None:
if upper_right is None:
raise ValueError('Both lower-left and upper-right coordinates '
@ -193,7 +192,7 @@ class VolumeCalculation(object):
cv.check_length(name, upper_right, 3)
self._upper_right = upper_right
@threshold.setter
@threshold.setter
def threshold(self, threshold):
name = 'volume std. dev. threshold'
cv.check_type(name, threshold, Real)
@ -203,7 +202,7 @@ class VolumeCalculation(object):
@trigger_type.setter
def trigger_type(self, trigger_type):
cv.check_value('tally trigger type', trigger_type,
['variance', 'std_dev', 'rel_err'])
('variance', 'std_dev', 'rel_err'))
self._trigger_type = trigger_type
@iterations.setter
@ -293,7 +292,7 @@ class VolumeCalculation(object):
# Instantiate the class and assign results
vol = cls(domains, samples, lower_left, upper_right)
if trigger_type is not None:
vol.set_trigger(threshold, trigger_type.decode())

View file

@ -64,13 +64,13 @@ VolumeCalculation::VolumeCalculation(pugi::xml_node node)
if (size_t_stream.fail()) {
std::stringstream msg;
msg << "Could not read number of samples ("
<< size_t_stream.str() << ")\n";
<< size_t_stream.str() << ")";
fatal_error(msg);
}
if (check_for_node(node, "threshold")) {
pugi::xml_node threshold_node = node.child("threshold");
threshold_ = std::stod(get_node_value(threshold_node, "threshold"));
if (threshold_ <= 0.0) {
std::stringstream msg;
@ -124,6 +124,7 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
}
while (true) {
#pragma omp parallel
{
// Variables that are private to each thread
@ -223,7 +224,8 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
iterations++;
size_t total_samples = iterations * n_samples_;
double max_vol_err = -INFTY;
// reset
double trigger_val = -INFTY;
// Set size for members of the Result struct
std::vector<Result> results(n);
@ -237,7 +239,7 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
auto n_nuc = data::nuclides.size();
xt::xtensor<double, 2> atoms({n_nuc, 2}, 0.0);
#ifdef OPENMC_MPI
#ifdef OPENMC_MPI
if (mpi::master) {
for (int j = 1; j < mpi::n_procs; j++) {
int q;
@ -264,7 +266,7 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
MPI_Send(&q, 1, MPI_INTEGER, 0, 0, mpi::intracomm);
MPI_Send(&buffer[0], 2*q, MPI_INTEGER, 0, 1, mpi::intracomm);
}
#endif
#endif
if (mpi::master) {
int total_hits = 0;
@ -299,14 +301,14 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
val = result.volume[1];
break;
case VolumeTriggerMetric::REL_ERR:
val = result.volume[1] / result.volume[0];
val = result.volume[0] == 0.0 ? 0.0 : result.volume[1] / result.volume[0];
break;
case VolumeTriggerMetric::VARIANCE:
val = result.volume[1] * result.volume[1];
break;
}
// update max if entry is valid
if (val > 0.0) { max_vol_err = std::max(max_vol_err, val); }
if (val > 0.0) { trigger_val = std::max(trigger_val, val); }
}
for (int j = 0; j < n_nuc; ++j) {
@ -323,29 +325,30 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
}
}
}
}
} // end domain loop
// if no trigger is applied, we're done
if (trigger_type_ == VolumeTriggerMetric::NONE) { return results; }
#ifdef OPENMC_MPI
// update maximum error value on all processes
if (mpi::master) {
for (int i = 1; i < mpi::n_procs; i++) {
MPI_Send(&max_vol_err, 1, MPI_DOUBLE, i, 0, mpi::intracomm);
MPI_Send(&trigger_val, 1, MPI_DOUBLE, i, 0, mpi::intracomm);
}
} else {
MPI_Recv(&max_vol_err, 1, MPI_DOUBLE, 0, 0, mpi::intracomm, MPI_STATUS_IGNORE);
}
MPI_Recv(&trigger_val, 1, MPI_DOUBLE, 0, 0, mpi::intracomm, MPI_STATUS_IGNORE);
}
#endif
// return results of the calculation
if (trigger_type_ == VolumeTriggerMetric::NONE || max_vol_err < threshold_) {
return results;
}
if (trigger_val < threshold_) { return results; }
#ifdef OPENMC_MPI
// if iterating in MPI, need to zero indices and hits to they aren't counted twice
// if iterating in an MPI run, need to zero indices and hits so they aren't counted twice
if (!mpi::master) {
for (auto& v : master_indices) { std::fill(v.begin(), v.end(), 0.0); }
for (auto& v : master_hits) { std::fill(v.begin(), v.end(), 0.0); }
for (auto& v : master_indices) { std::fill(v.begin(), v.end(), 0); }
for (auto& v : master_hits) { std::fill(v.begin(), v.end(), 0); }
}
#endif
@ -373,7 +376,7 @@ void VolumeCalculation::to_hdf5(const std::string& filename,
write_attribute(file_id, "samples", n_samples_);
write_attribute(file_id, "lower_left", lower_left_);
write_attribute(file_id, "upper_right", upper_right_);
// Write trigger info
// Write trigger info
if (trigger_type_ != VolumeTriggerMetric::NONE) {
write_attribute(file_id, "iterations", results[0].iterations);
write_attribute(file_id, "threshold", threshold_);
@ -390,6 +393,8 @@ void VolumeCalculation::to_hdf5(const std::string& filename,
break;
}
write_attribute(file_id, "trigger_type", trigger_str);
} else {
write_attribute(file_id, "iterations", 1);
}
if (domain_type_ == FILTER_CELL) {

View file

@ -64,7 +64,7 @@ class VolumeTest(PyAPITestHarness):
openmc.VolumeCalculation(list(root.cells.values()), 100)
]
vol_calcs[3].set_trigger(self.exp_std_dev, 'std_dev')
vol_calcs[4].set_trigger(self.exp_rel_err, 'rel_err')
@ -102,7 +102,7 @@ class VolumeTest(PyAPITestHarness):
assert(volume_calc.threshold == self.exp_variance)
assert(volume_calc.iterations == self.variance_iters)
for vol in volume_calc.volumes.values():
assert(vol.std_dev * vol.std_dev <= self.exp_variance)
assert(vol.std_dev * vol.std_dev <= self.exp_variance)
else:
assert(volume_calc.trigger_type == None)
assert(volume_calc.threshold == None)
@ -120,4 +120,4 @@ class VolumeTest(PyAPITestHarness):
def test_volume_calc():
harness = VolumeTest('')
harness.main()
harness.main()