From b005aace7e2014e0d6b211d760ab50b8e94ac3db Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Sat, 15 Oct 2016 11:33:00 -0400 Subject: [PATCH] Added a scatter_shape parameter to the library format and the ability to read/write it (but do nothing with it aside from check for the default value). Also converted back from is checks in the python for a string to ==, since is does not work for many cases --- docs/source/io_formats/mgxs_library.rst | 74 +++++++++++------------ openmc/mgxs/library.py | 62 ++++++++++---------- openmc/mgxs_library.py | 75 +++++++++++++++--------- scripts/openmc-update-mgxs | 14 ++--- src/mgxs_header.F90 | 7 +++ tests/1d_mgxs.h5 | Bin 123864 -> 124632 bytes 6 files changed, 128 insertions(+), 104 deletions(-) diff --git a/docs/source/io_formats/mgxs_library.rst b/docs/source/io_formats/mgxs_library.rst index 9262a234e..2a1e63d43 100644 --- a/docs/source/io_formats/mgxs_library.rst +++ b/docs/source/io_formats/mgxs_library.rst @@ -38,10 +38,10 @@ MGXS Library Specification The data within contains the temperature-dependent multi-group data for the nuclide or material that it represents. -:Attributes: - **atomic_weight_ratio** (*double*) -- The atomic weight ratio (optional, - i.e. it is not meaningful for material-wise data) - - **fissionable** (*int*) -- Whether the dataset is fissionable - (1) or not (0). +:Attributes: - **atomic_weight_ratio** (*double*) -- The atomic weight ratio + (optional, i.e. it is not meaningful for material-wise data). + - **fissionable** (*bool*) -- Whether the dataset is fissionable + (True) or not (False). - **representation** (*char[]*) -- The method used to generate and represent the multi-group cross sections. That is, whether they were generated with scalar flux weighting (or reduced to a @@ -65,6 +65,15 @@ data for the nuclide or material that it represents. or number of points (depending on the value of `scatter_format`) used to describe the angular distribution associated with each group-to-group transfer probability. + - **scatter_shape** (*char[]*) -- The shape of the provided + scatter and multiplicity matrix. The values provided are strings + describing the ordering the scattering array is provided in + row-major (i.e., C/C++ and Python) indexing. Valid values are + "[Order][G][G']" or "[Order][G'][G]" where "G'" denotes the + secondary/outgoing energy groups, "G" denotes the incoming + energy groups, and "Order" is the angular distribution index. + This value is not required; if not the default value of + "[Order][G][G']" will be assumed. **//kTs/** @@ -79,29 +88,29 @@ Temperature-dependent data, provided for temperature K. :Datasets: - **total** (*double[]* or *double[][][]*) -- Total cross section. This is a 1-D vector if `representation` is "isotropic", or a 3-D vector if `representation` is "angle" with dimensions of - [groups, azimuthal, polar]. + [groups][azimuthal][polar]. - **absorption** (*double[]* or *double[][][]*) -- Absorption cross section. This is a 1-D vector if `representation` is "isotropic", or a 3-D vector if `representation` is "angle" with dimensions of - [groups, azimuthal, polar]. + [groups][azimuthal][polar]. - **fission** (*double[]* or *double[][][]*) -- Fission cross section. This is a 1-D vector if `representation` is "isotropic", or a 3-D vector if `representation` is "angle" with dimensions of - [groups, azimuthal, polar]. This is only required if the dataset + [groups][azimuthal][polar]. This is only required if the dataset is fissionable and fission-tallies are expected to be used. - **kappa-fission** (*double[]* or *double[][][]*) -- Kappa-Fission (energy-release from fission) cross section. This is a 1-D vector if `representation` is "isotropic", or a 3-D vector if `representation` is "angle" with dimensions of - [groups, azimuthal, polar]. This is only required if the dataset + [groups][azimuthal][polar]. This is only required if the dataset is fissionable and fission-tallies are expected to be used. - **chi** (*double[]* or *double[][][]*) -- Fission neutron energy spectra. This is a 1-D vector if `representation` is "isotropic", or a 3-D vector if `representation` is "angle" with dimensions of - [groups, azimuthal, polar]. This is only required if the dataset + [groups][azimuthal][polar]. This is only required if the dataset is fissionable and fission-tallies are expected to be used. - **nu-fission** (*double[]* to *double[][][][]*) -- Nu-Fission cross section. @@ -119,34 +128,30 @@ Temperature-dependent data, provided for temperature K. Data specific to neutron scattering for the temperature K :Datasets: - **g_min** (*int[]* or *int[][][]*) -- - Minimum (most energetic) outgoing groups with non-zero values of - the scattering matrix. These group numbers use the standard + Minimum (most energetic) groups with non-zero values of + the scattering matrix provided. If `scatter_shape` is + "[Order][G][G']" then `g_min` will describe the minimum values + of "G'" for each "G"; if `scatter_shape` is "[Order][G'][G]" + then `g_min` will describe the minimum values of "G" for each "G'". + These group numbers use the standard ordering where the fastest neutron energy group is group 1 while the slowest neutron energy group is group G. The dimensionality of `g_min` is: - `g_min[g_in]`, or `g_min[num_polar][num_azimuthal][g_in]`. + `g_min[g]`, or `g_min[num_polar][num_azimuthal][g]`. The former is used when `representation` is "isotropic", and the latter when `representation` is "angle". - **g_max** (*int[]* or *int[][][]*) -- - Maximum (least energetic) outgoing groups with non-zero values of - the scattering matrix. These group numbers use the standard - ordering where the fastest neutron energy group is group 1 while - the slowest neutron energy group is group G. - The dimensionality of `g_max` is: - `g_max[g_in]`, or `g_max[num_polar][num_azimuthal][g_in]`. - The former is used when `representation` is "isotropic", and the - latter when `representation` is "angle". + Similar to `g_min`, except this dataset describes the maximum + (least energetic) groups with non-zero values of + the scattering matrix. - **scatter_matrix** (*double[]*) -- Flattened representation of the - scattering moment matrices. The pre-flattened array is shaped as - follows (in row-major format): - `scatter_matrix[order(+1)][g_in][g_out]`, or - `scatter_matrix[num_polar][num_azimuthal][order(+1)][g_in][g_out]` - The former is used when `representation` is "isotropic", and the - latter when `representation` is "angle". Note that if the value of - `scatter_format` is "legendre", the order dimension will be one - larger than the value of `order`, otherwise it will match `order`. - Finally, the g_out dimension has a dimensionality of - `g_min` to `g_max`. + scattering moment matrices. The pre-flattened array corresponds to + the shape provied in `scatter_shape`, but if `representation` is + "angle" the dimensionality in `scatter_shape` is prepended by + "[num_polar][num_azimuthal]" dimensions. The right-most energy + group dimension will only include the entries between `g_min` and + `g_max`. + dimension has a dimensionality of `g_min` to `g_max`. - **multiplicity_matrix** (*double[]*) -- Flattened representation of the scattering moment matrices. This dataset provides the code with a scaling factor to account for neutrons being produced in (n,xn) @@ -154,9 +159,6 @@ Data specific to neutron scattering for the temperature K for every Legendre moment or histogram/tabular bin. This dataset is optional, if it is not provided no multiplication (i.e., values of 1.0) will be assumed. - The pre-flattened array is shaped as follows (in row-major format): - `multiplicity_matrix[g_in][g_out]`, or - `multiplicity_matrix[num_polar][num_azimuthal][g_in][g_out]` - The former is used when `representation` is "isotropic", and the - latter when `representation` is "angle". Finally, the g_out - dimension has a dimensionality of `g_min` to `g_max`. \ No newline at end of file + The pre-flattened array is shapes consistent with `scatter_matrix` + except the "[Order]" dimension in `scatter_shape` is ignored since + this data is assumed isotropic. \ No newline at end of file diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 64210606d..c03aa7877 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -186,14 +186,14 @@ class Library(object): @property def domains(self): - if self._domains is 'all': - if self.domain_type is 'material': + if self._domains == 'all': + if self.domain_type == 'material': return self.openmc_geometry.get_all_materials() elif self.domain_type in ['cell', 'distribcell']: return self.openmc_geometry.get_all_material_cells() - elif self.domain_type is 'universe': + elif self.domain_type == 'universe': return self.openmc_geometry.get_all_universes() - elif self.domain_type is 'mesh': + elif self.domain_type == 'mesh': raise ValueError('Unable to get domains for Mesh domain type') else: raise ValueError('Unable to get domains without a domain type') @@ -265,7 +265,7 @@ class Library(object): @mgxs_types.setter def mgxs_types(self, mgxs_types): all_mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES - if mgxs_types is 'all': + if mgxs_types == 'all': self._mgxs_types = all_mgxs_types else: cv.check_iterable_type('mgxs_types', mgxs_types, basestring) @@ -277,7 +277,7 @@ class Library(object): def by_nuclide(self, by_nuclide): cv.check_type('by_nuclide', by_nuclide, bool) - if by_nuclide == True and self.domain_type is 'mesh': + if by_nuclide == True and self.domain_type == 'mesh': raise ValueError('Unable to create MGXS library by nuclide with ' 'mesh domain') @@ -287,7 +287,7 @@ class Library(object): def domain_type(self, domain_type): cv.check_value('domain type', domain_type, openmc.mgxs.DOMAIN_TYPES) - if self.by_nuclide == True and domain_type is 'mesh': + if self.by_nuclide == True and domain_type == 'mesh': raise ValueError('Unable to create MGXS library by nuclide with ' 'mesh domain') @@ -297,21 +297,21 @@ class Library(object): def domains(self, domains): # Use all materials, cells or universes in the geometry as domains - if domains is 'all': + if domains == 'all': self._domains = domains # User specified a list of material, cell or universe domains else: - if self.domain_type is 'material': + if self.domain_type == 'material': cv.check_iterable_type('domain', domains, openmc.Material) all_domains = self.openmc_geometry.get_all_materials() elif self.domain_type in ['cell', 'distribcell']: cv.check_iterable_type('domain', domains, openmc.Cell) all_domains = self.openmc_geometry.get_all_material_cells() - elif self.domain_type is 'universe': + elif self.domain_type == 'universe': cv.check_iterable_type('domain', domains, openmc.Universe) all_domains = self.openmc_geometry.get_all_universes() - elif self.domain_type is 'mesh': + elif self.domain_type == 'mesh': cv.check_iterable_type('domain', domains, openmc.Mesh) # The mesh and geometry are independent, so set all_domains @@ -355,7 +355,7 @@ class Library(object): def correction(self, correction): cv.check_value('correction', correction, ('P0', None)) - if correction is 'P0' and self.legendre_order > 0: + if correction == 'P0' and self.legendre_order > 0: warn('The P0 correction will be ignored since the scattering ' 'order "{}" is greater than zero'.format(self.legendre_order)) @@ -367,7 +367,7 @@ class Library(object): cv.check_greater_than('legendre_order', legendre_order, 0, equality=True) cv.check_less_than('legendre_order', legendre_order, 10, equality=True) - if self.correction is 'P0' and legendre_order > 0: + if self.correction == 'P0' and legendre_order > 0: msg = 'The P0 correction will be ignored since the scattering ' \ 'order {} is greater than zero'.format(self.legendre_order) warn(msg, RuntimeWarning) @@ -505,7 +505,7 @@ class Library(object): self._openmc_geometry = statepoint.summary.openmc_geometry self._nuclides = statepoint.summary.nuclides - if statepoint.run_mode is 'k-eigenvalue': + if statepoint.run_mode == 'k-eigenvalue': self._keff = statepoint.k_combined[0] # Load tallies for each MGXS for each domain and mgxs type @@ -543,13 +543,13 @@ class Library(object): """ - if self.domain_type is 'material': + if self.domain_type == 'material': cv.check_type('domain', domain, (openmc.Material, Integral)) - elif self.domain_type is 'cell' or self.domain_type is 'distribcell': + elif self.domain_type == 'cell' or self.domain_type == 'distribcell': cv.check_type('domain', domain, (openmc.Cell, Integral)) - elif self.domain_type is 'universe': + elif self.domain_type == 'universe': cv.check_type('domain', domain, (openmc.Universe, Integral)) - elif self.domain_type is 'mesh': + elif self.domain_type == 'mesh': cv.check_type('domain', domain, (openmc.Mesh, Integral)) # Check that requested domain is included in library @@ -662,7 +662,7 @@ class Library(object): # Clone this Library to initialize the subdomain-averaged version subdomain_avg_library = copy.deepcopy(self) - if subdomain_avg_library.domain_type is 'distribcell': + if subdomain_avg_library.domain_type == 'distribcell': subdomain_avg_library.domain_type = 'cell' else: return subdomain_avg_library @@ -671,7 +671,7 @@ class Library(object): for domain in self.domains: for mgxs_type in self.mgxs_types: mgxs = subdomain_avg_library.get_mgxs(domain, mgxs_type) - if mgxs.domain_type is 'distribcell': + if mgxs.domain_type == 'distribcell': avg_mgxs = mgxs.get_subdomain_avg_xs() subdomain_avg_library.all_mgxs[domain.id][mgxs_type] = avg_mgxs @@ -751,7 +751,7 @@ class Library(object): for mgxs_type in self.mgxs_types: mgxs = self.all_mgxs[domain.id][mgxs_type] - if subdomains is 'avg': + if subdomains == 'avg': mgxs = mgxs.get_subdomain_avg_xs() mgxs.build_hdf5_store(filename, directory, xs_type=xs_type, @@ -896,7 +896,7 @@ class Library(object): # Build & add metadata to XSdata object name = xsdata_name - if nuclide is not 'total': + if nuclide != 'total': name += '_' + nuclide xsdata = openmc.XSdata(name, self.energy_groups) @@ -912,7 +912,7 @@ class Library(object): self.scatter_format = 'legendre' self.representation = 'isotropic' - if nuclide is not 'total': + if nuclide != 'total': xsdata.atomic_weight_ratio = self._nuclides[nuclide][1] if subdomain is None: @@ -921,7 +921,7 @@ class Library(object): subdomain = [subdomain] # Now get xs data itself - if 'nu-transport' in self.mgxs_types and self.correction is 'P0': + 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], subdomain=subdomain) @@ -1056,7 +1056,7 @@ class Library(object): # Initialize file mgxs_file = openmc.MGXSLibrary(self.energy_groups) - if self.domain_type is 'mesh': + if self.domain_type == 'mesh': # Create the xsdata objects and add to the mgxs_file i = 0 for domain in self.domains: @@ -1089,7 +1089,7 @@ class Library(object): xsdata_name = 'set' + str(i + 1) else: xsdata_name = xsdata_names[i] - if nuclide is not 'total': + if nuclide != 'total': xsdata_name += '_' + nuclide xsdata = self.get_xsdata(domain, xsdata_name, @@ -1159,14 +1159,14 @@ class Library(object): # 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 is 'mesh': + 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) # Now move on the creating the geometry and assigning materials - if self.domain_type is 'mesh': + if self.domain_type == 'mesh': root = openmc.Universe(name='root', universe_id=0) # Add cells representative of the mesh with reflective BC @@ -1212,13 +1212,13 @@ class Library(object): materials.append(material) # Differentiate Geometry with new Material - if self.domain_type is '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 is 'cell': + elif self.domain_type == 'cell': for cell in all_cells: if cell.id == domain.id: cell.fill = material @@ -1283,7 +1283,7 @@ class Library(object): ('nu-transport' not in self.mgxs_types))): error_flag = True warn('A "nu-transport" MGXS type is required since a "P0" ' - 'correction is applied, but a "nu-transport" MGXS is ' + 'correction is applied, but a "nu-transport" MGXS == ' 'not provided.') elif (((self.correction is None) and ('total' not in self.mgxs_types))): diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index edddd0bfa..35dff1223 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -8,7 +8,7 @@ import h5py import openmc import openmc.mgxs from openmc.checkvalue import check_type, check_value, check_greater_than, \ - check_less_than, check_iterable_type + check_iterable_type if sys.version_info[0] >= 3: basestring = str @@ -16,6 +16,7 @@ if sys.version_info[0] >= 3: # Supported incoming particle MGXS angular treatment representations _REPRESENTATIONS = ['isotropic', 'angle'] _SCATTER_TYPES = ['tabular', 'legendre', 'histogram'] +_SCATTER_SHAPES = ["[Order][G][G']"] class XSdata(object): @@ -51,6 +52,8 @@ class XSdata(object): Whether or not this is a fissionable data set. scatter_format : {'legendre', 'histogram', or 'tabular'} Angular distribution representation (legendre, histogram, or tabular) + scatter_shapes : {"[Order][G][G']"} + Dimensionality of the scattering and multiplicity matrices order : int Either the Legendre order, number of bins, or number of points used to describe the angular distribution associated with each group-to-group @@ -106,8 +109,8 @@ class XSdata(object): :attr:`XSdata.nu_fission` attribute instead. nu_fission : dict of numpy.ndarray Group-wise fission production cross section vector (i.e., if - :attr:`XSdata.chi` is provided), or is the group-wise fission production - matrix. + :attr:`XSdata.chi` is provided), or is the group-wise fission + production matrix. inverse_velocities : dict of numpy.ndarray Inverse of velocities, in units of sec/cm. @@ -142,6 +145,7 @@ class XSdata(object): self._atomic_weight_ratio = None self._fissionable = False self._scatter_format = 'legendre' + self._scatter_shape = "[Order][G][G']" self._order = None self._num_polar = None self._num_azimuthal = None @@ -184,6 +188,10 @@ class XSdata(object): def scatter_format(self): return self._scatter_format + @property + def scatter_shape(self): + return self._scatter_shape + @property def order(self): return self._order @@ -242,28 +250,28 @@ class XSdata(object): @property def vector_shape(self): - if self.representation is 'isotropic': + if self.representation == 'isotropic': return (self.energy_groups.num_groups,) - elif self.representation is 'angle': + elif self.representation == 'angle': return (self.num_polar, self.num_azimuthal, self.energy_groups.num_groups) @property def matrix_shape(self): - if self.representation is 'isotropic': + if self.representation == 'isotropic': return (self.energy_groups.num_groups, self.energy_groups.num_groups) - elif self.representation is 'angle': + elif self.representation == 'angle': return (self.num_polar, self.num_azimuthal, self.energy_groups.num_groups, self.energy_groups.num_groups) @property def pn_matrix_shape(self): - if self.representation is 'isotropic': + if self.representation == 'isotropic': return (self.num_orders, self.energy_groups.num_groups, self.energy_groups.num_groups) - elif self.representation is 'angle': + elif self.representation == 'angle': return (self.num_polar, self.num_azimuthal, self.num_orders, self.energy_groups.num_groups, self.energy_groups.num_groups) @@ -309,6 +317,12 @@ class XSdata(object): check_value('scatter_format', scatter_format, _SCATTER_TYPES) self._scatter_format = scatter_format + @scatter_shape.setter + def scatter_shape(self, scatter_shape): + # check to see it is of a valid type and value + check_value('scatter_shape', scatter_shape, _SCATTER_SHAPES) + self._scatter_shape = scatter_shape + @order.setter def order(self, order): # Check type and value @@ -694,10 +708,10 @@ class XSdata(object): check_value('temperature', temperature, self.temperatures) i = np.where(self.temperatures == temperature)[0][0] - if self.representation is 'isotropic': + if self.representation == 'isotropic': self._total[i] = total.get_xs(nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - elif self.representation is 'angle': + elif self.representation == 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) @@ -740,11 +754,11 @@ class XSdata(object): check_value('temperature', temperature, self.temperatures) i = np.where(self.temperatures == temperature)[0][0] - if self.representation is 'isotropic': + if self.representation == 'isotropic': self._absorption[i] = absorption.get_xs(nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - elif self.representation is 'angle': + elif self.representation == 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) @@ -787,11 +801,11 @@ class XSdata(object): check_value('temperature', temperature, self.temperatures) i = np.where(self.temperatures == temperature)[0][0] - if self.representation is 'isotropic': + if self.representation == 'isotropic': self._fission[i] = fission.get_xs(nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - elif self.representation is 'angle': + elif self.representation == 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) @@ -835,11 +849,11 @@ class XSdata(object): check_value('temperature', temperature, self.temperatures) i = np.where(self.temperatures == temperature)[0][0] - if self.representation is 'isotropic': + if self.representation == 'isotropic': self._nu_fission[i] = nu_fission.get_xs(nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - elif self.representation is 'angle': + elif self.representation == 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) @@ -892,11 +906,11 @@ class XSdata(object): check_value('temperature', temperature, self.temperatures) i = np.where(self.temperatures == temperature)[0][0] - if self.representation is 'isotropic': + if self.representation == 'isotropic': self._kappa_fission[i] = k_fission.get_xs(nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - elif self.representation is 'angle': + elif self.representation == 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) @@ -943,10 +957,10 @@ class XSdata(object): check_value('temperature', temperature, self.temperatures) i = np.where(self.temperatures == temperature)[0][0] - if self.representation is 'isotropic': + if self.representation == 'isotropic': self._chi[i] = chi.get_xs(nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - elif self.representation is 'angle': + elif self.representation == 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) @@ -994,7 +1008,7 @@ class XSdata(object): check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) - if self.scatter_format is not 'legendre': + if self.scatter_format != 'legendre': msg = 'Anisotropic scattering representations other than ' \ 'Legendre expansions have not yet been implemented in ' \ 'openmc.mgxs.' @@ -1011,7 +1025,7 @@ class XSdata(object): [self.order]) i = np.where(self.temperatures == temperature)[0][0] - if self.representation is 'isotropic': + if self.representation == 'isotropic': # Get the scattering orders in the outermost dimension self._scatter_matrix[i] = np.zeros((self.num_orders, self.energy_groups.num_groups, @@ -1021,7 +1035,7 @@ class XSdata(object): scatter.get_xs(nuclides=nuclide, xs_type=xs_type, moment=moment, subdomains=subdomain) - elif self.representation is 'angle': + elif self.representation == 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) @@ -1089,7 +1103,7 @@ class XSdata(object): ['universe', 'cell', 'material', 'mesh']) i = np.where(self.temperatures == temperature)[0][0] - if self.representation is 'isotropic': + if self.representation == 'isotropic': nuscatt = nuscatter.get_xs(nuclides=nuclide, xs_type=xs_type, moment=0, subdomains=subdomain) @@ -1100,7 +1114,7 @@ class XSdata(object): xs_type=xs_type, moment=0, subdomains=subdomain) self._multiplicity_matrix[i] = np.divide(nuscatt, scatt) - elif self.representation is 'angle': + elif self.representation == 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) self._multiplicity_matrix[i] = \ @@ -1123,7 +1137,7 @@ class XSdata(object): if self.representation is not None: grp.attrs['representation'] = np.array(self.representation, dtype='S') - if self.representation is 'angle': + if self.representation == 'angle': if self.num_azimuthal is not None: grp.attrs['num_azimuthal'] = self.num_azimuthal if self.num_polar is not None: @@ -1131,6 +1145,9 @@ class XSdata(object): if self.scatter_format is not None: grp.attrs['scatter_format'] = np.array(self.scatter_format, dtype='S') + if self.scatter_shape is not None: + grp.attrs['scatter_shape'] = np.array(self.scatter_shape, + dtype='S') if self.order is not None: grp.attrs['order'] = self.order @@ -1170,7 +1187,7 @@ class XSdata(object): # Get the sparse scattering data to print to the library G = self.energy_groups.num_groups - if self.representation is 'isotropic': + if self.representation == 'isotropic': g_out_bounds = np.zeros((G, 2), dtype=np.int) for g_in in range(G): nz = np.nonzero(self._scatter_matrix[i][0, g_in, :]) @@ -1206,7 +1223,7 @@ class XSdata(object): scatt_grp.create_dataset("g_min", data=g_out_bounds[:, 0]) scatt_grp.create_dataset("g_max", data=g_out_bounds[:, 1]) - elif self.representation is 'angle': + elif self.representation == 'angle': Np = self.num_polar Na = self.num_azimuthal g_out_bounds = np.zeros((Np, Na, G, 2), dtype=np.int) diff --git a/scripts/openmc-update-mgxs b/scripts/openmc-update-mgxs index 6122ff626..658be9fef 100755 --- a/scripts/openmc-update-mgxs +++ b/scripts/openmc-update-mgxs @@ -47,14 +47,12 @@ def parse_args(): help='input XML file') parser.add_argument('-o', '--output', nargs='?', default='', help='output file, in HDF5 format') - parser.add_argument('-c', '--compression', type=int, - help='HDF5 Compression Level') args = vars(parser.parse_args()) - if args['output'] is '': + if args['output'] == '': filename = args['input'].name extension = filenameos.path.splitext() - if extension is '.xml': + if extension == '.xml': filename = filename[:filename.rfind('.')] + '.h5' args['output'] = filename @@ -75,7 +73,7 @@ def get_data(element, entry): return value -if __name__ is '__main__': +if __name__ == '__main__': args = parse_args() # Parse the XML data. @@ -117,7 +115,7 @@ if __name__ is '__main__': representation = get_data(xsdata_elem, 'representation') if representation is None: representation = 'isotropic' - if representation is 'angle': + if representation == 'angle': n_azi = int(get_data(xsdata_elem, 'num_azimuthal')) n_pol = int(get_data(xsdata_elem, 'num_polar')) @@ -146,14 +144,14 @@ if __name__ is '__main__': representation=representation)) if awr is not None: xsd[-1].atomic_weight_ratio = awr - if representation is 'angle': + if representation == 'angle': xsd[-1].num_azimuthal = n_azi xsd[-1].num_polar = n_pol xsd[-1].scatter_format = scatter_format xsd[-1].order = order names.append(name) - if scatter_format is 'legendre': + if scatter_format == 'legendre': order_dim = order + 1 else: order_dim = order diff --git a/src/mgxs_header.F90 b/src/mgxs_header.F90 index ddce50be3..cbdf470b0 100644 --- a/src/mgxs_header.F90 +++ b/src/mgxs_header.F90 @@ -338,6 +338,13 @@ module mgxs_header else this % scatter_format = ANGLE_LEGENDRE end if + if (attribute_exists(xs_id, "scatter_shape")) then + call read_attribute(temp_str, xs_id, "scatter_shape") + temp_str = trim(temp_str) + if (to_lower(temp_str) /= "[order][g][g']") then + call fatal_error("Invalid scatter_shape option!") + end if + end if if (attribute_exists(xs_id, "fissionable")) then call read_attribute(this % fissionable, xs_id, "fissionable") else diff --git a/tests/1d_mgxs.h5 b/tests/1d_mgxs.h5 index 401fe02fc54bedac6d1b5443db23a923de30c5f0..3befba194015f15f271447424bd93c7163e81324 100644 GIT binary patch delta 7975 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 delta 7769 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