예제 #1
0
 def universes(self, universes):
     cv.check_iterable_type('lattice universes',
                            universes,
                            Universe,
                            min_depth=2,
                            max_depth=3)
     self._universes = universes
예제 #2
0
def write_source_file(source_particles, filename, **kwargs):
    """Write a source file using a collection of source particles

    Parameters
    ----------
    source_particles : iterable of SourceParticle
        Source particles to write to file
    filename : str or path-like
        Path to source file to write
    **kwargs
        Keyword arguments to pass to :class:`h5py.File`

    """
    # Create compound datatype for source particles
    pos_dtype = np.dtype([('x', '<f8'), ('y', '<f8'), ('z', '<f8')])
    source_dtype = np.dtype([
        ('r', pos_dtype),
        ('u', pos_dtype),
        ('E', '<f8'),
        ('wgt', '<f8'),
        ('delayed_group', '<i4'),
        ('surf_id', '<i4'),
        ('particle', '<i4'),
    ])

    # Create array of source particles
    cv.check_iterable_type("source particles", source_particles, SourceParticle)
    arr = np.array([s.to_tuple() for s in source_particles], dtype=source_dtype)

    # Write array to file
    kwargs.setdefault('mode', 'w')
    with h5py.File(filename, **kwargs) as fh:
        fh.attrs['filetype'] = np.string_("source")
        fh.create_dataset('source_bank', data=arr, dtype=source_dtype)
예제 #3
0
 def universes(self, universes):
     cv.check_iterable_type('lattice universes',
                            universes,
                            openmc.Universe,
                            min_depth=2,
                            max_depth=3)
     self._universes = np.asarray(universes)
예제 #4
0
    def nu_fission(self, nu_fission):
        # 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.
        # nu_fission can be given as a vector or a matrix
        # Vector is used when chi also exists.
        # Matrix is used when chi does not exist.
        # We have to check that the correct form is given, but only if
        # chi already has been set.  If not, we just check that this is OK
        # and set the use_chi flag accordingly

        # Convert to a numpy array so we can easily get the shape for
        # checking
        npnu_fission = np.asarray(nu_fission)

        check_iterable_type('nu_fission', npnu_fission, Real,
                            max_depth=len(npnu_fission.shape))

        if self.use_chi is not None:
            if self.use_chi:
                check_value('nu_fission shape', npnu_fission.shape,
                            [self.vector_shape])
            else:
                check_value('nu_fission shape', npnu_fission.shape,
                            [self.matrix_shape])
        else:
            check_value('nu_fission shape', npnu_fission.shape,
                        [self.vector_shape, self.matrix_shape])
            # Find out if we have a nu-fission matrix or vector
            # and set a flag to allow other methods to check this later.
            self.use_chi = (npnu_fission.shape == self.vector_shape)

        self._nu_fission = npnu_fission
        if np.sum(self._nu_fission) > 0.0:
            self._fissionable = True
예제 #5
0
파일: filter.py 프로젝트: maolongliu/openmc
    def bins(self, bins):
        if bins is None:
            self.num_bins = 0
        elif self._type is None:
            msg = 'Unable to set bins for Filter to "{0}" since ' \
                  'the Filter type has not yet been set'.format(bins)
            raise ValueError(msg)

        # If the bin edge is a single value, it is a Cell, Material, etc. ID
        if not isinstance(bins, Iterable):
            bins = [bins]

        # If the bins are in a collection, convert it to a list
        else:
            bins = list(bins)

        if self.type in ['cell', 'cellborn', 'surface', 'material',
                          'universe', 'distribcell']:
            check_iterable_type('filter bins', bins, Integral)
            for edge in bins:
                check_greater_than('filter bin', edge, 0, equality=True)

        elif self._type in ['energy', 'energyout']:
            for edge in bins:
                if not isinstance(edge, Real):
                    msg = 'Unable to add bin edge "{0}" to a "{1}" Filter ' \
                          'since it is a non-integer or floating point ' \
                          'value'.format(edge, self.type)
                    raise ValueError(msg)
                elif edge < 0.:
                    msg = 'Unable to add bin edge "{0}" to a "{1}" Filter ' \
                          'since it is a negative value'.format(edge, self.type)
                    raise ValueError(msg)

            # Check that bin edges are monotonically increasing
            for index in range(len(bins)):
                if index > 0 and bins[index] < bins[index-1]:
                    msg = 'Unable to add bin edges "{0}" to a "{1}" Filter ' \
                          'since they are not monotonically ' \
                          'increasing'.format(bins, self.type)
                    raise ValueError(msg)

        # mesh filters
        elif self._type == 'mesh':
            if not len(bins) == 1:
                msg = 'Unable to add bins "{0}" to a mesh Filter since ' \
                      'only a single mesh can be used per tally'.format(bins)
                raise ValueError(msg)
            elif not isinstance(bins[0], Integral):
                msg = 'Unable to add bin "{0}" to mesh Filter since it ' \
                       'is a non-integer'.format(bins[0])
                raise ValueError(msg)
            elif bins[0] < 0:
                msg = 'Unable to add bin "{0}" to mesh Filter since it ' \
                       'is a negative integer'.format(bins[0])
                raise ValueError(msg)

        # If all error checks passed, add bin edges
        self._bins = np.array(bins)
예제 #6
0
    def bins(self, bins):
        if self.type is None:
            msg = 'Unable to set bins for Filter to "{0}" since ' \
                  'the Filter type has not yet been set'.format(bins)
            raise ValueError(msg)

        # If the bin edge is a single value, it is a Cell, Material, etc. ID
        if not isinstance(bins, Iterable):
            bins = [bins]

        # If the bins are in a collection, convert it to a list
        else:
            bins = list(bins)

        if self.type in [
                'cell', 'cellborn', 'surface', 'material', 'universe',
                'distribcell', 'delayedgroup'
        ]:
            cv.check_iterable_type('filter bins', bins, Integral)
            for edge in bins:
                cv.check_greater_than('filter bin', edge, 0, equality=True)

        elif self.type in ['energy', 'energyout']:
            for edge in bins:
                if not isinstance(edge, Real):
                    msg = 'Unable to add bin edge "{0}" to a "{1}" Filter ' \
                          'since it is a non-integer or floating point ' \
                          'value'.format(edge, self.type)
                    raise ValueError(msg)
                elif edge < 0.:
                    msg = 'Unable to add bin edge "{0}" to a "{1}" Filter ' \
                          'since it is a negative value'.format(edge, self.type)
                    raise ValueError(msg)

            # Check that bin edges are monotonically increasing
            for index in range(len(bins)):
                if index > 0 and bins[index] < bins[index - 1]:
                    msg = 'Unable to add bin edges "{0}" to a "{1}" Filter ' \
                          'since they are not monotonically ' \
                          'increasing'.format(bins, self.type)
                    raise ValueError(msg)

        # mesh filters
        elif self.type == 'mesh':
            if not len(bins) == 1:
                msg = 'Unable to add bins "{0}" to a mesh Filter since ' \
                      'only a single mesh can be used per tally'.format(bins)
                raise ValueError(msg)
            elif not isinstance(bins[0], Integral):
                msg = 'Unable to add bin "{0}" to mesh Filter since it ' \
                       'is a non-integer'.format(bins[0])
                raise ValueError(msg)
            elif bins[0] < 0:
                msg = 'Unable to add bin "{0}" to mesh Filter since it ' \
                       'is a negative integer'.format(bins[0])
                raise ValueError(msg)

        # If all error checks passed, add bin edges
        self._bins = np.array(bins)
예제 #7
0
 def mgxs_types(self, mgxs_types):
     if mgxs_types == 'all':
         self._mgxs_types = openmc.mgxs.MGXS_TYPES
     else:
         cv.check_iterable_type('mgxs_types', mgxs_types, basestring)
         for mgxs_type in mgxs_types:
             cv.check_value('mgxs_type', mgxs_type, openmc.mgxs.MGXS_TYPES)
         self._mgxs_types = mgxs_types
예제 #8
0
파일: library.py 프로젝트: albeanth/openmc
 def mgxs_types(self, mgxs_types):
     if mgxs_types == 'all':
         self._mgxs_types = openmc.mgxs.MGXS_TYPES
     else:
         cv.check_iterable_type('mgxs_types', mgxs_types, basestring)
         for mgxs_type in mgxs_types:
             cv.check_value('mgxs_type', mgxs_type, openmc.mgxs.MGXS_TYPES)
         self._mgxs_types = mgxs_types
예제 #9
0
파일: plots.py 프로젝트: sunxb10/openmc
    def highlight_domains(self,
                          geometry,
                          domains,
                          seed=1,
                          alpha=0.5,
                          background='gray'):
        """Use alpha compositing to highlight one or more domains in the plot.

        This routine generates a color scheme and applies alpha compositing
        to make all domains except the highlighted ones appear partially
        transparent.

        Parameters
        ----------
        geometry : openmc.Geometry
            The geometry for which the plot is defined
        domains : Iterable of Integral
            A collection of the domain IDs to highlight in the plot
        seed : Integral
            The random number seed used to generate the color scheme
        alpha : Real in [0,1]
            The value to apply in alpha compisiting
        background : 3-tuple of Integral or 'white' or 'black' or 'gray'
            The background color to apply in alpha compisiting

        """

        cv.check_iterable_type('domains', domains, Integral)
        cv.check_type('alpha', alpha, Real)
        cv.check_greater_than('alpha', alpha, 0., equality=True)
        cv.check_less_than('alpha', alpha, 1., equality=True)

        # Get a background (R,G,B) tuple to apply in alpha compositing
        if isinstance(background, basestring):
            if background == 'white':
                background = (255, 255, 255)
            elif background == 'black':
                background = (0, 0, 0)
            elif background == 'gray':
                background = (160, 160, 160)
            else:
                msg = 'The background "{}" is not defined'.format(background)
                raise ValueError(msg)

        cv.check_iterable_type('background', background, Integral)

        # Generate a color scheme
        self.colorize(geometry, seed)

        # Apply alpha compositing to the colors for all domains
        # other than those the user wishes to highlight
        for domain_id in self.col_spec:
            if domain_id not in domains:
                r, g, b = self.col_spec[domain_id]
                r = int(((1 - alpha) * background[0]) + (alpha * r))
                g = int(((1 - alpha) * background[1]) + (alpha * g))
                b = int(((1 - alpha) * background[2]) + (alpha * b))
                self._col_spec[domain_id] = (r, g, b)
예제 #10
0
    def scatter(self, scatter):
        # Convert to a numpy array so we can easily get the shape for
        # checking
        npscatter = np.asarray(scatter)
        check_iterable_type('scatter', npscatter, Real,
                            max_depth=len(npscatter.shape))
        check_value('scatter shape', npscatter.shape, [self.pn_matrix_shape])

        self._scatter = npscatter
예제 #11
0
    def multiplicity(self, multiplicity):
        # Convert to a numpy array so we can easily get the shape for
        # checking
        npmultiplicity = np.asarray(multiplicity)
        check_iterable_type('multiplicity', npmultiplicity, Real,
                            max_depth=len(npmultiplicity.shape))
        check_value('multiplicity shape', npmultiplicity.shape,
                    [self.matrix_shape])

        self._multiplicity = npmultiplicity
예제 #12
0
파일: plots.py 프로젝트: LMKerby/openmc
    def highlight_domains(self, geometry, domains, seed=1,
                          alpha=0.5, background='gray'):
        """Use alpha compositing to highlight one or more domains in the plot.

        This routine generates a color scheme and applies alpha compositing
        to make all domains except the highlighted ones appear partially
        transparent.

        Parameters
        ----------
        geometry : openmc.Geometry
            The geometry for which the plot is defined
        domains : Iterable of Integral
            A collection of the domain IDs to highlight in the plot
        seed : Integral
            The random number seed used to generate the color scheme
        alpha : Real in [0,1]
            The value to apply in alpha compisiting
        background : 3-tuple of Integral or 'white' or 'black' or 'gray'
            The background color to apply in alpha compisiting

        """

        cv.check_iterable_type('domains', domains, Integral)
        cv.check_type('alpha', alpha, Real)
        cv.check_greater_than('alpha', alpha, 0., equality=True)
        cv.check_less_than('alpha', alpha, 1., equality=True)

        # Get a background (R,G,B) tuple to apply in alpha compositing
        if isinstance(background, basestring):
            if background == 'white':
                background = (255, 255, 255)
            elif background == 'black':
                background = (0, 0, 0)
            elif background == 'gray':
                background = (160, 160, 160)
            else:
                msg = 'The background "{}" is not defined'.format(background)
                raise ValueError(msg)

        cv.check_iterable_type('background', background, Integral)

        # Generate a color scheme
        self.colorize(geometry, seed)

        # Apply alpha compositing to the colors for all domains
        # other than those the user wishes to highlight
        for domain_id in self.col_spec:
            if domain_id not in domains:
                r, g, b = self.col_spec[domain_id]
                r = int(((1-alpha) * background[0]) + (alpha * r))
                g = int(((1-alpha) * background[1]) + (alpha * g))
                b = int(((1-alpha) * background[2]) + (alpha * b))
                self._col_spec[domain_id] = (r, g, b)
예제 #13
0
    def add_xsdatas(self, xsdatas):
        """Add multiple xsdatas to the file.

        Parameters
        ----------
        xsdatas : tuple or list of openmc.XSdata
            XSdatas to add

        """
        check_iterable_type('xsdatas', xsdatas, XSdata)

        for xsdata in xsdatas:
            self.add_xsdata(xsdata)
예제 #14
0
파일: library.py 프로젝트: albeanth/openmc
    def domains(self, domains):

        # Use all materials, cells or universes in the geometry as domains
        if domains == 'all':
            self._domains = domains

        # User specified a list of material, cell or universe domains
        else:
            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 == 'universe':
                cv.check_iterable_type('domain', domains, openmc.Universe)
                all_domains = self.openmc_geometry.get_all_universes()
            else:
                raise ValueError('Unable to set domains with domain '
                                 'type "{}"'.format(self.domain_type))

            # Check that each domain can be found in the geometry
            for domain in domains:
                if domain not in all_domains:
                    raise ValueError('Domain "{}" could not be found in the '
                                     'geometry.'.format(domain))

            self._domains = domains
예제 #15
0
    def domains(self, domains):

        # Use all materials, cells or universes in the geometry as domains
        if domains == 'all':
            self._domains = domains

        # User specified a list of material, cell or universe domains
        else:
            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 == 'universe':
                cv.check_iterable_type('domain', domains, openmc.Universe)
                all_domains = self.openmc_geometry.get_all_universes()
            else:
                msg = 'Unable to set domains with ' \
                      'domain type "{}"'.format(self.domain_type)
                raise ValueError(msg)

            # Check that each domain can be found in the geometry
            for domain in domains:
                if domain not in all_domains:
                    msg = 'Domain "{}" could not be found in the ' \
                          'geometry.'.format(domain)
                    raise ValueError(msg)

            self._domains = domains
예제 #16
0
파일: plotter.py 프로젝트: biegelk/openmc
def calculate_mgxs(this, types, orders=None, temperature=294.,
                   cross_sections=None, ce_cross_sections=None,
                   enrichment=None):
    """Calculates continuous-energy cross sections of a requested type.

    If the data for the nuclide or macroscopic object in the library is
    represented as angle-dependent data then this method will return the
    geometric average cross section over all angles.

    Parameters
    ----------
    this : openmc.Element, openmc.Nuclide, openmc.Material, or openmc.Macroscopic
        Object to source data from
    types : Iterable of values of PLOT_TYPES_MGXS
        The type of cross sections to calculate
    orders : Iterable of Integral, optional
        The scattering order or delayed group index to use for the
        corresponding entry in types. Defaults to the 0th order for scattering
        and the total delayed neutron data.
    temperature : float, optional
        Temperature in Kelvin to plot. If not specified, a default
        temperature of 294K will be plotted. Note that the nearest
        temperature in the library for each nuclide will be used as opposed
        to using any interpolation.
    cross_sections : str, optional
        Location of MGXS HDF5 Library file. Default is None.
    ce_cross_sections : str, optional
        Location of continuous-energy cross_sections.xml file. Default is None.
        This is used only for expanding an openmc.Element object passed as this
    enrichment : float, optional
        Enrichment for U235 in weight percent. For example, input 4.95 for
        4.95 weight percent enriched U. Default is None
        (natural composition).

    Returns
    -------
    energy_grid : numpy.ndarray
        Energies at which cross sections are calculated, in units of eV
    data : numpy.ndarray
        Cross sections calculated at the energy grid described by energy_grid

    """

    # Check types
    cv.check_type('temperature', temperature, Real)
    if enrichment:
        cv.check_type('enrichment', enrichment, Real)
    cv.check_iterable_type('types', types, string_types)

    cv.check_type("cross_sections", cross_sections, str)
    library = openmc.MGXSLibrary.from_hdf5(cross_sections)

    if isinstance(this, (openmc.Nuclide, openmc.Macroscopic)):
        mgxs = _calculate_mgxs_nuc_macro(this, types, library, orders,
                                         temperature)
    elif isinstance(this, (openmc.Element, openmc.Material)):
        mgxs = _calculate_mgxs_elem_mat(this, types, library, orders,
                                        temperature, ce_cross_sections,
                                        enrichment)
    else:
        raise TypeError("Invalid type")

    # Convert the data to the format needed
    data = np.zeros((len(types), 2 * library.energy_groups.num_groups))
    energy_grid = np.zeros(2 * library.energy_groups.num_groups)
    for g in range(library.energy_groups.num_groups):
        energy_grid[g * 2: g * 2 + 2] = \
            library.energy_groups.group_edges[g: g + 2]
    # Ensure the energy will show on a log-axis by replacing 0s with a
    # sufficiently small number
    energy_grid[0] = max(energy_grid[0], _MIN_E)

    for line in range(len(types)):
        for g in range(library.energy_groups.num_groups):
            data[line, g * 2: g * 2 + 2] = mgxs[line, g]

    return energy_grid[::-1], data
예제 #17
0
파일: plotter.py 프로젝트: biegelk/openmc
def _calculate_mgxs_nuc_macro(this, types, library, orders=None,
                              temperature=294.):
    """Determines the multi-group cross sections of a nuclide or macroscopic
    object.

    If the data for the nuclide or macroscopic object in the library is
    represented as angle-dependent data then this method will return the
    geometric average cross section over all angles.

    Parameters
    ----------
    this : openmc.Nuclide or openmc.Macroscopic
        Object to source data from
    types : Iterable of str
        The type of cross sections to calculate; values can either be those
        in openmc.PLOT_TYPES_MGXS
    library : openmc.MGXSLibrary
        MGXS Library containing the data of interest
    orders : Iterable of Integral, optional
        The scattering order or delayed group index to use for the
        corresponding entry in types. Defaults to the 0th order for scattering
        and the total delayed neutron data.
    temperature : float, optional
        Temperature in Kelvin to plot. If not specified, a default
        temperature of 294K will be plotted. Note that the nearest
        temperature in the library for each nuclide will be used as opposed
        to using any interpolation.

    Returns
    -------
    data : numpy.ndarray
        Cross sections calculated at the energy grid described by energy_grid

    """

    # Check the parameters and grab order/delayed groups
    if orders:
        cv.check_iterable_type('orders', orders, Integral,
                               min_depth=len(types), max_depth=len(types))
    else:
        orders = [None] * len(types)
    for i, line in enumerate(types):
        cv.check_type("line", line, str)
        cv.check_value("line", line, PLOT_TYPES_MGXS)
        if orders[i]:
            cv.check_greater_than("order value", orders[i], 0, equality=True)

    xsdata = library.get_by_name(this.name)

    if xsdata is not None:
        # Obtain the nearest temperature
        t = np.abs(xsdata.temperatures - temperature).argmin()

        # Get the data
        data = np.zeros((len(types), library.energy_groups.num_groups))
        for i, line in enumerate(types):
            if 'fission' in line and not xsdata.fissionable:
                continue
            elif line == 'unity':
                data[i, :] = 1.
            else:
                # Now we have to get the cross section data and properly
                # treat it depending on the requested type.
                # First get the data in a generic fashion
                temp_data = getattr(xsdata, _PLOT_MGXS_ATTR[line])[t]
                shape = temp_data.shape[:]
                # If we have angular data, then want the geometric
                # average over all provided angles.  Since the angles are
                # equi-distant, un-weighted averaging will suffice
                if xsdata.representation == 'angle':
                    temp_data = np.mean(temp_data, axis=(0, 1))

                # Now we can look at the shape of the data to identify how
                # it should be modified to produce an array of values
                # with groups.
                if shape in (xsdata.xs_shapes["[G']"],
                             xsdata.xs_shapes["[G]"]):
                    # Then the data is already an array vs groups so copy
                    # and move along
                    data[i, :] = temp_data
                elif shape == xsdata.xs_shapes["[G][G']"]:
                    # Sum the data over outgoing groups to create our array vs
                    # groups
                    data[i, :] = np.sum(temp_data, axis=1)
                elif shape == xsdata.xs_shapes["[DG]"]:
                    # Then we have a constant vs groups with a value for each
                    # delayed group. The user-provided value of orders tells us
                    # which delayed group we want. If none are provided, then
                    # we sum all the delayed groups together.
                    if orders[i]:
                        if orders[i] < len(shape[0]):
                            data[i, :] = temp_data[orders[i]]
                    else:
                        data[i, :] = np.sum(temp_data[:])
                elif shape in (xsdata.xs_shapes["[DG][G']"],
                               xsdata.xs_shapes["[DG][G]"]):
                    # Then we have an array vs groups with values for each
                    # delayed group. The user-provided value of orders tells us
                    # which delayed group we want. If none are provided, then
                    # we sum all the delayed groups together.
                    if orders[i]:
                        if orders[i] < len(shape[0]):
                            data[i, :] = temp_data[orders[i], :]
                    else:
                        data[i, :] = np.sum(temp_data[:, :], axis=0)
                elif shape == xsdata.xs_shapes["[DG][G][G']"]:
                    # Then we have a delayed group matrix. We will first
                    # remove the outgoing group dependency
                    temp_data = np.sum(temp_data, axis=-1)
                    # And then proceed in exactly the same manner as the
                    # "[DG][G']" or "[DG][G]" shapes in the previous block.
                    if orders[i]:
                        if orders[i] < len(shape[0]):
                            data[i, :] = temp_data[orders[i], :]
                    else:
                        data[i, :] = np.sum(temp_data[:, :], axis=0)
                elif shape == xsdata.xs_shapes["[G][G'][Order]"]:
                    # This is a scattering matrix with angular data
                    # First remove the outgoing group dependence
                    temp_data = np.sum(temp_data, axis=1)
                    # The user either provided a specific order or we resort
                    # to the default 0th order
                    if orders[i]:
                        order = orders[i]
                    else:
                        order = 0
                    # If the order is available, store the data for that order
                    # if it is not available, then the expansion coefficient
                    # is zero and thus we already have the correct value.
                    if order < shape[1]:
                        data[i, :] = temp_data[:, order]
    else:
        raise ValueError("{} not present in provided MGXS "
                         "library".format(this.name))

    return data
예제 #18
0
 def nuclides(self, nuclides):
     cv.check_iterable_type('nuclides', nuclides,
                            (basestring, Nuclide, CrossNuclide))
     self._nuclides = nuclides
예제 #19
0
    def universes(self, universes):
        cv.check_iterable_type('lattice universes',
                               universes,
                               openmc.Universe,
                               min_depth=2,
                               max_depth=3)
        self._universes = universes

        # NOTE: This routine assumes that the user creates a "ragged" list of
        # lists, where each sub-list corresponds to one ring of Universes.
        # The sub-lists are ordered from outermost ring to innermost ring.
        # The Universes within each sub-list are ordered from the "top" in a
        # clockwise fashion.

        # Set the number of axial positions.
        if self.ndim == 3:
            self._num_axial = len(self._universes)
        else:
            self._num_axial = None

        # Set the number of rings and make sure this number is consistent for
        # all axial positions.
        if self.ndim == 3:
            self._num_rings = len(self._universes[0])
            for rings in self._universes:
                if len(rings) != self._num_rings:
                    msg = 'HexLattice ID={0:d} has an inconsistent number of ' \
                          'rings per axial positon'.format(self._id)
                    raise ValueError(msg)

        else:
            self._num_rings = len(self._universes)

        # Make sure there are the correct number of elements in each ring.
        if self.ndim == 3:
            for axial_slice in self._universes:
                # Check the center ring.
                if len(axial_slice[-1]) != 1:
                    msg = 'HexLattice ID={0:d} has the wrong number of ' \
                          'elements in the innermost ring.  Only 1 element is ' \
                          'allowed in the innermost ring.'.format(self._id)
                    raise ValueError(msg)

                # Check the outer rings.
                for r in range(self._num_rings - 1):
                    if len(axial_slice[r]) != 6 * (self._num_rings - 1 - r):
                        msg = 'HexLattice ID={0:d} has the wrong number of ' \
                              'elements in ring number {1:d} (counting from the '\
                              'outermost ring).  This ring should have {2:d} ' \
                              'elements.'.format(self._id, r,
                                                 6*(self._num_rings - 1 - r))
                        raise ValueError(msg)

        else:
            axial_slice = self._universes
            # Check the center ring.
            if len(axial_slice[-1]) != 1:
                msg = 'HexLattice ID={0:d} has the wrong number of ' \
                      'elements in the innermost ring.  Only 1 element is ' \
                      'allowed in the innermost ring.'.format(self._id)
                raise ValueError(msg)

            # Check the outer rings.
            for r in range(self._num_rings - 1):
                if len(axial_slice[r]) != 6 * (self._num_rings - 1 - r):
                    msg = 'HexLattice ID={0:d} has the wrong number of ' \
                          'elements in ring number {1:d} (counting from the '\
                          'outermost ring).  This ring should have {2:d} ' \
                          'elements.'.format(self._id, r,
                                             6*(self._num_rings - 1 - r))
                    raise ValueError(msg)
예제 #20
0
 def bins(self, bins):
     cv.check_iterable_type('bins', bins, Iterable)
     self._bins = list(map(tuple, bins))
예제 #21
0
파일: material.py 프로젝트: mit-crpg/openmc
 def isotropic(self, isotropic):
     cv.check_iterable_type('Isotropic scattering nuclides', isotropic,
                            string_types)
     self._isotropic = list(isotropic)
예제 #22
0
 def nuclides(self, nuclides):
     cv.check_iterable_type('nuclides', nuclides,
                            string_types + (openmc.Nuclide, CrossNuclide))
     self._nuclides = nuclides
예제 #23
0
 def scores(self, scores):
     cv.check_iterable_type('scores', scores, str)
     self._scores = scores
예제 #24
0
 def breakpoints(self, breakpoints):
     cv.check_iterable_type('breakpoints', breakpoints, Real)
     self._breakpoints = breakpoints
예제 #25
0
 def mu(self, mu):
     cv.check_iterable_type('correlated angle-energy outgoing cosine',
                            mu, Univariate, 2, 2)
     self._mu = mu
예제 #26
0
파일: lattice.py 프로젝트: albeanth/openmc
 def universes(self, universes):
     cv.check_iterable_type('lattice universes', universes, openmc.Universe,
                            min_depth=2, max_depth=3)
     self._universes = np.asarray(universes)
예제 #27
0
def pin(surfaces, items, subdivisions=None, divide_vols=True, **kwargs):
    """Convenience function for building a fuel pin

    Parameters
    ----------
    surfaces : iterable of :class:`openmc.Cylinder`
        Cylinders used to define boundaries
        between items. All cylinders must be
        concentric and of the same orientation, e.g.
        all :class:`openmc.ZCylinder`
    items : iterable
        Objects to go between ``surfaces``. These can be anything
        that can fill a :class:`openmc.Cell`, including
        :class:`openmc.Material`, or other :class:`openmc.Universe`
        objects. There must be one more item than surfaces,
        which will span all space outside the final ring.
    subdivisions : None or dict of int to int
        Dictionary describing which rings to subdivide and how
        many times. Keys are indexes of the annular rings
        to be divided. Will construct equal area rings
    divide_vols : bool
        If this evaluates to ``True``, then volumes of subdivided
        :class:`openmc.Material` instances will also be divided by the
        number of divisions.  Otherwise the volume of the
        original material will not be modified before subdivision
    kwargs:
        Additional key-word arguments to be passed to
        :class:`openmc.Universe`, like ``name="Fuel pin"``

    Returns
    -------
    :class:`openmc.Universe`
        Universe of concentric cylinders filled with the desired
        items
    """
    if "cells" in kwargs:
        raise SyntaxError(
            "Cells will be set by this function, not from input arguments.")
    check_type("items", items, Iterable)
    check_length("surfaces", surfaces, len(items) - 1, len(items) - 1)
    # Check that all surfaces are of similar orientation
    check_type("surface", surfaces[0], Cylinder)
    surf_type = type(surfaces[0])
    check_iterable_type("surfaces", surfaces[1:], surf_type)

    # Check for increasing radii and equal centers
    if surf_type is ZCylinder:
        center_getter = attrgetter("x0", "y0")
    elif surf_type is YCylinder:
        center_getter = attrgetter("x0", "z0")
    elif surf_type is XCylinder:
        center_getter = attrgetter("z0", "y0")
    else:
        raise TypeError("Not configured to interpret {} surfaces".format(
            surf_type.__name__))

    centers = set()
    prev_rad = 0
    for ix, surf in enumerate(surfaces):
        cur_rad = surf.r
        if cur_rad <= prev_rad:
            raise ValueError(
                "Surfaces do not appear to be increasing in radius. "
                "Surface {} at index {} has radius {:7.3e} compared to "
                "previous radius of {:7.5e}".format(surf.id, ix, cur_rad,
                                                    prev_rad))
        prev_rad = cur_rad
        centers.add(center_getter(surf))

    if len(centers) > 1:
        raise ValueError(
            "Surfaces do not appear to be concentric. The following "
            "centers were found: {}".format(centers))

    if subdivisions is not None:
        check_length("subdivisions", subdivisions, 1, len(surfaces))
        orig_indexes = list(subdivisions.keys())
        check_iterable_type("ring indexes", orig_indexes, int)
        check_iterable_type("number of divisions", list(subdivisions.values()),
                            int)
        for ix in orig_indexes:
            if ix < 0:
                subdivisions[len(surfaces) + ix] = subdivisions.pop(ix)
        # Dissallow subdivision on outer most, infinite region
        check_less_than("outer ring",
                        max(subdivisions),
                        len(surfaces),
                        equality=True)

        # ensure ability to concatenate
        if not isinstance(items, list):
            items = list(items)
        if not isinstance(surfaces, list):
            surfaces = list(surfaces)

        # generate equal area divisions
        # Adding N - 1 new regions
        # N - 2 surfaces are made
        # Original cell is not removed, but not occupies last ring
        for ring_index in reversed(sorted(subdivisions.keys())):
            nr = subdivisions[ring_index]
            new_surfs = []

            lower_rad = 0.0 if ring_index == 0 else surfaces[ring_index - 1].r

            upper_rad = surfaces[ring_index].r

            area_term = (upper_rad**2 - lower_rad**2) / nr

            for new_index in range(nr - 1):
                lower_rad = sqrt(area_term + lower_rad**2)
                new_surfs.append(surf_type(r=lower_rad))

            surfaces = (surfaces[:ring_index] + new_surfs +
                        surfaces[ring_index:])

            filler = items[ring_index]
            if (divide_vols and hasattr(filler, "volume")
                    and filler.volume is not None):
                filler.volume /= nr

            items[ring_index:ring_index] = [
                filler.clone() for _i in range(nr - 1)
            ]

    # Build the universe
    regions = subdivide(surfaces)
    cells = [Cell(fill=f, region=r) for r, f in zip(regions, items)]
    return Universe(cells=cells, **kwargs)
예제 #28
0
파일: filter.py 프로젝트: albeanth/openmc
 def distribcell_paths(self, distribcell_paths):
     cv.check_iterable_type('distribcell_paths', distribcell_paths, str)
     self._distribcell_paths = distribcell_paths
예제 #29
0
    def create_mg_library(self, xs_type='macro', xsdata_names=None,
                          xs_ids=None, tabular_legendre=None,
                          tabular_points=33):
        """Creates an openmc.MGXSLibrary object to contain the MGXS data for the
        Multi-Group mode of OpenMC.

        Parameters
        ----------
        xs_type: {'macro', 'micro'}
            Provide the macro or micro cross section in units of cm^-1 or
            barns. Defaults to 'macro'. If the Library object is not tallied by
            nuclide this will be set to 'macro' regardless.
        xsdata_names : Iterable of str
            List of names to apply to the "xsdata" entries in the
            resultant mgxs data file. Defaults to 'set1', 'set2', ...
        xs_ids : str or Iterable of str
            Cross section set identifier (i.e., '71c') for all
            data sets (if only str) or for each individual one
            (if iterable of str). Defaults to '1m'.
        tabular_legendre : None or bool
            Flag to denote whether or not the Legendre expansion of the
            scattering angular distribution is to be converted to a tabular
            representation by OpenMC.  A value of `True` means that it is to be
            converted while a value of `False` means that it will not be.
            Defaults to `None` which leaves the default behavior of OpenMC in
            place (the distribution is converted to a tabular representation).
        tabular_points : int
            This parameter is not used unless the ``tabular_legendre``
            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`.

        Returns
        -------
        mgxs_file : openmc.MGXSLibrary
            Multi-Group Cross Section File that is ready to be printed to the
            file of choice by the user.

        Raises
        ------
        ValueError
            When the Library object is initialized with insufficient types of
            cross sections for the Library.

        See also
        --------
        Library.dump_to_file()
        Library.create_mg_mode()

        """

        # Check to ensure the Library contains the correct
        # multi-group cross section types
        self.check_library_for_openmc_mgxs()

        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:
            xs_type = 'macro'

        # 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 = list(domain.get_all_nuclides().keys())
            else:
                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)

                mgxs_file.add_xsdata(xsdata)

        return mgxs_file
예제 #30
0
 def scores(self, scores):
     cv.check_iterable_type('scores', scores, string_types)
     self._scores = scores
예제 #31
0
파일: universe.py 프로젝트: LMKerby/openmc
 def universes(self, universes):
     cv.check_iterable_type('lattice universes', universes, Universe,
                            min_depth=2, max_depth=3)
     self._universes = universes
예제 #32
0
    def create_mg_mode(self, xsdata_names=None, xs_ids=None,
                       tabular_legendre=None, tabular_points=33):
        """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
        used to generate the MGXS data, with the only differences being
        modifications to point to newly-created Materials which point to the
        multi-group data. This method only creates a macroscopic
        MGXS Library even if nuclidic tallies are specified in the Library.

        Parameters
        ----------
        xsdata_names : Iterable of str
            List of names to apply to the "xsdata" entries in the
            resultant mgxs data file. Defaults to 'set1', 'set2', ...
        xs_ids : str or Iterable of str
            Cross section set identifier (i.e., '71c') for all
            data sets (if only str) or for each individual one
            (if iterable of str). Defaults to '1m'.
        tabular_legendre : None or bool
            Flag to denote whether or not the Legendre expansion of the
            scattering angular distribution is to be converted to a tabular
            representation by OpenMC.  A value of `True` means that it is to be
            converted while a value of `False` means that it will not be.
            Defaults to `None` which leaves the default behavior of OpenMC in
            place (the distribution is converted to a tabular representation).
        tabular_points : int
            This parameter is not used unless the ``tabular_legendre``
            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`.

        Returns
        -------
        mgxs_file : openmc.MGXSLibrary
            Multi-Group Cross Section File that is ready to be printed to the
            file of choice by the user.
        materials : openmc.Materials
            Materials file ready to be printed with all the macroscopic data
            present within this Library.
        geometry : openmc.Geometry
            Materials file ready to be printed with all the macroscopic data
            present within this Library.

        Raises
        ------
        ValueError
            When the Library object is initialized with insufficient types of
            cross sections for the Library.

        See also
        --------
        Library.create_mg_library()
        Library.dump_to_file()

        """

        # Check to ensure the Library contains the correct
        # 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)
        else:
            xs_ids = ['1m' for i in range(len(self.domains))]
        xs_type = 'macro'

        # Initialize MGXS File
        mgxs_file = openmc.MGXSLibrary(self.energy_groups)

        # Create a copy of the Geometry to differentiate for these Macroscopics
        geometry = copy.deepcopy(self.openmc_geometry)
        materials = openmc.Materials()

        # Get all Cells from the Geometry for differentiation
        all_cells = geometry.get_all_material_cells()

        # Create the xsdata object and add it to the mgxs_file
        for i, domain in enumerate(self.domains):

            # 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, 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

        return mgxs_file, materials, geometry
예제 #33
0
 def nuclides(self, nuclides):
     cv.check_iterable_type('nuclides', nuclides, (str, CrossNuclide))
     self._nuclides = nuclides
예제 #34
0
 def nuclides(self, nuclides):
     cv.check_iterable_type('nuclides', nuclides,
                            string_types + (openmc.Nuclide, CrossNuclide))
     self._nuclides = nuclides
예제 #35
0
def search_for_keff(model_builder,
                    initial_guess=None,
                    target=1.0,
                    bracket=None,
                    model_args=None,
                    tol=None,
                    bracketed_method='bisect',
                    print_iterations=False,
                    print_output=False,
                    **kwargs):
    """Function to perform a keff search by modifying a model parametrized by a
    single independent variable.

    Parameters
    ----------
    model_builder : collections.Callable
        Callable function which builds a model according to a passed
        parameter. This function must return an openmc.model.Model object.
    initial_guess : Real, optional
        Initial guess for the parameter to be searched in
        `model_builder`. One of `guess` or `bracket` must be provided.
    target : Real, optional
        keff value to search for, defaults to 1.0.
    bracket : None or Iterable of Real, optional
        Bracketing interval to search for the solution; if not provided,
        a generic non-bracketing method is used. If provided, the brackets
        are used. Defaults to no brackets provided. One of `guess` or `bracket`
        must be provided. If both are provided, the bracket will be
        preferentially used.
    model_args : dict, optional
        Keyword-based arguments to pass to the `model_builder` method. Defaults
        to no arguments.
    tol : float
        Tolerance to pass to the search method
    bracketed_method : {'brentq', 'brenth', 'ridder', 'bisect'}, optional
        Solution method to use; only applies if
        `bracket` is set, otherwise the Secant method is used.
        Defaults to 'bisect'.
    print_iterations : bool
        Whether or not to print the guess and the result during the iteration
        process. Defaults to False.
    print_output : bool
        Whether or not to print the OpenMC output during the iterations.
        Defaults to False.
    **kwargs
        All remaining keyword arguments are passed to the root-finding
        method.

    Returns
    -------
    zero_value : float
        Estimated value of the variable parameter where keff is the
        targeted value
    guesses : List of Real
        List of guesses attempted by the search
    results : List of 2-tuple of Real
        List of keffs and uncertainties corresponding to the guess attempted by
        the search

    """

    if initial_guess is not None:
        cv.check_type('initial_guess', initial_guess, Real)
    if bracket is not None:
        cv.check_iterable_type('bracket', bracket, Real)
        cv.check_length('bracket', bracket, 2)
        cv.check_less_than('bracket values', bracket[0], bracket[1])
    if model_args is None:
        model_args = {}
    else:
        cv.check_type('model_args', model_args, dict)
    cv.check_type('target', target, Real)
    cv.check_type('tol', tol, Real)
    cv.check_value('bracketed_method', bracketed_method,
                   _SCALAR_BRACKETED_METHODS)
    cv.check_type('print_iterations', print_iterations, bool)
    cv.check_type('print_output', print_output, bool)
    cv.check_type('model_builder', model_builder, Callable)

    # Run the model builder function once to make sure it provides the correct
    # output type
    if bracket is not None:
        model = model_builder(bracket[0], **model_args)
    elif initial_guess is not None:
        model = model_builder(initial_guess, **model_args)
    cv.check_type('model_builder return', model, openmc.model.Model)

    # Set the iteration data storage variables
    guesses = []
    results = []

    # Set the searching function (for easy replacement should a later
    # generic function be added.
    search_function = _search_keff

    if bracket is not None:
        # Generate our arguments
        args = {'f': search_function, 'a': bracket[0], 'b': bracket[1]}
        if tol is not None:
            args['rtol'] = tol

        # Set the root finding method
        if bracketed_method == 'brentq':
            root_finder = sopt.brentq
        elif bracketed_method == 'brenth':
            root_finder = sopt.brenth
        elif bracketed_method == 'ridder':
            root_finder = sopt.ridder
        elif bracketed_method == 'bisect':
            root_finder = sopt.bisect

    elif initial_guess is not None:

        # Generate our arguments
        args = {'func': search_function, 'x0': initial_guess}
        if tol is not None:
            args['tol'] = tol

        # Set the root finding method
        root_finder = sopt.newton

    else:
        raise ValueError("Either the 'bracket' or 'initial_guess' parameters "
                         "must be set")

    # Add information to be passed to the searching function
    args['args'] = (target, model_builder, model_args, print_iterations,
                    print_output, guesses, results)

    # Create a new dictionary with the arguments from args and kwargs
    args.update(kwargs)

    # Perform the search
    zero_value = root_finder(**args)

    return zero_value, guesses, results
예제 #36
0
 def bins(self, bins):
     cv.check_iterable_type('bins', bins, Iterable)
     self._bins = list(map(tuple, bins))
예제 #37
0
def _calculate_mgxs_nuc_macro(this, types, library, orders=None,
                              temperature=294.):
    """Determines the multi-group cross sections of a nuclide or macroscopic
    object.

    If the data for the nuclide or macroscopic object in the library is
    represented as angle-dependent data then this method will return the
    geometric average cross section over all angles.

    Parameters
    ----------
    this : openmc.Nuclide or openmc.Macroscopic
        Object to source data from
    types : Iterable of str
        The type of cross sections to calculate; values can either be those
        in openmc.PLOT_TYPES_MGXS
    library : openmc.MGXSLibrary
        MGXS Library containing the data of interest
    orders : Iterable of Integral, optional
        The scattering order or delayed group index to use for the
        corresponding entry in types. Defaults to the 0th order for scattering
        and the total delayed neutron data.
    temperature : float, optional
        Temperature in Kelvin to plot. If not specified, a default
        temperature of 294K will be plotted. Note that the nearest
        temperature in the library for each nuclide will be used as opposed
        to using any interpolation.

    Returns
    -------
    data : numpy.ndarray
        Cross sections calculated at the energy grid described by energy_grid

    """

    # Check the parameters and grab order/delayed groups
    if orders:
        cv.check_iterable_type('orders', orders, Integral,
                               min_depth=len(types), max_depth=len(types))
    else:
        orders = [None] * len(types)
    for i, line in enumerate(types):
        cv.check_type("line", line, str)
        cv.check_value("line", line, PLOT_TYPES_MGXS)
        if orders[i]:
            cv.check_greater_than("order value", orders[i], 0, equality=True)

    xsdata = library.get_by_name(this)

    if xsdata is not None:
        # Obtain the nearest temperature
        t = np.abs(xsdata.temperatures - temperature).argmin()

        # Get the data
        data = np.zeros((len(types), library.energy_groups.num_groups))
        for i, line in enumerate(types):
            if 'fission' in line and not xsdata.fissionable:
                continue
            elif line == 'unity':
                data[i, :] = 1.
            else:
                # Now we have to get the cross section data and properly
                # treat it depending on the requested type.
                # First get the data in a generic fashion
                temp_data = getattr(xsdata, _PLOT_MGXS_ATTR[line])[t]
                shape = temp_data.shape[:]
                # If we have angular data, then want the geometric
                # average over all provided angles.  Since the angles are
                # equi-distant, un-weighted averaging will suffice
                if xsdata.representation == 'angle':
                    temp_data = np.mean(temp_data, axis=(0, 1))

                # Now we can look at the shape of the data to identify how
                # it should be modified to produce an array of values
                # with groups.
                if shape in (xsdata.xs_shapes["[G']"],
                             xsdata.xs_shapes["[G]"]):
                    # Then the data is already an array vs groups so copy
                    # and move along
                    data[i, :] = temp_data
                elif shape == xsdata.xs_shapes["[G][G']"]:
                    # Sum the data over outgoing groups to create our array vs
                    # groups
                    data[i, :] = np.sum(temp_data, axis=1)
                elif shape == xsdata.xs_shapes["[DG]"]:
                    # Then we have a constant vs groups with a value for each
                    # delayed group. The user-provided value of orders tells us
                    # which delayed group we want. If none are provided, then
                    # we sum all the delayed groups together.
                    if orders[i]:
                        if orders[i] < len(shape[0]):
                            data[i, :] = temp_data[orders[i]]
                    else:
                        data[i, :] = np.sum(temp_data[:])
                elif shape in (xsdata.xs_shapes["[DG][G']"],
                               xsdata.xs_shapes["[DG][G]"]):
                    # Then we have an array vs groups with values for each
                    # delayed group. The user-provided value of orders tells us
                    # which delayed group we want. If none are provided, then
                    # we sum all the delayed groups together.
                    if orders[i]:
                        if orders[i] < len(shape[0]):
                            data[i, :] = temp_data[orders[i], :]
                    else:
                        data[i, :] = np.sum(temp_data[:, :], axis=0)
                elif shape == xsdata.xs_shapes["[DG][G][G']"]:
                    # Then we have a delayed group matrix. We will first
                    # remove the outgoing group dependency
                    temp_data = np.sum(temp_data, axis=-1)
                    # And then proceed in exactly the same manner as the
                    # "[DG][G']" or "[DG][G]" shapes in the previous block.
                    if orders[i]:
                        if orders[i] < len(shape[0]):
                            data[i, :] = temp_data[orders[i], :]
                    else:
                        data[i, :] = np.sum(temp_data[:, :], axis=0)
                elif shape == xsdata.xs_shapes["[G][G'][Order]"]:
                    # This is a scattering matrix with angular data
                    # First remove the outgoing group dependence
                    temp_data = np.sum(temp_data, axis=1)
                    # The user either provided a specific order or we resort
                    # to the default 0th order
                    if orders[i]:
                        order = orders[i]
                    else:
                        order = 0
                    # If the order is available, store the data for that order
                    # if it is not available, then the expansion coefficient
                    # is zero and thus we already have the correct value.
                    if order < shape[1]:
                        data[i, :] = temp_data[:, order]
    else:
        raise ValueError(f"{this} not present in provided MGXS library")

    return data
예제 #38
0
 def scores(self, scores):
     cv.check_iterable_type('scores', scores, basestring)
     self._scores = scores
예제 #39
0
파일: lattice.py 프로젝트: albeanth/openmc
    def universes(self, universes):
        cv.check_iterable_type('lattice universes', universes, openmc.Universe,
                               min_depth=2, max_depth=3)
        self._universes = universes

        # NOTE: This routine assumes that the user creates a "ragged" list of
        # lists, where each sub-list corresponds to one ring of Universes.
        # The sub-lists are ordered from outermost ring to innermost ring.
        # The Universes within each sub-list are ordered from the "top" in a
        # clockwise fashion.

        # Check to see if the given universes look like a 2D or a 3D array.
        if isinstance(self._universes[0][0], openmc.Universe):
            n_dims = 2

        elif isinstance(self._universes[0][0][0], openmc.Universe):
            n_dims = 3

        else:
            msg = 'HexLattice ID={0:d} does not appear to be either 2D or ' \
                  '3D.  Make sure set_universes was given a two-deep or ' \
                  'three-deep iterable of universes.'.format(self._id)
            raise RuntimeError(msg)

        # Set the number of axial positions.
        if n_dims == 3:
            self._num_axial = len(self._universes)
        else:
            self._num_axial = None

        # Set the number of rings and make sure this number is consistent for
        # all axial positions.
        if n_dims == 3:
            self._num_rings = len(self._universes[0])
            for rings in self._universes:
                if len(rings) != self._num_rings:
                    msg = 'HexLattice ID={0:d} has an inconsistent number of ' \
                          'rings per axial positon'.format(self._id)
                    raise ValueError(msg)

        else:
            self._num_rings = len(self._universes)

        # Make sure there are the correct number of elements in each ring.
        if n_dims == 3:
            for axial_slice in self._universes:
                # Check the center ring.
                if len(axial_slice[-1]) != 1:
                    msg = 'HexLattice ID={0:d} has the wrong number of ' \
                          'elements in the innermost ring.  Only 1 element is ' \
                          'allowed in the innermost ring.'.format(self._id)
                    raise ValueError(msg)

                # Check the outer rings.
                for r in range(self._num_rings-1):
                    if len(axial_slice[r]) != 6*(self._num_rings - 1 - r):
                        msg = 'HexLattice ID={0:d} has the wrong number of ' \
                              'elements in ring number {1:d} (counting from the '\
                              'outermost ring).  This ring should have {2:d} ' \
                              'elements.'.format(self._id, r,
                                                 6*(self._num_rings - 1 - r))
                        raise ValueError(msg)

        else:
            axial_slice = self._universes
            # Check the center ring.
            if len(axial_slice[-1]) != 1:
                msg = 'HexLattice ID={0:d} has the wrong number of ' \
                      'elements in the innermost ring.  Only 1 element is ' \
                      'allowed in the innermost ring.'.format(self._id)
                raise ValueError(msg)

            # Check the outer rings.
            for r in range(self._num_rings-1):
                if len(axial_slice[r]) != 6*(self._num_rings - 1 - r):
                    msg = 'HexLattice ID={0:d} has the wrong number of ' \
                          'elements in ring number {1:d} (counting from the '\
                          'outermost ring).  This ring should have {2:d} ' \
                          'elements.'.format(self._id, r,
                                             6*(self._num_rings - 1 - r))
                    raise ValueError(msg)
예제 #40
0
    def export_to_materials(self, burnup_index, nuc_with_data=None) -> Materials:
        """Return openmc.Materials object based on results at a given step

        .. versionadded:: 0.12.1

        Parameters
        ----------
        burn_index : int
            Index of burnup step to evaluate. See also: get_step_where for
            obtaining burnup step indices from other data such as the time.
        nuc_with_data : Iterable of str, optional
            Nuclides to include in resulting materials.
            This can be specified if not all nuclides appearing in
            depletion results have associated neutron cross sections, and
            as such cannot be used in subsequent transport calculations.
            If not provided, nuclides from the cross_sections element of
            materials.xml will be used. If that element is not present,
            nuclides from OPENMC_CROSS_SECTIONS will be used.

        Returns
        -------
        mat_file : Materials
            A modified Materials instance containing depleted material data
            and original isotopic compositions of non-depletable materials
        """
        result = self[burnup_index]

        # Only materials found in the original materials.xml file will be
        # updated. If for some reason you have modified OpenMC to produce
        # new materials as depletion takes place, this method will not
        # work as expected and leave out that material.
        mat_file = Materials.from_xml("materials.xml")

        # Only nuclides with valid transport data will be written to
        # the new materials XML file. The precedence of nuclides to select
        # is first ones provided as a kwarg here, then ones specified
        # in the materials.xml file if provided, then finally from
        # the environment variable OPENMC_CROSS_SECTIONS.
        if nuc_with_data:
            cv.check_iterable_type('nuclide names', nuc_with_data, str)
            available_cross_sections = nuc_with_data
        else:
            # select cross_sections.xml file to use
            if mat_file.cross_sections:
                this_library = DataLibrary.from_xml(path=mat_file.cross_sections)
            else:
                this_library = DataLibrary.from_xml()

            # Find neutron libraries we have access to
            available_cross_sections = set()
            for lib in this_library.libraries:
                if lib['type'] == 'neutron':
                    available_cross_sections.update(lib['materials'])
            if not available_cross_sections:
                raise DataError('No neutron libraries found in cross_sections.xml')

        # Overwrite material definitions, if they can be found in the depletion
        # results, and save them to the new depleted xml file.
        for mat in mat_file:
            mat_id = str(mat.id)
            if mat_id in result.mat_to_ind:
                mat.volume = result.volume[mat_id]
                mat.set_density('sum')
                for nuc in result.nuc_to_ind:
                    if nuc not in available_cross_sections:
                        continue
                    atoms = result[0, mat_id, nuc]
                    if atoms > 0.0:
                        atoms_per_barn_cm = 1e-24 * atoms / mat.volume
                        mat.remove_nuclide(nuc) # Replace if it's there
                        mat.add_nuclide(nuc, atoms_per_barn_cm)

        return mat_file
예제 #41
0
 def mu(self, mu):
     cv.check_iterable_type('correlated angle-energy outgoing cosine',
                            mu, Univariate, 2, 2)
     self._mu = mu
예제 #42
0
 def energy_out(self, energy_out):
     cv.check_iterable_type('laboratory angle-energy outgoing energy',
                            energy_out, Univariate, 2, 2)
     self._energy_out = energy_out
예제 #43
0
def calculate_mgxs(this, data_type, types, orders=None, temperature=294.,
                   cross_sections=None, ce_cross_sections=None,
                   enrichment=None):
    """Calculates multi-group cross sections of a requested type.

    If the data for the nuclide or macroscopic object in the library is
    represented as angle-dependent data then this method will return the
    geometric average cross section over all angles.

    Parameters
    ----------
    this : str or openmc.Material
        Object to source data from
    data_type : {'nuclide', 'element', 'material', 'macroscopic'}
        Type of object to plot
    types : Iterable of values of PLOT_TYPES_MGXS
        The type of cross sections to calculate
    orders : Iterable of Integral, optional
        The scattering order or delayed group index to use for the
        corresponding entry in types. Defaults to the 0th order for scattering
        and the total delayed neutron data.
    temperature : float, optional
        Temperature in Kelvin to plot. If not specified, a default
        temperature of 294K will be plotted. Note that the nearest
        temperature in the library for each nuclide will be used as opposed
        to using any interpolation.
    cross_sections : str, optional
        Location of MGXS HDF5 Library file. Default is None.
    ce_cross_sections : str, optional
        Location of continuous-energy cross_sections.xml file. Default is None.
        This is used only for expanding an openmc.Element object passed as this
    enrichment : float, optional
        Enrichment for U235 in weight percent. For example, input 4.95 for
        4.95 weight percent enriched U. Default is None
        (natural composition).

    Returns
    -------
    energy_grid : numpy.ndarray
        Energies at which cross sections are calculated, in units of eV
    data : numpy.ndarray
        Cross sections calculated at the energy grid described by energy_grid

    """

    # Check types
    cv.check_type('temperature', temperature, Real)
    if enrichment:
        cv.check_type('enrichment', enrichment, Real)
    cv.check_iterable_type('types', types, str)

    cv.check_type("cross_sections", cross_sections, str)
    library = openmc.MGXSLibrary.from_hdf5(cross_sections)

    if data_type in ('nuclide', 'macroscopic'):
        mgxs = _calculate_mgxs_nuc_macro(this, types, library, orders,
                                         temperature)
    elif data_type in ('element', 'material'):
        mgxs = _calculate_mgxs_elem_mat(this, types, library, orders,
                                        temperature, ce_cross_sections,
                                        enrichment)
    else:
        raise TypeError("Invalid type")

    # Convert the data to the format needed
    data = np.zeros((len(types), 2 * library.energy_groups.num_groups))
    energy_grid = np.zeros(2 * library.energy_groups.num_groups)
    for g in range(library.energy_groups.num_groups):
        energy_grid[g * 2: g * 2 + 2] = \
            library.energy_groups.group_edges[g: g + 2]
    # Ensure the energy will show on a log-axis by replacing 0s with a
    # sufficiently small number
    energy_grid[0] = max(energy_grid[0], _MIN_E)

    for line in range(len(types)):
        for g in range(library.energy_groups.num_groups):
            data[line, g * 2: g * 2 + 2] = mgxs[line, g]

    return energy_grid[::-1], data
예제 #44
0
 def distribcell_paths(self, distribcell_paths):
     cv.check_iterable_type('distribcell_paths', distribcell_paths, str)
     self._distribcell_paths = distribcell_paths
예제 #45
0
 def isotropic(self, isotropic):
     cv.check_iterable_type('Isotropic scattering nuclides', isotropic, str)
     self._isotropic = list(isotropic)
예제 #46
0
파일: search.py 프로젝트: mit-crpg/openmc
def search_for_keff(model_builder, initial_guess=None, target=1.0,
                    bracket=None, model_args=None, tol=None,
                    bracketed_method='bisect', print_iterations=False,
                    print_output=False, **kwargs):
    """Function to perform a keff search by modifying a model parametrized by a
    single independent variable.

    Parameters
    ----------
    model_builder : collections.Callable
        Callable function which builds a model according to a passed
        parameter. This function must return an openmc.model.Model object.
    initial_guess : Real, optional
        Initial guess for the parameter to be searched in
        `model_builder`. One of `guess` or `bracket` must be provided.
    target : Real, optional
        keff value to search for, defaults to 1.0.
    bracket : None or Iterable of Real, optional
        Bracketing interval to search for the solution; if not provided,
        a generic non-bracketing method is used. If provided, the brackets
        are used. Defaults to no brackets provided. One of `guess` or `bracket`
        must be provided. If both are provided, the bracket will be
        preferentially used.
    model_args : dict, optional
        Keyword-based arguments to pass to the `model_builder` method. Defaults
        to no arguments.
    tol : float
        Tolerance to pass to the search method
    bracketed_method : {'brentq', 'brenth', 'ridder', 'bisect'}, optional
        Solution method to use; only applies if
        `bracket` is set, otherwise the Secant method is used.
        Defaults to 'bisect'.
    print_iterations : bool
        Whether or not to print the guess and the result during the iteration
        process. Defaults to False.
    print_output : bool
        Whether or not to print the OpenMC output during the iterations.
        Defaults to False.
    **kwargs
        All remaining keyword arguments are passed to the root-finding
        method.

    Returns
    -------
    zero_value : float
        Estimated value of the variable parameter where keff is the
        targeted value
    guesses : List of Real
        List of guesses attempted by the search
    results : List of 2-tuple of Real
        List of keffs and uncertainties corresponding to the guess attempted by
        the search

    """

    if initial_guess is not None:
        cv.check_type('initial_guess', initial_guess, Real)
    if bracket is not None:
        cv.check_iterable_type('bracket', bracket, Real)
        cv.check_length('bracket', bracket, 2)
        cv.check_less_than('bracket values', bracket[0], bracket[1])
    if model_args is None:
        model_args = {}
    else:
        cv.check_type('model_args', model_args, dict)
    cv.check_type('target', target, Real)
    cv.check_type('tol', tol, Real)
    cv.check_value('bracketed_method', bracketed_method,
                   _SCALAR_BRACKETED_METHODS)
    cv.check_type('print_iterations', print_iterations, bool)
    cv.check_type('print_output', print_output, bool)
    cv.check_type('model_builder', model_builder, Callable)

    # Run the model builder function once to make sure it provides the correct
    # output type
    if bracket is not None:
        model = model_builder(bracket[0], **model_args)
    elif initial_guess is not None:
        model = model_builder(initial_guess, **model_args)
    cv.check_type('model_builder return', model, openmc.model.Model)

    # Set the iteration data storage variables
    guesses = []
    results = []

    # Set the searching function (for easy replacement should a later
    # generic function be added.
    search_function = _search_keff

    if bracket is not None:
        # Generate our arguments
        args = {'f': search_function, 'a': bracket[0], 'b': bracket[1]}
        if tol is not None:
            args['rtol'] = tol

        # Set the root finding method
        if bracketed_method == 'brentq':
            root_finder = sopt.brentq
        elif bracketed_method == 'brenth':
            root_finder = sopt.brenth
        elif bracketed_method == 'ridder':
            root_finder = sopt.ridder
        elif bracketed_method == 'bisect':
            root_finder = sopt.bisect

    elif initial_guess is not None:

        # Generate our arguments
        args = {'func': search_function, 'x0': initial_guess}
        if tol is not None:
            args['tol'] = tol

        # Set the root finding method
        root_finder = sopt.newton

    else:
        raise ValueError("Either the 'bracket' or 'initial_guess' parameters "
                         "must be set")

    # Add information to be passed to the searching function
    args['args'] = (target, model_builder, model_args, print_iterations,
                    print_output, guesses, results)

    # Create a new dictionary with the arguments from args and kwargs
    args.update(kwargs)

    # Perform the search
    zero_value = root_finder(**args)

    return zero_value, guesses, results
예제 #47
0
파일: function.py 프로젝트: biegelk/openmc
 def breakpoints(self, breakpoints):
     cv.check_iterable_type('breakpoints', breakpoints, Real)
     self._breakpoints = breakpoints
예제 #48
0
 def energy_out(self, energy_out):
     cv.check_iterable_type('laboratory angle-energy outgoing energy',
                            energy_out, Univariate, 2, 2)
     self._energy_out = energy_out