Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/openmc/particle_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ class ParticleData : public GeometryState {
CacheDataMG mg_xs_cache_;

ParticleType type_ {ParticleType::neutron};
ParticleType type_last_ {ParticleType::neutron};

double E_;
double E_last_;
Expand Down Expand Up @@ -566,6 +567,8 @@ class ParticleData : public GeometryState {
// Particle type (n, p, e, gamma, etc)
ParticleType& type() { return type_; }
const ParticleType& type() const { return type_; }
ParticleType& type_last() { return type_last_; }
const ParticleType& type_last() const { return type_last_; }

// Current particle energy, energy before collision,
// and corresponding multigroup group indices. Energy
Expand Down
1 change: 1 addition & 0 deletions include/openmc/tallies/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum class FilterType {
MUSURFACE,
PARENT_NUCLIDE,
PARTICLE,
PARTICLE_OUT,
POLAR,
SPHERICAL_HARMONICS,
SPATIAL_LEGENDRE,
Expand Down
40 changes: 40 additions & 0 deletions include/openmc/tallies/filter_particle.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,45 @@ class ParticleFilter : public Filter {
vector<ParticleType> particles_;
};

//==============================================================================
//! Bins by type of outgoing particle (e.g. neutron, photon).
//==============================================================================

class ParticleOutFilter : public Filter {
public:
//----------------------------------------------------------------------------
// Constructors, destructors

~ParticleOutFilter() = default;

//----------------------------------------------------------------------------
// Methods

std::string type_str() const override { return "particleout"; }
FilterType type() const override { return FilterType::PARTICLE_OUT; }

void from_xml(pugi::xml_node node) override;

void get_all_bins(const Particle& p, TallyEstimator estimator,
FilterMatch& match) const override;

void to_statepoint(hid_t filter_group) const override;

std::string text_label(int bin) const override;

//----------------------------------------------------------------------------
// Accessors

const vector<ParticleType>& particles() const { return particles_; }

void set_particles(span<ParticleType> particles);

private:
//----------------------------------------------------------------------------
// Data members

vector<ParticleType> particles_;
};

} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_PARTICLE_H
1 change: 1 addition & 0 deletions include/openmc/tallies/tally.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ extern std::unordered_map<int, int> tally_map;
extern vector<unique_ptr<Tally>> tallies;
extern vector<int> active_tallies;
extern vector<int> active_analog_tallies;
extern vector<int> active_particleout_analog_tallies;
extern vector<int> active_tracklength_tallies;
extern vector<int> active_timed_tracklength_tallies;
extern vector<int> active_collision_tallies;
Expand Down
6 changes: 4 additions & 2 deletions include/openmc/tallies/tally_scoring.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,16 @@ void score_collision_tally(Particle& p);
//! Analog tallies are triggered at every collision, not every event.
//
//! \param p The particle being tracked
void score_analog_tally_ce(Particle& p);
//! \param tallies A vector of the indices of the tallies to score to
void score_analog_tally_ce(Particle& p, const vector<int>& tallies);

//! Score tallies based on a simple count of events (for multigroup).
//
//! Analog tallies are triggered at every collision, not every event.
//
//! \param p The particle being tracked
void score_analog_tally_mg(Particle& p);
//! \param tallies A vector of the indices of the tallies to score to
void score_analog_tally_mg(Particle& p, const vector<int>& tallies);

//! Score tallies using a tracklength estimate of the flux.
//
Expand Down
29 changes: 26 additions & 3 deletions openmc/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
'universe', 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy',
'energyout', 'mu', 'musurface', 'polar', 'azimuthal', 'distribcell', 'delayedgroup',
'energyfunction', 'cellfrom', 'materialfrom', 'legendre', 'spatiallegendre',
'sphericalharmonics', 'zernike', 'zernikeradial', 'particle', 'cellinstance',
'collision', 'time', 'parentnuclide', 'weight', 'meshborn', 'meshsurface',
'meshmaterial',
'sphericalharmonics', 'zernike', 'zernikeradial', 'particle', 'particleout',
'cellinstance', 'collision', 'time', 'parentnuclide', 'weight', 'meshborn',
'meshsurface', 'meshmaterial',
)

_CURRENT_NAMES = (
Expand Down Expand Up @@ -785,6 +785,29 @@ def from_xml_element(cls, elem, **kwargs):
filter_id = int(get_text(elem, "id"))
bins = get_elem_list(elem, "bins", str) or []
return cls(bins, filter_id=filter_id)


class ParticleoutFilter(ParticleFilter):
"""Bins tally events based on the outgoing particle type.

Parameters
----------
bins : str, or sequence of str
The particles to tally represented as strings ('neutron', 'photon',
'electron', 'positron').
filter_id : int
Unique identifier for the filter

Attributes
----------
bins : sequence of str
The particles to tally
id : int
Unique identifier for the filter
num_bins : Integral
The number of filter bins

"""


class ParentNuclideFilter(ParticleFilter):
Expand Down
10 changes: 7 additions & 3 deletions openmc/lib/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
'EnergyFilter', 'EnergyoutFilter', 'EnergyFunctionFilter', 'LegendreFilter',
'MaterialFilter', 'MaterialFromFilter', 'MeshFilter', 'MeshBornFilter',
'MeshMaterialFilter', 'MeshSurfaceFilter', 'MuFilter', 'MuSurfaceFilter',
'ParentNuclideFilter', 'ParticleFilter', 'PolarFilter', 'SphericalHarmonicsFilter',
'SpatialLegendreFilter', 'SurfaceFilter', 'TimeFilter', 'UniverseFilter',
'WeightFilter', 'ZernikeFilter', 'ZernikeRadialFilter', 'filters'
'ParentNuclideFilter', 'ParticleFilter', 'ParticleoutFilter', 'PolarFilter',
'SphericalHarmonicsFilter', 'SpatialLegendreFilter', 'SurfaceFilter', 'TimeFilter',
'UniverseFilter', 'WeightFilter', 'ZernikeFilter', 'ZernikeRadialFilter', 'filters'
]

# Tally functions
Expand Down Expand Up @@ -564,6 +564,10 @@ def bins(self):
return [ParticleType(i) for i in particle_i]


class ParticleoutFilter(ParticleFilter):
filter_type = 'particleout'


class PolarFilter(Filter):
filter_type = 'polar'

Expand Down
28 changes: 26 additions & 2 deletions src/particle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@

namespace openmc {

namespace simulation {
thread_local Particle tmp_particle;
}

//==============================================================================
// Particle implementation
//==============================================================================
Expand Down Expand Up @@ -88,6 +92,24 @@ bool Particle::create_secondary(
bank.E = settings::run_CE ? E : g();
bank.time = time();
bank_second_E() += bank.E;

// Score tallies affected by secondary particles
if (!model::active_particleout_analog_tallies.empty()) {
// Create secondary particle for tallying purposes only
simulation::tmp_particle.from_source(&bank);
simulation::tmp_particle.u_last() = this->u();
simulation::tmp_particle.r_last() = this->r();
simulation::tmp_particle.E_last() = this->E();
simulation::tmp_particle.type_last() = this->type();

if (settings::run_CE) {
score_analog_tally_ce(
simulation::tmp_particle, model::active_particleout_analog_tallies);
} else {
score_analog_tally_mg(
simulation::tmp_particle, model::active_particleout_analog_tallies);
}
}
return true;
}

Expand Down Expand Up @@ -124,6 +146,7 @@ void Particle::from_source(const SourceSite* src)

// Copy attributes from source bank site
type() = src->particle;
type_last() = src->particle;
wgt() = src->wgt;
wgt_last() = src->wgt;
r() = src->r;
Expand Down Expand Up @@ -160,6 +183,7 @@ void Particle::event_calculate_xs()
// Store pre-collision particle properties
wgt_last() = wgt();
E_last() = E();
type_last() = type();
u_last() = u();
r_last() = r();
time_last() = time();
Expand Down Expand Up @@ -353,9 +377,9 @@ void Particle::event_collide()
score_collision_tally(*this);
if (!model::active_analog_tallies.empty()) {
if (settings::run_CE) {
score_analog_tally_ce(*this);
score_analog_tally_ce(*this, model::active_analog_tallies);
} else {
score_analog_tally_mg(*this);
score_analog_tally_mg(*this, model::active_analog_tallies);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/particle_restart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ void read_particle_restart(Particle& p, RunMode& previous_run_mode)
p.r_last() = p.r();
p.u_last() = p.u();
p.E_last() = p.E();
p.type_last() = p.type();
p.g_last() = p.g();
p.time_last() = p.time();

Expand Down
2 changes: 2 additions & 0 deletions src/tallies/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ Filter* Filter::create(const std::string& type, int32_t id)
return Filter::create<ParentNuclideFilter>(id);
} else if (type == "particle") {
return Filter::create<ParticleFilter>(id);
} else if (type == "particleout") {
return Filter::create<ParticleOutFilter>(id);
} else if (type == "polar") {
return Filter::create<PolarFilter>(id);
} else if (type == "surface") {
Expand Down
69 changes: 68 additions & 1 deletion src/tallies/filter_particle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

namespace openmc {

//==============================================================================
// ParticleFilter implementation
//==============================================================================

void ParticleFilter::from_xml(pugi::xml_node node)
{
auto particles = get_node_array<std::string>(node, "bins");
Expand Down Expand Up @@ -34,8 +38,11 @@ void ParticleFilter::set_particles(span<ParticleType> particles)
void ParticleFilter::get_all_bins(
const Particle& p, TallyEstimator estimator, FilterMatch& match) const
{
// Get the pre-collision type of the particle.
auto type = p.type_last();

for (auto i = 0; i < particles_.size(); i++) {
if (particles_[i] == p.type()) {
if (particles_[i] == type) {
match.bins_.push_back(i);
match.weights_.push_back(1.0);
}
Expand All @@ -58,6 +65,66 @@ std::string ParticleFilter::text_label(int bin) const
return fmt::format("Particle: {}", particle_type_to_str(p));
}

//==============================================================================
// ParticleOutFilter implementation
//==============================================================================

void ParticleOutFilter::from_xml(pugi::xml_node node)
{
auto particles = get_node_array<std::string>(node, "bins");

// Convert to vector of ParticleType
vector<ParticleType> types;
for (auto& p : particles) {
types.push_back(str_to_particle_type(p));
}
this->set_particles(types);
}

void ParticleOutFilter::set_particles(span<ParticleType> particles)
{
// Clear existing particles
particles_.clear();
particles_.reserve(particles.size());

// Set particles and number of bins
for (auto p : particles) {
particles_.push_back(p);
}
n_bins_ = particles_.size();
}

void ParticleOutFilter::get_all_bins(
const Particle& p, TallyEstimator estimator, FilterMatch& match) const
{
for (auto i = 0; i < particles_.size(); i++) {
if (particles_[i] == p.type()) {
match.bins_.push_back(i);
match.weights_.push_back(1.0);
}
}
}

void ParticleOutFilter::to_statepoint(hid_t filter_group) const
{
Filter::to_statepoint(filter_group);
vector<std::string> particles;
for (auto p : particles_) {
particles.push_back(particle_type_to_str(p));
}
write_dataset(filter_group, "bins", particles);
}

std::string ParticleOutFilter::text_label(int bin) const
{
const auto& p = particles_.at(bin);
return fmt::format("ParticleOut: {}", particle_type_to_str(p));
}

//==============================================================================
// C-API functions
//==============================================================================

extern "C" int openmc_particle_filter_get_bins(int32_t idx, int bins[])
{
if (int err = verify_filter(idx))
Expand Down
Loading
Loading