mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-29 06:35:48 -04:00
Random Ray Normalization Improvements (#3051)
Co-authored-by: Olek <45364492+yardasol@users.noreply.github.com>
This commit is contained in:
parent
ac0ad0bac2
commit
391450ce01
23 changed files with 2572 additions and 154 deletions
|
|
@ -740,6 +740,8 @@ scalar flux value for the FSR).
|
|||
global::volume[fsr] += s;
|
||||
}
|
||||
|
||||
.. _methods_random_tallies:
|
||||
|
||||
------------------------
|
||||
How are Tallies Handled?
|
||||
------------------------
|
||||
|
|
@ -757,6 +759,18 @@ behavior if a single simulation cell is able to score to multiple filter mesh
|
|||
cells. In the future, the capability to fully support mesh tallies may be added
|
||||
to OpenMC, but for now this restriction needs to be respected.
|
||||
|
||||
Flux tallies are handled slightly differently than in Monte Carlo. By default,
|
||||
in MC, flux tallies are reported in units of tracklength (cm), so must be
|
||||
manually normalized by volume by the user to produce an estimate of flux in
|
||||
units of cm\ :sup:`-2`\. Alternatively, MC flux tallies can be normalized via a
|
||||
separated volume calculation process as discussed in the :ref:`Volume
|
||||
Calculation Section<usersguide_volume>`. In random ray, as the volumes are
|
||||
computed on-the-fly as part of the transport process, the flux tallies can
|
||||
easily be reported either in units of flux (cm\ :sup:`-2`\) or tracklength (cm).
|
||||
By default, the unnormalized flux values (units of cm) will be reported. If the
|
||||
user wishes to received volume normalized flux tallies, then an option for this
|
||||
is available, as described in the :ref:`User Guide<usersguide_flux_norm>`.
|
||||
|
||||
.. _methods-shannon-entropy-random-ray:
|
||||
|
||||
-----------------------------
|
||||
|
|
|
|||
|
|
@ -330,6 +330,8 @@ of a two-dimensional 2x2 reflective pincell lattice:
|
|||
|
||||
In the future, automated subdivision of FSRs via mesh overlay may be supported.
|
||||
|
||||
.. _usersguide_flux_norm:
|
||||
|
||||
-------
|
||||
Tallies
|
||||
-------
|
||||
|
|
@ -367,6 +369,25 @@ Note that there is no difference between the analog, tracklength, and collision
|
|||
estimators in random ray mode as individual particles are not being simulated.
|
||||
Tracklength-style tally estimation is inherent to the random ray method.
|
||||
|
||||
As discussed in the random ray theory section on :ref:`Random Ray
|
||||
Tallies<methods_random_tallies>`, by default flux tallies in the random ray mode
|
||||
are not normalized by the spatial tally volumes such that flux tallies are in
|
||||
units of cm. While the volume information is readily available as a byproduct of
|
||||
random ray integration, the flux value is reported in unnormalized units of cm
|
||||
so that the user will be able to compare "apples to apples" with the default
|
||||
flux tallies from the Monte Carlo solver (also reported by default in units of
|
||||
cm). If volume normalized flux tallies (in units of cm\ :sup:`-2`) are desired,
|
||||
then the user can set the ``volume_normalized_flux_tallies`` field in the
|
||||
:attr:`openmc.Settings.random_ray` dictionary to ``True``. An example is given
|
||||
below:
|
||||
|
||||
::
|
||||
|
||||
settings.random_ray['volume_normalized_flux_tallies'] = True
|
||||
|
||||
Note that MC mode flux tallies can also be normalized by volume, as discussed in
|
||||
the :ref:`Volume Calculation Section<usersguide_volume>` of the user guide.
|
||||
|
||||
--------
|
||||
Plotting
|
||||
--------
|
||||
|
|
|
|||
|
|
@ -108,6 +108,11 @@ public:
|
|||
void all_reduce_replicated_source_regions();
|
||||
void convert_external_sources();
|
||||
void count_external_source_regions();
|
||||
double compute_fixed_source_normalization_factor() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Static Data members
|
||||
static bool volume_normalized_flux_tallies_;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Public Data members
|
||||
|
|
|
|||
|
|
@ -157,6 +157,12 @@ class Settings:
|
|||
:ray_source:
|
||||
Starting ray distribution (must be uniform in space and angle) as
|
||||
specified by a :class:`openmc.SourceBase` object.
|
||||
:volume_normalized_flux_tallies:
|
||||
Whether to normalize flux tallies by volume (bool). The default
|
||||
is 'False'. When enabled, flux tallies will be reported in units of
|
||||
cm/cm^3. When disabled, flux tallies will be reported in units
|
||||
of cm (i.e., total distance traveled by neutrons in the spatial
|
||||
tally region).
|
||||
|
||||
.. versionadded:: 0.15.0
|
||||
resonance_scattering : dict
|
||||
|
|
@ -1084,6 +1090,8 @@ class Settings:
|
|||
random_ray[key], 0.0, True)
|
||||
elif key == 'ray_source':
|
||||
cv.check_type('random ray source', random_ray[key], SourceBase)
|
||||
elif key == 'volume_normalized_flux_tallies':
|
||||
cv.check_type('volume normalized flux tallies', random_ray[key], bool)
|
||||
else:
|
||||
raise ValueError(f'Unable to set random ray to "{key}" which is '
|
||||
'unsupported by OpenMC')
|
||||
|
|
@ -1877,6 +1885,10 @@ class Settings:
|
|||
elif child.tag == 'source':
|
||||
source = SourceBase.from_xml_element(child)
|
||||
self.random_ray['ray_source'] = source
|
||||
elif child.tag == 'volume_normalized_flux_tallies':
|
||||
self.random_ray['volume_normalized_flux_tallies'] = (
|
||||
child.text in ('true', '1')
|
||||
)
|
||||
|
||||
def to_xml_element(self, mesh_memo=None):
|
||||
"""Create a 'settings' element to be written to an XML file.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ namespace openmc {
|
|||
// FlatSourceDomain implementation
|
||||
//==============================================================================
|
||||
|
||||
// Static Variable Declarations
|
||||
bool FlatSourceDomain::volume_normalized_flux_tallies_ {false};
|
||||
|
||||
FlatSourceDomain::FlatSourceDomain() : negroups_(data::mg.num_energy_groups_)
|
||||
{
|
||||
// Count the number of source regions, compute the cell offset
|
||||
|
|
@ -81,15 +84,17 @@ FlatSourceDomain::FlatSourceDomain() : negroups_(data::mg.num_energy_groups_)
|
|||
}
|
||||
|
||||
// Initialize tally volumes
|
||||
tally_volumes_.resize(model::tallies.size());
|
||||
for (int i = 0; i < model::tallies.size(); i++) {
|
||||
// Get the shape of the 3D result tensor
|
||||
auto shape = model::tallies[i]->results().shape();
|
||||
if (volume_normalized_flux_tallies_) {
|
||||
tally_volumes_.resize(model::tallies.size());
|
||||
for (int i = 0; i < model::tallies.size(); i++) {
|
||||
// Get the shape of the 3D result tensor
|
||||
auto shape = model::tallies[i]->results().shape();
|
||||
|
||||
// Create a new 2D tensor with the same size as the first
|
||||
// two dimensions of the 3D tensor
|
||||
tally_volumes_[i] =
|
||||
xt::xtensor<double, 2>::from_shape({shape[0], shape[1]});
|
||||
// Create a new 2D tensor with the same size as the first
|
||||
// two dimensions of the 3D tensor
|
||||
tally_volumes_[i] =
|
||||
xt::xtensor<double, 2>::from_shape({shape[0], shape[1]});
|
||||
}
|
||||
}
|
||||
|
||||
// Compute simulation domain volume based on ray source
|
||||
|
|
@ -462,13 +467,65 @@ void FlatSourceDomain::convert_source_regions_to_tallies()
|
|||
// Set the volume accumulators to zero for all tallies
|
||||
void FlatSourceDomain::reset_tally_volumes()
|
||||
{
|
||||
if (volume_normalized_flux_tallies_) {
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < tally_volumes_.size(); i++) {
|
||||
auto& tensor = tally_volumes_[i];
|
||||
tensor.fill(0.0); // Set all elements of the tensor to 0.0
|
||||
for (int i = 0; i < tally_volumes_.size(); i++) {
|
||||
auto& tensor = tally_volumes_[i];
|
||||
tensor.fill(0.0); // Set all elements of the tensor to 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In fixed source mode, due to the way that volumetric fixed sources are
|
||||
// converted and applied as volumetric sources in one or more source regions,
|
||||
// we need to perform an additional normalization step to ensure that the
|
||||
// reported scalar fluxes are in units per source neutron. This allows for
|
||||
// direct comparison of reported tallies to Monte Carlo flux results.
|
||||
// This factor needs to be computed at each iteration, as it is based on the
|
||||
// volume estimate of each FSR, which improves over the course of the simulation
|
||||
double FlatSourceDomain::compute_fixed_source_normalization_factor() const
|
||||
{
|
||||
// If we are not in fixed source mode, then there are no external sources
|
||||
// so no normalization is needed.
|
||||
if (settings::run_mode != RunMode::FIXED_SOURCE) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
// Step 1 is to sum over all source regions and energy groups to get the
|
||||
// total external source strength in the simulation.
|
||||
double simulation_external_source_strength = 0.0;
|
||||
#pragma omp parallel for reduction(+ : simulation_external_source_strength)
|
||||
for (int sr = 0; sr < n_source_regions_; sr++) {
|
||||
int material = material_[sr];
|
||||
double volume = volume_[sr] * simulation_volume_;
|
||||
for (int e = 0; e < negroups_; e++) {
|
||||
// Temperature and angle indices, if using multiple temperature
|
||||
// data sets and/or anisotropic data sets.
|
||||
// TODO: Currently assumes we are only using single temp/single
|
||||
// angle data.
|
||||
const int t = 0;
|
||||
const int a = 0;
|
||||
float sigma_t = data::mg.macro_xs_[material].get_xs(
|
||||
MgxsType::TOTAL, e, nullptr, nullptr, nullptr, t, a);
|
||||
simulation_external_source_strength +=
|
||||
external_source_[sr * negroups_ + e] * sigma_t * volume;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2 is to determine the total user-specified external source strength
|
||||
double user_external_source_strength = 0.0;
|
||||
for (auto& ext_source : model::external_sources) {
|
||||
user_external_source_strength += ext_source->strength();
|
||||
}
|
||||
|
||||
// The correction factor is the ratio of the user-specified external source
|
||||
// strength to the simulation external source strength.
|
||||
double source_normalization_factor =
|
||||
user_external_source_strength / simulation_external_source_strength;
|
||||
|
||||
return source_normalization_factor;
|
||||
}
|
||||
|
||||
// Tallying in random ray is not done directly during transport, rather,
|
||||
// it is done only once after each power iteration. This is made possible
|
||||
// by way of a mapping data structure that relates spatial source regions
|
||||
|
|
@ -492,6 +549,9 @@ void FlatSourceDomain::random_ray_tally()
|
|||
const int t = 0;
|
||||
const int a = 0;
|
||||
|
||||
double source_normalization_factor =
|
||||
compute_fixed_source_normalization_factor();
|
||||
|
||||
// We loop over all source regions and energy groups. For each
|
||||
// element, we check if there are any scores needed and apply
|
||||
// them.
|
||||
|
|
@ -510,7 +570,7 @@ void FlatSourceDomain::random_ray_tally()
|
|||
double material = material_[sr];
|
||||
for (int g = 0; g < negroups_; g++) {
|
||||
int idx = sr * negroups_ + g;
|
||||
double flux = scalar_flux_new_[idx];
|
||||
double flux = scalar_flux_new_[idx] * source_normalization_factor;
|
||||
|
||||
// Determine numerical score value
|
||||
for (auto& task : tally_task_[idx]) {
|
||||
|
|
@ -561,11 +621,13 @@ void FlatSourceDomain::random_ray_tally()
|
|||
// For flux tallies, the total volume of the spatial region is needed
|
||||
// for normalizing the flux. We store this volume in a separate tensor.
|
||||
// We only contribute to each volume tally bin once per FSR.
|
||||
for (const auto& task : volume_task_[sr]) {
|
||||
if (task.score_type == SCORE_FLUX) {
|
||||
if (volume_normalized_flux_tallies_) {
|
||||
for (const auto& task : volume_task_[sr]) {
|
||||
if (task.score_type == SCORE_FLUX) {
|
||||
#pragma omp atomic
|
||||
tally_volumes_[task.tally_idx](task.filter_idx, task.score_idx) +=
|
||||
volume;
|
||||
tally_volumes_[task.tally_idx](task.filter_idx, task.score_idx) +=
|
||||
volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end FSR loop
|
||||
|
|
@ -575,16 +637,18 @@ void FlatSourceDomain::random_ray_tally()
|
|||
// and then scores. For each score, we check the tally data structure to
|
||||
// see what index that score corresponds to. If that score is a flux score,
|
||||
// then we divide it by volume.
|
||||
for (int i = 0; i < model::tallies.size(); i++) {
|
||||
Tally& tally {*model::tallies[i]};
|
||||
if (volume_normalized_flux_tallies_) {
|
||||
for (int i = 0; i < model::tallies.size(); i++) {
|
||||
Tally& tally {*model::tallies[i]};
|
||||
#pragma omp parallel for
|
||||
for (int bin = 0; bin < tally.n_filter_bins(); bin++) {
|
||||
for (int score_idx = 0; score_idx < tally.n_scores(); score_idx++) {
|
||||
auto score_type = tally.scores_[score_idx];
|
||||
if (score_type == SCORE_FLUX) {
|
||||
double vol = tally_volumes_[i](bin, score_idx);
|
||||
if (vol > 0.0) {
|
||||
tally.results_(bin, score_idx, TallyResult::VALUE) /= vol;
|
||||
for (int bin = 0; bin < tally.n_filter_bins(); bin++) {
|
||||
for (int score_idx = 0; score_idx < tally.n_scores(); score_idx++) {
|
||||
auto score_type = tally.scores_[score_idx];
|
||||
if (score_type == SCORE_FLUX) {
|
||||
double vol = tally_volumes_[i](bin, score_idx);
|
||||
if (vol > 0.0) {
|
||||
tally.results_(bin, score_idx, TallyResult::VALUE) /= vol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -767,6 +831,9 @@ void FlatSourceDomain::output_to_vtk() const
|
|||
}
|
||||
}
|
||||
|
||||
double source_normalization_factor =
|
||||
compute_fixed_source_normalization_factor();
|
||||
|
||||
// Open file for writing
|
||||
std::FILE* plot = std::fopen(filename.c_str(), "wb");
|
||||
|
||||
|
|
@ -786,7 +853,8 @@ void FlatSourceDomain::output_to_vtk() const
|
|||
std::fprintf(plot, "LOOKUP_TABLE default\n");
|
||||
for (int fsr : voxel_indices) {
|
||||
int64_t source_element = fsr * negroups_ + g;
|
||||
float flux = scalar_flux_final_[source_element];
|
||||
float flux =
|
||||
scalar_flux_final_[source_element] * source_normalization_factor;
|
||||
flux /= (settings::n_batches - settings::n_inactive);
|
||||
flux = convert_to_big_endian<float>(flux);
|
||||
std::fwrite(&flux, sizeof(float), 1, plot);
|
||||
|
|
@ -819,7 +887,8 @@ void FlatSourceDomain::output_to_vtk() const
|
|||
int mat = material_[fsr];
|
||||
for (int g = 0; g < negroups_; g++) {
|
||||
int64_t source_element = fsr * negroups_ + g;
|
||||
float flux = scalar_flux_final_[source_element];
|
||||
float flux =
|
||||
scalar_flux_final_[source_element] * source_normalization_factor;
|
||||
flux /= (settings::n_batches - settings::n_inactive);
|
||||
float Sigma_f = data::mg.macro_xs_[mat].get_xs(
|
||||
MgxsType::FISSION, g, nullptr, nullptr, nullptr, 0, 0);
|
||||
|
|
|
|||
|
|
@ -269,6 +269,10 @@ void get_run_parameters(pugi::xml_node node_base)
|
|||
} else {
|
||||
fatal_error("Specify random ray source in settings XML");
|
||||
}
|
||||
if (check_for_node(random_ray_node, "volume_normalized_flux_tallies")) {
|
||||
FlatSourceDomain::volume_normalized_flux_tallies_ =
|
||||
get_node_value_bool(random_ray_node, "volume_normalized_flux_tallies");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@
|
|||
<parameters>-1.26 -1.26 -1 1.26 1.26 1</parameters>
|
||||
</space>
|
||||
</source>
|
||||
<volume_normalized_flux_tallies>True</volume_normalized_flux_tallies>
|
||||
</random_ray>
|
||||
</settings>
|
||||
<tallies>
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ def random_ray_model() -> openmc.Model:
|
|||
settings.random_ray['distance_active'] = 100.0
|
||||
settings.random_ray['distance_inactive'] = 20.0
|
||||
settings.random_ray['ray_source'] = rr_source
|
||||
settings.random_ray['volume_normalized_flux_tallies'] = True
|
||||
|
||||
###############################################################################
|
||||
# Define tallies
|
||||
|
|
|
|||
1018
tests/regression_tests/random_ray_cube/False_hybrid/inputs_true.dat
Normal file
1018
tests/regression_tests/random_ray_cube/False_hybrid/inputs_true.dat
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,9 @@
|
|||
tally 1:
|
||||
-5.920549E+04
|
||||
2.321317E+09
|
||||
tally 2:
|
||||
4.761087E+02
|
||||
4.909570E+04
|
||||
tally 3:
|
||||
2.206028E+01
|
||||
1.019164E+02
|
||||
1018
tests/regression_tests/random_ray_cube/True_hybrid/inputs_true.dat
Normal file
1018
tests/regression_tests/random_ray_cube/True_hybrid/inputs_true.dat
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,9 @@
|
|||
tally 1:
|
||||
-5.230164E+02
|
||||
1.818988E+05
|
||||
tally 2:
|
||||
3.067508E-02
|
||||
2.037701E-04
|
||||
tally 3:
|
||||
1.941220E-03
|
||||
7.892297E-07
|
||||
0
tests/regression_tests/random_ray_cube/__init__.py
Normal file
0
tests/regression_tests/random_ray_cube/__init__.py
Normal file
231
tests/regression_tests/random_ray_cube/test.py
Normal file
231
tests/regression_tests/random_ray_cube/test.py
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
import os
|
||||
|
||||
import numpy as np
|
||||
import openmc
|
||||
from openmc.utility_funcs import change_directory
|
||||
import pytest
|
||||
|
||||
from tests.testing_harness import TolerantPyAPITestHarness
|
||||
|
||||
# Creates a 3 region cube with different fills in each region
|
||||
def fill_cube(N, n_1, n_2, fill_1, fill_2, fill_3):
|
||||
cube = [[[0 for _ in range(N)] for _ in range(N)] for _ in range(N)]
|
||||
for i in range(N):
|
||||
for j in range(N):
|
||||
for k in range(N):
|
||||
if i < n_1 and j >= (N-n_1) and k < n_1:
|
||||
cube[i][j][k] = fill_1
|
||||
elif i < n_2 and j >= (N-n_2) and k < n_2:
|
||||
cube[i][j][k] = fill_2
|
||||
else:
|
||||
cube[i][j][k] = fill_3
|
||||
return cube
|
||||
|
||||
class MGXSTestHarness(TolerantPyAPITestHarness):
|
||||
def _cleanup(self):
|
||||
super()._cleanup()
|
||||
f = 'mgxs.h5'
|
||||
if os.path.exists(f):
|
||||
os.remove(f)
|
||||
|
||||
def create_random_ray_model(volume_normalize, estimator):
|
||||
openmc.reset_auto_ids()
|
||||
###############################################################################
|
||||
# Create multigroup data
|
||||
|
||||
# Instantiate the energy group data
|
||||
ebins = [1e-5, 20.0e6]
|
||||
groups = openmc.mgxs.EnergyGroups(group_edges=ebins)
|
||||
|
||||
void_sigma_a = 4.0e-6
|
||||
void_sigma_s = 3.0e-4
|
||||
void_mat_data = openmc.XSdata('void', groups)
|
||||
void_mat_data.order = 0
|
||||
void_mat_data.set_total([void_sigma_a + void_sigma_s])
|
||||
void_mat_data.set_absorption([void_sigma_a])
|
||||
void_mat_data.set_scatter_matrix(np.rollaxis(np.array([[[void_sigma_s]]]),0,3))
|
||||
|
||||
absorber_sigma_a = 0.75
|
||||
absorber_sigma_s = 0.25
|
||||
absorber_mat_data = openmc.XSdata('absorber', groups)
|
||||
absorber_mat_data.order = 0
|
||||
absorber_mat_data.set_total([absorber_sigma_a + absorber_sigma_s])
|
||||
absorber_mat_data.set_absorption([absorber_sigma_a])
|
||||
absorber_mat_data.set_scatter_matrix(np.rollaxis(np.array([[[absorber_sigma_s]]]),0,3))
|
||||
|
||||
multiplier = 0.1
|
||||
source_sigma_a = void_sigma_a * multiplier
|
||||
source_sigma_s = void_sigma_s * multiplier
|
||||
source_mat_data = openmc.XSdata('source', groups)
|
||||
source_mat_data.order = 0
|
||||
print(source_sigma_a + source_sigma_s)
|
||||
source_mat_data.set_total([source_sigma_a + source_sigma_s])
|
||||
source_mat_data.set_absorption([source_sigma_a])
|
||||
source_mat_data.set_scatter_matrix(np.rollaxis(np.array([[[source_sigma_s]]]),0,3))
|
||||
|
||||
mg_cross_sections_file = openmc.MGXSLibrary(groups)
|
||||
mg_cross_sections_file.add_xsdatas([source_mat_data, void_mat_data, absorber_mat_data])
|
||||
mg_cross_sections_file.export_to_hdf5()
|
||||
|
||||
###############################################################################
|
||||
# Create materials for the problem
|
||||
|
||||
# Instantiate some Macroscopic Data
|
||||
source_data = openmc.Macroscopic('source')
|
||||
void_data = openmc.Macroscopic('void')
|
||||
absorber_data = openmc.Macroscopic('absorber')
|
||||
|
||||
# Instantiate some Materials and register the appropriate Macroscopic objects
|
||||
source_mat = openmc.Material(name='source')
|
||||
source_mat.set_density('macro', 1.0)
|
||||
source_mat.add_macroscopic(source_data)
|
||||
|
||||
void_mat = openmc.Material(name='void')
|
||||
void_mat.set_density('macro', 1.0)
|
||||
void_mat.add_macroscopic(void_data)
|
||||
|
||||
absorber_mat = openmc.Material(name='absorber')
|
||||
absorber_mat.set_density('macro', 1.0)
|
||||
absorber_mat.add_macroscopic(absorber_data)
|
||||
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials([source_mat, void_mat, absorber_mat])
|
||||
materials_file.cross_sections = "mgxs.h5"
|
||||
|
||||
###############################################################################
|
||||
# Define problem geometry
|
||||
|
||||
source_cell = openmc.Cell(fill=source_mat, name='infinite source region')
|
||||
void_cell = openmc.Cell(fill=void_mat, name='infinite void region')
|
||||
absorber_cell = openmc.Cell(fill=absorber_mat, name='infinite absorber region')
|
||||
|
||||
source_universe = openmc.Universe()
|
||||
source_universe.add_cells([source_cell])
|
||||
|
||||
void_universe = openmc.Universe()
|
||||
void_universe.add_cells([void_cell])
|
||||
|
||||
absorber_universe = openmc.Universe()
|
||||
absorber_universe.add_cells([absorber_cell])
|
||||
|
||||
absorber_width = 30.0
|
||||
n_base = 6
|
||||
|
||||
# This variable can be increased above 1 to refine the FSR mesh resolution further
|
||||
refinement_level = 5
|
||||
|
||||
n = n_base * refinement_level
|
||||
pitch = absorber_width / n
|
||||
|
||||
pattern = fill_cube(n, 1*refinement_level, 5*refinement_level, source_universe, void_universe, absorber_universe)
|
||||
|
||||
lattice = openmc.RectLattice()
|
||||
lattice.lower_left = [0.0, 0.0, 0.0]
|
||||
lattice.pitch = [pitch, pitch, pitch]
|
||||
lattice.universes = pattern
|
||||
#print(lattice)
|
||||
|
||||
lattice_cell = openmc.Cell(fill=lattice)
|
||||
|
||||
lattice_uni = openmc.Universe()
|
||||
lattice_uni.add_cells([lattice_cell])
|
||||
|
||||
x_low = openmc.XPlane(x0=0.0,boundary_type='reflective')
|
||||
x_high = openmc.XPlane(x0=absorber_width,boundary_type='vacuum')
|
||||
|
||||
y_low = openmc.YPlane(y0=0.0,boundary_type='reflective')
|
||||
y_high = openmc.YPlane(y0=absorber_width,boundary_type='vacuum')
|
||||
|
||||
z_low = openmc.ZPlane(z0=0.0,boundary_type='reflective')
|
||||
z_high = openmc.ZPlane(z0=absorber_width,boundary_type='vacuum')
|
||||
|
||||
full_domain = openmc.Cell(fill=lattice_uni, region=+x_low & -x_high & +y_low & -y_high & +z_low & -z_high, name='full domain')
|
||||
|
||||
root = openmc.Universe(name='root universe')
|
||||
root.add_cell(full_domain)
|
||||
|
||||
# Create a geometry with the two cells and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
|
||||
###############################################################################
|
||||
# Define problem settings
|
||||
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings = openmc.Settings()
|
||||
settings.energy_mode = "multi-group"
|
||||
settings.inactive = 5
|
||||
settings.batches = 10
|
||||
settings.particles = 90
|
||||
settings.run_mode = 'fixed source'
|
||||
|
||||
# Create an initial uniform spatial source for ray integration
|
||||
lower_left_ray = [0.0, 0.0, 0.0]
|
||||
upper_right_ray = [absorber_width, absorber_width, absorber_width]
|
||||
uniform_dist_ray = openmc.stats.Box(lower_left_ray, upper_right_ray, only_fissionable=False)
|
||||
rr_source = openmc.IndependentSource(space=uniform_dist_ray)
|
||||
|
||||
settings.random_ray['distance_active'] = 500.0
|
||||
settings.random_ray['distance_inactive'] = 100.0
|
||||
settings.random_ray['ray_source'] = rr_source
|
||||
settings.random_ray['volume_normalized_flux_tallies'] = volume_normalize
|
||||
|
||||
#settings.random_ray['volume_estimator'] = estimator
|
||||
|
||||
# Create the neutron source in the bottom right of the moderator
|
||||
strengths = [1.0] # Good - fast group appears largest (besides most thermal)
|
||||
midpoints = [100.0]
|
||||
energy_distribution = openmc.stats.Discrete(x=midpoints,p=strengths)
|
||||
|
||||
source = openmc.IndependentSource(energy=energy_distribution, constraints={'domains':[source_universe]}, strength=3.14)
|
||||
|
||||
settings.source = [source]
|
||||
|
||||
###############################################################################
|
||||
# Define tallies
|
||||
|
||||
estimator = 'tracklength'
|
||||
|
||||
absorber_filter = openmc.MaterialFilter(absorber_mat)
|
||||
absorber_tally = openmc.Tally(name="Absorber Tally")
|
||||
absorber_tally.filters = [absorber_filter]
|
||||
absorber_tally.scores = ['flux']
|
||||
absorber_tally.estimator = estimator
|
||||
|
||||
void_filter = openmc.MaterialFilter(void_mat)
|
||||
void_tally = openmc.Tally(name="Void Tally")
|
||||
void_tally.filters = [void_filter]
|
||||
void_tally.scores = ['flux']
|
||||
void_tally.estimator = estimator
|
||||
|
||||
source_filter = openmc.MaterialFilter(source_mat)
|
||||
source_tally = openmc.Tally(name="Source Tally")
|
||||
source_tally.filters = [source_filter]
|
||||
source_tally.scores = ['flux']
|
||||
source_tally.estimator = estimator
|
||||
|
||||
# Instantiate a Tallies collection and export to XML
|
||||
tallies = openmc.Tallies([source_tally, void_tally, absorber_tally])
|
||||
|
||||
###############################################################################
|
||||
# Assmble Model
|
||||
|
||||
model = openmc.model.Model()
|
||||
model.geometry = geometry
|
||||
model.materials = materials_file
|
||||
model.settings = settings
|
||||
model.xs_data = mg_cross_sections_file
|
||||
model.tallies = tallies
|
||||
|
||||
return model
|
||||
|
||||
@pytest.mark.parametrize("volume_normalize, estimator", [
|
||||
(False, "hybrid"),
|
||||
(True, "hybrid")
|
||||
])
|
||||
def test_random_ray_cube(volume_normalize, estimator):
|
||||
# Generating a unique directory name from the parameters
|
||||
directory_name = f"{volume_normalize}_{estimator}"
|
||||
with change_directory(directory_name):
|
||||
model = create_random_ray_model(volume_normalize, estimator)
|
||||
harness = MGXSTestHarness('statepoint.10.h5', model)
|
||||
harness.main()
|
||||
|
|
@ -153,6 +153,7 @@
|
|||
<random_ray>
|
||||
<distance_active>400.0</distance_active>
|
||||
<distance_inactive>100.0</distance_inactive>
|
||||
<volume_normalized_flux_tallies>False</volume_normalized_flux_tallies>
|
||||
<source particle="neutron" strength="1.0" type="independent">
|
||||
<space type="box">
|
||||
<parameters>0.0 0.0 0.0 60.0 100.0 60.0</parameters>
|
||||
|
|
|
|||
|
|
@ -1,47 +1,47 @@
|
|||
tally 1:
|
||||
3.751048E+01
|
||||
3.751047E+01
|
||||
2.841797E+02
|
||||
9.930788E+00
|
||||
1.988180E+01
|
||||
3.781121E+00
|
||||
3.005165E+00
|
||||
2.383139E+00
|
||||
1.232560E+00
|
||||
1.561884E+00
|
||||
6.440577E-01
|
||||
1.089787E+00
|
||||
3.724896E-01
|
||||
6.608456E-01
|
||||
1.285592E-01
|
||||
2.372611E-01
|
||||
1.601299E-02
|
||||
7.814803E-02
|
||||
1.765829E-03
|
||||
2.862108E-02
|
||||
2.460129E-04
|
||||
1.000671E+01
|
||||
2.020214E+01
|
||||
3.979569E+00
|
||||
3.330838E+00
|
||||
2.552971E+00
|
||||
1.407542E+00
|
||||
1.736764E+00
|
||||
7.948004E-01
|
||||
1.178834E+00
|
||||
4.328006E-01
|
||||
6.953895E-01
|
||||
1.408391E-01
|
||||
2.389347E-01
|
||||
1.617450E-02
|
||||
8.128516E-02
|
||||
1.903860E-03
|
||||
2.764062E-02
|
||||
2.285458E-04
|
||||
tally 2:
|
||||
1.089787E+00
|
||||
3.724896E-01
|
||||
3.767926E-01
|
||||
3.724399E-02
|
||||
8.614121E-02
|
||||
1.526889E-03
|
||||
3.610725E-02
|
||||
2.629885E-04
|
||||
1.466261E-02
|
||||
4.536997E-05
|
||||
4.653106E-03
|
||||
4.381672E-06
|
||||
1.178834E+00
|
||||
4.328006E-01
|
||||
3.982124E-01
|
||||
4.138078E-02
|
||||
9.676374E-02
|
||||
1.919297E-03
|
||||
3.944531E-02
|
||||
3.133733E-04
|
||||
1.554518E-02
|
||||
5.084822E-05
|
||||
4.815079E-03
|
||||
4.681450E-06
|
||||
tally 3:
|
||||
1.617918E-03
|
||||
6.317049E-07
|
||||
1.161473E-03
|
||||
2.789553E-07
|
||||
1.198879E-03
|
||||
3.189531E-07
|
||||
1.031737E-03
|
||||
2.207381E-07
|
||||
5.466329E-04
|
||||
6.166808E-08
|
||||
2.146062E-04
|
||||
9.937520E-09
|
||||
1.635823E-03
|
||||
6.482611E-07
|
||||
1.248235E-03
|
||||
3.227247E-07
|
||||
1.248195E-03
|
||||
3.488233E-07
|
||||
1.030935E-03
|
||||
2.206418E-07
|
||||
5.670315E-04
|
||||
6.648507E-08
|
||||
2.393638E-04
|
||||
1.242517E-08
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@
|
|||
<random_ray>
|
||||
<distance_active>400.0</distance_active>
|
||||
<distance_inactive>100.0</distance_inactive>
|
||||
<volume_normalized_flux_tallies>False</volume_normalized_flux_tallies>
|
||||
<source particle="neutron" strength="1.0" type="independent">
|
||||
<space type="box">
|
||||
<parameters>0.0 0.0 0.0 60.0 100.0 60.0</parameters>
|
||||
|
|
|
|||
|
|
@ -1,47 +1,47 @@
|
|||
tally 1:
|
||||
3.751047E+01
|
||||
2.841797E+02
|
||||
9.930788E+00
|
||||
1.988181E+01
|
||||
3.781121E+00
|
||||
3.005165E+00
|
||||
2.383139E+00
|
||||
1.232560E+00
|
||||
1.561884E+00
|
||||
6.440577E-01
|
||||
1.089787E+00
|
||||
3.724896E-01
|
||||
6.608456E-01
|
||||
1.285592E-01
|
||||
2.372611E-01
|
||||
1.601299E-02
|
||||
7.814803E-02
|
||||
1.765829E-03
|
||||
2.862108E-02
|
||||
2.460129E-04
|
||||
1.000671E+01
|
||||
2.020214E+01
|
||||
3.979569E+00
|
||||
3.330838E+00
|
||||
2.552971E+00
|
||||
1.407542E+00
|
||||
1.736764E+00
|
||||
7.948004E-01
|
||||
1.178834E+00
|
||||
4.328006E-01
|
||||
6.953895E-01
|
||||
1.408391E-01
|
||||
2.389347E-01
|
||||
1.617450E-02
|
||||
8.128516E-02
|
||||
1.903860E-03
|
||||
2.764062E-02
|
||||
2.285458E-04
|
||||
tally 2:
|
||||
1.089787E+00
|
||||
3.724896E-01
|
||||
3.767925E-01
|
||||
3.724398E-02
|
||||
8.614120E-02
|
||||
1.526889E-03
|
||||
3.610725E-02
|
||||
2.629885E-04
|
||||
1.466261E-02
|
||||
4.536997E-05
|
||||
4.653106E-03
|
||||
4.381672E-06
|
||||
1.178834E+00
|
||||
4.328006E-01
|
||||
3.982124E-01
|
||||
4.138078E-02
|
||||
9.676374E-02
|
||||
1.919297E-03
|
||||
3.944531E-02
|
||||
3.133733E-04
|
||||
1.554518E-02
|
||||
5.084822E-05
|
||||
4.815079E-03
|
||||
4.681450E-06
|
||||
tally 3:
|
||||
1.617918E-03
|
||||
6.317049E-07
|
||||
1.161473E-03
|
||||
2.789553E-07
|
||||
1.198879E-03
|
||||
3.189531E-07
|
||||
1.031737E-03
|
||||
2.207381E-07
|
||||
5.466329E-04
|
||||
6.166809E-08
|
||||
2.146062E-04
|
||||
9.937520E-09
|
||||
1.635823E-03
|
||||
6.482611E-07
|
||||
1.248235E-03
|
||||
3.227247E-07
|
||||
1.248195E-03
|
||||
3.488233E-07
|
||||
1.030935E-03
|
||||
2.206418E-07
|
||||
5.670315E-04
|
||||
6.648507E-08
|
||||
2.393638E-04
|
||||
1.242517E-08
|
||||
|
|
|
|||
|
|
@ -251,6 +251,7 @@ def create_random_ray_model(domain_type):
|
|||
|
||||
settings.random_ray['distance_active'] = 400.0
|
||||
settings.random_ray['distance_inactive'] = 100.0
|
||||
settings.random_ray['volume_normalized_flux_tallies'] = False
|
||||
|
||||
# Create an initial uniform spatial source for ray integration
|
||||
lower_left = (0.0, 0.0, 0.0)
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@
|
|||
<random_ray>
|
||||
<distance_active>400.0</distance_active>
|
||||
<distance_inactive>100.0</distance_inactive>
|
||||
<volume_normalized_flux_tallies>False</volume_normalized_flux_tallies>
|
||||
<source particle="neutron" strength="1.0" type="independent">
|
||||
<space type="box">
|
||||
<parameters>0.0 0.0 0.0 60.0 100.0 60.0</parameters>
|
||||
|
|
|
|||
|
|
@ -1,47 +1,47 @@
|
|||
tally 1:
|
||||
3.751047E+01
|
||||
2.841797E+02
|
||||
9.930788E+00
|
||||
1.988180E+01
|
||||
3.781121E+00
|
||||
3.005165E+00
|
||||
2.383139E+00
|
||||
1.232560E+00
|
||||
1.561884E+00
|
||||
6.440577E-01
|
||||
1.089787E+00
|
||||
3.724896E-01
|
||||
6.608456E-01
|
||||
1.285592E-01
|
||||
2.372611E-01
|
||||
1.601299E-02
|
||||
7.814803E-02
|
||||
1.765829E-03
|
||||
2.862107E-02
|
||||
2.460129E-04
|
||||
1.000671E+01
|
||||
2.020214E+01
|
||||
3.979569E+00
|
||||
3.330838E+00
|
||||
2.552971E+00
|
||||
1.407542E+00
|
||||
1.736764E+00
|
||||
7.948004E-01
|
||||
1.178834E+00
|
||||
4.328006E-01
|
||||
6.953895E-01
|
||||
1.408391E-01
|
||||
2.389347E-01
|
||||
1.617450E-02
|
||||
8.128516E-02
|
||||
1.903860E-03
|
||||
2.764062E-02
|
||||
2.285458E-04
|
||||
tally 2:
|
||||
1.089787E+00
|
||||
3.724896E-01
|
||||
3.767926E-01
|
||||
3.724399E-02
|
||||
8.614120E-02
|
||||
1.526889E-03
|
||||
3.610725E-02
|
||||
2.629885E-04
|
||||
1.466261E-02
|
||||
4.536997E-05
|
||||
4.653106E-03
|
||||
4.381672E-06
|
||||
1.178834E+00
|
||||
4.328006E-01
|
||||
3.982124E-01
|
||||
4.138078E-02
|
||||
9.676374E-02
|
||||
1.919297E-03
|
||||
3.944531E-02
|
||||
3.133733E-04
|
||||
1.554518E-02
|
||||
5.084822E-05
|
||||
4.815079E-03
|
||||
4.681450E-06
|
||||
tally 3:
|
||||
1.617918E-03
|
||||
6.317049E-07
|
||||
1.161473E-03
|
||||
2.789553E-07
|
||||
1.198879E-03
|
||||
3.189531E-07
|
||||
1.031737E-03
|
||||
2.207381E-07
|
||||
5.466329E-04
|
||||
6.166808E-08
|
||||
2.146062E-04
|
||||
9.937520E-09
|
||||
1.635823E-03
|
||||
6.482611E-07
|
||||
1.248235E-03
|
||||
3.227247E-07
|
||||
1.248195E-03
|
||||
3.488233E-07
|
||||
1.030935E-03
|
||||
2.206418E-07
|
||||
5.670315E-04
|
||||
6.648507E-08
|
||||
2.393638E-04
|
||||
1.242517E-08
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@
|
|||
<parameters>-1.26 -1.26 -1 1.26 1.26 1</parameters>
|
||||
</space>
|
||||
</source>
|
||||
<volume_normalized_flux_tallies>True</volume_normalized_flux_tallies>
|
||||
</random_ray>
|
||||
</settings>
|
||||
<tallies>
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ def random_ray_model() -> openmc.Model:
|
|||
settings.random_ray['distance_active'] = 100.0
|
||||
settings.random_ray['distance_inactive'] = 20.0
|
||||
settings.random_ray['ray_source'] = rr_source
|
||||
settings.random_ray['volume_normalized_flux_tallies'] = True
|
||||
|
||||
###############################################################################
|
||||
# Define tallies
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue