diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 1a0569148b..457c5efd8f 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -204,20 +204,22 @@ should be used: Compiling with MPI ++++++++++++++++++ -To compile with MPI, set the :envvar:`FC` environment variable to the path to -the MPI Fortran wrapper. For example, in a bash shell: +To compile with MPI, set the :envvar:`FC` and :envvar:`CC` environment variables +to the path to the MPI Fortran and C wrappers, respectively. For example, in a +bash shell: .. code-block:: sh export FC=mpif90 + export CC=mpicc cmake /path/to/openmc -Note that in many shells, an environment variable can be set for a single -command, i.e. +Note that in many shells, environment variables can be set for a single command, +i.e. .. code-block:: sh - FC=mpif90 cmake /path/to/openmc + FC=mpif90 CC=mpicc cmake /path/to/openmc Selecting HDF5 Installation +++++++++++++++++++++++++++ @@ -343,7 +345,7 @@ compiler, it is necessary to specify that all objects be compiled with the .. code-block:: sh mkdir build && cd build - FC=ifort FFLAGS=-mmic cmake -Dopenmp=on .. + FC=ifort CC=icc FFLAGS=-mmic cmake -Dopenmp=on .. make Note that unless an HDF5 build for the Intel Xeon Phi is already on your target diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index d729e41ecc..34981e566b 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -34,6 +34,7 @@ _THERMAL_NAMES = {'al': 'c_Al27', 'al27': 'c_Al27', 'orthod': 'c_ortho_D', 'dortho': 'c_ortho_D', 'orthoh': 'c_ortho_H', 'hortho': 'c_ortho_H', 'ouo2': 'c_O_in_UO2', 'o2-u': 'c_O_in_UO2', 'o2/u': 'c_O_in_UO2', + 'sio2': 'c_SiO2', 'parad': 'c_para_D', 'dpara': 'c_para_D', 'parah': 'c_para_H', 'hpara': 'c_para_H', 'sch4': 'c_solid_CH4', 'smeth': 'c_solid_CH4', diff --git a/openmc/filter.py b/openmc/filter.py index 256674af3e..9b4eb67dd2 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -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 diff --git a/openmc/macroscopic.py b/openmc/macroscopic.py index 1dd087903f..9f55998e3a 100644 --- a/openmc/macroscopic.py +++ b/openmc/macroscopic.py @@ -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: diff --git a/openmc/mesh.py b/openmc/mesh.py index 169e7705cc..58b9c7c0e5 100644 --- a/openmc/mesh.py +++ b/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 diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index bf1195f1a9..9e5dba310c 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -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 diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 0a2f898c07..5e5d840b6c 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -793,7 +793,8 @@ class MDGXS(MGXS): df.rename(columns={'energyout low [MeV]': 'group out'}, inplace=True) - out_groups = np.tile(all_groups, int(df.shape[0] / all_groups.size)) + out_groups = np.repeat(all_groups, self.xs_tally.num_scores) + out_groups = np.tile(out_groups, int(df.shape[0] / out_groups.size)) df['group out'] = out_groups del df['energyout high [MeV]'] columns = ['group in', 'group out'] diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 5d12be0b0a..de7475308c 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -548,12 +548,6 @@ class MGXS(object): float The atomic number density (atom/b-cm) for the nuclide of interest - Raises - ------- - ValueError - When the density is requested for a nuclide which is not found in - the spatial domain. - """ cv.check_type('nuclide', nuclide, basestring) @@ -561,13 +555,7 @@ class MGXS(object): # Get list of all nuclides in the spatial domain nuclides = self.domain.get_nuclide_densities() - if nuclide not in nuclides: - msg = 'Unable to get density for nuclide "{0}" which is not in ' \ - '{1} "{2}"'.format(nuclide, self.domain_type, self.domain.id) - ValueError(msg) - - density = nuclides[nuclide][1] - return density + return nuclides[nuclide][1] if nuclide in nuclides else 0.0 def get_nuclide_densities(self, nuclides='all'): """Get an array of atomic number densities in units of atom/b-cm for all @@ -789,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,)) @@ -1535,7 +1524,8 @@ class MGXS(object): df.rename(columns={'energyout low [MeV]': 'group out'}, inplace=True) - out_groups = np.tile(all_groups, int(df.shape[0] / all_groups.size)) + out_groups = np.repeat(all_groups, self.xs_tally.num_scores) + out_groups = np.tile(out_groups, int(df.shape[0] / out_groups.size)) df['group out'] = out_groups del df['energyout high [MeV]'] columns = ['group in', 'group out'] @@ -1573,6 +1563,10 @@ class MGXS(object): df['mean'] /= np.tile(densities, tile_factor) df['std. dev.'] /= np.tile(densities, tile_factor) + # Replace NaNs by zeros (happens if nuclide density is zero) + df['mean'].replace(np.nan, 0.0, inplace=True) + df['std. dev.'].replace(np.nan, 0.0, inplace=True) + # Sort the dataframe by domain type id (e.g., distribcell id) and # energy groups such that data is from fast to thermal if self.domain_type == 'mesh': diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index 6f8188b101..a3a2187b75 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -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) diff --git a/openmc/opencg_compatible.py b/openmc/opencg_compatible.py index 58ce0d0c29..8983f5fa05 100644 --- a/openmc/opencg_compatible.py +++ b/openmc/opencg_compatible.py @@ -997,13 +997,17 @@ def get_opencg_geometry(openmc_geometry): return opencg_geometry -def get_openmc_geometry(opencg_geometry): +def get_openmc_geometry(opencg_geometry, compatible=False): """Return an OpenMC geometry corresponding to an OpenCG geometry. Parameters ---------- opencg_geometry : opencg.Geometry OpenCG geometry + compatible : bool + Whether the OpenCG geometry is compatible with OpenMC's geometric + primitives. This should be set to False if the OpenCG geometry + uses SquarePrism surfaces. False by default. Returns ------- @@ -1019,9 +1023,6 @@ def get_openmc_geometry(opencg_geometry): opencg_geometry.assign_auto_ids() opencg_geometry = copy.deepcopy(opencg_geometry) - # Update Cell bounding boxes in Geometry - opencg_geometry.update_bounding_boxes() - # Clear dictionaries and auto-generated ID OPENMC_SURFACES.clear() OPENCG_SURFACES.clear() @@ -1033,12 +1034,13 @@ def get_openmc_geometry(opencg_geometry): OPENCG_LATTICES.clear() # Make the entire geometry "compatible" before assigning auto IDs - universes = opencg_geometry.get_all_universes() - for universe in universes.values(): - if not isinstance(universe, opencg.Lattice): - make_opencg_cells_compatible(universe) + if not compatible: + universes = opencg_geometry.get_all_universes() + for universe in universes.values(): + if not isinstance(universe, opencg.Lattice): + make_opencg_cells_compatible(universe) - opencg_geometry.assign_auto_ids() + opencg_geometry.assign_auto_ids() opencg_root_universe = opencg_geometry.root_universe openmc_root_universe = get_openmc_universe(opencg_root_universe) diff --git a/openmc/volume.py b/openmc/volume.py index e9b1dac1d3..2a2a92f61e 100644 --- a/openmc/volume.py +++ b/openmc/volume.py @@ -1,6 +1,7 @@ from collections import Iterable, Mapping from numbers import Real, Integral from xml.etree import ElementTree as ET +from warnings import warn import numpy as np import pandas as pd @@ -68,10 +69,26 @@ class VolumeCalculation(object): self.samples = samples if lower_left is not None: - self.lower_left = lower_left if upper_right is None: raise ValueError('Both lower-left and upper-right coordinates ' 'should be specified') + + # For cell domains, try to compute bounding box and make sure + # user-specified one is valid + if self.domain_type == 'cell': + for c in domains: + if c.region is None: + continue + ll, ur = c.region.bounding_box + if np.any(np.isinf(ll)) or np.any(np.isinf(ur)): + continue + if (np.any(np.asarray(lower_left) > ll) or + np.any(np.asarray(upper_right) < ur)): + warn("Specified bounding box is smaller than computed " + "bounding box for cell {}. Volume calculation may " + "be incorrect!".format(c.id)) + + self.lower_left = lower_left self.upper_right = upper_right else: if self.domain_type == 'cell': diff --git a/src/constants.F90 b/src/constants.F90 index 182be97725..6d5f2fc107 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -54,7 +54,8 @@ module constants ! Maximum number of external source spatial resamples to encounter before an ! error is thrown. - integer, parameter :: MAX_EXTSRC_RESAMPLES = 10000 + integer, parameter :: EXTSRC_REJECT_THRESHOLD = 10000 + real(8), parameter :: EXTSRC_REJECT_FRACTION = 0.05 ! ============================================================================ ! PHYSICAL CONSTANTS diff --git a/src/relaxng/settings.rnc b/src/relaxng/settings.rnc index e23cbdd6cd..742e137738 100644 --- a/src/relaxng/settings.rnc +++ b/src/relaxng/settings.rnc @@ -153,7 +153,7 @@ element settings { attribute lower_left { list { xsd:double+ } }) & (element upper_right { list { xsd:double+ } } | attribute upper_right { list { xsd:double+ } }) - }+ & + }* & element uniform_fs{ (element dimension { list { xsd:positiveInteger+ } } | diff --git a/src/relaxng/settings.rng b/src/relaxng/settings.rng index 38acea5985..39bed4a62f 100644 --- a/src/relaxng/settings.rng +++ b/src/relaxng/settings.rng @@ -625,7 +625,7 @@ - + @@ -694,7 +694,7 @@ - + diff --git a/src/source.F90 b/src/source.F90 index 194c8c6add..452d8ddfce 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -107,7 +107,8 @@ contains real(8) :: r(3) ! sampled coordinates logical :: found ! Does the source particle exist within geometry? type(Particle) :: p ! Temporary particle for using find_cell - integer, save :: num_resamples = 0 ! Number of resamples encountered + integer, save :: n_accept = 0 ! Number of samples accepted + integer, save :: n_reject = 0 ! Number of samples rejected ! Set weight to one by default site % wgt = ONE @@ -143,13 +144,6 @@ contains ! Now search to see if location exists in geometry call find_cell(p, found) - if (.not. found) then - num_resamples = num_resamples + 1 - if (num_resamples == MAX_EXTSRC_RESAMPLES) then - call fatal_error("Maximum number of external source spatial & - &resamples reached!") - end if - end if ! Check if spatial site is in fissionable material select type (space => external_source(i) % space) @@ -162,8 +156,21 @@ contains end if end if end select + + ! Check for rejection + if (.not. found) then + n_reject = n_reject + 1 + if (n_reject >= EXTSRC_REJECT_THRESHOLD .and. & + real(n_accept, 8)/n_reject <= EXTSRC_REJECT_FRACTION) then + call fatal_error("More than 95% of external source sites sampled & + &were rejected. Please check your external source definition.") + end if + end if end do + ! Increment number of accepted samples + n_accept = n_accept + 1 + call p % clear() ! Sample angle diff --git a/tests/test_mgxs_library_no_nuclides/results_true.dat b/tests/test_mgxs_library_no_nuclides/results_true.dat index 3563f141b1..edd99b44c5 100644 --- a/tests/test_mgxs_library_no_nuclides/results_true.dat +++ b/tests/test_mgxs_library_no_nuclides/results_true.dat @@ -29,39 +29,39 @@ 1 10000 1 total 0.385188 0.026946 0 10000 2 total 0.412389 0.015425 material group in group out nuclide moment mean std. dev. -9 10000 1 1 total P0 -0.000207 0.000149 -11 10000 1 1 total P1 0.000234 0.000128 -13 10000 1 1 total P2 0.051870 0.006983 +12 10000 1 1 total P0 0.384199 0.027001 +13 10000 1 1 total P1 0.051870 0.006983 +14 10000 1 1 total P2 0.020069 0.002846 15 10000 1 1 total P3 0.009478 0.002234 8 10000 1 2 total P0 0.000989 0.000482 -10 10000 1 2 total P1 -0.000103 0.000184 -12 10000 1 2 total P2 0.384199 0.027001 -14 10000 1 2 total P3 0.020069 0.002846 -1 10000 2 1 total P0 0.016482 0.004502 -3 10000 2 1 total P1 -0.010499 0.010438 -5 10000 2 1 total P2 -0.000768 0.000768 +9 10000 1 2 total P1 -0.000207 0.000149 +10 10000 1 2 total P2 -0.000103 0.000184 +11 10000 1 2 total P3 0.000234 0.000128 +4 10000 2 1 total P0 0.000925 0.000925 +5 10000 2 1 total P1 -0.000768 0.000768 +6 10000 2 1 total P2 0.000494 0.000494 7 10000 2 1 total P3 -0.000171 0.000172 0 10000 2 2 total P0 0.411465 0.015245 -2 10000 2 2 total P1 0.006371 0.010551 -4 10000 2 2 total P2 0.000925 0.000925 -6 10000 2 2 total P3 0.000494 0.000494 +1 10000 2 2 total P1 0.016482 0.004502 +2 10000 2 2 total P2 0.006371 0.010551 +3 10000 2 2 total P3 -0.010499 0.010438 material group in group out nuclide moment mean std. dev. -9 10000 1 1 total P0 -0.000207 0.000149 -11 10000 1 1 total P1 0.000234 0.000128 -13 10000 1 1 total P2 0.051870 0.006983 +12 10000 1 1 total P0 0.384199 0.027001 +13 10000 1 1 total P1 0.051870 0.006983 +14 10000 1 1 total P2 0.020069 0.002846 15 10000 1 1 total P3 0.009478 0.002234 8 10000 1 2 total P0 0.000989 0.000482 -10 10000 1 2 total P1 -0.000103 0.000184 -12 10000 1 2 total P2 0.384199 0.027001 -14 10000 1 2 total P3 0.020069 0.002846 -1 10000 2 1 total P0 0.016482 0.004502 -3 10000 2 1 total P1 -0.010499 0.010438 -5 10000 2 1 total P2 -0.000768 0.000768 +9 10000 1 2 total P1 -0.000207 0.000149 +10 10000 1 2 total P2 -0.000103 0.000184 +11 10000 1 2 total P3 0.000234 0.000128 +4 10000 2 1 total P0 0.000925 0.000925 +5 10000 2 1 total P1 -0.000768 0.000768 +6 10000 2 1 total P2 0.000494 0.000494 7 10000 2 1 total P3 -0.000171 0.000172 0 10000 2 2 total P0 0.411465 0.015245 -2 10000 2 2 total P1 0.006371 0.010551 -4 10000 2 2 total P2 0.000925 0.000925 -6 10000 2 2 total P3 0.000494 0.000494 +1 10000 2 2 total P1 0.016482 0.004502 +2 10000 2 2 total P2 0.006371 0.010551 +3 10000 2 2 total P3 -0.010499 0.010438 material group in group out nuclide mean std. dev. 3 10000 1 1 total 1.0 0.078516 2 10000 1 2 total 1.0 0.687184 @@ -154,39 +154,39 @@ 1 10001 1 total 0.310121 0.033788 0 10001 2 total 0.296264 0.043792 material group in group out nuclide moment mean std. dev. -9 10001 1 1 total P0 0.000000 0.000000 -11 10001 1 1 total P1 0.000000 0.000000 -13 10001 1 1 total P2 0.038230 0.008484 +12 10001 1 1 total P0 0.310121 0.033788 +13 10001 1 1 total P1 0.038230 0.008484 +14 10001 1 1 total P2 0.020745 0.004696 15 10001 1 1 total P3 0.007964 0.003732 8 10001 1 2 total P0 0.000000 0.000000 -10 10001 1 2 total P1 0.000000 0.000000 -12 10001 1 2 total P2 0.310121 0.033788 -14 10001 1 2 total P3 0.020745 0.004696 -1 10001 2 1 total P0 -0.011214 0.016180 -3 10001 2 1 total P1 -0.003270 0.007329 -5 10001 2 1 total P2 0.000000 0.000000 +9 10001 1 2 total P1 0.000000 0.000000 +10 10001 1 2 total P2 0.000000 0.000000 +11 10001 1 2 total P3 0.000000 0.000000 +4 10001 2 1 total P0 0.000000 0.000000 +5 10001 2 1 total P1 0.000000 0.000000 +6 10001 2 1 total P2 0.000000 0.000000 7 10001 2 1 total P3 0.000000 0.000000 0 10001 2 2 total P0 0.296264 0.043792 -2 10001 2 2 total P1 0.008837 0.011504 -4 10001 2 2 total P2 0.000000 0.000000 -6 10001 2 2 total P3 0.000000 0.000000 +1 10001 2 2 total P1 -0.011214 0.016180 +2 10001 2 2 total P2 0.008837 0.011504 +3 10001 2 2 total P3 -0.003270 0.007329 material group in group out nuclide moment mean std. dev. -9 10001 1 1 total P0 0.000000 0.000000 -11 10001 1 1 total P1 0.000000 0.000000 -13 10001 1 1 total P2 0.038230 0.008484 +12 10001 1 1 total P0 0.310121 0.033788 +13 10001 1 1 total P1 0.038230 0.008484 +14 10001 1 1 total P2 0.020745 0.004696 15 10001 1 1 total P3 0.007964 0.003732 8 10001 1 2 total P0 0.000000 0.000000 -10 10001 1 2 total P1 0.000000 0.000000 -12 10001 1 2 total P2 0.310121 0.033788 -14 10001 1 2 total P3 0.020745 0.004696 -1 10001 2 1 total P0 -0.011214 0.016180 -3 10001 2 1 total P1 -0.003270 0.007329 -5 10001 2 1 total P2 0.000000 0.000000 +9 10001 1 2 total P1 0.000000 0.000000 +10 10001 1 2 total P2 0.000000 0.000000 +11 10001 1 2 total P3 0.000000 0.000000 +4 10001 2 1 total P0 0.000000 0.000000 +5 10001 2 1 total P1 0.000000 0.000000 +6 10001 2 1 total P2 0.000000 0.000000 7 10001 2 1 total P3 0.000000 0.000000 0 10001 2 2 total P0 0.296264 0.043792 -2 10001 2 2 total P1 0.008837 0.011504 -4 10001 2 2 total P2 0.000000 0.000000 -6 10001 2 2 total P3 0.000000 0.000000 +1 10001 2 2 total P1 -0.011214 0.016180 +2 10001 2 2 total P2 0.008837 0.011504 +3 10001 2 2 total P3 -0.003270 0.007329 material group in group out nuclide mean std. dev. 3 10001 1 1 total 1.0 0.108779 2 10001 1 2 total 0.0 0.000000 @@ -279,39 +279,39 @@ 1 10002 1 total 0.671269 0.026186 0 10002 2 total 2.035388 0.258060 material group in group out nuclide moment mean std. dev. -9 10002 1 1 total P0 0.008758 0.000926 -11 10002 1 1 total P1 -0.003785 0.000817 -13 10002 1 1 total P2 0.381167 0.016243 +12 10002 1 1 total P0 0.639901 0.024709 +13 10002 1 1 total P1 0.381167 0.016243 +14 10002 1 1 total P2 0.152392 0.008156 15 10002 1 1 total P3 0.009148 0.003889 8 10002 1 2 total P0 0.031368 0.001728 -10 10002 1 2 total P1 -0.002568 0.001014 -12 10002 1 2 total P2 0.639901 0.024709 -14 10002 1 2 total P3 0.152392 0.008156 -1 10002 2 1 total P0 0.509941 0.051236 -3 10002 2 1 total P1 0.024988 0.008312 -5 10002 2 1 total P2 0.000400 0.000401 +9 10002 1 2 total P1 0.008758 0.000926 +10 10002 1 2 total P2 -0.002568 0.001014 +11 10002 1 2 total P3 -0.003785 0.000817 +4 10002 2 1 total P0 0.000443 0.000445 +5 10002 2 1 total P1 0.000400 0.000401 +6 10002 2 1 total P2 0.000320 0.000321 7 10002 2 1 total P3 0.000214 0.000215 0 10002 2 2 total P0 2.034945 0.257800 -2 10002 2 2 total P1 0.111175 0.013020 -4 10002 2 2 total P2 0.000443 0.000445 -6 10002 2 2 total P3 0.000320 0.000321 +1 10002 2 2 total P1 0.509941 0.051236 +2 10002 2 2 total P2 0.111175 0.013020 +3 10002 2 2 total P3 0.024988 0.008312 material group in group out nuclide moment mean std. dev. -9 10002 1 1 total P0 0.008758 0.000926 -11 10002 1 1 total P1 -0.003785 0.000817 -13 10002 1 1 total P2 0.381167 0.016243 +12 10002 1 1 total P0 0.639901 0.024709 +13 10002 1 1 total P1 0.381167 0.016243 +14 10002 1 1 total P2 0.152392 0.008156 15 10002 1 1 total P3 0.009148 0.003889 8 10002 1 2 total P0 0.031368 0.001728 -10 10002 1 2 total P1 -0.002568 0.001014 -12 10002 1 2 total P2 0.639901 0.024709 -14 10002 1 2 total P3 0.152392 0.008156 -1 10002 2 1 total P0 0.509941 0.051236 -3 10002 2 1 total P1 0.024988 0.008312 -5 10002 2 1 total P2 0.000400 0.000401 +9 10002 1 2 total P1 0.008758 0.000926 +10 10002 1 2 total P2 -0.002568 0.001014 +11 10002 1 2 total P3 -0.003785 0.000817 +4 10002 2 1 total P0 0.000443 0.000445 +5 10002 2 1 total P1 0.000400 0.000401 +6 10002 2 1 total P2 0.000320 0.000321 7 10002 2 1 total P3 0.000214 0.000215 0 10002 2 2 total P0 2.034945 0.257800 -2 10002 2 2 total P1 0.111175 0.013020 -4 10002 2 2 total P2 0.000443 0.000445 -6 10002 2 2 total P3 0.000320 0.000321 +1 10002 2 2 total P1 0.509941 0.051236 +2 10002 2 2 total P2 0.111175 0.013020 +3 10002 2 2 total P3 0.024988 0.008312 material group in group out nuclide mean std. dev. 3 10002 1 1 total 1.0 0.038609 2 10002 1 2 total 1.0 0.067667 diff --git a/tests/test_mgxs_library_nuclides/results_true.dat b/tests/test_mgxs_library_nuclides/results_true.dat index d3e3235ccc..3da8146042 100644 --- a/tests/test_mgxs_library_nuclides/results_true.dat +++ b/tests/test_mgxs_library_nuclides/results_true.dat @@ -1 +1 @@ -8142ae4e107002a835999e4ace85c17376f262a7059fc224f3756a2de19aba6ca4c4fa14ca2085c87d7729aa8d6d6f78fdae21ac6dfe33ca303449c769076074 \ No newline at end of file +e494320a213b5704a2ac915a2ba504857be91961ceb6735b6ad05d81eb31c44c9584d5bd9d40baececf1dcb5b030e6ecec63cfbd20639baf69bcb596c5c46591 \ No newline at end of file