Move write_tallies to C++

This commit is contained in:
Sterling Harper 2019-02-11 13:58:12 -05:00
parent ddaed7311b
commit 8bb0fa7791
6 changed files with 366 additions and 373 deletions

View file

@ -2,6 +2,7 @@
#define OPENMC_TALLIES_TALLY_H
#include "openmc/constants.h"
#include "openmc/tallies/filter.h"
#include "openmc/tallies/trigger.h"
#include "pugixml.hpp"
@ -21,6 +22,8 @@ class Tally {
public:
Tally() {}
void init_from_xml(pugi::xml_node node);
void set_scores(pugi::xml_node node);
void set_scores(std::vector<std::string> scores);
@ -50,6 +53,8 @@ public:
int id_; //!< user-defined identifier
std::string name_; //!< user-defined name
int type_ {TALLY_VOLUME}; //!< volume, surface current
//! Event type that contributes to this tally
@ -93,6 +98,41 @@ private:
int32_t n_filter_bins_ {0};
};
//==============================================================================
//! An iterator over all combinations of a tally's matching filter bins.
//
//! This iterator handles two distinct tasks. First, it maps the N-dimensional
//! space created by the indices of N filters onto a 1D sequence. In other
//! words, it provides a single number that uniquely identifies a combination of
//! bins for many filters. Second, it handles the task of finding each all
//! valid combinations of filter bins given that each filter can have 1 or 2 or
//! many bins that are valid for the current tally event.
//==============================================================================
class FilterBinIter
{
public:
FilterBinIter(const Tally& tally, Particle* p);
FilterBinIter(const Tally& tally, bool end);
bool operator==(const FilterBinIter& other) const
{return index_ == other.index_;}
bool operator!=(const FilterBinIter& other) const
{return !(*this == other);}
FilterBinIter& operator++();
int index_ {1};
double weight_ {1.};
private:
void compute_index_weight();
const Tally& tally_;
};
//==============================================================================
// Global variable declarations
//==============================================================================

View file

@ -473,6 +473,12 @@ contains
type(TallyDerivative), pointer :: deriv
interface
subroutine tally_init_from_xml(tally_ptr, xml_node) bind(C)
import C_PTR
type(C_PTR), value :: tally_ptr
type(C_PTR) :: xml_node
end subroutine
subroutine tally_set_scores(tally_ptr, xml_node) bind(C)
import C_PTR
type(C_PTR), value :: tally_ptr
@ -630,6 +636,8 @@ contains
! Get pointer to tally xml node
node_tal = node_tal_list(i)
call tally_init_from_xml(t % ptr, node_tal % ptr)
! Copy and set tally id
if (check_for_node(node_tal, "id")) then
call get_node_value(node_tal, "id", tally_id)

View file

@ -39,6 +39,9 @@ module output
import Particle
type(Particle), intent(in) :: p
end subroutine
subroutine write_tallies() bind(C)
end subroutine
end interface
contains
@ -441,238 +444,6 @@ contains
end subroutine print_results
!===============================================================================
! WRITE_TALLIES creates an output file and writes out the mean values of all
! tallies and their standard deviations
!===============================================================================
subroutine write_tallies() bind(C)
integer :: i ! index in tallies array
integer :: j ! level in tally hierarchy
integer :: k ! loop index for scoring bins
integer :: n ! loop index for nuclides
integer :: h ! loop index for tally filters
integer :: indent ! number of spaces to preceed output
integer :: filter_index ! index in results array for filters
integer :: score_index ! scoring bin index
integer :: i_nuclide ! index in nuclides array
integer :: i_filt
integer :: unit_tally ! tallies.out file unit
integer :: nr ! number of realizations
real(8) :: t_value ! t-values for confidence intervals
real(8) :: alpha ! significance level for CI
real(8) :: x(2) ! mean and standard deviation
character(MAX_FILE_LEN) :: filename ! name of output file
character(36) :: score_names(N_SCORE_TYPES) ! names of scoring function
character(36) :: score_name ! names of scoring function
! to be applied at write-time
integer, allocatable :: filter_bins(:)
character(MAX_WORD_LEN) :: temp_name
type(TallyDerivative), pointer :: deriv
! Skip if there are no tallies
if (n_tallies == 0) return
allocate(filter_bins(n_filters))
! Initialize names for scores
score_names(abs(SCORE_FLUX)) = "Flux"
score_names(abs(SCORE_TOTAL)) = "Total Reaction Rate"
score_names(abs(SCORE_SCATTER)) = "Scattering Rate"
score_names(abs(SCORE_NU_SCATTER)) = "Scattering Production Rate"
score_names(abs(SCORE_ABSORPTION)) = "Absorption Rate"
score_names(abs(SCORE_FISSION)) = "Fission Rate"
score_names(abs(SCORE_NU_FISSION)) = "Nu-Fission Rate"
score_names(abs(SCORE_KAPPA_FISSION)) = "Kappa-Fission Rate"
score_names(abs(SCORE_EVENTS)) = "Events"
score_names(abs(SCORE_DECAY_RATE)) = "Decay Rate"
score_names(abs(SCORE_DELAYED_NU_FISSION)) = "Delayed-Nu-Fission Rate"
score_names(abs(SCORE_PROMPT_NU_FISSION)) = "Prompt-Nu-Fission Rate"
score_names(abs(SCORE_INVERSE_VELOCITY)) = "Flux-Weighted Inverse Velocity"
score_names(abs(SCORE_FISS_Q_PROMPT)) = "Prompt fission power"
score_names(abs(SCORE_FISS_Q_RECOV)) = "Recoverable fission power"
score_names(abs(SCORE_CURRENT)) = "Current"
! Create filename for tally output
filename = trim(path_output) // "tallies.out"
! Open tally file for writing
open(FILE=filename, NEWUNIT=unit_tally, STATUS='replace', ACTION='write')
! Calculate t-value for confidence intervals
if (confidence_intervals) then
alpha = ONE - CONFIDENCE_LEVEL
t_value = t_percentile(ONE - alpha/TWO, n_realizations - 1)
else
t_value = ONE
end if
TALLY_LOOP: do i = 1, n_tallies
associate (t => tallies(i) % obj)
nr = t % n_realizations
if (confidence_intervals) then
! Calculate t-value for confidence intervals
alpha = ONE - CONFIDENCE_LEVEL
t_value = t_percentile(ONE - alpha/TWO, nr - 1)
else
t_value = ONE
end if
! Write header block
if (t % name == "") then
call header("TALLY " // trim(to_str(t % id())), 1, unit=unit_tally)
else
call header("TALLY " // trim(to_str(t % id())) // ": " &
// trim(t % name), 1, unit=unit_tally)
endif
! Write derivative information.
if (t % deriv() /= C_NONE) then
!associate(deriv => tally_derivs(t % deriv()))
deriv => tally_deriv_c(t % deriv())
select case (deriv % variable)
case (DIFF_DENSITY)
write(unit=unit_tally, fmt="(' Density derivative Material ',A)") &
to_str(deriv % diff_material)
case (DIFF_NUCLIDE_DENSITY)
write(unit=unit_tally, fmt="(' Nuclide density derivative &
&Material ',A,' Nuclide ',A)") &
trim(to_str(deriv % diff_material)), &
trim(nuclides(deriv % diff_nuclide) % name)
case (DIFF_TEMPERATURE)
write(unit=unit_tally, fmt="(' Temperature derivative Material ',&
&A)") to_str(deriv % diff_material)
case default
call fatal_error("Differential tally dependent variable for tally "&
// trim(to_str(t % id())) // " not defined in output.F90.")
end select
!end associate
end if
! WARNING: Admittedly, the logic for moving for printing results is
! extremely confusing and took quite a bit of time to get correct. The
! logic is structured this way since it is not practical to have a do
! loop for each filter variable (given that only a few filters are likely
! to be used for a given tally.
! Initialize bins, filter level, and indentation
do h = 1, t % n_filters()
filter_bins(t % filter(h) + 1) = 0
end do
j = 1
indent = 0
print_bin: do
find_bin: do
! Check for no filters
if (t % n_filters() == 0) exit find_bin
! Increment bin combination
filter_bins(t % filter(j) + 1) = filter_bins(t % filter(j) + 1) + 1
! =================================================================
! REACHED END OF BINS FOR THIS FILTER, MOVE TO NEXT FILTER
if (filter_bins(t % filter(j) + 1) > &
filters(t % filter(j) + 1) % obj % n_bins) then
! If this is the first filter, then exit
if (j == 1) exit print_bin
filter_bins(t % filter(j) + 1) = 0
j = j - 1
indent = indent - 2
! =================================================================
! VALID BIN -- WRITE FILTER INFORMATION OR EXIT TO WRITE RESULTS
else
! Check if this is last filter
if (j == t % n_filters()) exit find_bin
! Print current filter information
i_filt = t % filter(j) + 1
write(UNIT=unit_tally, FMT='(1X,2A)') repeat(" ", indent), &
trim(filters(i_filt) % obj % &
text_label(filter_bins(i_filt)))
indent = indent + 2
j = j + 1
end if
end do find_bin
! Print filter information
if (t % n_filters() > 0) then
i_filt = t % filter(j) + 1
write(UNIT=unit_tally, FMT='(1X,2A)') repeat(" ", indent), &
trim(filters(i_filt) % obj % &
text_label(filter_bins(i_filt)))
end if
! Determine scoring index for this bin combination -- note that unlike
! in the score_tally subroutine, we have to use max(bins,1) since all
! bins below the lowest filter level will be zeros
filter_index = 1
do h = 1, t % n_filters()
filter_index = filter_index &
+ (max(filter_bins(t % filter(h)+1) ,1) - 1) * t % stride(h)
end do
! Write results for this filter bin combination
score_index = 0
if (t % n_filters() > 0) indent = indent + 2
do n = 1, t % n_nuclide_bins()
! Write label for nuclide
i_nuclide = t % nuclide_bins(n)
if (i_nuclide == -1) then
write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), &
"Total Material"
else
if (run_CE) then
write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), &
trim(nuclides(i_nuclide+1) % name)
else
call get_name_c(i_nuclide+1, len(temp_name), temp_name)
write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), &
trim(temp_name)
end if
end if
indent = indent + 2
do k = 1, t % n_score_bins()
score_index = score_index + 1
associate(r => t % results(RESULT_SUM:RESULT_SUM_SQ, :, :))
if (t % score_bins(k) > 0) then
score_name = reaction_name(t % score_bins(k))
else
score_name = score_names(abs(t % score_bins(k)))
end if
x(:) = mean_stdev(r(:, score_index, filter_index), nr)
write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') &
repeat(" ", indent), score_name, &
to_str(x(1)), trim(to_str(t_value * x(2)))
end associate
end do
indent = indent - 2
end do
indent = indent - 2
if (t % n_filters() == 0) exit print_bin
end do print_bin
end associate
end do TALLY_LOOP
close(UNIT=unit_tally)
end subroutine write_tallies
!===============================================================================
! MEAN_STDEV computes the sample mean and standard deviation of the mean of a
! single tally score

View file

@ -2,27 +2,37 @@
#include <algorithm> // for std::transform
#include <cstring> // for strlen
#include <iomanip> // for setw
#include <iostream>
#include <sstream>
#include <ctime>
#include <iomanip> // for setw, setprecision
#include <ios> // for left
#include <iostream>
#include <fstream>
#include <sstream>
#include <unordered_map>
#include "openmc/capi.h"
#include "openmc/cell.h"
#include "openmc/constants.h"
#include "openmc/error.h"
#include "openmc/geometry.h"
#include "openmc/lattice.h"
#include "openmc/math_functions.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/plot.h"
#include "openmc/reaction.h"
#include "openmc/settings.h"
#include "openmc/surface.h"
#include "openmc/tallies/derivative.h"
#include "openmc/tallies/tally.h"
namespace openmc {
//==============================================================================
void
header(const char* msg, int level) {
std::string
header(const char* msg) {
// Determine how many times to repeat the '=' character.
int n_prefix = (63 - strlen(msg)) / 2;
int n_suffix = n_prefix;
@ -39,10 +49,18 @@ header(const char* msg, int level) {
out << "> " << upper << " <";
for (int i = 0; i < n_suffix; i++) out << '=';
return out.str();
}
std::string header(const std::string& msg) {return header(msg.c_str());}
void
header(const char* msg, int level) {
auto out = header(msg);
// Print header based on verbosity level.
if (settings::verbosity >= level) {
std::cout << out.str() << "\n\n";
}
if (settings::verbosity >= level)
std::cout << out << "\n\n";
}
//==============================================================================
@ -230,4 +248,152 @@ print_overlap_check()
}
}
//==============================================================================
std::pair<double, double>
mean_stdev(double sum, double sum_sq, int n)
{
double mean, std_dev;
mean = sum / n;
if (n > 1) {
std_dev = std::sqrt((sum_sq / n - mean*mean) / (n - 1));
} else {
std_dev = 0;
}
return {mean, std_dev};
}
const std::unordered_map<int, const char*> score_names = {
{SCORE_FLUX, "Flux"},
{SCORE_TOTAL, "Total Reaction Rate"},
{SCORE_SCATTER, "Scattering Rate"},
{SCORE_NU_SCATTER, "Scattering Production Rate"},
{SCORE_ABSORPTION, "Absorption Rate"},
{SCORE_FISSION, "Fission Rate"},
{SCORE_NU_FISSION, "Nu-Fission Rate"},
{SCORE_KAPPA_FISSION, "Kappa-Fission Rate"},
{SCORE_EVENTS, "Events"},
{SCORE_DECAY_RATE, "Decay Rate"},
{SCORE_DELAYED_NU_FISSION, "Delayed-Nu-Fission Rate"},
{SCORE_PROMPT_NU_FISSION, "Prompt-Nu-Fission Rate"},
{SCORE_INVERSE_VELOCITY, "Flux-Weighted Inverse Velocity"},
{SCORE_FISS_Q_PROMPT, "Prompt fission power"},
{SCORE_FISS_Q_RECOV, "Recoverable fission power"},
{SCORE_CURRENT, "Current"},
};
//! Create an ASCII output file showing all tally results.
extern "C" void
write_tallies()
{
if (model::tallies.empty()) return;
// Open the tallies.out file.
std::ofstream tallies_out;
tallies_out.open("tallies.out", std::ios::out | std::ios::trunc);
tallies_out << std::setprecision(6);
// Loop over each tally.
for (auto i_tally = 0; i_tally < model::tallies.size(); ++i_tally) {
const auto& tally {*model::tallies[i_tally]};
auto results = tally_results(i_tally+1);
// TODO: get this directly from the tally object when it's been translated
int32_t n_realizations;
auto err = openmc_tally_get_n_realizations(i_tally+1, &n_realizations);
// Calculate t-value for confidence intervals
double t_value = 1;
if (settings::confidence_intervals) {
auto alpha = 1 - CONFIDENCE_LEVEL;
t_value = t_percentile_c(1 - alpha*0.5, n_realizations - 1);
}
// Write header block.
std::string tally_header("TALLY " + std::to_string(tally.id_));
if (!tally.name_.empty()) tally_header += ": " + tally.name_;
tallies_out << "\n" << header(tally_header) << "\n\n";
// Write derivative information.
if (tally.deriv_ != C_NONE) {
const auto& deriv {model::tally_derivs[tally.deriv_]};
switch (deriv.variable) {
case DIFF_DENSITY:
tallies_out << " Density derivative Material "
<< std::to_string(deriv.diff_material) << "\n";
break;
case DIFF_NUCLIDE_DENSITY:
tallies_out << " Nuclide density derivative Material "
<< std::to_string(deriv.diff_material) << " Nuclide "
// TODO: off-by-one
<< data::nuclides[deriv.diff_nuclide-1]->name_ << "\n";
break;
case DIFF_TEMPERATURE:
tallies_out << " Temperature derivative Material "
<< std::to_string(deriv.diff_material) << "\n";
break;
default:
fatal_error("Differential tally dependent variable for tally "
+ std::to_string(tally.id_) + " not defined in output.cpp");
}
}
// Loop over all filter bin combinations.
auto filter_iter = FilterBinIter(tally, false);
auto end = FilterBinIter(tally, true);
for (; filter_iter != end; ++filter_iter) {
auto filter_index = filter_iter.index_;
// Print info about this combination of filter bins. The stride check
// prevents redundant output.
int indent = 0;
for (auto i = 0; i < tally.filters().size(); ++i) {
if ((filter_index-1) % tally.strides(i) == 0) {
auto i_filt = tally.filters(i);
const auto& filt {*model::tally_filters[i_filt]};
auto& match {simulation::filter_matches[i_filt]};
tallies_out << std::string(indent+1, ' ')
<< filt.text_label(match.i_bin_) << "\n";
}
indent += 2;
}
// Loop over all nuclide and score combinations.
int score_index = 0;
for (auto i_nuclide : tally.nuclides_) {
// Write label for this nuclide bin.
if (i_nuclide == -1) {
tallies_out << std::string(indent+1, ' ') << "Total Material\n";
} else {
if (settings::run_CE) {
tallies_out << std::string(indent+1, ' ')
<< data::nuclides[i_nuclide]->name_ << "\n";
} else {
tallies_out << std::string(indent+1, ' ')
<< data::nuclides_MG[i_nuclide].name << "\n";
}
}
// Write the score, mean, and uncertainty.
indent += 2;
for (auto score : tally.scores_) {
std::string score_name = score > 0 ? reaction_name(score)
: score_names.at(score);
double mean, stdev;
//TODO: off-by-one
std::tie(mean, stdev) = mean_stdev(
results(filter_index-1, score_index, RESULT_SUM),
results(filter_index-1, score_index, RESULT_SUM_SQ),
n_realizations);
tallies_out << std::string(indent+1, ' ') << std::left
<< std::setw(36) << score_name << " " << mean << " +/- "
<< t_value * stdev << "\n";
score_index += 1;
}
indent -= 2;
}
}
}
}
} // namespace openmc

View file

@ -144,11 +144,6 @@ int openmc_simulation_finalize()
simulation::time_active.stop();
simulation::time_finalize.start();
#pragma omp parallel
{
simulation::filter_matches.clear();
}
// Deallocate Fortran variables, set tallies to inactive
for (auto& mat : model::materials) {
mat->mat_nuclide_index_.clear();
@ -165,6 +160,11 @@ int openmc_simulation_finalize()
// Write tally results to tallies.out
if (settings::output_tallies && mpi::master) write_tallies();
#pragma omp parallel
{
simulation::filter_matches.clear();
}
// Deactivate all tallies
for (int i = 1; i <= n_tallies; ++i) {
openmc_tally_set_active(i, false);

View file

@ -63,124 +63,6 @@ double global_tally_collision;
double global_tally_tracklength;
double global_tally_leakage;
//==============================================================================
//! An iterator over all combinations of a tally's matching filter bins.
//
//! This iterator handles two distinct tasks. First, it maps the N-dimensional
//! space created by the indices of N filters onto a 1D sequence. In other
//! words, it provides a single number that uniquely identifies a combination of
//! bins for many filters. Second, it handles the task of finding each all
//! valid combinations of filter bins given that each filter can have 1 or 2 or
//! many bins that are valid for the current tally event.
//==============================================================================
class FilterBinIter
{
public:
FilterBinIter(const Tally& tally, Particle* p, bool end)
: tally_{tally}
{
// Handle the special case for an iterator that points to the end.
if (end) {
index_ = -1;
return;
}
// Find all valid bins in each relevant filter if they have not already been
// found for this event.
for (auto i_filt : tally_.filters()) {
auto& match {simulation::filter_matches[i_filt]};
if (!match.bins_present_) {
match.bins_.clear();
match.weights_.clear();
model::tally_filters[i_filt]->get_all_bins(p, tally_.estimator_, match);
match.bins_present_ = true;
}
// If there are no valid bins for this filter, then there are no valid
// filter bin combinations so all iterators are end iterators.
if (match.bins_.size() == 0) {
index_ = -1;
return;
}
// Set the index of the bin used in the first filter combination
match.i_bin_ = 1;
}
// Compute the initial index and weight.
compute_index_weight();
}
bool
operator==(const FilterBinIter& other)
{
return index_ == other.index_;
}
bool
operator!=(const FilterBinIter& other)
{
return !(*this == other);
}
FilterBinIter&
operator++()
{
// Find the next valid combination of filter bins. To do this, we search
// backwards through the filters until we find the first filter whose bins
// can be incremented.
bool done_looping = true;
for (int i = tally_.filters().size()-1; i >= 0; --i) {
auto i_filt = tally_.filters(i);
auto& match {simulation::filter_matches[i_filt]};
if (match.i_bin_< match.bins_.size()) {
// The bin for this filter can be incremented. Increment it and do not
// touch any of the remaining filters.
++match.i_bin_;
done_looping = false;
break;
} else {
// This bin cannot be incremented so reset it and continue to the next
// filter.
match.i_bin_ = 1;
}
}
if (done_looping) {
// We have visited every valid combination. All done!
index_ = -1;
} else {
// The loop found a new valid combination. Compute the corresponding
// index and weight.
compute_index_weight();
}
return *this;
}
int index_ {1};
double weight_ {1.};
private:
void
compute_index_weight()
{
index_ = 1;
weight_ = 1.;
for (auto i = 0; i < tally_.filters().size(); ++i) {
auto i_filt = tally_.filters(i);
auto& match {simulation::filter_matches[i_filt]};
auto i_bin = match.i_bin_;
//TODO: off-by-one
index_ += (match.bins_[i_bin-1] - 1) * tally_.strides(i);
weight_ *= match.weights_[i_bin-1];
}
}
const Tally& tally_;
};
int
score_str_to_int(std::string score_str)
{
@ -341,6 +223,12 @@ score_str_to_int(std::string score_str)
// Tally object implementation
//==============================================================================
void
Tally::init_from_xml(pugi::xml_node node)
{
if (check_for_node(node, "name")) name_ = get_node_value(node, "name");
}
void
Tally::set_filters(const int32_t filter_indices[], int n)
{
@ -632,6 +520,123 @@ Tally::init_triggers(pugi::xml_node node, int i_tally)
}
}
//==============================================================================
// FilterBinIter implementation
//==============================================================================
FilterBinIter::FilterBinIter(const Tally& tally, Particle* p)
: tally_{tally}
{
// Find all valid bins in each relevant filter if they have not already been
// found for this event.
for (auto i_filt : tally_.filters()) {
auto& match {simulation::filter_matches[i_filt]};
if (!match.bins_present_) {
match.bins_.clear();
match.weights_.clear();
model::tally_filters[i_filt]->get_all_bins(p, tally_.estimator_, match);
match.bins_present_ = true;
}
// If there are no valid bins for this filter, then there are no valid
// filter bin combinations so all iterators are end iterators.
if (match.bins_.size() == 0) {
index_ = -1;
return;
}
// Set the index of the bin used in the first filter combination
match.i_bin_ = 1;
}
// Compute the initial index and weight.
compute_index_weight();
}
FilterBinIter::FilterBinIter(const Tally& tally, bool end)
: tally_{tally}
{
// Handle the special case for an iterator that points to the end.
if (end) {
index_ = -1;
return;
}
for (auto i_filt : tally_.filters()) {
auto& match {simulation::filter_matches[i_filt]};
if (!match.bins_present_) {
match.bins_.clear();
match.weights_.clear();
for (auto i = 0; i < model::tally_filters[i_filt]->n_bins_; ++i) {
// TODO: off-by-one
match.bins_.push_back(i+1);
match.weights_.push_back(1.0);
}
match.bins_present_ = true;
}
if (match.bins_.size() == 0) {
index_ = -1;
return;
}
match.i_bin_ = 1;
}
// Compute the initial index and weight.
compute_index_weight();
}
FilterBinIter&
FilterBinIter::operator++()
{
// Find the next valid combination of filter bins. To do this, we search
// backwards through the filters until we find the first filter whose bins
// can be incremented.
bool done_looping = true;
for (int i = tally_.filters().size()-1; i >= 0; --i) {
auto i_filt = tally_.filters(i);
auto& match {simulation::filter_matches[i_filt]};
if (match.i_bin_< match.bins_.size()) {
// The bin for this filter can be incremented. Increment it and do not
// touch any of the remaining filters.
++match.i_bin_;
done_looping = false;
break;
} else {
// This bin cannot be incremented so reset it and continue to the next
// filter.
match.i_bin_ = 1;
}
}
if (done_looping) {
// We have visited every valid combination. All done!
index_ = -1;
} else {
// The loop found a new valid combination. Compute the corresponding
// index and weight.
compute_index_weight();
}
return *this;
}
void
FilterBinIter::compute_index_weight()
{
index_ = 1;
weight_ = 1.;
for (auto i = 0; i < tally_.filters().size(); ++i) {
auto i_filt = tally_.filters(i);
auto& match {simulation::filter_matches[i_filt]};
auto i_bin = match.i_bin_;
//TODO: off-by-one
index_ += (match.bins_[i_bin-1] - 1) * tally_.strides(i);
weight_ *= match.weights_[i_bin-1];
}
}
//==============================================================================
// Non-member functions
//==============================================================================
@ -2511,8 +2516,8 @@ score_analog_tally_ce(Particle* p)
// Initialize an iterator over valid filter bin combinations. If there are
// no valid combinations, use a continue statement to ensure we skip the
// assume_separate break below.
auto filter_iter = FilterBinIter(tally, p, false);
auto end = FilterBinIter(tally, nullptr, true);
auto filter_iter = FilterBinIter(tally, p);
auto end = FilterBinIter(tally, true);
if (filter_iter == end) continue;
// Loop over filter bins.
@ -2576,8 +2581,8 @@ score_analog_tally_mg(Particle* p)
// Initialize an iterator over valid filter bin combinations. If there are
// no valid combinations, use a continue statement to ensure we skip the
// assume_separate break below.
auto filter_iter = FilterBinIter(tally, p, false);
auto end = FilterBinIter(tally, nullptr, true);
auto filter_iter = FilterBinIter(tally, p);
auto end = FilterBinIter(tally, true);
if (filter_iter == end) continue;
// Loop over filter bins.
@ -2636,8 +2641,8 @@ score_tracklength_tally(Particle* p, double distance)
// Initialize an iterator over valid filter bin combinations. If there are
// no valid combinations, use a continue statement to ensure we skip the
// assume_separate break below.
auto filter_iter = FilterBinIter(tally, p, false);
auto end = FilterBinIter(tally, nullptr, true);
auto filter_iter = FilterBinIter(tally, p);
auto end = FilterBinIter(tally, true);
if (filter_iter == end) continue;
// Loop over filter bins.
@ -2718,8 +2723,8 @@ score_collision_tally(Particle* p)
// Initialize an iterator over valid filter bin combinations. If there are
// no valid combinations, use a continue statement to ensure we skip the
// assume_separate break below.
auto filter_iter = FilterBinIter(tally, p, false);
auto end = FilterBinIter(tally, nullptr, true);
auto filter_iter = FilterBinIter(tally, p);
auto end = FilterBinIter(tally, true);
if (filter_iter == end) continue;
// Loop over filter bins.
@ -2786,8 +2791,8 @@ score_surface_tally_inner(Particle* p, const std::vector<int>& tallies)
// Initialize an iterator over valid filter bin combinations. If there are
// no valid combinations, use a continue statement to ensure we skip the
// assume_separate break below.
auto filter_iter = FilterBinIter(tally, p, false);
auto end = FilterBinIter(tally, nullptr, true);
auto filter_iter = FilterBinIter(tally, p);
auto end = FilterBinIter(tally, true);
if (filter_iter == end) continue;
// Loop over filter bins.
@ -3172,6 +3177,9 @@ extern "C" {
int active_surface_tallies_size()
{return model::active_surface_tallies.size();}
void tally_init_from_xml(Tally* tally, pugi::xml_node* node)
{tally->init_from_xml(*node);}
int tally_get_id_c(Tally* tally) {return tally->id_;}
void tally_set_id_c(Tally* tally, int id) {tally->id_ = id;}