Skip to content

Commit

Permalink
External sources alias sampler (#3201)
Browse files Browse the repository at this point in the history
Co-authored-by: Paul Romano <[email protected]>
  • Loading branch information
magnoxemo and paulromano authored Nov 23, 2024
1 parent dd01c40 commit 2d988a6
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 16 deletions.
3 changes: 3 additions & 0 deletions include/openmc/source.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ namespace model {

extern vector<unique_ptr<Source>> external_sources;

// Probability distribution for selecting external sources
extern DiscreteIndex external_sources_probability;

} // namespace model

//==============================================================================
Expand Down
4 changes: 2 additions & 2 deletions openmc/model/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ def sample_external_source(
n_samples: int = 1000,
prn_seed: int | None = None,
**init_kwargs
) -> list[openmc.SourceParticle]:
) -> openmc.ParticleList:
"""Sample external source and return source particles.
.. versionadded:: 0.15.1
Expand All @@ -902,7 +902,7 @@ def sample_external_source(
Returns
-------
list of openmc.SourceParticle
openmc.ParticleList
List of samples source particles
"""
import openmc.lib
Expand Down
7 changes: 7 additions & 0 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,13 @@ void read_settings_xml(pugi::xml_node root)
model::external_sources.push_back(make_unique<FileSource>(path));
}

// Build probability mass function for sampling external sources
vector<double> source_strengths;
for (auto& s : model::external_sources) {
source_strengths.push_back(s->strength());
}
model::external_sources_probability.assign(source_strengths);

// If no source specified, default to isotropic point source at origin with
// Watt spectrum. No default source is needed in random ray mode.
if (model::external_sources.empty() &&
Expand Down
18 changes: 5 additions & 13 deletions src/source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ namespace openmc {
namespace model {

vector<unique_ptr<Source>> external_sources;
}

DiscreteIndex external_sources_probability;

} // namespace model

//==============================================================================
// Source implementation
Expand Down Expand Up @@ -608,24 +611,13 @@ void initialize_source()

SourceSite sample_external_source(uint64_t* seed)
{
// Determine total source strength
double total_strength = 0.0;
for (auto& s : model::external_sources)
total_strength += s->strength();

// Sample from among multiple source distributions
int i = 0;
if (model::external_sources.size() > 1) {
if (settings::uniform_source_sampling) {
i = prn(seed) * model::external_sources.size();
} else {
double xi = prn(seed) * total_strength;
double c = 0.0;
for (; i < model::external_sources.size(); ++i) {
c += model::external_sources[i]->strength();
if (xi < c)
break;
}
i = model::external_sources_probability.sample(seed);
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/regression_tests/source/results_true.dat
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
k-combined:
3.054101E-01 1.167865E-03
2.959436E-01 2.782384E-03
12 changes: 12 additions & 0 deletions tests/unit_tests/test_uniform_source_sampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,15 @@ def test_tally_mean(run_in_tmpdir, sphere_model):

# Check that tally means match
assert mean == pytest.approx(reference_mean)


def test_multiple_sources(sphere_model):
low_strength_src = openmc.IndependentSource(
energy=openmc.stats.delta_function(1.0e6), strength=1e-7)
sphere_model.settings.source.append(low_strength_src)
sphere_model.settings.uniform_source_sampling = True

# Sample particles from source and make sure 1 MeV shows up despite
# negligible strength
particles = sphere_model.sample_external_source(100)
assert {p.E for p in particles} == {1.0e3, 1.0e6}

0 comments on commit 2d988a6

Please sign in to comment.