mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 21:55:41 -04:00
Merge pull request #696 from nelsonag/mesh
Support MGXS Tallied over a mesh in Library.create_mg_library and related
This commit is contained in:
commit
dd8d8d0aef
6 changed files with 368 additions and 122 deletions
|
|
@ -376,7 +376,7 @@ class Filter(object):
|
|||
cell instance ID for 'distribcell' Filters. The bin is a 2-tuple of
|
||||
floats for 'energy' and 'energyout' filters corresponding to the
|
||||
energy boundaries of the bin of interest. The bin is an (x,y,z)
|
||||
3-tuple for 'mesh' filters corresponding to the mesh cell
|
||||
3-tuple for 'mesh' filters corresponding to the mesh cell of
|
||||
interest.
|
||||
|
||||
Returns
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class Macroscopic(object):
|
|||
self._name = ''
|
||||
self._xs = None
|
||||
|
||||
# Set the Material class attributes
|
||||
# Set the Macroscopic class attributes
|
||||
self.name = name
|
||||
|
||||
if xs is not None:
|
||||
|
|
|
|||
124
openmc/mesh.py
124
openmc/mesh.py
|
|
@ -6,6 +6,7 @@ import sys
|
|||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
import openmc
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
|
|
@ -181,6 +182,33 @@ class Mesh(object):
|
|||
string += '{0: <16}{1}{2}\n'.format('\tPixels', '=\t', self._width)
|
||||
return string
|
||||
|
||||
def cell_generator(self):
|
||||
"""Generator function to traverse through every [i,j,k] index
|
||||
of the mesh.
|
||||
|
||||
For example the following code:
|
||||
for mesh_index in mymesh.cell_generator():
|
||||
print mesh_index
|
||||
|
||||
will produce the following output for a 3-D 2x2x2 mesh in mymesh:
|
||||
[1, 1, 1]
|
||||
[1, 1, 2]
|
||||
[1, 2, 1]
|
||||
[1, 2, 2]
|
||||
...
|
||||
|
||||
"""
|
||||
|
||||
if len(self.dimension) == 2:
|
||||
for x in range(self.dimension[0]):
|
||||
for y in range(self.dimension[1]):
|
||||
yield [x + 1, y + 1, 1]
|
||||
else:
|
||||
for x in range(self.dimension[0]):
|
||||
for y in range(self.dimension[1]):
|
||||
for z in range(self.dimension[2]):
|
||||
yield [x + 1, y + 1, z + 1]
|
||||
|
||||
def get_mesh_xml(self):
|
||||
"""Return XML representation of the mesh
|
||||
|
||||
|
|
@ -210,3 +238,99 @@ class Mesh(object):
|
|||
subelement.text = ' '.join(map(str, self._width))
|
||||
|
||||
return element
|
||||
|
||||
def build_cells(self, bc=['reflective'] * 6):
|
||||
"""Generates a lattice of universes with the same dimensionality
|
||||
as the mesh object. The individual cells/universes produced
|
||||
will not have material definitions applied and so downstream code
|
||||
will have to apply that information.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bc : iterable of {'reflective', 'periodic', 'transmission', or 'vacuum'}
|
||||
Boundary conditions for each of the four faces of a rectangle
|
||||
(if aplying to a 2D mesh) or six faces of a parallelepiped
|
||||
(if applying to a 3D mesh) provided in the following order:
|
||||
[x min, x max, y min, y max, z min, z max]. 2-D cells do not
|
||||
contain the z min and z max entries.
|
||||
|
||||
Returns
|
||||
-------
|
||||
root_cell : openmc.Cell
|
||||
The cell containing the lattice representing the mesh geometry;
|
||||
this cell is a single parallelepiped with boundaries matching
|
||||
the outermost mesh boundary with the boundary conditions from bc
|
||||
applied.
|
||||
cells : iterable of openmc.Cell
|
||||
The list of cells within each lattice position mimicking the mesh
|
||||
geometry.
|
||||
|
||||
"""
|
||||
|
||||
twod = len(self.dimension) == 2
|
||||
cv.check_length('bc', bc, length_min=4, length_max=6)
|
||||
for entry in bc:
|
||||
cv.check_value('bc', entry, ['transmission', 'vacuum',
|
||||
'reflective', 'periodic'])
|
||||
|
||||
# Build the cell which will contain the lattice
|
||||
xplanes = [openmc.XPlane(x0=self.lower_left[0],
|
||||
boundary_type=bc[0]),
|
||||
openmc.XPlane(x0=self.upper_right[0],
|
||||
boundary_type=bc[1])]
|
||||
yplanes = [openmc.YPlane(y0=self.lower_left[1],
|
||||
boundary_type=bc[2]),
|
||||
openmc.YPlane(y0=self.upper_right[1],
|
||||
boundary_type=bc[3])]
|
||||
if twod:
|
||||
zplanes = [openmc.ZPlane(z0=np.finfo(np.float).min,
|
||||
boundary_type='reflective'),
|
||||
openmc.ZPlane(z0=np.finfo(np.float).max,
|
||||
boundary_type='reflective')]
|
||||
else:
|
||||
zplanes = [openmc.ZPlane(z0=self.lower_left[2],
|
||||
boundary_type=bc[4]),
|
||||
openmc.ZPlane(z0=self.upper_right[2],
|
||||
boundary_type=bc[5])]
|
||||
root_cell = openmc.Cell()
|
||||
root_cell.region = ((+xplanes[0] & -xplanes[1]) &
|
||||
(+yplanes[0] & -yplanes[1]) &
|
||||
(+zplanes[0] & -zplanes[1]))
|
||||
|
||||
# Build the universes which will be used for each of the [i,j,k]
|
||||
# locations within the mesh.
|
||||
# We will also have to build cells to assign to these universes
|
||||
universes = np.ndarray(self.dimension[::-1], dtype=np.object)
|
||||
cells = []
|
||||
for [i, j, k] in self.cell_generator():
|
||||
if twod:
|
||||
universes[j - 1, i - 1] = openmc.Universe()
|
||||
cells.append(openmc.Cell())
|
||||
universes[j - 1, i - 1].add_cells([cells[-1]])
|
||||
else:
|
||||
universes[k - 1, j - 1, i - 1] = openmc.Universe()
|
||||
cells.append(openmc.Cell())
|
||||
universes[k - 1, j - 1, i - 1].add_cells([cells[-1]])
|
||||
|
||||
lattice = openmc.RectLattice()
|
||||
lattice.lower_left = self.lower_left
|
||||
|
||||
if self.width is not None:
|
||||
lattice.pitch = self.width
|
||||
else:
|
||||
dx = ((self.upper_right[0] - self.lower_left[0]) /
|
||||
self.dimension[0])
|
||||
dy = ((self.upper_right[1] - self.lower_left[1]) /
|
||||
self.dimension[1])
|
||||
if twod:
|
||||
lattice.pitch = [dx, dy]
|
||||
else:
|
||||
dz = ((self.upper_right[2] - self.lower_left[2]) /
|
||||
self.dimension[2])
|
||||
lattice.pitch = [dx, dy, dz]
|
||||
lattice.universes = universes
|
||||
|
||||
# Fill Cell with the Lattice
|
||||
root_cell.fill = lattice
|
||||
|
||||
return root_cell, cells
|
||||
|
|
|
|||
|
|
@ -823,7 +823,7 @@ class Library(object):
|
|||
|
||||
def get_xsdata(self, domain, xsdata_name, nuclide='total', xs_type='macro',
|
||||
xs_id='1m', order=None, tabular_legendre=None,
|
||||
tabular_points=33):
|
||||
tabular_points=33, subdomain=None):
|
||||
"""Generates an openmc.XSdata object describing a multi-group cross section
|
||||
data set for eventual combination in to an openmc.MGXSLibrary object
|
||||
(i.e., the library).
|
||||
|
|
@ -859,6 +859,12 @@ class Library(object):
|
|||
parameter is set to `True`. In this case, this parameter sets the
|
||||
number of equally-spaced points in the domain of [-1,1] to be used
|
||||
in building the tabular distribution. Default is `33`.
|
||||
subdomain : iterable of int
|
||||
This parameter is not used unless using a mesh domain. In that
|
||||
case, the subdomain is an [i,j,k] index (1-based indexing) of the
|
||||
mesh cell of interest in the openmc.Mesh object. Note:
|
||||
this parameter currently only supports subdomains within a mesh,
|
||||
and not the subdomains of a distribcell.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -878,7 +884,7 @@ class Library(object):
|
|||
"""
|
||||
|
||||
cv.check_type('domain', domain, (openmc.Material, openmc.Cell,
|
||||
openmc.Cell, openmc.Mesh))
|
||||
openmc.Universe, openmc.Mesh))
|
||||
cv.check_type('xsdata_name', xsdata_name, basestring)
|
||||
cv.check_type('nuclide', nuclide, basestring)
|
||||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
|
|
@ -891,6 +897,9 @@ class Library(object):
|
|||
(type(None), bool))
|
||||
if tabular_points is not None:
|
||||
cv.check_greater_than('tabular_points', tabular_points, 1)
|
||||
if subdomain is not None:
|
||||
cv.check_iterable_type('subdomain', subdomain, Integral,
|
||||
max_depth=3)
|
||||
|
||||
# Make sure statepoint has been loaded
|
||||
if self._sp_filename is None:
|
||||
|
|
@ -926,52 +935,66 @@ class Library(object):
|
|||
xsdata.zaid = self._nuclides[nuclide][0]
|
||||
xsdata.awr = self._nuclides[nuclide][1]
|
||||
|
||||
if subdomain is None:
|
||||
subdomain = 'all'
|
||||
else:
|
||||
subdomain = [subdomain]
|
||||
|
||||
# Now get xs data itself
|
||||
if 'nu-transport' in self.mgxs_types and self.correction == 'P0':
|
||||
mymgxs = self.get_mgxs(domain, 'nu-transport')
|
||||
xsdata.set_total_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide])
|
||||
xsdata.set_total_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide],
|
||||
subdomains=subdomain)
|
||||
elif 'total' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'total')
|
||||
xsdata.set_total_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide])
|
||||
xsdata.set_total_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
if 'absorption' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'absorption')
|
||||
xsdata.set_absorption_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
if 'fission' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'fission')
|
||||
xsdata.set_fission_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
nuclide=[nuclide], subdomain=subdomain)
|
||||
if 'kappa-fission' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'kappa-fission')
|
||||
xsdata.set_kappa_fission_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
# For chi and nu-fission we can either have only a nu-fission matrix
|
||||
# provided, or vectors of chi and nu-fission provided
|
||||
if 'nu-fission matrix' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'nu-fission matrix')
|
||||
xsdata.set_nu_fission_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
else:
|
||||
if 'chi' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'chi')
|
||||
xsdata.set_chi_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide])
|
||||
xsdata.set_chi_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
if 'nu-fission' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'nu-fission')
|
||||
xsdata.set_nu_fission_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
# If multiplicity matrix is available, prefer that
|
||||
if 'multiplicity matrix' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'multiplicity matrix')
|
||||
xsdata.set_multiplicity_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
using_multiplicity = True
|
||||
# multiplicity wil fall back to using scatter and nu-scatter
|
||||
# multiplicity will fall back to using scatter and nu-scatter
|
||||
elif ((('scatter matrix' in self.mgxs_types) and
|
||||
('nu-scatter matrix' in self.mgxs_types))):
|
||||
scatt_mgxs = self.get_mgxs(domain, 'scatter matrix')
|
||||
nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix')
|
||||
xsdata.set_multiplicity_mgxs(nuscatt_mgxs, scatt_mgxs,
|
||||
xs_type=xs_type, nuclide=[nuclide])
|
||||
xs_type=xs_type, nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
using_multiplicity = True
|
||||
else:
|
||||
using_multiplicity = False
|
||||
|
|
@ -979,12 +1002,13 @@ class Library(object):
|
|||
if using_multiplicity:
|
||||
nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix')
|
||||
xsdata.set_scatter_mgxs(nuscatt_mgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
nuclide=[nuclide], subdomain=subdomain)
|
||||
else:
|
||||
if 'nu-scatter matrix' in self.mgxs_types:
|
||||
nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix')
|
||||
xsdata.set_scatter_mgxs(nuscatt_mgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
nuclide=[nuclide],
|
||||
subdomain=subdomain)
|
||||
|
||||
# Since we are not using multiplicity, then
|
||||
# scattering multiplication (nu-scatter) must be
|
||||
|
|
@ -1055,15 +1079,6 @@ class Library(object):
|
|||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
if xsdata_names is not None:
|
||||
cv.check_iterable_type('xsdata_names', xsdata_names, basestring)
|
||||
if xs_ids is not None:
|
||||
if isinstance(xs_ids, basestring):
|
||||
# If we only have a string lets convert it now to a list
|
||||
# of strings.
|
||||
xs_ids = [xs_ids for i in range(len(self.domains))]
|
||||
else:
|
||||
cv.check_iterable_type('xs_ids', xs_ids, basestring)
|
||||
else:
|
||||
xs_ids = ['1m' for i in range(len(self.domains))]
|
||||
|
||||
# If gathering material-specific data, set the xs_type to macro
|
||||
if not self.by_nuclide:
|
||||
|
|
@ -1072,32 +1087,78 @@ class Library(object):
|
|||
# Initialize file
|
||||
mgxs_file = openmc.MGXSLibrary(self.energy_groups)
|
||||
|
||||
# Create the xsdata object and add it to the mgxs_file
|
||||
for i, domain in enumerate(self.domains):
|
||||
if self.by_nuclide:
|
||||
nuclides = domain.get_nuclides()
|
||||
# Get the number of domains to size arrays with
|
||||
if self.domain_type is 'mesh':
|
||||
num_domains = np.sum(d.num_mesh_cells for d in self.domains)
|
||||
else:
|
||||
num_domains = len(self.domains)
|
||||
|
||||
# Set id names
|
||||
if xs_ids is not None:
|
||||
if isinstance(xs_ids, basestring):
|
||||
# If we only have a string lets convert it now to a list
|
||||
# of strings.
|
||||
all_xs_ids = [xs_ids] * num_domains
|
||||
else:
|
||||
nuclides = ['total']
|
||||
for nuclide in nuclides:
|
||||
# Build & add metadata to XSdata object
|
||||
if xsdata_names is None:
|
||||
xsdata_name = 'set' + str(i + 1)
|
||||
cv.check_iterable_type('xs_ids', xs_ids, basestring)
|
||||
cv.check_length('xs_ids', xs_ids, num_domains, num_domains)
|
||||
all_xs_ids = xs_ids
|
||||
|
||||
else:
|
||||
all_xs_ids = ['1m'] * num_domains
|
||||
|
||||
if self.domain_type == 'mesh':
|
||||
# Create the xsdata objects and add to the mgxs_file
|
||||
i = 0
|
||||
for domain in self.domains:
|
||||
if self.by_nuclide:
|
||||
raise NotImplementedError("Mesh domains do not currently "
|
||||
"support nuclidic tallies")
|
||||
for subdomain in domain.cell_generator():
|
||||
# Build & add metadata to XSdata object
|
||||
if xsdata_names is None:
|
||||
xsdata_name = 'set' + str(i + 1)
|
||||
else:
|
||||
xsdata_name = xsdata_names[i]
|
||||
|
||||
# Create XSdata and Macroscopic for this domain
|
||||
xsdata = self.get_xsdata(domain, xsdata_name,
|
||||
xs_id=all_xs_ids[i],
|
||||
tabular_legendre=tabular_legendre,
|
||||
tabular_points=tabular_points,
|
||||
subdomain=subdomain)
|
||||
mgxs_file.add_xsdata(xsdata)
|
||||
i += 1
|
||||
|
||||
else:
|
||||
# Create the xsdata object and add it to the mgxs_file
|
||||
for i, domain in enumerate(self.domains):
|
||||
if self.by_nuclide:
|
||||
nuclides = domain.get_nuclides()
|
||||
else:
|
||||
xsdata_name = xsdata_names[i]
|
||||
if nuclide is not 'total':
|
||||
xsdata_name += '_' + nuclide
|
||||
nuclides = ['total']
|
||||
for nuclide in nuclides:
|
||||
# Build & add metadata to XSdata object
|
||||
if xsdata_names is None:
|
||||
xsdata_name = 'set' + str(i + 1)
|
||||
else:
|
||||
xsdata_name = xsdata_names[i]
|
||||
if nuclide is not 'total':
|
||||
xsdata_name += '_' + nuclide
|
||||
|
||||
xsdata = self.get_xsdata(domain, xsdata_name, nuclide=nuclide,
|
||||
xs_type=xs_type, xs_id=xs_ids[i],
|
||||
tabular_legendre=tabular_legendre,
|
||||
tabular_points=tabular_points)
|
||||
xsdata = self.get_xsdata(domain, xsdata_name,
|
||||
nuclide=nuclide, xs_type=xs_type,
|
||||
xs_id=all_xs_ids[i],
|
||||
tabular_legendre=tabular_legendre,
|
||||
tabular_points=tabular_points)
|
||||
|
||||
mgxs_file.add_xsdata(xsdata)
|
||||
mgxs_file.add_xsdata(xsdata)
|
||||
|
||||
return mgxs_file
|
||||
|
||||
def create_mg_mode(self, xsdata_names=None, xs_ids=None,
|
||||
tabular_legendre=None, tabular_points=33):
|
||||
tabular_legendre=None, tabular_points=33,
|
||||
bc=['reflective'] * 6):
|
||||
"""Creates an openmc.MGXSLibrary object to contain the MGXS data for the
|
||||
Multi-Group mode of OpenMC as well as the associated openmc.Materials
|
||||
and openmc.Geometry objects. The created Geometry is the same as that
|
||||
|
|
@ -1127,6 +1188,12 @@ class Library(object):
|
|||
parameter is set to `True`. In this case, this parameter sets the
|
||||
number of equally-spaced points in the domain of [-1,1] to be used
|
||||
in building the tabular distribution. Default is `33`.
|
||||
bc : iterable of {'reflective', 'periodic', 'transmission', or 'vacuum'}
|
||||
Boundary conditions for each of the four faces of a rectangle
|
||||
(if applying to a 2D mesh) or six faces of a parallelepiped
|
||||
(if applying to a 3D mesh) provided in the following order:
|
||||
[x min, x max, y min, y max, z min, z max]. 2-D cells do not
|
||||
contain the z min and z max entries.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -1157,62 +1224,77 @@ class Library(object):
|
|||
# multi-group cross section types
|
||||
self.check_library_for_openmc_mgxs()
|
||||
|
||||
if xsdata_names is not None:
|
||||
cv.check_iterable_type('xsdata_names', xsdata_names, basestring)
|
||||
if xs_ids is not None:
|
||||
if isinstance(xs_ids, basestring):
|
||||
# If we only have a string lets convert it now to a list
|
||||
# of strings.
|
||||
xs_ids = [xs_ids for i in range(len(self.domains))]
|
||||
else:
|
||||
cv.check_iterable_type('xs_ids', xs_ids, basestring)
|
||||
# If the domain type is a mesh, then there can only be one domain for
|
||||
# this method. This is because we can build a model automatically if
|
||||
# the user provided multiple mesh domains for library generation since
|
||||
# the multiple meshes could be overlapping or in disparate regions
|
||||
# of the continuous energy model. The next step makes sure there is
|
||||
# only one before continuing.
|
||||
if self.domain_type == 'mesh':
|
||||
cv.check_length("domains", self.domains, 1, 1)
|
||||
|
||||
# Get the MGXS File Data
|
||||
mgxs_file = self.create_mg_library('macro', xsdata_names, xs_ids,
|
||||
tabular_legendre, tabular_points)
|
||||
|
||||
# Now move on the creating the geometry and assigning materials
|
||||
if self.domain_type == 'mesh':
|
||||
root = openmc.Universe(name='root', universe_id=0)
|
||||
|
||||
# Add cells representative of the mesh with reflective BC
|
||||
root_cell, cells = \
|
||||
self.domains[0].build_cells(bc)
|
||||
root.add_cell(root_cell)
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
materials = openmc.Materials()
|
||||
|
||||
for i, subdomain in enumerate(self.domains[0].cell_generator()):
|
||||
xsdata = mgxs_file.xsdatas[i]
|
||||
[name, id] = xsdata.name.split('.')
|
||||
# Build the macroscopic and assign it to the cell of
|
||||
# interest
|
||||
macroscopic = openmc.Macroscopic(name=name, xs=id)
|
||||
|
||||
# Create Material and add to collection
|
||||
material = openmc.Material(name=xsdata.name)
|
||||
material.add_macroscopic(macroscopic)
|
||||
materials.append(material)
|
||||
|
||||
# Set the materials for each of the universes
|
||||
cells[i].fill = materials[i]
|
||||
|
||||
else:
|
||||
xs_ids = ['1m' for i in range(len(self.domains))]
|
||||
xs_type = 'macro'
|
||||
# Create a copy of the Geometry for these Macroscopics
|
||||
geometry = copy.deepcopy(self.openmc_geometry)
|
||||
materials = openmc.Materials()
|
||||
|
||||
# Initialize MGXS File
|
||||
mgxs_file = openmc.MGXSLibrary(self.energy_groups)
|
||||
# Get all Cells from the Geometry for differentiation
|
||||
all_cells = geometry.get_all_material_cells()
|
||||
|
||||
# Create a copy of the Geometry to differentiate for these Macroscopics
|
||||
geometry = copy.deepcopy(self.openmc_geometry)
|
||||
materials = openmc.Materials()
|
||||
# Create the xsdata object and add it to the mgxs_file
|
||||
for i, domain in enumerate(self.domains):
|
||||
xsdata = mgxs_file.xsdatas[i]
|
||||
[name, id] = xsdata.name.split('.')
|
||||
|
||||
# Get all Cells from the Geometry for differentiation
|
||||
all_cells = geometry.get_all_material_cells()
|
||||
macroscopic = openmc.Macroscopic(name=name, xs=id)
|
||||
|
||||
# Create the xsdata object and add it to the mgxs_file
|
||||
for i, domain in enumerate(self.domains):
|
||||
# Create Material and add to collection
|
||||
material = openmc.Material(name=xsdata.name)
|
||||
material.add_macroscopic(macroscopic)
|
||||
materials.append(material)
|
||||
|
||||
# Build & add metadata to XSdata object
|
||||
if xsdata_names is None:
|
||||
xsdata_name = 'set' + str(i + 1)
|
||||
else:
|
||||
xsdata_name = xsdata_names[i]
|
||||
# Differentiate Geometry with new Material
|
||||
if self.domain_type == 'material':
|
||||
# Fill all appropriate Cells with new Material
|
||||
for cell in all_cells:
|
||||
if cell.fill.id == domain.id:
|
||||
cell.fill = material
|
||||
|
||||
# Create XSdata and Macroscopic for this domain
|
||||
xsdata = self.get_xsdata(domain, xsdata_name, nuclide='total',
|
||||
xs_type=xs_type, xs_id=xs_ids[i],
|
||||
tabular_legendre=tabular_legendre,
|
||||
tabular_points=tabular_points)
|
||||
mgxs_file.add_xsdata(xsdata)
|
||||
macroscopic = openmc.Macroscopic(name=xsdata_name, xs=xs_ids[i])
|
||||
|
||||
# Create Material and add to collection
|
||||
material = openmc.Material(name=xsdata_name + '.' + xs_ids[i])
|
||||
material.add_macroscopic(macroscopic)
|
||||
materials.append(material)
|
||||
|
||||
# Differentiate Geometry with new Material
|
||||
if self.domain_type == 'material':
|
||||
# Fill all appropriate Cells with new Material
|
||||
for cell in all_cells:
|
||||
if cell.fill.id == domain.id:
|
||||
cell.fill = material
|
||||
|
||||
elif self.domain_type == 'cell':
|
||||
for cell in all_cells:
|
||||
if cell.id == domain.id:
|
||||
cell.fill = material
|
||||
elif self.domain_type == 'cell':
|
||||
for cell in all_cells:
|
||||
if cell.id == domain.id:
|
||||
cell.fill = material
|
||||
|
||||
return mgxs_file, materials, geometry
|
||||
|
||||
|
|
|
|||
|
|
@ -777,7 +777,8 @@ class MGXS(object):
|
|||
|
||||
# Construct a collection of the domain filter bins
|
||||
if not isinstance(subdomains, basestring):
|
||||
cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3)
|
||||
cv.check_iterable_type('subdomains', subdomains, Integral,
|
||||
max_depth=3)
|
||||
for subdomain in subdomains:
|
||||
filters.append(self.domain_type)
|
||||
filter_bins.append((subdomain,))
|
||||
|
|
|
|||
|
|
@ -603,7 +603,8 @@ class XSdata(object):
|
|||
if np.sum(self._nu_fission) > 0.0:
|
||||
self._fissionable = True
|
||||
|
||||
def set_total_mgxs(self, total, nuclide='total', xs_type='macro'):
|
||||
def set_total_mgxs(self, total, nuclide='total', xs_type='macro',
|
||||
subdomain='all'):
|
||||
"""This method allows for an openmc.mgxs.TotalXS or
|
||||
openmc.mgxs.TransportXS to be used to set the total cross section
|
||||
for this XSdata object.
|
||||
|
|
@ -619,6 +620,9 @@ class XSdata(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'.
|
||||
subdomain : iterable of int
|
||||
If the MGXS contains a mesh domain type, the subdomain parameter
|
||||
specifies which mesh cell (i.e., [i, j, k] index) to use.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -631,16 +635,17 @@ class XSdata(object):
|
|||
openmc.mgxs.TransportXS))
|
||||
check_value('energy_groups', total.energy_groups, [self.energy_groups])
|
||||
check_value('domain_type', total.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
|
||||
if self.representation is 'isotropic':
|
||||
self._total = total.get_xs(nuclides=nuclide, xs_type=xs_type)
|
||||
self._total = total.get_xs(nuclides=nuclide, xs_type=xs_type,
|
||||
subdomains=subdomain)
|
||||
elif self.representation is 'angle':
|
||||
msg = 'Angular-Dependent MGXS have not yet been implemented'
|
||||
raise ValueError(msg)
|
||||
|
||||
def set_absorption_mgxs(self, absorption, nuclide='total',
|
||||
xs_type='macro'):
|
||||
xs_type='macro', subdomain=None):
|
||||
"""This method allows for an openmc.mgxs.AbsorptionXS
|
||||
to be used to set the absorption cross section for this XSdata object.
|
||||
|
||||
|
|
@ -655,6 +660,9 @@ class XSdata(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'.
|
||||
subdomain : iterable of int
|
||||
If the MGXS contains a mesh domain type, the subdomain parameter
|
||||
specifies which mesh cell (i.e., [i, j, k] index) to use.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -667,16 +675,18 @@ class XSdata(object):
|
|||
check_value('energy_groups', absorption.energy_groups,
|
||||
[self.energy_groups])
|
||||
check_value('domain_type', absorption.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
|
||||
if self.representation is 'isotropic':
|
||||
self._absorption = absorption.get_xs(nuclides=nuclide,
|
||||
xs_type=xs_type)
|
||||
xs_type=xs_type,
|
||||
subdomains=subdomain)
|
||||
elif self.representation is 'angle':
|
||||
msg = 'Angular-Dependent MGXS have not yet been implemented'
|
||||
raise ValueError(msg)
|
||||
|
||||
def set_fission_mgxs(self, fission, nuclide='total', xs_type='macro'):
|
||||
def set_fission_mgxs(self, fission, nuclide='total', xs_type='macro',
|
||||
subdomain=None):
|
||||
"""This method allows for an openmc.mgxs.FissionXS
|
||||
to be used to set the fission cross section for this XSdata object.
|
||||
|
||||
|
|
@ -691,6 +701,9 @@ class XSdata(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'.
|
||||
subdomain : iterable of int
|
||||
If the MGXS contains a mesh domain type, the subdomain parameter
|
||||
specifies which mesh cell (i.e., [i, j, k] index) to use.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -703,17 +716,18 @@ class XSdata(object):
|
|||
check_value('energy_groups', fission.energy_groups,
|
||||
[self.energy_groups])
|
||||
check_value('domain_type', fission.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
|
||||
if self.representation is 'isotropic':
|
||||
self._fission = fission.get_xs(nuclides=nuclide,
|
||||
xs_type=xs_type)
|
||||
xs_type=xs_type,
|
||||
subdomains=subdomain)
|
||||
elif self.representation is 'angle':
|
||||
msg = 'Angular-Dependent MGXS have not yet been implemented'
|
||||
raise ValueError(msg)
|
||||
|
||||
def set_nu_fission_mgxs(self, nu_fission, nuclide='total',
|
||||
xs_type='macro'):
|
||||
xs_type='macro', subdomain=None):
|
||||
"""This method allows for an openmc.mgxs.NuFissionXS
|
||||
to be used to set the nu-fission cross section for this XSdata object.
|
||||
|
||||
|
|
@ -728,6 +742,9 @@ class XSdata(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'.
|
||||
subdomain : iterable of int
|
||||
If the MGXS contains a mesh domain type, the subdomain parameter
|
||||
specifies which mesh cell (i.e., [i, j, k] index) to use.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -741,11 +758,12 @@ class XSdata(object):
|
|||
check_value('energy_groups', nu_fission.energy_groups,
|
||||
[self.energy_groups])
|
||||
check_value('domain_type', nu_fission.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
|
||||
if self.representation is 'isotropic':
|
||||
self._nu_fission = nu_fission.get_xs(nuclides=nuclide,
|
||||
xs_type=xs_type)
|
||||
xs_type=xs_type,
|
||||
subdomains=subdomain)
|
||||
elif self.representation is 'angle':
|
||||
msg = 'Angular-Dependent MGXS have not yet been implemented'
|
||||
raise ValueError(msg)
|
||||
|
|
@ -759,7 +777,7 @@ class XSdata(object):
|
|||
self._fissionable = True
|
||||
|
||||
def set_kappa_fission_mgxs(self, k_fission, nuclide='total',
|
||||
xs_type='macro'):
|
||||
xs_type='macro', subdomain=None):
|
||||
"""This method allows for an openmc.mgxs.KappaFissionXS
|
||||
to be used to set the kappa-fission cross section for this XSdata
|
||||
object.
|
||||
|
|
@ -775,6 +793,9 @@ class XSdata(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'.
|
||||
subdomain : iterable of int
|
||||
If the MGXS contains a mesh domain type, the subdomain parameter
|
||||
specifies which mesh cell (i.e., [i, j, k] index) to use.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -787,16 +808,18 @@ class XSdata(object):
|
|||
check_value('energy_groups', k_fission.energy_groups,
|
||||
[self.energy_groups])
|
||||
check_value('domain_type', k_fission.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
|
||||
if self.representation is 'isotropic':
|
||||
self._kappa_fission = k_fission.get_xs(nuclides=nuclide,
|
||||
xs_type=xs_type)
|
||||
xs_type=xs_type,
|
||||
subdomains=subdomain)
|
||||
elif self.representation is 'angle':
|
||||
msg = 'Angular-Dependent MGXS have not yet been implemented'
|
||||
raise ValueError(msg)
|
||||
|
||||
def set_chi_mgxs(self, chi, nuclide='total', xs_type='macro'):
|
||||
def set_chi_mgxs(self, chi, nuclide='total', xs_type='macro',
|
||||
subdomain=None):
|
||||
"""This method allows for an openmc.mgxs.Chi
|
||||
to be used to set chi for this XSdata object.
|
||||
|
||||
|
|
@ -810,6 +833,9 @@ class XSdata(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'.
|
||||
subdomain : iterable of int
|
||||
If the MGXS contains a mesh domain type, the subdomain parameter
|
||||
specifies which mesh cell (i.e., [i, j, k] index) to use.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -827,11 +853,11 @@ class XSdata(object):
|
|||
check_type('chi', chi, openmc.mgxs.Chi)
|
||||
check_value('energy_groups', chi.energy_groups, [self.energy_groups])
|
||||
check_value('domain_type', chi.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
|
||||
if self.representation is 'isotropic':
|
||||
self._chi = chi.get_xs(nuclides=nuclide,
|
||||
xs_type=xs_type)
|
||||
xs_type=xs_type, subdomains=subdomain)
|
||||
elif self.representation is 'angle':
|
||||
msg = 'Angular-Dependent MGXS have not yet been implemented'
|
||||
raise ValueError(msg)
|
||||
|
|
@ -839,7 +865,8 @@ class XSdata(object):
|
|||
if self.use_chi is not None:
|
||||
self.use_chi = True
|
||||
|
||||
def set_scatter_mgxs(self, scatter, nuclide='total', xs_type='macro'):
|
||||
def set_scatter_mgxs(self, scatter, nuclide='total', xs_type='macro',
|
||||
subdomain=None):
|
||||
"""This method allows for an openmc.mgxs.ScatterMatrixXS
|
||||
to be used to set the scatter matrix cross section for this XSdata
|
||||
object. If the XSdata.order attribute has not yet been set, then
|
||||
|
|
@ -856,6 +883,9 @@ class XSdata(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'.
|
||||
subdomain : iterable of int
|
||||
If the MGXS contains a mesh domain type, the subdomain parameter
|
||||
specifies which mesh cell (i.e., [i, j, k] index) to use.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -868,7 +898,7 @@ class XSdata(object):
|
|||
check_value('energy_groups', scatter.energy_groups,
|
||||
[self.energy_groups])
|
||||
check_value('domain_type', scatter.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
|
||||
if self.scatt_type != 'legendre':
|
||||
msg = 'Anisotropic scattering representations other than ' \
|
||||
|
|
@ -892,16 +922,16 @@ class XSdata(object):
|
|||
self.energy_groups.num_groups,
|
||||
self.energy_groups.num_groups))
|
||||
for moment in range(self.num_orders):
|
||||
self._scatter[moment, :, :] = scatter.get_xs(nuclides=nuclide,
|
||||
xs_type=xs_type,
|
||||
moment=moment)
|
||||
self._scatter[moment, :, :] = \
|
||||
scatter.get_xs(nuclides=nuclide, xs_type=xs_type,
|
||||
moment=moment, subdomains=subdomain)
|
||||
|
||||
elif self.representation is 'angle':
|
||||
msg = 'Angular-Dependent MGXS have not yet been implemented'
|
||||
raise ValueError(msg)
|
||||
|
||||
def set_multiplicity_mgxs(self, nuscatter, scatter=None, nuclide='total',
|
||||
xs_type='macro'):
|
||||
xs_type='macro', subdomain=None):
|
||||
"""This method allows for either the direct use of only an
|
||||
openmc.mgxs.MultiplicityMatrixXS OR an openmc.mgxs.NuScatterMatrixXS and
|
||||
openmc.mgxs.ScatterMatrixXS to be used to set the scattering
|
||||
|
|
@ -926,6 +956,9 @@ class XSdata(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'.
|
||||
subdomain : iterable of int
|
||||
If the MGXS contains a mesh domain type, the subdomain parameter
|
||||
specifies which mesh cell (i.e., [i, j, k] index) to use.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -939,7 +972,7 @@ class XSdata(object):
|
|||
check_value('energy_groups', nuscatter.energy_groups,
|
||||
[self.energy_groups])
|
||||
check_value('domain_type', nuscatter.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
if scatter is not None:
|
||||
check_type('scatter', scatter, openmc.mgxs.ScatterMatrixXS)
|
||||
if isinstance(nuscatter, openmc.mgxs.MultiplicityMatrixXS):
|
||||
|
|
@ -950,16 +983,18 @@ class XSdata(object):
|
|||
check_value('energy_groups', scatter.energy_groups,
|
||||
[self.energy_groups])
|
||||
check_value('domain_type', scatter.domain_type,
|
||||
['universe', 'cell', 'material'])
|
||||
['universe', 'cell', 'material', 'mesh'])
|
||||
|
||||
if self.representation is 'isotropic':
|
||||
nuscatt = nuscatter.get_xs(nuclides=nuclide,
|
||||
xs_type=xs_type, moment=0)
|
||||
xs_type=xs_type, moment=0,
|
||||
subdomains=subdomain)
|
||||
if isinstance(nuscatter, openmc.mgxs.MultiplicityMatrixXS):
|
||||
self._multiplicity = nuscatt
|
||||
else:
|
||||
scatt = scatter.get_xs(nuclides=nuclide,
|
||||
xs_type=xs_type, moment=0)
|
||||
xs_type=xs_type, moment=0,
|
||||
subdomains=subdomain)
|
||||
self._multiplicity = np.divide(nuscatt, scatt)
|
||||
elif self.representation is 'angle':
|
||||
msg = 'Angular-Dependent MGXS have not yet been implemented'
|
||||
|
|
@ -1085,6 +1120,10 @@ class MGXSLibrary(object):
|
|||
def energy_groups(self):
|
||||
return self._energy_groups
|
||||
|
||||
@property
|
||||
def xsdatas(self):
|
||||
return self._xsdatas
|
||||
|
||||
@inverse_velocities.setter
|
||||
def inverse_velocities(self, inverse_velocities):
|
||||
check_type('inverse_velocities', inverse_velocities, Iterable, Real)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue