mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 14:15:42 -04:00
Implement mesh-based weight windows (squashed)
Co-authored-by: Andrew Davis <andrew.davis@ukaea.uk> Co-authored-by: Patrick Shriwise <pshriwise@gmail.com> Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
This commit is contained in:
parent
d12e390f1a
commit
e08af3c374
24 changed files with 1690 additions and 12 deletions
|
|
@ -361,6 +361,7 @@ list(APPEND libopenmc_SOURCES
|
|||
src/track_output.cpp
|
||||
src/urr.cpp
|
||||
src/volume_calc.cpp
|
||||
src/weight_windows.cpp
|
||||
src/wmp.cpp
|
||||
src/xml_interface.cpp
|
||||
src/xsdata.cpp)
|
||||
|
|
|
|||
|
|
@ -1007,3 +1007,170 @@ sub-elements/attributes:
|
|||
sample points within.
|
||||
|
||||
*Default*: None
|
||||
|
||||
-------------------------
|
||||
``<weightwindow>`` Element
|
||||
-------------------------
|
||||
|
||||
The ``<weightwindow>`` element specifies all necessary parameters for weight
|
||||
window mesh function.This element has the following sub-elements/attributes:
|
||||
|
||||
:type:
|
||||
This input indicates where the space-energy cell boundary and lower weight
|
||||
window bound should read from. 0 means read these from the settings.xml, 1
|
||||
means read these from MCNP WWINP file. This input is necessary for weight
|
||||
window mesh function to be used.
|
||||
|
||||
*Default*: None
|
||||
|
||||
:origin:
|
||||
The lower-left coordinates of weight window mesh.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 0 0 0
|
||||
|
||||
:xmesh:
|
||||
The locations of the coarse meshes in the X direction.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 10 20
|
||||
|
||||
:xints:
|
||||
The number of fine meshes within corresponding coarse meshes in the X direction.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 10 20
|
||||
|
||||
:ymesh:
|
||||
The locations of the coarse meshes in the Y direction.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 10 20
|
||||
|
||||
:yints:
|
||||
The number of fine meshes within corresponding coarse meshes in the Y direction.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 10 20
|
||||
|
||||
:zmesh:
|
||||
The locations of the coarse meshes in the Z direction.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 10 20
|
||||
|
||||
:zints:
|
||||
The number of fine meshes within corresponding coarse meshes in the Z direction.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 10 20
|
||||
|
||||
:energy:
|
||||
The energy groups for neutron and/or photon in eV.
|
||||
|
||||
:neutron:
|
||||
The energy groups for neutron in eV.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 1e6 2e6 10e6
|
||||
|
||||
:photon:
|
||||
The energy groups for photon in eV.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*: 1e6 5e6
|
||||
|
||||
:lower_ww:
|
||||
The lower weight window bound for weight window mesh to be used.
|
||||
|
||||
*Default*: None
|
||||
|
||||
*Example*:
|
||||
[x0,y0,z0,E0] ...... [xn,y0,z0,E0] Index of X increasing first
|
||||
|
||||
...
|
||||
|
||||
[x0,y1,z0,E0] ...... [xn,y1,z0,E0] Index of Y increasing second
|
||||
|
||||
...
|
||||
|
||||
[x0,y0,z1,E0] ...... [xn,yn,z1,E0] Index of Z increasing third
|
||||
|
||||
...
|
||||
|
||||
[x0,y0,z0,E1] ...... [xn,yn,zn,E1] Index of Energy increasing forth
|
||||
|
||||
.. note:: All these sub-elements (from ``<origin>`` to ``<lower_ww>``) are only
|
||||
valide for ``<type>`` 0. ``<type>`` 1 will read all these necessary
|
||||
parameters from MCNP wwinp file, which should named as ``wwinp``.
|
||||
The examples above indicate that there are 10 fine meshes in 0~10 cm
|
||||
and 10 fine meshes in 10~20 cm at all 3 dimensions, and 3 energy
|
||||
groups (0~1e6, 1e6~2e6, 2e6~10e6) for neutron and 2 energy groups
|
||||
(0~1e6, 1e6~5e6) for photon.
|
||||
|
||||
:neutron_parameters:
|
||||
The weight window parameters for neutron.
|
||||
|
||||
:upper:
|
||||
The ratio of upper weight window bound and lower weight window bound.
|
||||
|
||||
*Default*: 5
|
||||
|
||||
:survival:
|
||||
The ratio of survival weight and lower weight window bound.
|
||||
|
||||
*Default*: 3
|
||||
|
||||
:max_split:
|
||||
The max number of split particles.
|
||||
|
||||
*Default*: 5
|
||||
|
||||
:multiplier:
|
||||
The multiplier for all lower weight window bounds.
|
||||
|
||||
*Default*: 1
|
||||
|
||||
:photon_parameters:
|
||||
The weight window parameters for photon.
|
||||
|
||||
:upper:
|
||||
The ratio of upper weight window bound and lower weight window bound.
|
||||
|
||||
*Default*: 5
|
||||
|
||||
:survival:
|
||||
The ratio of survival weight and lower weight window bound.
|
||||
|
||||
*Default*: 3
|
||||
|
||||
:max_split:
|
||||
The max number of split particles.
|
||||
|
||||
*Default*: 5
|
||||
|
||||
:multiplier:
|
||||
The multiplier for all lower weight window bounds.
|
||||
|
||||
*Default*: 1
|
||||
|
||||
:user_defined_biasing:
|
||||
The usder defined weight biasing in energy.
|
||||
|
||||
:biasing_energy:
|
||||
The energy groups for source.
|
||||
|
||||
:origin_probability:
|
||||
The origin probability for each energy groups.
|
||||
|
||||
:biasing:
|
||||
The biasing probability for each energy groups.
|
||||
|
|
|
|||
|
|
@ -358,6 +358,10 @@ constexpr int CMFD_NOACCEL {-1};
|
|||
|
||||
enum class GeometryType { CSG, DAG };
|
||||
|
||||
//==============================================================================
|
||||
// Variance Reduction constants
|
||||
constexpr double WEIGHT_CUTOFF {1.0e-38}; // default low weight cutoff
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_CONSTANTS_H
|
||||
|
|
|
|||
|
|
@ -305,6 +305,9 @@ private:
|
|||
|
||||
int n_event_ {0}; // number of events executed in this particle's history
|
||||
|
||||
// Weight window information
|
||||
int n_split_ {0}; // Number of splits this particle has undergone
|
||||
|
||||
// DagMC state variables
|
||||
#ifdef DAGMC
|
||||
moab::DagMC::RayHistory history_;
|
||||
|
|
@ -426,6 +429,9 @@ public:
|
|||
double& collision_distance() { return collision_distance_; }
|
||||
int& n_event() { return n_event_; }
|
||||
|
||||
int n_split() const { return n_split_; }
|
||||
int& n_split() { return n_split_; }
|
||||
|
||||
#ifdef DAGMC
|
||||
moab::DagMC::RayHistory& history() { return history_; }
|
||||
Direction& last_dir() { return last_dir_; }
|
||||
|
|
|
|||
|
|
@ -89,6 +89,11 @@ void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p);
|
|||
|
||||
void sample_secondary_photons(Particle& p, int i_nuclide);
|
||||
|
||||
//!Split or Roulette particles based their weight and the lower weight window
|
||||
// bound.
|
||||
//! \param[in] p, particle to be split or rouletted with the weight window.
|
||||
void split_particle(Particle& p);
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_PHYSICS_H
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ extern "C" bool trigger_on; //!< tally triggers enabled?
|
|||
extern bool trigger_predict; //!< predict batches for triggers?
|
||||
extern bool ufs_on; //!< uniform fission site method on?
|
||||
extern bool urr_ptables_on; //!< use unresolved resonance prob. tables?
|
||||
extern bool weight_windows_on; //!< are weight windows are enabled?
|
||||
extern bool write_all_tracks; //!< write track files for every particle?
|
||||
extern bool write_initial_source; //!< write out initial source file?
|
||||
|
||||
|
|
@ -99,6 +100,7 @@ extern std::unordered_set<int>
|
|||
statepoint_batch; //!< Batches when state should be written
|
||||
extern std::unordered_set<int>
|
||||
source_write_surf_id; //!< Surface ids where sources will be written
|
||||
extern int max_splits; //!< maximum number of particle splits for weight windows
|
||||
extern int64_t max_surface_particles; //!< maximum number of particles to be
|
||||
//!< banked on surfaces per process
|
||||
extern TemperatureMethod
|
||||
|
|
|
|||
95
include/openmc/weight_windows.h
Normal file
95
include/openmc/weight_windows.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#ifndef OPENMC_WEIGHT_WINDOWS_H
|
||||
#define OPENMC_WEIGHT_WINDOWS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <hdf5.h>
|
||||
#include <pugixml.hpp>
|
||||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/memory.h"
|
||||
#include "openmc/mesh.h"
|
||||
#include "openmc/particle.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// Non-member functions
|
||||
//==============================================================================
|
||||
|
||||
//! Free memory associated with weight windows
|
||||
void free_memory_weight_windows();
|
||||
|
||||
//==============================================================================
|
||||
// Global variables
|
||||
//==============================================================================
|
||||
|
||||
class WeightWindows;
|
||||
|
||||
namespace variance_reduction {
|
||||
|
||||
extern std::unordered_map<int32_t, int32_t> ww_map;
|
||||
extern vector<unique_ptr<WeightWindows>> weight_windows;
|
||||
|
||||
} // namespace variance_reduction
|
||||
|
||||
//==============================================================================
|
||||
//! Individual weight window information
|
||||
//==============================================================================
|
||||
|
||||
struct WeightWindow {
|
||||
double lower_weight {-1}; // -1 indicates not valid state
|
||||
double upper_weight {1};
|
||||
double survival_weight {0.5};
|
||||
double weight_cutoff {WEIGHT_CUTOFF};
|
||||
int max_split {1};
|
||||
|
||||
//! Whether the weight window is in a valid state
|
||||
operator bool() const { return lower_weight >= 0.0; }
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Weight window settings
|
||||
//==============================================================================
|
||||
|
||||
class WeightWindows {
|
||||
public:
|
||||
// Constructors
|
||||
WeightWindows();
|
||||
WeightWindows(pugi::xml_node node);
|
||||
|
||||
// Methods
|
||||
|
||||
//! Set the weight window ID
|
||||
void set_id(int32_t id = -1);
|
||||
|
||||
// NOTE: This is unused for now but may be used in the future
|
||||
//! Write weight window settings to an HDF5 file
|
||||
//! \param[in] group HDF5 group to write to
|
||||
void to_hdf5(hid_t group) const;
|
||||
|
||||
//! Return a weight window at the specified index
|
||||
//! \param[in] p Particle to get weight window for
|
||||
WeightWindow get_weight_window(const Particle& p) const;
|
||||
|
||||
// Accessors
|
||||
int32_t id() const { return id_; }
|
||||
const Mesh& mesh() const { return *model::meshes[mesh_idx_]; }
|
||||
|
||||
private:
|
||||
// Data members
|
||||
int32_t id_; //!< Unique ID
|
||||
ParticleType particle_type_; //!< Particle type to apply weight windows to
|
||||
vector<double> energy_bins_; //!< Energy bins [eV]
|
||||
vector<double> lower_ww_; //!< Lower weight window bounds
|
||||
vector<double> upper_ww_; //!< Upper weight window bounds
|
||||
double survival_ratio_; //!< Survival weight ratio
|
||||
double weight_cutoff_; //!< Weight cutoff
|
||||
int max_split_; //!< Maximum value for particle splitting
|
||||
int32_t mesh_idx_; //!< index in meshes vector
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
#endif // OPENMC_WEIGHT_WINDOWS_H
|
||||
|
|
@ -11,6 +11,7 @@ from openmc.plots import *
|
|||
from openmc.region import *
|
||||
from openmc.volume import *
|
||||
from openmc.source import *
|
||||
from openmc.weight_windows import *
|
||||
from openmc.settings import *
|
||||
from openmc.surface import *
|
||||
from openmc.universe import *
|
||||
|
|
|
|||
|
|
@ -84,6 +84,32 @@ class MeshBase(IDManagerMixin, ABC):
|
|||
else:
|
||||
raise ValueError('Unrecognized mesh type: "' + mesh_type + '"')
|
||||
|
||||
@classmethod
|
||||
def from_xml(cls, elem):
|
||||
"""Generates a mesh from an XML element
|
||||
|
||||
Parameters
|
||||
----------
|
||||
elem : xml.etree.ElementTree.Element
|
||||
XML element
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.MeshBase
|
||||
an openmc mesh object
|
||||
|
||||
"""
|
||||
mesh_type = get_text(elem, 'type')
|
||||
|
||||
if mesh_type == 'regular' or mesh_type is None:
|
||||
return RegularMesh.from_xml_element(elem)
|
||||
elif mesh_type == 'rectilinear':
|
||||
return RectilinearMesh.from_xml_element(elem)
|
||||
elif mesh_type == 'unstructured':
|
||||
return UnstructuredMesh.from_xml_element(elem)
|
||||
else:
|
||||
raise ValueError(f'Unrecognized mesh type "{mesh_type}" found.')
|
||||
|
||||
|
||||
class RegularMesh(MeshBase):
|
||||
"""A regular Cartesian mesh in one, two, or three dimensions
|
||||
|
|
@ -301,7 +327,6 @@ class RegularMesh(MeshBase):
|
|||
if self._upper_right is not None:
|
||||
subelement = ET.SubElement(element, "upper_right")
|
||||
subelement.text = ' '.join(map(str, self._upper_right))
|
||||
|
||||
if self._width is not None:
|
||||
subelement = ET.SubElement(element, "width")
|
||||
subelement.text = ' '.join(map(str, self._width))
|
||||
|
|
@ -570,19 +595,19 @@ class RectilinearMesh(MeshBase):
|
|||
fmt = '{0: <16}{1}{2}\n'
|
||||
string = super().__repr__()
|
||||
string += fmt.format('\tDimensions', '=\t', self.n_dimension)
|
||||
x_grid_str = str(self._x_grid) if not self._x_grid else len(self._x_grid)
|
||||
x_grid_str = str(self._x_grid) if self._x_grid is None else len(self._x_grid)
|
||||
string += fmt.format('\tN X pnts:', '=\t', x_grid_str)
|
||||
if self._x_grid:
|
||||
if self._x_grid is not None:
|
||||
string += fmt.format('\tX Min:', '=\t', self._x_grid[0])
|
||||
string += fmt.format('\tX Max:', '=\t', self._x_grid[-1])
|
||||
y_grid_str = str(self._y_grid) if not self._y_grid else len(self._y_grid)
|
||||
y_grid_str = str(self._y_grid) if self._y_grid is None else len(self._y_grid)
|
||||
string += fmt.format('\tN Y pnts:', '=\t', y_grid_str)
|
||||
if self._y_grid:
|
||||
if self._y_grid is not None:
|
||||
string += fmt.format('\tY Min:', '=\t', self._y_grid[0])
|
||||
string += fmt.format('\tY Max:', '=\t', self._y_grid[-1])
|
||||
z_grid_str = str(self._z_grid) if not self._z_grid else len(self._z_grid)
|
||||
z_grid_str = str(self._z_grid) if self._z_grid is None else len(self._z_grid)
|
||||
string += fmt.format('\tN Z pnts:', '=\t', z_grid_str)
|
||||
if self._z_grid:
|
||||
if self._z_grid is not None:
|
||||
string += fmt.format('\tZ Min:', '=\t', self._z_grid[0])
|
||||
string += fmt.format('\tZ Max:', '=\t', self._z_grid[-1])
|
||||
return string
|
||||
|
|
@ -599,6 +624,29 @@ class RectilinearMesh(MeshBase):
|
|||
|
||||
return mesh
|
||||
|
||||
@classmethod
|
||||
def from_xml_element(cls, elem):
|
||||
"""Generate a rectilinear mesh from an XML element
|
||||
|
||||
Parameters
|
||||
----------
|
||||
elem : xml.etree.ElementTree.Element
|
||||
XML element
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.RectilinearMesh
|
||||
Rectilinear mesh object
|
||||
|
||||
"""
|
||||
id = int(get_text(elem, 'id'))
|
||||
mesh = cls(id)
|
||||
mesh.x_grid = [float(x) for x in get_text(elem, 'x_grid').split()]
|
||||
mesh.y_grid = [float(y) for y in get_text(elem, 'y_grid').split()]
|
||||
mesh.z_grid = [float(z) for z in get_text(elem, 'z_grid').split()]
|
||||
|
||||
return mesh
|
||||
|
||||
def to_xml_element(self):
|
||||
"""Return XML representation of the mesh
|
||||
|
||||
|
|
@ -911,4 +959,4 @@ class UnstructuredMesh(MeshBase):
|
|||
library = get_text(elem, 'library')
|
||||
length_multiplier = float(get_text(elem, 'length_multiplier', 1.0))
|
||||
|
||||
return cls(filename, library, mesh_id, '', length_multiplier)
|
||||
return cls(filename, library, mesh_id, '', length_multiplier)
|
||||
|
|
@ -6,7 +6,7 @@ from xml.etree import ElementTree as ET
|
|||
from math import ceil
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from . import VolumeCalculation, Source, RegularMesh
|
||||
from . import VolumeCalculation, Source, RegularMesh, WeightWindows
|
||||
from ._xml import clean_indentation, get_text, reorder_attributes
|
||||
|
||||
|
||||
|
|
@ -96,6 +96,10 @@ class Settings:
|
|||
.. versionadded:: 0.12
|
||||
max_order : None or int
|
||||
Maximum scattering order to apply globally when in multi-group mode.
|
||||
max_splits : int
|
||||
Maximum number of times a particle can split during a history
|
||||
|
||||
.. versionadded:: 0.13
|
||||
no_reduce : bool
|
||||
Indicate that all user-defined and global tallies should not be reduced
|
||||
across processes in a parallel calculation.
|
||||
|
|
@ -197,9 +201,16 @@ class Settings:
|
|||
described in :ref:`verbosity`.
|
||||
volume_calculations : VolumeCalculation or iterable of VolumeCalculation
|
||||
Stochastic volume calculation specifications
|
||||
weight_windows : iterable of openmc.WeightWindows
|
||||
Weight windows to use for variance reduction
|
||||
|
||||
.. versionadded:: 0.13
|
||||
weight_windows_on : bool
|
||||
Whether weight windows are enabled
|
||||
|
||||
.. versionadded:: 0.13
|
||||
write_initial_source : bool
|
||||
Indicate whether to write the initial source distribution to file
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -272,6 +283,9 @@ class Settings:
|
|||
self._event_based = None
|
||||
self._max_particles_in_flight = None
|
||||
self._write_initial_source = None
|
||||
self._weight_windows = cv.CheckedList(Source, 'weight windows')
|
||||
self._weight_windows_on = None
|
||||
self._max_splits = None
|
||||
|
||||
@property
|
||||
def run_mode(self):
|
||||
|
|
@ -445,6 +459,18 @@ class Settings:
|
|||
def write_initial_source(self):
|
||||
return self._write_initial_source
|
||||
|
||||
@property
|
||||
def weight_windows(self):
|
||||
return self._weight_windows
|
||||
|
||||
@property
|
||||
def weight_windows_on(self):
|
||||
return self._weight_windows_on
|
||||
|
||||
@property
|
||||
def max_splits(self):
|
||||
return self._max_splits
|
||||
|
||||
@run_mode.setter
|
||||
def run_mode(self, run_mode):
|
||||
cv.check_value('run mode', run_mode, {x.value for x in RunMode})
|
||||
|
|
@ -835,6 +861,23 @@ class Settings:
|
|||
cv.check_type('write initial source', value, bool)
|
||||
self._write_initial_source = value
|
||||
|
||||
@weight_windows.setter
|
||||
def weight_windows(self, value):
|
||||
if not isinstance(value, MutableSequence):
|
||||
value = [value]
|
||||
self._weight_windows = cv.CheckedList(WeightWindows, 'weight windows', value)
|
||||
|
||||
@weight_windows_on.setter
|
||||
def weight_windows_on(self, value):
|
||||
cv.check_type('weight windows on', value, bool)
|
||||
self._weight_windows_on = value
|
||||
|
||||
@max_splits.setter
|
||||
def max_splits(self, value):
|
||||
cv.check_type('maximum particle splits', value, Integral)
|
||||
cv.check_greater_than('max particles in flight', value, 0)
|
||||
self._max_splits = value
|
||||
|
||||
def _create_run_mode_subelement(self, root):
|
||||
elem = ET.SubElement(root, "run_mode")
|
||||
elem.text = self._run_mode.value
|
||||
|
|
@ -1128,6 +1171,25 @@ class Settings:
|
|||
elem = ET.SubElement(root, "write_initial_source")
|
||||
elem.text = str(self._write_initial_source).lower()
|
||||
|
||||
def _create_weight_windows_subelement(self, root):
|
||||
for ww in self._weight_windows:
|
||||
# Add weight window information
|
||||
root.append(ww.to_xml_element())
|
||||
|
||||
# See if a <mesh> element already exists -- if not, add it
|
||||
path = f"./mesh[@id='{ww.mesh.id}']"
|
||||
if root.find(path) is None:
|
||||
root.append(ww.mesh.to_xml_element())
|
||||
|
||||
if self._weight_windows_on is not None:
|
||||
elem = ET.SubElement(root, "weight_windows_on")
|
||||
elem.text = str(self._weight_windows_on).lower()
|
||||
|
||||
def _create_max_splits_subelement(self, root):
|
||||
if self._max_splits is not None:
|
||||
elem = ET.SubElement(root, "max_splits")
|
||||
elem.text = str(self._max_splits)
|
||||
|
||||
def _eigenvalue_from_xml_element(self, root):
|
||||
elem = root.find('eigenvalue')
|
||||
if elem is not None:
|
||||
|
|
@ -1410,6 +1472,20 @@ class Settings:
|
|||
if text is not None:
|
||||
self.write_initial_source = text in ('true', '1')
|
||||
|
||||
def _weight_windows_from_xml_element(self, root):
|
||||
for elem in root.findall('weight_windows'):
|
||||
ww = WeightWindows.from_xml_element(elem, root)
|
||||
self.weight_windows.append(ww)
|
||||
|
||||
text = get_text(root, 'weight_windows_on')
|
||||
if text is not None:
|
||||
self.weight_windows_on = text in ('true', '1')
|
||||
|
||||
def _max_splits_from_xml_element(self, root):
|
||||
text = get_text(root, 'max_splits')
|
||||
if text is not None:
|
||||
self.max_splits = int(text)
|
||||
|
||||
def export_to_xml(self, path='settings.xml'):
|
||||
"""Export simulation settings to an XML file.
|
||||
|
||||
|
|
@ -1464,6 +1540,8 @@ class Settings:
|
|||
self._create_material_cell_offsets_subelement(root_element)
|
||||
self._create_log_grid_bins_subelement(root_element)
|
||||
self._create_write_initial_source_subelement(root_element)
|
||||
self._create_weight_windows_subelement(root_element)
|
||||
self._create_max_splits_subelement(root_element)
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
clean_indentation(root_element)
|
||||
|
|
@ -1538,6 +1616,8 @@ class Settings:
|
|||
settings._material_cell_offsets_from_xml_element(root)
|
||||
settings._log_grid_bins_from_xml_element(root)
|
||||
settings._write_initial_source_from_xml_element(root)
|
||||
settings._weight_windows_from_xml_element(root)
|
||||
settings._max_splits_from_xml_element(root)
|
||||
|
||||
# TODO: Get volume calculations
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ _VERSION_SUMMARY = 6
|
|||
|
||||
|
||||
class Summary:
|
||||
"""Summary of geometry, materials, and tallies used in a simulation.
|
||||
"""Summary of model used in a simulation.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
|
|
|||
317
openmc/weight_windows.py
Normal file
317
openmc/weight_windows.py
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
from collections.abc import Iterable
|
||||
from numbers import Real, Integral
|
||||
|
||||
from xml.etree import ElementTree as ET
|
||||
import numpy as np
|
||||
|
||||
from openmc.filter import _PARTICLES
|
||||
from openmc.mesh import MeshBase
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
from ._xml import get_text
|
||||
from .mixin import IDManagerMixin
|
||||
|
||||
|
||||
class WeightWindows(IDManagerMixin):
|
||||
""" A class to handle the creation of a set of specific weight window
|
||||
paramaters - a variance reduction class may have several of these
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh : openmc.MeshBase
|
||||
Mesh for the weight windows
|
||||
lower_ww_bounds : Iterable of Real
|
||||
A list of values for which each value is the lower bound of a weight
|
||||
window
|
||||
upper_ww_bounds : Iterable of Real
|
||||
A list of values for which each value is the upper bound of a weight
|
||||
window
|
||||
upper_bound_ratio : float
|
||||
Ratio of the lower to upper weight window bounds
|
||||
energy_bins : Iterable of Real
|
||||
A list of values for which each successive pair constitutes a range of
|
||||
energies in [eV] for a single bin
|
||||
particle_type : {'neutron', 'photon'}
|
||||
Particle type the weight windows apply to
|
||||
survival_ratio : float
|
||||
Ratio of the lower weight window bound to the survival weight for
|
||||
rouletting
|
||||
max_split : int
|
||||
Maximum allowable number of particles when splitting
|
||||
weight_cutoff : float
|
||||
Threshold below which particles will be terminated
|
||||
id : int
|
||||
Unique identifier for the weight window settings. If not
|
||||
specified an identifier will automatically be assigned.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id : int
|
||||
Unique identifier for the weight window settings.
|
||||
mesh : openmc.MeshBase
|
||||
Mesh for the weight windows
|
||||
particle_type : str
|
||||
Particle type the weight windows apply to
|
||||
energy_bins : Iterable of Real
|
||||
A list of values for which each successive pair constitutes a range of
|
||||
energies in [eV] for a single bin
|
||||
lower_ww_bounds : Iterable of Real
|
||||
A list of values for which each value is the lower bound of a weight
|
||||
window
|
||||
upper_ww_bounds : Iterable of Real
|
||||
A list of values for which each value is the upper bound of a weight
|
||||
window
|
||||
survival_ratio : float
|
||||
Ratio of the lower weight window bound to the survival weight for
|
||||
rouletting
|
||||
max_split : int
|
||||
Maximum allowable number of particles when splitting
|
||||
weight_cutoff : float
|
||||
Threshold below which particles will be terminated
|
||||
"""
|
||||
next_id = 1
|
||||
used_ids = set()
|
||||
|
||||
def __init__(self, mesh, lower_ww_bounds, upper_ww_bounds=None,
|
||||
upper_bound_ratio=None, energy_bins=None, particle_type='neutron',
|
||||
survival_ratio=3, max_split=10, weight_cutoff=1.e-38, id=None):
|
||||
self.mesh = mesh
|
||||
self.id = id
|
||||
self.particle_type = particle_type
|
||||
self.energy_bins = energy_bins
|
||||
self.lower_ww_bounds = lower_ww_bounds
|
||||
|
||||
cv.check_length('Lower window bounds', self.lower_ww_bounds, len(self.energy_bins))
|
||||
|
||||
if upper_ww_bounds is not None and upper_bound_ratio:
|
||||
raise ValueError("Exactly one of uppwer_ww_bounds and "
|
||||
"upper_bound_ratio must be present.")
|
||||
|
||||
if upper_ww_bounds is None and upper_bound_ratio is None:
|
||||
raise ValueError("Exactly one of uppwer_ww_bounds and "
|
||||
"upper_bound_ratio must be present.")
|
||||
|
||||
if upper_bound_ratio:
|
||||
self.upper_ww_bounds = [
|
||||
lb * upper_bound_ratio for lb in self.lower_ww_bounds
|
||||
]
|
||||
|
||||
if upper_ww_bounds is not None:
|
||||
self.upper_ww_bounds = upper_ww_bounds
|
||||
|
||||
if len(self.lower_ww_bounds) != len(self.upper_ww_bounds):
|
||||
raise ValueError('Size of the lower and upper weight window bounds'
|
||||
'do not match')
|
||||
|
||||
self.survival_ratio = survival_ratio
|
||||
self.max_split = max_split
|
||||
self.weight_cutoff = weight_cutoff
|
||||
|
||||
def __repr__(self):
|
||||
string = type(self).__name__ + '\n'
|
||||
string += '{: <16}=\t{}\n'.format('\tID', self._id)
|
||||
string += '{: <16}=\t{}\n'.format('\tMesh:', self.mesh)
|
||||
string += '{: <16}=\t{}\n'.format('\tParticle Type', self._particle_type)
|
||||
string += '{: <16}=\t{}\n'.format('\tEnergy Bins', self._energy_bins)
|
||||
string += '{: <16}=\t{}\n'.format('\tLower WW Bounds', self._lower_ww_bounds)
|
||||
string += '{: <16}=\t{}\n'.format('\tUpper WW Bounds', self._upper_ww_bounds)
|
||||
string += '{: <16}=\t{}\n'.format('\tSurvival Ratio', self._survival_ratio)
|
||||
string += '{: <16}=\t{}\n'.format('\tMax Split', self._max_split)
|
||||
string += '{: <16}=\t{}\n'.format('\tWeight Cutoff', self._weight_cutoff)
|
||||
return string
|
||||
|
||||
@property
|
||||
def mesh(self):
|
||||
return self._mesh
|
||||
|
||||
@mesh.setter
|
||||
def mesh(self, mesh):
|
||||
cv.check_type('Weight window mesh', mesh, MeshBase)
|
||||
self._mesh = mesh
|
||||
|
||||
@property
|
||||
def particle_type(self):
|
||||
return self._particle_type
|
||||
|
||||
@particle_type.setter
|
||||
def particle_type(self, pt):
|
||||
cv.check_value('Particle type', pt, _PARTICLES)
|
||||
self._particle_type = pt
|
||||
|
||||
@property
|
||||
def energy_bins(self):
|
||||
return self._energy_bins
|
||||
|
||||
@energy_bins.setter
|
||||
def energy_bins(self, bins):
|
||||
cv.check_type('Energy bins', bins, Iterable, Real)
|
||||
self._energy_bins = np.array(bins)
|
||||
|
||||
@property
|
||||
def lower_ww_bounds(self):
|
||||
return self._lower_ww_bounds
|
||||
|
||||
@lower_ww_bounds.setter
|
||||
def lower_ww_bounds(self, bounds):
|
||||
cv.check_type('Lower WW bounds', bounds, Iterable, Real)
|
||||
self._lower_ww_bounds = np.array(bounds)
|
||||
|
||||
@property
|
||||
def upper_ww_bounds(self):
|
||||
return self._upper_ww_bounds
|
||||
|
||||
@upper_ww_bounds.setter
|
||||
def upper_ww_bounds(self, bounds):
|
||||
cv.check_type('Upper WW bounds', bounds, Iterable, Real)
|
||||
self._upper_ww_bounds = np.array(bounds)
|
||||
|
||||
@property
|
||||
def survival_ratio(self):
|
||||
return self._survival_ratio
|
||||
|
||||
@survival_ratio.setter
|
||||
def survival_ratio(self, val):
|
||||
cv.check_type('Survival ratio', val, Real)
|
||||
cv.check_greater_than('Survival ratio', val, 1.0, True)
|
||||
self._survival_ratio = val
|
||||
|
||||
@property
|
||||
def max_split(self):
|
||||
return self._max_split
|
||||
|
||||
@max_split.setter
|
||||
def max_split(self, val):
|
||||
cv.check_type('Max split', val, Integral)
|
||||
self._max_split = val
|
||||
|
||||
@property
|
||||
def weight_cutoff(self):
|
||||
return self._weight_cutoff
|
||||
|
||||
@weight_cutoff.setter
|
||||
def weight_cutoff(self, cutoff):
|
||||
cv.check_type('Weight cutoff', cutoff, Real)
|
||||
cv.check_greater_than('Weight cutoff', cutoff, 0.0, True)
|
||||
self._weight_cutoff = cutoff
|
||||
|
||||
def to_xml_element(self):
|
||||
"""Return an XML representation of the weight window settings
|
||||
|
||||
Returns
|
||||
-------
|
||||
element : xml.etree.ElementTree.Element
|
||||
XML element containing the weight window information
|
||||
"""
|
||||
element = ET.Element('weight_windows')
|
||||
|
||||
element.set('id', str(self._id))
|
||||
|
||||
subelement = ET.SubElement(element, 'mesh')
|
||||
subelement.text = str(self.mesh.id)
|
||||
|
||||
subelement = ET.SubElement(element, 'particle_type')
|
||||
subelement.text = self.particle_type
|
||||
|
||||
subelement = ET.SubElement(element, 'energy_bins')
|
||||
subelement.text = ' '.join(str(e) for e in self.energy_bins)
|
||||
|
||||
subelement = ET.SubElement(element, 'lower_ww_bounds')
|
||||
subelement.text = ' '.join(str(b) for b in self.lower_ww_bounds)
|
||||
|
||||
subelement = ET.SubElement(element, 'upper_ww_bounds')
|
||||
subelement.text = ' '.join(str(b) for b in self.upper_ww_bounds)
|
||||
|
||||
subelement = ET.SubElement(element, 'survival_ratio')
|
||||
subelement.text = str(self.survival_ratio)
|
||||
|
||||
subelement = ET.SubElement(element, 'max_split')
|
||||
subelement.text = str(self.max_split)
|
||||
|
||||
subelement = ET.SubElement(element, 'weight_cutoff')
|
||||
subelement.text = str(self.weight_cutoff)
|
||||
|
||||
return element
|
||||
|
||||
@classmethod
|
||||
def from_xml_element(cls, elem, root):
|
||||
"""Generate weight window settings from an XML element
|
||||
|
||||
Parameters
|
||||
----------
|
||||
elem : xml.etree.ElementTree.Element
|
||||
XML element
|
||||
root : xml.etree.ElementTree.Element
|
||||
Root element for the file where meshes can be found
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.WeightWindows
|
||||
Weight windows object
|
||||
"""
|
||||
# Get mesh for weight windows
|
||||
mesh_id = int(get_text(elem, 'mesh'))
|
||||
path = f"./mesh[@id='{mesh_id}']"
|
||||
mesh_elem = root.find(path)
|
||||
if mesh_elem is not None:
|
||||
mesh = MeshBase.from_xml(elem)
|
||||
|
||||
# Read all other parameters
|
||||
lower_ww_bounds = [float(l) for l in get_text(elem, 'lower_ww_bounds').split()]
|
||||
upper_ww_bounds = [float(u) for u in get_text(elem, 'upper_ww_bounds').split()]
|
||||
ebins = [float(b) for b in get_text(elem, 'energy_bins').split()]
|
||||
particle_type = get_text(elem, 'particle_type')
|
||||
survival_ratio = float(get_text(elem, 'survival_ratio'))
|
||||
max_split = int(get_text(elem, 'max_split'))
|
||||
weight_cutoff = float(get_text(elem, 'weight_cutoff'))
|
||||
id = int(get_text(elem, 'id'))
|
||||
|
||||
return cls(
|
||||
mesh=mesh,
|
||||
lower_ww_bounds=lower_ww_bounds,
|
||||
upper_ww_bounds=upper_ww_bounds,
|
||||
energy_bins=ebins,
|
||||
particle_type=particle_type,
|
||||
survival_ratio=survival_ratio,
|
||||
max_split=max_split,
|
||||
weight_cutoff=weight_cutoff,
|
||||
id=id
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_hdf5(cls, group, meshes):
|
||||
"""Create weight windows from HDF5 group
|
||||
|
||||
Parameters
|
||||
----------
|
||||
group : h5py.Group
|
||||
Group in HDF5 file
|
||||
meshes : dict
|
||||
Dictionary mapping IDs to mesh objects
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.WeightWindows
|
||||
A weight window object
|
||||
"""
|
||||
|
||||
id = int(group.name.split('/')[-1].lstrip('weight_windows'))
|
||||
mesh_id = group['mesh'][()]
|
||||
ptype = group['particle_type'][()].decode()
|
||||
ebins = group['energy_bins'][()]
|
||||
lower_ww_bounds = group['lower_ww_bounds'][()]
|
||||
upper_ww_bounds = group['upper_ww_bounds'][()]
|
||||
survival_ratio = group['survival_ratio'][()]
|
||||
max_split = group['max_split'][()]
|
||||
weight_cutoff = group['weight_cutoff'][()]
|
||||
|
||||
return cls(
|
||||
mesh=meshes[mesh_id],
|
||||
lower_ww_bounds=lower_ww_bounds,
|
||||
upper_ww_bounds=upper_ww_bounds,
|
||||
energy_bins=ebins,
|
||||
particle_type=ptype,
|
||||
survival_ratio=survival_ratio,
|
||||
max_split=max_split,
|
||||
weight_cutoff=weight_cutoff,
|
||||
id=id
|
||||
)
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
#include "openmc/thermal.h"
|
||||
#include "openmc/timer.h"
|
||||
#include "openmc/volume_calc.h"
|
||||
#include "openmc/weight_windows.h"
|
||||
|
||||
#include "xtensor/xview.hpp"
|
||||
|
||||
|
|
@ -47,6 +48,7 @@ void free_memory()
|
|||
free_memory_tally();
|
||||
free_memory_bank();
|
||||
free_memory_plot();
|
||||
free_memory_weight_windows();
|
||||
if (mpi::master) {
|
||||
free_memory_cmfd();
|
||||
}
|
||||
|
|
@ -82,6 +84,7 @@ int openmc_finalize()
|
|||
settings::legendre_to_tabular_points = -1;
|
||||
settings::material_cell_offsets = true;
|
||||
settings::max_particles_in_flight = 100000;
|
||||
settings::max_splits = 1000;
|
||||
settings::n_inactive = 0;
|
||||
settings::n_particles = -1;
|
||||
settings::output_summary = true;
|
||||
|
|
@ -113,6 +116,7 @@ int openmc_finalize()
|
|||
settings::verbosity = 7;
|
||||
settings::weight_cutoff = 0.25;
|
||||
settings::weight_survive = 1.0;
|
||||
settings::weight_windows_on = false;
|
||||
settings::write_all_tracks = false;
|
||||
settings::write_initial_source = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@
|
|||
#include "openmc/xml_interface.h"
|
||||
|
||||
#ifdef LIBMESH
|
||||
#include "libmesh/mesh_modification.h"
|
||||
#include "libmesh/mesh_tools.h"
|
||||
#include "libmesh/numeric_vector.h"
|
||||
#include "libmesh/mesh_modification.h"
|
||||
#endif
|
||||
|
||||
namespace openmc {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "openmc/string_utils.h"
|
||||
#include "openmc/tallies/tally.h"
|
||||
#include "openmc/thermal.h"
|
||||
#include "openmc/weight_windows.h"
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
|
|
@ -44,9 +45,15 @@ void collision(Particle& p)
|
|||
switch (p.type()) {
|
||||
case ParticleType::neutron:
|
||||
sample_neutron_reaction(p);
|
||||
if (settings::weight_windows_on) {
|
||||
split_particle(p);
|
||||
}
|
||||
break;
|
||||
case ParticleType::photon:
|
||||
sample_photon_reaction(p);
|
||||
if (settings::weight_windows_on) {
|
||||
split_particle(p);
|
||||
}
|
||||
break;
|
||||
case ParticleType::electron:
|
||||
sample_electron_reaction(p);
|
||||
|
|
@ -1197,4 +1204,69 @@ void sample_secondary_photons(Particle& p, int i_nuclide)
|
|||
}
|
||||
}
|
||||
|
||||
// split a particle based on the statistical weight of the current location
|
||||
void split_particle(Particle& p)
|
||||
{
|
||||
// skip dead or no energy
|
||||
if (p.E() <= 0 || !p.alive())
|
||||
return;
|
||||
|
||||
bool in_domain = false;
|
||||
// TODO: this is a linear search - should do something more clever
|
||||
WeightWindow weight_window;
|
||||
for (const auto& ww : variance_reduction::weight_windows) {
|
||||
weight_window = ww->get_weight_window(p);
|
||||
if (weight_window)
|
||||
break;
|
||||
}
|
||||
// particle is not in any of the ww domains, do nothing
|
||||
if (!weight_window)
|
||||
return;
|
||||
|
||||
// get the paramters
|
||||
double weight = p.wgt();
|
||||
p.wgt_last() = weight;
|
||||
|
||||
// first check to see if particle should be killed for weight cutoff
|
||||
if (p.wgt() < weight_window.weight_cutoff) {
|
||||
p.alive() = false;
|
||||
p.wgt() = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// if particle's weight is above the weight window split until they are within
|
||||
// the window
|
||||
if (weight > weight_window.upper_weight) {
|
||||
// do not further split the particle if above the limit
|
||||
if (p.n_split() >= settings::max_splits)
|
||||
return;
|
||||
|
||||
double n_split = std::ceil(weight / weight_window.upper_weight);
|
||||
double max_split = weight_window.max_split;
|
||||
n_split = std::min(n_split, max_split);
|
||||
|
||||
p.n_split() += n_split;
|
||||
|
||||
// Create secondaries and divide weight among all particles
|
||||
int i_split = std::round(n_split);
|
||||
for (int l = 0; l < i_split - 1; l++) {
|
||||
p.create_secondary(weight / n_split, p.u(), p.E(), p.type());
|
||||
}
|
||||
// TODO: maybe weight should be weight - sum of child weight
|
||||
p.wgt() = weight / n_split;
|
||||
|
||||
} else if (weight <= weight_window.lower_weight) {
|
||||
// if the particle weight is below the window, play Russian roulette
|
||||
double weight_survive =
|
||||
std::min(weight * weight_window.max_split, weight_window.survival_weight);
|
||||
if (weight_survive * prn(p.current_seed()) <= weight) {
|
||||
p.wgt() = weight_survive;
|
||||
} else {
|
||||
p.alive() = false;
|
||||
p.wgt() = 0.0;
|
||||
}
|
||||
// else particle is in the window, continue as normal
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "openmc/string_utils.h"
|
||||
#include "openmc/tallies/trigger.h"
|
||||
#include "openmc/volume_calc.h"
|
||||
#include "openmc/weight_windows.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
namespace openmc {
|
||||
|
|
@ -67,6 +68,7 @@ bool trigger_on {false};
|
|||
bool trigger_predict {false};
|
||||
bool ufs_on {false};
|
||||
bool urr_ptables_on {true};
|
||||
bool weight_windows_on {false};
|
||||
bool write_all_tracks {false};
|
||||
bool write_initial_source {false};
|
||||
|
||||
|
|
@ -92,6 +94,7 @@ int max_order {0};
|
|||
int n_log_bins {8000};
|
||||
int n_batches;
|
||||
int n_max_batches;
|
||||
int max_splits {1000};
|
||||
ResScatMethod res_scat_method {ResScatMethod::rvs};
|
||||
double res_scat_energy_min {0.01};
|
||||
double res_scat_energy_max {1000.0};
|
||||
|
|
@ -848,6 +851,23 @@ void read_settings_xml()
|
|||
if (check_for_node(root, "material_cell_offsets")) {
|
||||
material_cell_offsets = get_node_value_bool(root, "material_cell_offsets");
|
||||
}
|
||||
|
||||
// Weight window information
|
||||
for (pugi::xml_node node_ww : root.children("weight_windows")) {
|
||||
variance_reduction::weight_windows.emplace_back(
|
||||
std::make_unique<WeightWindows>(node_ww));
|
||||
|
||||
// Enable weight windows by default if one or more are present
|
||||
settings::weight_windows_on = true;
|
||||
}
|
||||
|
||||
if (check_for_node(root, "weight_windows_on")) {
|
||||
weight_windows_on = get_node_value_bool(root, "weight_windows_on");
|
||||
}
|
||||
|
||||
if (check_for_node(root, "max_splits")) {
|
||||
settings::max_splits = std::stoi(get_node_value(root, "max_splits"));
|
||||
}
|
||||
}
|
||||
|
||||
void free_memory_settings()
|
||||
|
|
|
|||
220
src/weight_windows.cpp
Normal file
220
src/weight_windows.cpp
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
#include "openmc/weight_windows.h"
|
||||
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/file_utils.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/particle.h"
|
||||
#include "openmc/particle_data.h"
|
||||
#include "openmc/search.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <gsl/gsl-lite.hpp>
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// Global variables
|
||||
//==============================================================================
|
||||
|
||||
namespace variance_reduction {
|
||||
|
||||
std::unordered_map<int32_t, int32_t> ww_map;
|
||||
openmc::vector<unique_ptr<WeightWindows>> weight_windows;
|
||||
|
||||
} // namespace variance_reduction
|
||||
|
||||
//==============================================================================
|
||||
// Non-member functions
|
||||
//==============================================================================
|
||||
|
||||
void free_memory_weight_windows()
|
||||
{
|
||||
variance_reduction::ww_map.clear();
|
||||
variance_reduction::weight_windows.clear();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// WeightWindowSettings implementation
|
||||
//==============================================================================
|
||||
|
||||
WeightWindows::WeightWindows(pugi::xml_node node)
|
||||
{
|
||||
if (!check_for_node(node, "id")) {
|
||||
fatal_error("Must specify 'id' for weight windows.");
|
||||
}
|
||||
int32_t id = std::stoi(get_node_value(node, "id"));
|
||||
this->set_id(id);
|
||||
|
||||
// get the particle type
|
||||
if (!check_for_node(node, "particle_type")) {
|
||||
fatal_error("Must specify 'particle_type' for weight windows.");
|
||||
}
|
||||
auto particle_type_str = std::string(get_node_value(node, "particle_type"));
|
||||
particle_type_ = openmc::str_to_particle_type(particle_type_str);
|
||||
|
||||
// get the survival value - optional
|
||||
if (check_for_node(node, "survival_ratio")) {
|
||||
survival_ratio_ = std::stod(get_node_value(node, "survival_ratio"));
|
||||
if (survival_ratio_ <= 1)
|
||||
fatal_error("Survival to lower weight window ratio must bigger than 1"
|
||||
"and less than the upper to lower weight window ratio.");
|
||||
}
|
||||
|
||||
// get the max split - optional
|
||||
if (check_for_node(node, "max_split")) {
|
||||
max_split_ = std::stod(get_node_value(node, "max_split"));
|
||||
if (max_split_ <= 1)
|
||||
fatal_error("max split must be larger than 1");
|
||||
}
|
||||
|
||||
// weight cutoff - optional - but default is 1e-38
|
||||
if (check_for_node(node, "weight_cutoff")) {
|
||||
weight_cutoff_ = std::stod(get_node_value(node, "weight_cutoff"));
|
||||
if (weight_cutoff_ <= 0)
|
||||
fatal_error("weight_cutoff must be larger than 0");
|
||||
if (weight_cutoff_ > 1)
|
||||
fatal_error("weight_cutoff must be less than 1");
|
||||
}
|
||||
|
||||
// get the mesh id
|
||||
int32_t mesh_id;
|
||||
if (check_for_node(node, "mesh")) {
|
||||
mesh_id = std::stoi(get_node_value(node, "mesh"));
|
||||
} else {
|
||||
fatal_error("No mesh specifier in the domain.");
|
||||
}
|
||||
|
||||
// set the indices to save time later
|
||||
mesh_idx_ = model::mesh_map.at(mesh_id);
|
||||
|
||||
// energy bounds
|
||||
if (check_for_node(node, "energy_bins")) {
|
||||
energy_bins_ = get_node_array<double>(node, "energy_bins");
|
||||
} else {
|
||||
fatal_error("<energy_bins> is missing from the weight_windows.xml file.");
|
||||
}
|
||||
|
||||
// read the lower weight bounds
|
||||
if (check_for_node(node, "lower_ww_bounds")) {
|
||||
lower_ww_ = get_node_array<double>(node, "lower_ww_bounds");
|
||||
} else {
|
||||
fatal_error("<lower_ww_bounds> section is missing from the "
|
||||
"variance_reduction.xml file.");
|
||||
}
|
||||
|
||||
// read the upper weight bounds
|
||||
if (check_for_node(node, "upper_ww_bounds")) {
|
||||
upper_ww_ = get_node_array<double>(node, "upper_ww_bounds");
|
||||
} else {
|
||||
fatal_error("<upper_ww_bounds> node is missing from the "
|
||||
"variance_reduction.xml file.");
|
||||
}
|
||||
|
||||
// make sure that the upper and lower bounds have the same size
|
||||
if (upper_ww_.size() != lower_ww_.size()) {
|
||||
fatal_error("The upper and lower weight window lengths do not match.");
|
||||
}
|
||||
|
||||
// num spatial*energy bins must match num weight bins
|
||||
int num_spatial_bins = this->mesh().n_bins();
|
||||
int num_energy_bins = energy_bins_.size() - 1;
|
||||
int num_weight_bins = lower_ww_.size();
|
||||
if (num_weight_bins != num_spatial_bins * num_energy_bins) {
|
||||
auto err_msg =
|
||||
fmt::format("In weight window domain {} the number of spatial "
|
||||
"energy/spatial bins ({}) does not match the number "
|
||||
"of weight bins ({})",
|
||||
id_, num_energy_bins, num_weight_bins);
|
||||
fatal_error(err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void WeightWindows::set_id(int32_t id)
|
||||
{
|
||||
Expects(id >= 0 || id == C_NONE);
|
||||
|
||||
// Clear entry in mesh map in case one was already assigned
|
||||
if (id_ != C_NONE) {
|
||||
variance_reduction::ww_map.erase(id_);
|
||||
id_ = C_NONE;
|
||||
}
|
||||
|
||||
// Ensure no other mesh has the same ID
|
||||
if (variance_reduction::ww_map.find(id) != variance_reduction::ww_map.end()) {
|
||||
throw std::runtime_error {
|
||||
fmt::format("Two weight windows have the same ID: {}", id)};
|
||||
}
|
||||
|
||||
// If no ID is specified, auto-assign the next ID in the sequence
|
||||
if (id == C_NONE) {
|
||||
id = 0;
|
||||
for (const auto& m : variance_reduction::weight_windows) {
|
||||
id = std::max(id, m->id_);
|
||||
}
|
||||
++id;
|
||||
}
|
||||
|
||||
// Update ID and entry in the mesh map
|
||||
id_ = id;
|
||||
variance_reduction::ww_map[id] =
|
||||
variance_reduction::weight_windows.size() - 1;
|
||||
}
|
||||
|
||||
WeightWindow WeightWindows::get_weight_window(const Particle& p) const
|
||||
{
|
||||
// check for particle type
|
||||
if (particle_type_ != p.type()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Get mesh index for particle's position
|
||||
const auto& mesh = this->mesh();
|
||||
int ww_index = mesh.get_bin(p.r());
|
||||
|
||||
// particle is outside the weight window mesh
|
||||
if (ww_index < 0)
|
||||
return {};
|
||||
|
||||
// particle energy
|
||||
double E = p.E();
|
||||
|
||||
// check to make sure energy is in range, expects sorted energy values
|
||||
if (E < energy_bins_.front() || E > energy_bins_.back())
|
||||
return {};
|
||||
|
||||
// get the mesh bin in energy group
|
||||
int energy_bin =
|
||||
lower_bound_index(energy_bins_.begin(), energy_bins_.end(), E);
|
||||
|
||||
// indices now points to the correct weight for the given energy
|
||||
ww_index += energy_bin * mesh.n_bins();
|
||||
|
||||
// Create individual weight window
|
||||
WeightWindow ww;
|
||||
ww.lower_weight = lower_ww_[ww_index];
|
||||
ww.upper_weight = upper_ww_[ww_index];
|
||||
ww.survival_weight = ww.lower_weight * survival_ratio_;
|
||||
ww.max_split = max_split_;
|
||||
ww.weight_cutoff = weight_cutoff_;
|
||||
return ww;
|
||||
}
|
||||
|
||||
void WeightWindows::to_hdf5(hid_t group) const
|
||||
{
|
||||
hid_t ww_group = create_group(group, fmt::format("weight_windows {}", id_));
|
||||
|
||||
write_dataset(
|
||||
ww_group, "particle_type", openmc::particle_type_to_str(particle_type_));
|
||||
write_dataset(ww_group, "energy_bins", energy_bins_);
|
||||
write_dataset(ww_group, "lower_ww_bounds", lower_ww_);
|
||||
write_dataset(ww_group, "upper_ww_bounds", upper_ww_);
|
||||
write_dataset(ww_group, "survival_ratio", survival_ratio_);
|
||||
write_dataset(ww_group, "max_split", max_split_);
|
||||
write_dataset(ww_group, "weight_cutoff", weight_cutoff_);
|
||||
write_dataset(ww_group, "mesh", this->mesh().id_);
|
||||
|
||||
close_group(ww_group);
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
1
tests/regression_tests/weightwindow/__init__.py
Normal file
1
tests/regression_tests/weightwindow/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
12
tests/regression_tests/weightwindow/geometry.xml
Normal file
12
tests/regression_tests/weightwindow/geometry.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0"?>
|
||||
<geometry>
|
||||
|
||||
<surface id="5" type="sphere" coeffs="0. 0. 0. 120."/>
|
||||
<surface id="6" type="sphere" coeffs="0. 0. 0. 125."/>
|
||||
<surface id="10" type="sphere" coeffs="0. 0. 0. 126." boundary="vacuum"/>
|
||||
|
||||
<cell id="5" material="4" region="-5" />
|
||||
<cell id="6" material="void" region="5 -6" />
|
||||
<cell id="10" material="void" region="6 -10" />
|
||||
|
||||
</geometry>
|
||||
27
tests/regression_tests/weightwindow/materials.xml
Normal file
27
tests/regression_tests/weightwindow/materials.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<materials>
|
||||
<material id="4" name="M4">
|
||||
<density units="g/cc" value="2.3" />
|
||||
<nuclide ao="0.168018676" name="H1" />
|
||||
<nuclide ao="1.93244e-05" name="H2" />
|
||||
<nuclide ao="0.561814465" name="O16" />
|
||||
<nuclide ao="0.00021401" name="O17" />
|
||||
<!--nuclide ao="0.001154525" name="O18" /-->
|
||||
<nuclide ao="0.021365" name="Na23" />
|
||||
<nuclide ao="0.021343" name="Al27" />
|
||||
<nuclide ao="0.187439342" name="Si28" />
|
||||
<nuclide ao="0.009517714" name="Si29" />
|
||||
<nuclide ao="0.006273944" name="Si30" />
|
||||
<nuclide ao="0.018026179" name="Ca40" />
|
||||
<nuclide ao="0.00012031" name="Ca42" />
|
||||
<nuclide ao="2.51033e-05" name="Ca43" />
|
||||
<nuclide ao="0.000387892" name="Ca44" />
|
||||
<nuclide ao="7.438e-07" name="Ca46" />
|
||||
<nuclide ao="3.47727e-05" name="Ca48" />
|
||||
<nuclide ao="0.000248179" name="Fe54" />
|
||||
<nuclide ao="0.003895875" name="Fe56" />
|
||||
<nuclide ao="8.99727e-05" name="Fe57" />
|
||||
<nuclide ao="1.19737e-05" name="Fe58" />
|
||||
</material>
|
||||
|
||||
</materials>
|
||||
513
tests/regression_tests/weightwindow/results_true.dat
Normal file
513
tests/regression_tests/weightwindow/results_true.dat
Normal file
|
|
@ -0,0 +1,513 @@
|
|||
tally 1:
|
||||
1.853183E-02
|
||||
1.717351E-04
|
||||
3.029396E-03
|
||||
4.649064E-06
|
||||
7.544003E-05
|
||||
3.164069E-09
|
||||
9.706048E-05
|
||||
4.714215E-09
|
||||
8.632819E-05
|
||||
4.068658E-09
|
||||
9.248134E-05
|
||||
4.277560E-09
|
||||
1.057891E-04
|
||||
5.622465E-09
|
||||
8.678273E-05
|
||||
5.459032E-09
|
||||
1.030006E-04
|
||||
5.401900E-09
|
||||
6.530162E-05
|
||||
2.132845E-09
|
||||
8.429033E-05
|
||||
3.976020E-09
|
||||
5.307443E-05
|
||||
1.535662E-09
|
||||
6.990236E-05
|
||||
2.572885E-09
|
||||
1.046155E-04
|
||||
5.472211E-09
|
||||
7.487444E-05
|
||||
2.832742E-09
|
||||
1.215270E-04
|
||||
7.386937E-09
|
||||
1.526205E-04
|
||||
1.275134E-08
|
||||
1.129350E-04
|
||||
6.438217E-09
|
||||
1.072884E-04
|
||||
5.786945E-09
|
||||
5.986538E-05
|
||||
1.804378E-09
|
||||
7.724972E-05
|
||||
2.986308E-09
|
||||
9.752938E-05
|
||||
4.820728E-09
|
||||
1.090999E-04
|
||||
5.972473E-09
|
||||
7.551735E-05
|
||||
3.575893E-09
|
||||
8.860064E-05
|
||||
3.964865E-09
|
||||
1.018275E-04
|
||||
5.186898E-09
|
||||
4.915270E-05
|
||||
1.275256E-09
|
||||
1.173593E-04
|
||||
7.382579E-09
|
||||
9.243253E-05
|
||||
4.293582E-09
|
||||
6.170115E-05
|
||||
2.140169E-09
|
||||
8.808961E-05
|
||||
3.894854E-09
|
||||
6.941292E-05
|
||||
2.993412E-09
|
||||
9.880710E-05
|
||||
4.936860E-09
|
||||
8.013541E-05
|
||||
3.475624E-09
|
||||
1.234975E-04
|
||||
7.699401E-09
|
||||
1.109685E-04
|
||||
6.162383E-09
|
||||
4.015613E-05
|
||||
8.177789E-10
|
||||
3.194893E-05
|
||||
5.138631E-10
|
||||
2.612327E-05
|
||||
4.678400E-10
|
||||
1.514792E-05
|
||||
1.490146E-10
|
||||
1.388898E-05
|
||||
1.110648E-10
|
||||
6.051317E-05
|
||||
2.103995E-09
|
||||
3.670728E-05
|
||||
1.127649E-09
|
||||
8.000503E-05
|
||||
3.215581E-09
|
||||
1.028704E-04
|
||||
5.559097E-09
|
||||
1.497360E-04
|
||||
1.214582E-08
|
||||
7.122351E-05
|
||||
2.898636E-09
|
||||
6.040324E-05
|
||||
3.648552E-09
|
||||
3.249762E-05
|
||||
5.514740E-10
|
||||
9.107075E-05
|
||||
4.182561E-09
|
||||
1.009222E-04
|
||||
5.390605E-09
|
||||
3.321080E-05
|
||||
6.503888E-10
|
||||
3.723183E-05
|
||||
8.021551E-10
|
||||
7.536094E-06
|
||||
5.679271E-11
|
||||
6.966939E-06
|
||||
4.853823E-11
|
||||
3.370952E-05
|
||||
5.697978E-10
|
||||
4.413982E-06
|
||||
1.948324E-11
|
||||
1.773332E-05
|
||||
3.144706E-10
|
||||
3.287734E-05
|
||||
5.548423E-10
|
||||
1.616419E-05
|
||||
2.612810E-10
|
||||
8.737224E-05
|
||||
4.078498E-09
|
||||
9.726809E-05
|
||||
5.996334E-09
|
||||
7.896294E-05
|
||||
3.185197E-09
|
||||
1.250834E-05
|
||||
8.630440E-11
|
||||
9.543138E-05
|
||||
5.240082E-09
|
||||
4.106567E-05
|
||||
8.535411E-10
|
||||
1.050483E-04
|
||||
6.431150E-09
|
||||
8.632258E-06
|
||||
3.728368E-11
|
||||
3.777415E-05
|
||||
7.765760E-10
|
||||
4.351726E-05
|
||||
1.024806E-09
|
||||
5.019194E-05
|
||||
1.321650E-09
|
||||
5.498249E-05
|
||||
1.691511E-09
|
||||
5.087032E-05
|
||||
1.548439E-09
|
||||
4.339702E-05
|
||||
9.748317E-10
|
||||
4.487648E-05
|
||||
1.017509E-09
|
||||
3.912145E-05
|
||||
7.781069E-10
|
||||
3.360131E-05
|
||||
5.926580E-10
|
||||
4.181970E-05
|
||||
9.315176E-10
|
||||
4.996376E-05
|
||||
1.271321E-09
|
||||
6.953297E-05
|
||||
3.149553E-09
|
||||
2.341899E-05
|
||||
2.863270E-10
|
||||
2.463170E-05
|
||||
3.817933E-10
|
||||
4.287745E-05
|
||||
1.381986E-09
|
||||
4.863137E-05
|
||||
1.265768E-09
|
||||
3.546002E-05
|
||||
6.388007E-10
|
||||
2.768687E-05
|
||||
3.996862E-10
|
||||
4.620425E-05
|
||||
1.157612E-09
|
||||
8.765238E-05
|
||||
3.949969E-09
|
||||
9.122226E-06
|
||||
5.156352E-11
|
||||
2.923384E-05
|
||||
4.277534E-10
|
||||
6.110238E-06
|
||||
3.733501E-11
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
1.145086E-05
|
||||
8.044829E-11
|
||||
1.215673E-04
|
||||
7.922859E-09
|
||||
8.180970E-05
|
||||
3.346559E-09
|
||||
2.228237E-05
|
||||
2.960078E-10
|
||||
1.403128E-05
|
||||
9.848102E-11
|
||||
3.726259E-05
|
||||
9.376976E-10
|
||||
1.324914E-04
|
||||
8.860330E-09
|
||||
1.151127E-04
|
||||
7.050758E-09
|
||||
1.458422E-04
|
||||
1.064061E-08
|
||||
4.638976E-05
|
||||
1.132911E-09
|
||||
5.531801E-05
|
||||
2.260621E-09
|
||||
8.192886E-05
|
||||
3.508237E-09
|
||||
8.582256E-05
|
||||
3.799113E-09
|
||||
8.613792E-05
|
||||
3.771588E-09
|
||||
5.454735E-05
|
||||
1.530858E-09
|
||||
1.063688E-04
|
||||
6.220167E-09
|
||||
7.629155E-05
|
||||
3.048569E-09
|
||||
1.190013E-04
|
||||
7.093135E-09
|
||||
1.578917E-04
|
||||
1.272315E-08
|
||||
4.756033E-05
|
||||
1.614432E-09
|
||||
3.115637E-05
|
||||
6.286413E-10
|
||||
1.021201E-04
|
||||
5.685811E-09
|
||||
1.963249E-04
|
||||
2.098415E-08
|
||||
3.695671E-05
|
||||
7.886960E-10
|
||||
1.118071E-04
|
||||
6.287210E-09
|
||||
8.682908E-05
|
||||
5.090302E-09
|
||||
1.267453E-04
|
||||
8.145301E-09
|
||||
7.582105E-05
|
||||
2.877459E-09
|
||||
1.734581E-04
|
||||
1.695871E-08
|
||||
1.115115E-04
|
||||
6.240141E-09
|
||||
2.008189E-04
|
||||
2.031997E-08
|
||||
1.262066E-04
|
||||
9.106525E-09
|
||||
1.229430E-04
|
||||
8.223850E-09
|
||||
7.226708E-05
|
||||
2.611301E-09
|
||||
1.172134E-04
|
||||
1.086013E-08
|
||||
1.625937E-04
|
||||
1.629146E-08
|
||||
1.533641E-04
|
||||
1.372814E-08
|
||||
4.739040E-05
|
||||
1.128076E-09
|
||||
1.658554E-04
|
||||
1.423181E-08
|
||||
6.559022E-05
|
||||
2.372207E-09
|
||||
1.732080E-04
|
||||
1.517405E-08
|
||||
1.317351E-04
|
||||
1.119150E-08
|
||||
1.457401E-04
|
||||
1.073529E-08
|
||||
1.690169E-04
|
||||
1.466057E-08
|
||||
2.126906E-04
|
||||
2.486373E-08
|
||||
1.434676E-04
|
||||
1.039533E-08
|
||||
1.290828E-04
|
||||
8.377438E-09
|
||||
1.651708E-04
|
||||
1.433255E-08
|
||||
2.955022E-04
|
||||
4.651016E-08
|
||||
3.461359E-04
|
||||
6.077542E-08
|
||||
9.778295E-05
|
||||
5.112317E-09
|
||||
1.720872E-04
|
||||
1.512272E-08
|
||||
6.851550E-05
|
||||
3.140824E-09
|
||||
1.632821E-04
|
||||
2.581085E-08
|
||||
5.732748E-05
|
||||
1.680111E-09
|
||||
1.356990E-04
|
||||
1.313491E-08
|
||||
7.179892E-05
|
||||
4.020446E-09
|
||||
5.265125E-04
|
||||
2.525299E-07
|
||||
1.394079E-05
|
||||
1.943457E-10
|
||||
1.139166E-04
|
||||
9.430244E-09
|
||||
2.050982E-05
|
||||
2.114840E-10
|
||||
3.571743E-05
|
||||
7.843684E-10
|
||||
7.039875E-06
|
||||
4.955983E-11
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
3.035075E-05
|
||||
9.211678E-10
|
||||
4.571644E-04
|
||||
2.045276E-07
|
||||
4.586789E-04
|
||||
2.001054E-07
|
||||
9.622015E-05
|
||||
6.642202E-09
|
||||
4.513091E-05
|
||||
1.049061E-09
|
||||
6.177860E-05
|
||||
2.991654E-09
|
||||
1.534235E-05
|
||||
1.441999E-10
|
||||
4.071311E-05
|
||||
1.657557E-09
|
||||
2.162722E-05
|
||||
4.677365E-10
|
||||
5.371783E-04
|
||||
2.709166E-07
|
||||
5.156053E-05
|
||||
2.658489E-09
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
31
tests/regression_tests/weightwindow/settings.xml
Normal file
31
tests/regression_tests/weightwindow/settings.xml
Normal file
File diff suppressed because one or more lines are too long
46
tests/regression_tests/weightwindow/tallies.xml
Normal file
46
tests/regression_tests/weightwindow/tallies.xml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0"?>
|
||||
<tallies>
|
||||
|
||||
<filter id="6" type="cell">
|
||||
<bins>6</bins>
|
||||
</filter>
|
||||
|
||||
<filter id="10" type="particle">
|
||||
<bins>neutron</bins>
|
||||
</filter>
|
||||
|
||||
<filter id="3" type="energy">
|
||||
<bins>1.0000E-05 1.0000E-01 4.1399E-01 5.3158E-01 6.8256E-01 8.7643E-01 1.1254E+00 1.4450E+00 1.8554E+00 2.3824E+00
|
||||
3.0590E+00 3.9279E+00 5.0435E+00 6.4760E+00 8.3153E+00 1.0677E+01 1.3710E+01 1.7604E+01 2.2603E+01 2.9023E+01
|
||||
3.7267E+01 4.7851E+01 6.1442E+01 7.8893E+01 1.0130E+02 1.3007E+02 1.6702E+02 2.1445E+02 2.7536E+02 3.5358E+02
|
||||
4.5400E+02 5.8295E+02 7.4852E+02 9.6112E+02 1.2341E+03 1.5846E+03 2.0347E+03 2.2487E+03 2.4852E+03 2.6126E+03
|
||||
2.7465E+03 3.0354E+03 3.3546E+03 3.7074E+03 4.3074E+03 5.5308E+03 7.1017E+03 9.1188E+03 1.0595E+04 1.1709E+04
|
||||
1.5034E+04 1.9305E+04 2.1875E+04 2.3579E+04 2.4176E+04 2.4788E+04 2.6058E+04 2.7000E+04 2.8501E+04 3.1828E+04
|
||||
3.4307E+04 4.0868E+04 4.6309E+04 5.2475E+04 5.6562E+04 6.7380E+04 7.2025E+04 7.9499E+04 8.2503E+04 8.6517E+04
|
||||
9.8037E+04 1.1109E+05 1.1679E+05 1.2277E+05 1.2907E+05 1.3569E+05 1.4264E+05 1.4996E+05 1.5764E+05 1.6573E+05
|
||||
1.7422E+05 1.8316E+05 1.9255E+05 2.0242E+05 2.1280E+05 2.2371E+05 2.3518E+05 2.4724E+05 2.7324E+05 2.8725E+05
|
||||
2.9452E+05 2.9721E+05 2.9849E+05 3.0197E+05 3.3373E+05 3.6883E+05 3.8774E+05 4.0762E+05 4.5049E+05 4.9787E+05
|
||||
5.2340E+05 5.5023E+05 5.7844E+05 6.0810E+05 6.3928E+05 6.7206E+05 7.0651E+05 7.4274E+05 7.8082E+05 8.2085E+05
|
||||
8.6294E+05 9.0718E+05 9.6167E+05 1.0026E+06 1.1080E+06 1.1648E+06 1.2246E+06 1.2874E+06 1.3534E+06 1.4227E+06
|
||||
1.4957E+06 1.5724E+06 1.6530E+06 1.7377E+06 1.8268E+06 1.9205E+06 2.0190E+06 2.1225E+06 2.2313E+06 2.3069E+06
|
||||
2.3457E+06 2.3653E+06 2.3851E+06 2.4660E+06 2.5924E+06 2.7253E+06 2.8651E+06 3.0119E+06 3.1664E+06 3.3287E+06
|
||||
3.6788E+06 4.0657E+06 4.4933E+06 4.7237E+06 4.9659E+06 5.2205E+06 5.4881E+06 5.7695E+06 6.0653E+06 6.3763E+06
|
||||
6.5924E+06 6.7032E+06 7.0469E+06 7.4082E+06 7.7880E+06 8.1873E+06 8.6071E+06 9.0484E+06 9.5123E+06 1.0000E+07
|
||||
1.0513E+07 1.1052E+07 1.1618E+07 1.2214E+07 1.2523E+07 1.2840E+07 1.3499E+07 1.3840E+07 1.4191E+07 1.4550E+07
|
||||
1.4918E+07 1.5683E+07 1.6487E+07 1.6905E+07 1.7333E+07 1.9640E+07 2.0000E+07 2.1000E+07 2.2000E+07 2.3000E+07
|
||||
2.4000E+07 2.5000E+07 2.6000E+07 2.7000E+07 2.8000E+07 2.9000E+07 3.0000E+07 3.1000E+07 3.2000E+07 3.3000E+07
|
||||
3.4000E+07 3.5000E+07 3.6000E+07 3.7000E+07 3.8000E+07 3.9000E+07 4.0000E+07 4.1000E+07 4.2000E+07 4.3000E+07
|
||||
4.4000E+07 4.5000E+07 4.6000E+07 4.7000E+07 4.8000E+07 4.9000E+07 5.0000E+07 5.2000E+07 5.4000E+07 5.6000E+07
|
||||
5.8000E+07 6.0000E+07 6.2000E+07 6.4000E+07 6.6000E+07 6.8000E+07 7.0000E+07 7.2000E+07 7.4000E+07 7.6000E+07
|
||||
7.8000E+07 8.0000E+07 8.2000E+07 8.4000E+07 8.6000E+07 8.8000E+07 9.0000E+07 9.2000E+07 9.4000E+07 9.6000E+07
|
||||
9.8000E+07 1.0000E+08 1.0200E+08 1.0400E+08 1.0600E+08 1.0800E+08 1.1000E+08 1.1200E+08 1.1400E+08 1.1600E+08
|
||||
1.1800E+08 1.2000E+08 1.2200E+08 1.2400E+08 1.2600E+08 1.2800E+08 1.3000E+08 1.3200E+08 1.3400E+08 1.3600E+08
|
||||
1.3800E+08 1.4000E+08 1.4200E+08 1.4400E+08 1.4600E+08 1.4800E+08 1.5000E+08</bins>
|
||||
</filter>
|
||||
|
||||
<tally id="6">
|
||||
<filters>6 10 3</filters>
|
||||
<scores>flux </scores>
|
||||
</tally>
|
||||
|
||||
</tallies>
|
||||
6
tests/regression_tests/weightwindow/test.py
Normal file
6
tests/regression_tests/weightwindow/test.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
from tests.testing_harness import TestHarness
|
||||
|
||||
|
||||
def test_weight_window():
|
||||
harness = TestHarness('statepoint.2.h5')
|
||||
harness.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue