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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ list(APPEND libopenmc_SOURCES
src/tallies/filter_polar.cpp
src/tallies/filter_reaction.cpp
src/tallies/filter_sph_harm.cpp
src/tallies/filter_sptl_fourier.cpp
src/tallies/filter_sptl_legendre.cpp
src/tallies/filter_surface.cpp
src/tallies/filter_time.cpp
Expand Down
6 changes: 6 additions & 0 deletions include/openmc/capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ int openmc_set_n_batches(
int openmc_simulation_finalize();
int openmc_simulation_init();
int openmc_source_bank(void** ptr, int64_t* n);
int openmc_spatial_fourier_filter_get_order(int32_t index, int* order);
int openmc_spatial_fourier_filter_get_params(
int32_t index, int* axis, double* min, double* max);
int openmc_spatial_fourier_filter_set_order(int32_t index, int order);
int openmc_spatial_fourier_filter_set_params(
int32_t index, const int* axis, const double* min, const double* max);
int openmc_spatial_legendre_filter_get_order(int32_t index, int* order);
int openmc_spatial_legendre_filter_get_params(
int32_t index, int* axis, double* min, double* max);
Expand Down
1 change: 1 addition & 0 deletions include/openmc/tallies/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum class FilterType {
POLAR,
REACTION,
SPHERICAL_HARMONICS,
SPATIAL_FOURIER,
SPATIAL_LEGENDRE,
SURFACE,
TIME,
Expand Down
68 changes: 68 additions & 0 deletions include/openmc/tallies/filter_sptl_fourier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#ifndef OPENMC_TALLIES_FILTER_SPTL_FOURIER_H
#define OPENMC_TALLIES_FILTER_SPTL_FOURIER_H

#include <string>

#include "openmc/tallies/filter.h"

namespace openmc {

enum class FourierAxis { x, y, z };

//==============================================================================
//! Gives Fourier moments of the particle's normalized position along an axis
//==============================================================================

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

~SpatialFourierFilter() = default;

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

std::string type_str() const override { return "spatialfourier"; }
FilterType type() const override { return FilterType::SPATIAL_FOURIER; }

void from_xml(pugi::xml_node node) override;

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

void to_statepoint(hid_t filter_group) const override;

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

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

int order() const { return order_; }
void set_order(int order);

FourierAxis axis() const { return axis_; }
void set_axis(FourierAxis axis);

double min() const { return min_; }
double max() const { return max_; }
void set_minmax(double min, double max);

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

int order_;

//! The Cartesian coordinate axis that the Fourier expansion is applied to.
FourierAxis axis_;

//! The minimum coordinate along the reference axis that the expansion covers.
double min_;

//! The maximum coordinate along the reference axis that the expansion covers.
double max_;
};

} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_SPTL_FOURIER_H
3 changes: 2 additions & 1 deletion openmc/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
'universe', 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy',
'energyout', 'mu', 'musurface', 'polar', 'azimuthal', 'distribcell',
'delayedgroup', 'energyfunction', 'cellfrom', 'materialfrom', 'legendre',
'spatiallegendre', 'sphericalharmonics', 'zernike', 'zernikeradial', 'particle',
'spatialfourier', 'spatiallegendre', 'sphericalharmonics',
'zernike', 'zernikeradial', 'particle',
'particleproduction', 'cellinstance', 'collision', 'time', 'parentnuclide',
'weight', 'meshborn', 'meshsurface', 'meshmaterial', 'reaction',
)
Expand Down
144 changes: 115 additions & 29 deletions openmc/filter_expansion.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,18 @@ def from_hdf5(cls, group, **kwargs):
return out


class SpatialLegendreFilter(ExpansionFilter):
r"""Score Legendre expansion moments in space up to specified order.

This filter allows scores to be multiplied by Legendre polynomials of the
the particle's position along a particular axis, normalized to a given
range, up to a user-specified order.
class SpatialExpansionFilter(ExpansionFilter):
"""Abstract base class for spatial functional expansion filters.

This class provides common functionality for filters that expand
tally data along a spatial axis (x, y, or z) within a bounded region.
Subclasses must implement the order setter to define their specific
bin structure.

Parameters
----------
order : int
Maximum Legendre polynomial order
Maximum expansion order
axis : {'x', 'y', 'z'}
Axis along which to take the expansion
minimum : float
Expand All @@ -160,7 +161,7 @@ class SpatialLegendreFilter(ExpansionFilter):
Attributes
----------
order : int
Maximum Legendre polynomial order
Maximum expansion order
axis : {'x', 'y', 'z'}
Axis along which to take the expansion
minimum : float
Expand Down Expand Up @@ -197,11 +198,6 @@ def __repr__(self):
string += '{: <16}=\t{}\n'.format('\tID', self.id)
return string

@ExpansionFilter.order.setter
def order(self, order):
ExpansionFilter.order.__set__(self, order)
self.bins = [f'P{i}' for i in range(order + 1)]

@property
def axis(self):
return self._axis
Expand Down Expand Up @@ -229,27 +225,13 @@ def maximum(self, maximum):
cv.check_type('maximum', maximum, Real)
self._maximum = maximum

@classmethod
def from_hdf5(cls, group, **kwargs):
if group['type'][()].decode() != cls.short_name.lower():
raise ValueError("Expected HDF5 data for filter type '"
+ cls.short_name.lower() + "' but got '"
+ group['type'][()].decode() + " instead")

filter_id = int(group.name.split('/')[-1].lstrip('filter '))
order = group['order'][()]
axis = group['axis'][()].decode()
min_, max_ = group['min'][()], group['max'][()]

return cls(order, axis, min_, max_, filter_id)

def to_xml_element(self):
"""Return XML Element representing the filter.

Returns
-------
element : lxml.etree._Element
XML element containing Legendre filter data
XML element containing spatial expansion filter data

"""
element = super().to_xml_element()
Expand All @@ -259,7 +241,6 @@ def to_xml_element(self):
subelement.text = str(self.minimum)
subelement = ET.SubElement(element, 'max')
subelement.text = str(self.maximum)

return element

@classmethod
Expand All @@ -271,6 +252,111 @@ def from_xml_element(cls, elem, **kwargs):
maximum = float(get_text(elem, "max"))
return cls(order, axis, minimum, maximum, filter_id=filter_id)

@classmethod
def from_hdf5(cls, group, **kwargs):
if group['type'][()].decode() != cls.short_name.lower():
raise ValueError("Expected HDF5 data for filter type '"
+ cls.short_name.lower() + "' but got '"
+ group['type'][()].decode() + " instead")

filter_id = int(group.name.split('/')[-1].lstrip('filter '))
order = group['order'][()]
axis = group['axis'][()].decode()
min_, max_ = group['min'][()], group['max'][()]

return cls(order, axis, min_, max_, filter_id)


class SpatialFourierFilter(SpatialExpansionFilter):
r"""Score Fourier expansion moments in space up to specified order.

This filter allows scores to be multiplied by Fourier basis functions of
the particle's position along a particular axis, normalized to a given
range, up to a user-specified order.

Parameters
----------
order : int
Maximum Fourier expansion order
axis : {'x', 'y', 'z'}
Axis along which to take the expansion
minimum : float
Minimum value along selected axis
maximum : float
Maximum value along selected axis
filter_id : int or None
Unique identifier for the filter

Attributes
----------
order : int
Maximum Fourier expansion order
axis : {'x', 'y', 'z'}
Axis along which to take the expansion
minimum : float
Minimum value along selected axis
maximum : float
Maximum value along selected axis
id : int
Unique identifier for the filter
num_bins : int
The number of filter bins (2*order + 1)

"""

@ExpansionFilter.order.setter
def order(self, order):
ExpansionFilter.order.__set__(self, order)
self.bins = ['a0 (constant)'] + [None]*2*order
for i in range(1, order + 1):
a = 2*i - 1
b = 2*i
self.bins[a] = f'a{i} (cos)'
self.bins[b] = f'b{i} (sin)'


class SpatialLegendreFilter(SpatialExpansionFilter):
r"""Score Legendre expansion moments in space up to specified order.

This filter allows scores to be multiplied by Legendre polynomials of the
the particle's position along a particular axis, normalized to a given
range, up to a user-specified order.

Parameters
----------
order : int
Maximum Legendre polynomial order
axis : {'x', 'y', 'z'}
Axis along which to take the expansion
minimum : float
Minimum value along selected axis
maximum : float
Maximum value along selected axis
filter_id : int or None
Unique identifier for the filter

Attributes
----------
order : int
Maximum Legendre polynomial order
axis : {'x', 'y', 'z'}
Axis along which to take the expansion
minimum : float
Minimum value along selected axis
maximum : float
Maximum value along selected axis
id : int
Unique identifier for the filter
num_bins : int
The number of filter bins

"""

@ExpansionFilter.order.setter
def order(self, order):
ExpansionFilter.order.__set__(self, order)
self.bins = [f'P{i}' for i in range(order + 1)]


class SphericalHarmonicsFilter(ExpansionFilter):
r"""Score spherical harmonic expansion moments up to specified order.
Expand Down
21 changes: 20 additions & 1 deletion openmc/lib/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
'MaterialFilter', 'MaterialFromFilter', 'MeshFilter', 'MeshBornFilter',
'MeshMaterialFilter', 'MeshSurfaceFilter', 'MuFilter', 'MuSurfaceFilter',
'ParentNuclideFilter', 'ParticleFilter', 'ParticleProductionFilter', 'PolarFilter',
'ReactionFilter', 'SphericalHarmonicsFilter', 'SpatialLegendreFilter',
'ReactionFilter', 'SphericalHarmonicsFilter', 'SpatialFourierFilter', 'SpatialLegendreFilter',
'SurfaceFilter', 'TimeFilter', 'UniverseFilter', 'WeightFilter', 'ZernikeFilter',
'ZernikeRadialFilter', 'filters'
]
Expand Down Expand Up @@ -639,6 +639,25 @@ def order(self, order):
_dll.openmc_sphharm_filter_set_order(self._index, order)


class SpatialFourierFilter(Filter):
filter_type = 'spatialfourier'

def __init__(self, order=None, uid=None, new=True, index=None):
super().__init__(uid, new, index)
if order is not None:
self.order = order

@property
def order(self):
temp_order = c_int()
_dll.openmc_spatial_fourier_filter_get_order(self._index, temp_order)
return temp_order.value

@order.setter
def order(self, order):
_dll.openmc_spatial_fourier_filter_set_order(self._index, order)


class SpatialLegendreFilter(Filter):
filter_type = 'spatiallegendre'

Expand Down
3 changes: 3 additions & 0 deletions src/tallies/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "openmc/tallies/filter_polar.h"
#include "openmc/tallies/filter_reaction.h"
#include "openmc/tallies/filter_sph_harm.h"
#include "openmc/tallies/filter_sptl_fourier.h"
#include "openmc/tallies/filter_sptl_legendre.h"
#include "openmc/tallies/filter_surface.h"
#include "openmc/tallies/filter_time.h"
Expand Down Expand Up @@ -156,6 +157,8 @@ Filter* Filter::create(const std::string& type, int32_t id)
return Filter::create<ReactionFilter>(id);
} else if (type == "surface") {
return Filter::create<SurfaceFilter>(id);
} else if (type == "spatialfourier") {
return Filter::create<SpatialFourierFilter>(id);
} else if (type == "spatiallegendre") {
return Filter::create<SpatialLegendreFilter>(id);
} else if (type == "sphericalharmonics") {
Expand Down
Loading
Loading