From 6bbf83a9b6010bcabc8467d16d1c9013164b431e Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Thu, 12 May 2016 05:16:21 -0400 Subject: [PATCH] Revised docstrings and added some check_type commands instead of isinstance --- openmc/mgxs/library.py | 78 ++++++++-------- openmc/mgxs_library.py | 203 +++++++++++++++++++---------------------- 2 files changed, 134 insertions(+), 147 deletions(-) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 991a98f62c..82b7616735 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -17,7 +17,7 @@ if sys.version_info[0] >= 3: class Library(object): - '''A multi-group cross section library for some energy group structure. + """A multi-group cross section library for some energy group structure. This class can be used for both OpenMC input generation and tally data post-processing to compute spatially-homogenized and energy-integrated @@ -79,7 +79,7 @@ class Library(object): Whether or not the Library's tallies use SciPy's LIL sparse matrix format for compressed data storage - ''' + """ def __init__(self, openmc_geometry, by_nuclide=False, mgxs_types=None, name=''): @@ -300,7 +300,7 @@ class Library(object): @sparse.setter def sparse(self, sparse): - '''Convert tally data from NumPy arrays to SciPy list of lists (LIL) + """Convert tally data from NumPy arrays to SciPy list of lists (LIL) sparse matrices, and vice versa. This property may be used to reduce the amount of data in memory during @@ -308,7 +308,7 @@ class Library(object): matrices internally within the Tally object. All tally data access properties and methods will return data as a dense NumPy array. - ''' + """ cv.check_type('sparse', sparse, bool) @@ -321,14 +321,14 @@ class Library(object): self._sparse = sparse def build_library(self): - '''Initialize MGXS objects in each domain and for each reaction type + """Initialize MGXS objects in each domain and for each reaction type in the library. This routine will populate the all_mgxs instance attribute dictionary with MGXS subclass objects keyed by each domain ID (e.g., Material IDs) and cross section type (e.g., 'nu-fission', 'total', etc.). - ''' + """ # Initialize MGXS for each domain and mgxs type and store in dictionary for domain in self.domains: @@ -351,7 +351,7 @@ class Library(object): self.all_mgxs[domain.id][mgxs_type] = mgxs def add_to_tallies_file(self, tallies_file, merge=True): - '''Add all tallies from all MGXS objects to a tallies file. + """Add all tallies from all MGXS objects to a tallies file. NOTE: This assumes that :meth:`Library.build_library` has been called @@ -364,7 +364,7 @@ class Library(object): Indicate whether tallies should be merged when possible. Defaults to True. - ''' + """ cv.check_type('tallies_file', tallies_file, openmc.Tallies) @@ -376,7 +376,7 @@ class Library(object): tallies_file.append(tally, merge=merge) def load_from_statepoint(self, statepoint): - '''Extracts tallies in an OpenMC StatePoint with the data needed to + """Extracts tallies in an OpenMC StatePoint with the data needed to compute multi-group cross sections. This method is needed to compute cross section data from tallies @@ -395,7 +395,7 @@ class Library(object): When this method is called with a statepoint that has not been linked with a summary object. - ''' + """ cv.check_type('statepoint', statepoint, openmc.StatePoint) @@ -419,7 +419,7 @@ class Library(object): mgxs.sparse = self.sparse def get_mgxs(self, domain, mgxs_type): - '''Return the MGXS object for some domain and reaction rate type. + """Return the MGXS object for some domain and reaction rate type. This routine searches the library for an MGXS object for the spatial domain and reaction rate type requested by the user. @@ -444,7 +444,7 @@ class Library(object): If no MGXS object can be found for the requested domain or multi-group cross section type - ''' + """ if self.domain_type == 'material': cv.check_type('domain', domain, (openmc.Material, Integral)) @@ -474,7 +474,7 @@ class Library(object): return self.all_mgxs[domain_id][mgxs_type] def get_condensed_library(self, coarse_groups): - '''Construct an energy-condensed version of this library. + """Construct an energy-condensed version of this library. This routine condenses each of the multi-group cross sections in the library to a coarse energy group structure. NOTE: This routine must @@ -501,7 +501,7 @@ class Library(object): -------- MGXS.get_condensed_xs(coarse_groups) - ''' + """ if self.sp_filename is None: msg = 'Unable to get a condensed coarse group cross section ' \ @@ -530,7 +530,7 @@ class Library(object): return condensed_library def get_subdomain_avg_library(self): - '''Construct a subdomain-averaged version of this library. + """Construct a subdomain-averaged version of this library. This routine averages each multi-group cross section across distribcell instances. The method performs spatial homogenization to compute the @@ -553,7 +553,7 @@ class Library(object): -------- MGXS.get_subdomain_avg_xs(subdomains) - ''' + """ if self.sp_filename is None: msg = 'Unable to get a subdomain-averaged cross section ' \ @@ -581,7 +581,7 @@ class Library(object): def build_hdf5_store(self, filename='mgxs.h5', directory='mgxs', subdomains='all', nuclides='all', xs_type='macro', row_column='inout'): - '''Export the multi-group cross section library to an HDF5 binary file. + """Export the multi-group cross section library to an HDF5 binary file. This method constructs an HDF5 file which stores the library's multi-group cross section data. The data is stored in a hierarchy of @@ -624,7 +624,7 @@ class Library(object): -------- MGXS.build_hdf5_store(filename, directory, xs_type) - ''' + """ if self.sp_filename is None: msg = 'Unable to export multi-group cross section library ' \ @@ -659,7 +659,7 @@ class Library(object): nuclides=nuclides, row_column=row_column) def dump_to_file(self, filename='mgxs', directory='mgxs'): - '''Store this Library object in a pickle binary file. + """Store this Library object in a pickle binary file. Parameters ---------- @@ -672,7 +672,7 @@ class Library(object): -------- Library.load_from_file(filename, directory) - ''' + """ cv.check_type('filename', filename, basestring) cv.check_type('directory', directory, basestring) @@ -689,7 +689,7 @@ class Library(object): @staticmethod def load_from_file(filename='mgxs', directory='mgxs'): - '''Load a Library object from a pickle binary file. + """Load a Library object from a pickle binary file. Parameters ---------- @@ -707,7 +707,7 @@ class Library(object): -------- Library.dump_to_file(mgxs_lib, filename, directory) - ''' + """ cv.check_type('filename', filename, basestring) cv.check_type('directory', directory, basestring) @@ -725,7 +725,7 @@ class Library(object): def write_mg_library(self, xs_type='macro', domain_names=None, xs_ids=None, filename='mg_cross_sections', directory='./', return_names=True): - '''Creates a cross-section data library file for the Multi-Group + """Creates a cross-section data library file for the Multi-Group mode of OpenMC. Parameters @@ -768,7 +768,7 @@ class Library(object): -------- Library.dump_to_file(mgxs_lib, filename, directory) - ''' + """ # Check to ensure the Library contains the correct # multi-group cross section types @@ -904,10 +904,11 @@ class Library(object): # accounted for approximately by using an adjusted # absorption cross section. if 'total' in self.mgxs_types: - xsdata.absorption = \ + xsdata._absorption = \ np.subtract(xsdata.total, np.sum(xsdata.scatter[0, :, :], axis=1)) + xsdatas.append(xsdata) # Add XSdatas to file @@ -925,24 +926,20 @@ class Library(object): a MGXS Library for OpenMC's Multi-Group mode via the `Library.write_mg_library` method. The rules to check include: - - Fission is not required as a fixed source problem could be - the target. - - Absorption is required. + - Either total or transport should be present. + - Both can be available if one wants, but we should + use whatever corresponds to Library.correction (if P0: transport) + - Absorption and total (or transport) are required. + - A nu-fission cross section and chi values are not required as a + fixed source problem could be the target. + - Fission and kappa-fission are not required as they are only + needed to support tallies the user may wish to request. - A nu-scatter matrix is required. - Having both nu-scatter (of any order) and scatter (at least isotropic) matrices is preferred - If only nu-scatter, need total (not transport), to be used in adjusting absorption (i.e., reduced_abs = tot - nuscatt) - - Either total or transport should be present. - - Both can be available if one wants, but we should - use whatever corresponds to Library.correction (if P0: transport) - - Raises - ------ - ValueError - When the Library object is initialized with insufficient types of - cross sections for the Library. See also -------- @@ -979,7 +976,12 @@ class Library(object): msg = 'Transport MGXS type is required since a "P0" correction ' \ 'is applied, but a Transport MGXS is not provided.' warn(msg) + elif (((self.correction is None) and + ('total' not in self.mgxs_types))): + error_flag = True + msg = 'Total MGXS type is required, but not provided.' + warn(msg) if error_flag: - msg = "Invalid MGXS configuration encountered." + msg = 'Invalid MGXS configuration encountered.' raise ValueError(msg) diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index f9353f9cc7..29d0bfdd7d 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -449,17 +449,18 @@ class XSdata(object): @total.setter def total(self, total): """This method sets the total cross section by performing a - deep-copy of the provided ndarray. + deep-copy of the provided ndarray. If the angular + representation is "isotropic" the shape of the input array + must be the number of energy groups. If the angular + representation is "angle" then the shape of the input + array must be the number of polar angles, number azimuthal + angles and energy groups. Parameters ---------- total: ndarray Array of group-wise cross sections to apply - Raises - ------ - ValueError - When invalid parameters are passed. """ # check we have a numpy list @@ -472,18 +473,20 @@ class XSdata(object): @absorption.setter def absorption(self, absorption): """This method sets the absorption cross section by performing a - deep-copy of the provided ndarray. + deep-copy of the provided ndarray. If the angular + representation is "isotropic" the shape of the input array + must be the number of energy groups. If the angular + representation is "angle" then the shape of the input + array must be the number of polar angles, number azimuthal + angles and energy groups. Parameters ---------- absorption: ndarray Array of group-wise cross sections to apply - Raises - ------ - ValueError - When invalid parameters are passed. """ + # check we have a numpy list check_type('absorption', absorption, np.ndarray, expected_iter_type=Real) @@ -495,18 +498,20 @@ class XSdata(object): @fission.setter def fission(self, fission): """This method sets the fission cross section by performing a - deep-copy of the provided ndarray. + deep-copy of the provided ndarray. If the angular + representation is "isotropic" the shape of the input array + must be the number of energy groups. If the angular + representation is "angle" then the shape of the input + array must be the number of polar angles, number azimuthal + angles and energy groups. Parameters ---------- fission: ndarray Array of group-wise cross sections to apply - Raises - ------ - ValueError - When invalid parameters are passed. """ + # check we have a numpy list check_type('fission', fission, np.ndarray, expected_iter_type=Real) @@ -521,18 +526,20 @@ class XSdata(object): @kappa_fission.setter def kappa_fission(self, kappa_fission): """This method sets the kappa_fission cross section by performing a - deep-copy of the provided ndarray. + deep-copy of the provided ndarray. If the angular + representation is "isotropic" the shape of the input array + must be the number of energy groups. If the angular + representation is "angle" then the shape of the input + array must be the number of polar angles, number azimuthal + angles and energy groups. Parameters ---------- kappa_fission: ndarray Array of group-wise cross sections to apply - Raises - ------ - ValueError - When invalid parameters are passed. """ + # check we have a numpy list check_type('kappa_fission', fission, np.ndarray, expected_iter_type=Real) @@ -548,18 +555,20 @@ class XSdata(object): @chi.setter def chi(self, chi): """This method sets the chi cross section by performing a - deep-copy of the provided ndarray. + deep-copy of the provided ndarray. If the angular + representation is "isotropic" the shape of the input array + must be the number of energy groups. If the angular + representation is "angle" then the shape of the input + array must be the number of polar angles, number azimuthal + angles and energy groups. Parameters ---------- chi: ndarray - Array of group-wise cross sections to apply + Array of group-wise chi values to apply - Raises - ------ - ValueError - When invalid parameters are passed. """ + if self._use_chi is not None: if not self._use_chi: msg = 'Providing chi when nu_fission already provided as a' \ @@ -580,40 +589,50 @@ class XSdata(object): def scatter(self, scatter): """This method sets the scattering matrix cross sections by performing a deep-copy of the provided ndarray. + If the angular representation is "isotropic" the shape of + the input array must be the number of scattering orders, the + number of energy groups, and the number of energy groups. If + the angular representation is "angle" then the shape of the input + array must be the number of polar angles, number azimuthal + angles, number of scattering orders, energy groups, and energy groups. Parameters ---------- scatter : ndarrays - Array of group-wise cross sections to apply + Array of cross sections to apply - Raises - ------ - ValueError - When invalid parameters are passed. """ + # check we have a numpy list check_type('scatter', scatter, np.ndarray, expected_iter_type=Real, max_depth=len(scatter.shape)) # Check the dimensions of the data - check_value('scatter shape', scatter.shape, self.matrix_shape) + check_value('scatter shape', scatter.shape, self.pn_matrix_shape) self._scatter = np.copy(scatter) @multiplicity.setter def multiplicity(self, multiplicity): """This method sets the scattering multiplicity matrix cross sections - by performing a deep-copy of the provided ndarray. + by performing a deep-copy of the provided ndarray. Multiplicity, + in OpenMC parlance, is a factor used to account for the production + of neutrons introduced by scattering multiplication reactions, i.e., + (n,xn) events. In this sense, the multiplication matrix is simply + defined as the ratio of the nu-scatter and scatter matrices. + If the angular representation is "isotropic" the shape of + the input array must be the number of energy groups and the number + of energy groups. If the angular representation is "angle" then the + shape of the input array must be the number of polar angles, + number azimuthal angles, number of scattering orders, energy groups, + and energy groups. Parameters ---------- multiplicity : ndarrays - Array of group-wise cross sections to apply + Array of scattering multiplications to apply - Raises - ------ - ValueError - When invalid parameters are passed. """ + # check we have a numpy list check_type('multiplicity', multiplicity, np.ndarray, expected_iter_type=Real, max_depth=len(multiplicity.shape)) @@ -626,18 +645,20 @@ class XSdata(object): @nu_fission.setter def nu_fission(self, nu_fission): """This method sets the nu_fission cross section by performing a - deep-copy of the provided ndarray. + deep-copy of the provided ndarray. If the angular + representation is "isotropic" the shape of the input array + must be the number of energy groups. If the angular + representation is "angle" then the shape of the input + array must be the number of polar angles, number azimuthal + angles and energy groups. Parameters ---------- nu_fission: ndarray Array of group-wise cross sections to apply - Raises - ------ - ValueError - When invalid parameters are passed. """ + # The NuFissionXS class does not have the capability to produce # a fission matrix and therefore if this path is pursued, we know # chi must be used. @@ -691,16 +712,10 @@ class XSdata(object): Provide the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. - Raises - ------ - ValueError - When invalid parameters are passed. """ - if not isinstance(total, (openmc.mgxs.TotalXS, - openmc.mgxs.TransportXS)): - msg = 'Method must be passed an openmc.mgxs.TotalXS or ' \ - 'openmc.mgxs.TransportXS object' - raise TypeError(msg) + + check_type('total', total, (openmc.mgxs.TotalXS, + openmc.mgxs.TransportXS)) # Make sure passed MGXS object contains correct group structure check_value('energy_groups', total.energy_groups, [self.energy_groups]) @@ -715,7 +730,8 @@ class XSdata(object): msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) - def set_absorption_mgxs(self, absorption, nuclide='total', xs_type='macro'): + def set_absorption_mgxs(self, absorption, nuclide='total', + xs_type='macro'): """This method allows for an openmc.mgxs.AbsorptionXS to be used to set the absorption cross section for this XSdata object. @@ -731,14 +747,9 @@ class XSdata(object): Provide the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. - Raises - ------ - ValueError - When invalid parameters are passed. """ - if not isinstance(absorption, openmc.mgxs.AbsorptionXS): - msg = 'Method must be passed an openmc.mgxs.AbsorptionXS' - raise TypeError(msg) + + check_type('absorption', absorption, openmc.mgxs.AbsorptionXS) # Make sure passed MGXS object contains correct group structure check_value('energy_groups', absorption.energy_groups, @@ -771,14 +782,9 @@ class XSdata(object): Provide the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. - Raises - ------ - ValueError - When invalid parameters are passed. """ - if not isinstance(fission, openmc.mgxs.FissionXS): - msg = 'Method must be passed an openmc.mgxs.FissionXS' - raise TypeError(msg) + + check_type('fission', fission, openmc.mgxs.FissionXS) # Make sure passed MGXS object contains correct group structure check_value('energy_groups', fission.energy_groups, @@ -795,7 +801,8 @@ class XSdata(object): 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'): + def set_nu_fission_mgxs(self, nu_fission, nuclide='total', + xs_type='macro'): """This method allows for an openmc.mgxs.NuFissionXS to be used to set the nu-fission cross section for this XSdata object. @@ -811,17 +818,12 @@ class XSdata(object): Provide the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. - Raises - ------ - ValueError - When invalid parameters are passed. """ + # The NuFissionXS class does not have the capability to produce # a fission matrix and therefore if this path is pursued, we know # chi must be used. - if not isinstance(nu_fission, openmc.mgxs.NuFissionXS): - msg = 'Method must be passed an openmc.mgxs.NuFissionXS' - raise TypeError(msg) + check_type('nu_fission', nu_fission, openmc.mgxs.NuFissionXS) # Make sure passed MGXS object contains correct group structure check_value('energy_groups', nu_fission.energy_groups, @@ -861,14 +863,9 @@ class XSdata(object): Provide the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. - Raises - ------ - ValueError - When invalid parameters are passed. """ - if not isinstance(k_fission, openmc.mgxs.KappaFissionXS): - msg = 'Method must be passed an openmc.mgxs.KappaFissionXS' - raise TypeError(msg) + + check_type('k_fission', k_fission, openmc.mgxs.KappaFissionXS) # Make sure passed MGXS object contains correct group structure check_value('energy_groups', k_fission.energy_groups, @@ -900,20 +897,15 @@ class XSdata(object): Provide the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. - Raises - ------ - ValueError - When invalid parameters are passed. """ + if self._use_chi is not None: if not self._use_chi: msg = 'Providing chi when nu_fission already provided as a ' \ 'matrix!' raise ValueError(msg) - if not isinstance(chi, openmc.mgxs.Chi): - msg = 'Method must be passed an openmc.mgxs.Chi' - raise TypeError(msg) + check_type('chi', chi, openmc.mgxs.Chi) # Make sure passed MGXS object contains correct group structure check_value('energy_groups', chi.energy_groups, [self.energy_groups]) @@ -949,14 +941,9 @@ class XSdata(object): Provide the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. - Raises - ------ - ValueError - When invalid parameters are passed. """ - if not isinstance(scatter, openmc.mgxs.ScatterMatrixXS): - msg = 'Method must be passed an openmc.mgxs.ScatterMatrixXS' - raise TypeError(msg) + + check_type('scatter', scatter, openmc.mgxs.ScatterMatrixXS) # Make sure passed MGXS object contains correct group structure check_value('energy_groups', scatter.energy_groups, @@ -967,8 +954,9 @@ class XSdata(object): ['universe', 'cell', 'material']) if self._representation is 'isotropic': - self._scatter = scatter.get_xs(nuclides=nuclide, - xs_type=xs_type) + self._scatter = np.array([scatter.get_xs(nuclides=nuclide, + xs_type=xs_type)]) + elif self._representation is 'angle': msg = 'Angular-Dependent MGXS have not yet been implemented' raise ValueError(msg) @@ -977,7 +965,11 @@ class XSdata(object): xs_type='macro'): """This method allows for an openmc.mgxs.NuScatterMatrixXS and openmc.mgxs.ScatterMatrixXS to be used to set the scattering - multiplicity for this XSdata object. + multiplicity for this XSdata object. Multiplicity, + in OpenMC parlance, is a factor used to account for the production + of neutrons introduced by scattering multiplication reactions, i.e., + (n,xn) events. In this sense, the multiplication matrix is simply + defined as the ratio of the nu-scatter and scatter matrices. Parameters ---------- @@ -994,17 +986,10 @@ class XSdata(object): Provide the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. - Raises - ------ - ValueError - When invalid parameters are passed. """ - if not isinstance(nuscatter, openmc.mgxs.NuScatterMatrixXS): - msg = 'Method must be passed an openmc.mgxs.ScatterMatrixXS' - raise TypeError(msg) - if not isinstance(scatter, openmc.mgxs.ScatterMatrixXS): - msg = 'Method must be passed an openmc.mgxs.ScatterMatrixXS' - raise TypeError(msg) + + check_type('nuscatter', nuscatter, openmc.mgxs.NuScatterMatrixXS) + check_type('scatter', scatter, openmc.mgxs.ScatterMatrixXS) # Make sure passed MGXS object contains correct group structure check_value('energy_groups', nuscatter.energy_groups,