Ejemplo n.º 1
0
    def set_density(self, units, density=NO_DENSITY):
        """Set the density of the material

        Parameters
        ----------
        units : str
            Physical units of density
        density : float, optional
            Value of the density. Must be specified unless units is given as
            'sum'.

        """

        check_type('the density for Material ID="{0}"'.format(self._id), density, Real)
        check_value("density units", units, DENSITY_UNITS)

        if density == NO_DENSITY and units is not "sum":
            msg = (
                'Unable to set the density Material ID="{0}" '
                "because a density must be set when not using "
                "sum unit".format(self._id)
            )
            raise ValueError(msg)

        self._density = density
        self._density_units = units
Ejemplo n.º 2
0
    def set_density(self, units, density=NO_DENSITY):
        """Set the density of the material

        Parameters
        ----------
        units : str
            Physical units of density
        density : float, optional
            Value of the density. Must be specified unless units is given as
            'sum'.

        """

        check_type('the density for Material ID="{0}"'.format(self._id),
                   density, Real)
        check_value('density units', units, DENSITY_UNITS)

        if density == NO_DENSITY and units is not 'sum':
            msg = 'Unable to set the density Material ID="{0}" ' \
                  'because a density must be set when not using ' \
                  'sum unit'.format(self._id)
            raise ValueError(msg)

        self._density = density
        self._density_units = units
Ejemplo n.º 3
0
 def num_electrons(self, num_electrons):
     cv.check_type('number of electrons', num_electrons, Mapping)
     for subshell, num in num_electrons.items():
         cv.check_value('subshell', subshell, _SUBSHELLS)
         cv.check_type('number of electrons', num, Real)
         cv.check_greater_than('number of electrons', num, 0.0, True)
     self._num_electrons = num_electrons
Ejemplo n.º 4
0
 def binding_energy(self, binding_energy):
     cv.check_type('binding energies', binding_energy, Mapping)
     for subshell, energy in binding_energy.items():
         cv.check_value('subshell', subshell, _SUBSHELLS)
         cv.check_type('binding energy', energy, Real)
         cv.check_greater_than('binding energy', energy, 0.0, True)
     self._binding_energy = binding_energy
Ejemplo n.º 5
0
    def set_source_angle(self, stype, params=[]):
        """Defined the angular distribution of the external/starting source.

        Parameters
        ----------
        stype : str
            The type of angular distribution. Valid options are "isotropic" and
            "monodirectional". The angle of the particle emitted from a source
            site is isotropic if the "isotropic" option is given. The angle of
            the particle emitted from a source site is the direction specified
            in ``params`` if the "monodirectional" option is given.
        params : Iterable of float
            For an "isotropic" angular distribution, ``params`` should not
            be specified.

            For a "monodirectional" angular distribution, ``params`` should
            be given as three floats which specify the angular cosines
            with respect to each axis.

        """

        check_type("source angle type", stype, basestring)
        check_value("source angle type", stype, ["isotropic", "monodirectional"])
        check_type("source angle parameters", params, Iterable, Real)
        if stype == "isotropic" and params is not None:
            msg = (
                "Unable to set source angle parameters since they are not "
                "it is not supported for isotropic type sources"
            )
            raise ValueError(msg)
        elif stype == "monodirectional":
            check_length("source angle parameters for a monodirectional " "source", params, 3)

        self._source_angle_type = stype
        self._source_angle_params = params
Ejemplo n.º 6
0
    def set_source_space(self, stype, params):
        """Defined the spatial bounds of the external/starting source.

        Parameters
        ----------
        stype : str
            The type of spatial distribution. Valid options are "box",
            "fission", and "point". A "box" spatial distribution has coordinates
            sampled uniformly in a parallelepiped. A "fission" spatial
            distribution samples locations from a "box" distribution but only
            locations in fissionable materials are accepted. A "point" spatial
            distribution has coordinates specified by a triplet.
        params : Iterable of float
            For a "box" or "fission" spatial distribution, ``params`` should be
            given as six real numbers, the first three of which specify the
            lower-left corner of a parallelepiped and the last three of which
            specify the upper-right corner. Source sites are sampled uniformly
            through that parallelepiped.

            For a "point" spatial distribution, ``params`` should be given as
            three real numbers which specify the (x,y,z) location of an
            isotropic point source

        """

        check_type("source space type", stype, basestring)
        check_value("source space type", stype, ["box", "fission", "point"])
        check_type("source space parameters", params, Iterable, Real)
        if stype in ["box", "fission"]:
            check_length("source space parameters for a " "box/fission distribution", params, 6)
        elif stype == "point":
            check_length("source space parameters for a point source", params, 3)

        self._source_space_type = stype
        self._source_space_params = params
Ejemplo n.º 7
0
    def set_density(self, units, density=None):
        """Set the density of the material

        Parameters
        ----------
        units : {'g/cm3', 'g/cc', 'kg/m3', 'atom/b-cm', 'atom/cm3', 'sum', 'macro'}
            Physical units of density.
        density : float, optional
            Value of the density. Must be specified unless units is given as
            'sum'.

        """

        cv.check_value('density units', units, DENSITY_UNITS)
        self._density_units = units

        if units == 'sum':
            if density is not None:
                msg = 'Density "{}" for Material ID="{}" is ignored ' \
                      'because the unit is "sum"'.format(density, self.id)
                warnings.warn(msg)
        else:
            if density is None:
                msg = 'Unable to set the density for Material ID="{}" ' \
                      'because a density value must be given when not using ' \
                      '"sum" unit'.format(self.id)
                raise ValueError(msg)

            cv.check_type('the density for Material ID="{}"'.format(self.id),
                          density, Real)
            self._density = density
Ejemplo n.º 8
0
    def add_nuclide(self, nuclide, percent, percent_type='ao'):
        """Add a nuclide to the material

        Parameters
        ----------
        nuclide : str
            Nuclide to add, e.g., 'Mo95'
        percent : float
            Atom or weight percent
        percent_type : {'ao', 'wo'}
            'ao' for atom percent and 'wo' for weight percent

        """
        cv.check_type('nuclide', nuclide, str)
        cv.check_type('percent', percent, Real)
        cv.check_value('percent type', percent_type, {'ao', 'wo'})

        if self._macroscopic is not None:
            msg = 'Unable to add a Nuclide to Material ID="{}" as a ' \
                  'macroscopic data-set has already been added'.format(self._id)
            raise ValueError(msg)

        # If nuclide name doesn't look valid, give a warning
        try:
            Z, _, _ = openmc.data.zam(nuclide)
        except ValueError as e:
            warnings.warn(str(e))
        else:
            # For actinides, have the material be depletable by default
            if Z >= 89:
                self.depletable = True

        self._nuclides.append(NuclideTuple(nuclide, percent, percent_type))
Ejemplo n.º 9
0
    def set_density(self, units, density=None):
        """Set the density of the material

        Parameters
        ----------
        units : {'g/cm3', 'g/cc', 'km/cm3', 'atom/b-cm', 'atom/cm3', 'sum', 'macro'}
            Physical units of density.
        density : float, optional
            Value of the density. Must be specified unless units is given as
            'sum'.

        """

        cv.check_value('density units', units, DENSITY_UNITS)
        self._density_units = units

        if units is 'sum':
            if density is not None:
                msg = 'Density "{0}" for Material ID="{1}" is ignored ' \
                      'because the unit is "sum"'.format(density, self.id)
                warnings.warn(msg)
        else:
            if density is None:
                msg = 'Unable to set the density for Material ID="{0}" ' \
                      'because a density value must be given when not using ' \
                      '"sum" unit'.format(self.id)
                raise ValueError(msg)

            cv.check_type('the density for Material ID="{0}"'.format(self.id),
                          density, Real)
            self._density = density
Ejemplo n.º 10
0
    def set_fission_mgxs(self, fission, nuclide='total', xs_type='macro'):
        """This method allows for an openmc.mgxs.FissionXS
        to be used to set the fission cross section for this XSdata object.

        Parameters
        ----------
        fission: openmc.mgxs.FissionXS
            MGXS Object containing the fission cross section
            for the domain of interest.
        nuclide : str
            Individual nuclide (or 'total' if obtaining material-wise data)
            to gather data for.  Defaults to 'total'.
        xs_type: {'macro', 'micro'}
            Provide the macro or micro cross section in units of cm^-1 or
            barns. Defaults to 'macro'.

        See also
        --------
        openmc.mgxs.Library.create_mg_library()
        openmc.mgxs.Library.get_xsdata

        """

        check_type('fission', fission, openmc.mgxs.FissionXS)
        check_value('energy_groups', fission.energy_groups,
                    [self.energy_groups])
        check_value('domain_type', fission.domain_type,
                    ['universe', 'cell', 'material'])

        if self.representation is 'isotropic':
            self._fission = fission.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)
Ejemplo n.º 11
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
Ejemplo n.º 12
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
Ejemplo n.º 13
0
    def correction(self, correction):
        cv.check_value('correction', correction, ('P0', None))

        if correction == 'P0' and self.legendre_order > 0:
            warn('The P0 correction will be ignored since the scattering '
                 'order "{}" is greater than zero'.format(self.legendre_order))

        self._correction = correction
Ejemplo n.º 14
0
    def total(self, total):
        check_type('total', total, Iterable, expected_iter_type=Real)
        # Convert to a numpy array so we can easily get the shape for
        # checking
        nptotal = np.asarray(total)
        check_value('total shape', nptotal.shape, [self.vector_shape])

        self._total = nptotal
Ejemplo n.º 15
0
    def get_condensed_library(self, coarse_groups):
        """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
        be called after the load_from_statepoint(...) routine loads the tallies
        from the statepoint into each of the cross sections.

        Parameters
        ----------
        coarse_groups : openmc.mgxs.EnergyGroups
            The coarse energy group structure of interest

        Returns
        -------
        Library
            A new multi-group cross section library condensed to the group
            structure of interest

        Raises
        ------
        ValueError
            When this method is called before a statepoint has been loaded

        See also
        --------
        MGXS.get_condensed_xs(coarse_groups)

        """

        if self.sp_filename is None:
            msg = 'Unable to get a condensed coarse group cross section ' \
                  'library since the statepoint has not yet been loaded'
            raise ValueError(msg)

        cv.check_type('coarse_groups', coarse_groups, openmc.mgxs.EnergyGroups)
        cv.check_less_than('coarse groups',
                           coarse_groups.num_groups,
                           self.num_groups,
                           equality=True)
        cv.check_value('upper coarse energy', coarse_groups.group_edges[-1],
                       [self.energy_groups.group_edges[-1]])
        cv.check_value('lower coarse energy', coarse_groups.group_edges[0],
                       [self.energy_groups.group_edges[0]])

        # Clone this Library to initialize the condensed version
        condensed_library = copy.deepcopy(self)
        condensed_library.energy_groups = coarse_groups

        # Condense the MGXS for each domain and mgxs type
        for domain in self.domains:
            for mgxs_type in self.mgxs_types:
                mgxs = condensed_library.get_mgxs(domain, mgxs_type)
                condensed_mgxs = mgxs.get_condensed_xs(coarse_groups)
                condensed_library.all_mgxs[
                    domain.id][mgxs_type] = condensed_mgxs

        return condensed_library
Ejemplo n.º 16
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
Ejemplo n.º 17
0
    def absorption(self, absorption):
        check_type('absorption', absorption, Iterable, expected_iter_type=Real)
        # Convert to a numpy array so we can easily get the shape for
        # checking
        npabsorption = np.asarray(absorption)
        check_value('absorption shape', npabsorption.shape,
                    [self.vector_shape])

        self._absorption = npabsorption
Ejemplo n.º 18
0
 def output(self, output):
     cv.check_type('output', output, Mapping)
     for key, value in output.items():
         cv.check_value('output key', key, ('summary', 'tallies', 'path'))
         if key in ('summary', 'tallies'):
             cv.check_type("output['{}']".format(key), value, bool)
         else:
             cv.check_type("output['path']", value, string_types)
     self._output = output
Ejemplo n.º 19
0
 def output(self, output):
     cv.check_type('output', output, Mapping)
     for key, value in output.items():
         cv.check_value('output key', key, ('summary', 'tallies', 'path'))
         if key in ('summary', 'tallies'):
             cv.check_type("output['{}']".format(key), value, bool)
         else:
             cv.check_type("output['path']", value, string_types)
     self._output = output
Ejemplo n.º 20
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
Ejemplo n.º 21
0
    def get_condensed_library(self, coarse_groups):
        """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
        be called after the load_from_statepoint(...) routine loads the tallies
        from the statepoint into each of the cross sections.

        Parameters
        ----------
        coarse_groups : openmc.mgxs.EnergyGroups
            The coarse energy group structure of interest

        Returns
        -------
        Library
            A new multi-group cross section library condensed to the group
            structure of interest

        Raises
        ------
        ValueError
            When this method is called before a statepoint has been loaded

        See also
        --------
        MGXS.get_condensed_xs(coarse_groups)

        """

        if self.sp_filename is None:
            msg = 'Unable to get a condensed coarse group cross section ' \
                  'library since the statepoint has not yet been loaded'
            raise ValueError(msg)

        cv.check_type('coarse_groups', coarse_groups, openmc.mgxs.EnergyGroups)
        cv.check_less_than('coarse groups', coarse_groups.num_groups,
                           self.num_groups, equality=True)
        cv.check_value('upper coarse energy', coarse_groups.group_edges[-1],
                       [self.energy_groups.group_edges[-1]])
        cv.check_value('lower coarse energy', coarse_groups.group_edges[0],
                       [self.energy_groups.group_edges[0]])

        # Clone this Library to initialize the condensed version
        condensed_library = copy.deepcopy(self)
        condensed_library.energy_groups = coarse_groups

        # Condense the MGXS for each domain and mgxs type
        for domain in self.domains:
            for mgxs_type in self.mgxs_types:
                mgxs = condensed_library.get_mgxs(domain, mgxs_type)
                condensed_mgxs = mgxs.get_condensed_xs(coarse_groups)
                condensed_library.all_mgxs[domain.id][mgxs_type] = condensed_mgxs

        return condensed_library
Ejemplo n.º 22
0
    def fission(self, fission):
        check_type('fission', fission, Iterable, expected_iter_type=Real)
        # Convert to a numpy array so we can easily get the shape for
        # checking
        npfission = np.asarray(fission)
        check_value('fission shape', npfission.shape, [self.vector_shape])

        self._fission = npfission

        if np.sum(self._fission) > 0.0:
            self._fissionable = True
Ejemplo n.º 23
0
 def tabular_legendre(self, tabular_legendre):
     cv.check_type('tabular_legendre settings', tabular_legendre, Mapping)
     for key, value in tabular_legendre.items():
         cv.check_value('tabular_legendre key', key,
                        ['enable', 'num_points'])
         if key == 'enable':
             cv.check_type('enable tabular_legendre', value, bool)
         elif key == 'num_points':
             cv.check_type('num_points tabular_legendre', value, Integral)
             cv.check_greater_than('num_points tabular_legendre', value, 0)
     self._tabular_legendre = tabular_legendre
Ejemplo n.º 24
0
 def tabular_legendre(self, tabular_legendre):
     cv.check_type('tabular_legendre settings', tabular_legendre, Mapping)
     for key, value in tabular_legendre.items():
         cv.check_value('tabular_legendre key', key,
                        ['enable', 'num_points'])
         if key == 'enable':
             cv.check_type('enable tabular_legendre', value, bool)
         elif key == 'num_points':
             cv.check_type('num_points tabular_legendre', value, Integral)
             cv.check_greater_than('num_points tabular_legendre', value, 0)
     self._tabular_legendre = tabular_legendre
Ejemplo n.º 25
0
 def __init__(self, num, name, mat_names, groups, order, geom, rad, ref_k,
              params):
     cv.check_value('groups', groups, GROUPS)
     cv.check_value('order', order, ORDER)
     cv.check_value('groups', groups, GROUPS)
     cv.check_value('geom', geom, GEOM)
     self.number = num
     self.name = name
     self.mat_names = mat_names
     self.groups = groups
     self.order = order
     self.geom = geom
     self.rad = rad
     self.ref_k = ref_k
     self.mesh_dim = params['mesh_dim']
     self.batches = params['batches']
     self.inactive = params['inactive']
     self.particles = params['particles']
     if 'tab_leg' in params:
         self.tab_leg = params['tab_leg']
     else:
         self.tab_leg = None
     if 'tally' in params:
         self.tally = params['tally']
     else:
         self.tally = False
Ejemplo n.º 26
0
 def __init__(self, num, name, mat_names, groups, order, geom, rad, ref_k,
              params):
     cv.check_value('groups', groups, GROUPS)
     cv.check_value('order', order, ORDER)
     cv.check_value('groups', groups, GROUPS)
     cv.check_value('geom', geom, GEOM)
     self.number = num
     self.name = name
     self.mat_names = mat_names
     self.groups = groups
     self.order = order
     self.geom = geom
     self.rad = rad
     self.ref_k = ref_k
     self.mesh_dim = params['mesh_dim']
     self.batches = params['batches']
     self.inactive = params['inactive']
     self.particles = params['particles']
     if 'tab_leg' in params:
         self.tab_leg = params['tab_leg']
     else:
         self.tab_leg = None
     if 'tally' in params:
         self.tally = params['tally']
     else:
         self.tally = False
Ejemplo n.º 27
0
    def temperature(self, temperature):

        cv.check_type('temperature settings', temperature, Mapping)
        for key, value in temperature.items():
            cv.check_value('temperature key', key,
                           ['default', 'method', 'tolerance', 'multipole'])
            if key == 'default':
                cv.check_type('default temperature', value, Real)
            elif key == 'method':
                cv.check_value('temperature method', value,
                               ['nearest', 'interpolation'])
            elif key == 'tolerance':
                cv.check_type('temperature tolerance', value, Real)
            elif key == 'multipole':
                cv.check_type('temperature multipole', value, bool)
        self._temperature = temperature
Ejemplo n.º 28
0
    def temperature(self, temperature):

        cv.check_type('temperature settings', temperature, Mapping)
        for key, value in temperature.items():
            cv.check_value('temperature key', key,
                           ['default', 'method', 'tolerance', 'multipole'])
            if key == 'default':
                cv.check_type('default temperature', value, Real)
            elif key == 'method':
                cv.check_value('temperature method', value,
                               ['nearest', 'interpolation'])
            elif key == 'tolerance':
                cv.check_type('temperature tolerance', value, Real)
            elif key == 'multipole':
                cv.check_type('temperature multipole', value, bool)
        self._temperature = temperature
Ejemplo n.º 29
0
 def __init__(self, center_base, height, radius, axis='z', **kwargs):
     cx, cy, cz = center_base
     check_greater_than('cylinder height', height, 0.0)
     check_greater_than('cylinder radius', radius, 0.0)
     check_value('cylinder axis', axis, ('x', 'y', 'z'))
     if axis == 'x':
         self.cyl = openmc.XCylinder(y0=cy, z0=cz, r=radius, **kwargs)
         self.bottom = openmc.XPlane(x0=cx, **kwargs)
         self.top = openmc.XPlane(x0=cx + height, **kwargs)
     elif axis == 'y':
         self.cyl = openmc.YCylinder(x0=cx, z0=cz, r=radius, **kwargs)
         self.bottom = openmc.YPlane(y0=cy, **kwargs)
         self.top = openmc.YPlane(y0=cy + height, **kwargs)
     elif axis == 'z':
         self.cyl = openmc.ZCylinder(x0=cx, y0=cy, r=radius, **kwargs)
         self.bottom = openmc.ZPlane(z0=cz, **kwargs)
         self.top = openmc.ZPlane(z0=cz + height, **kwargs)
Ejemplo n.º 30
0
    def deplete(self,
                timesteps,
                chain_file=None,
                method='cecm',
                fission_q=None,
                **kwargs):
        """Deplete model using specified timesteps/power

        Parameters
        ----------
        timesteps : iterable of float
            Array of timesteps in units of [s]. Note that values are not
            cumulative.
        chain_file : str, optional
            Path to the depletion chain XML file.  Defaults to the chain
            found under the ``depletion_chain`` in the
            :envvar:`OPENMC_CROSS_SECTIONS` environment variable if it exists.
        method : str
             Integration method used for depletion (e.g., 'cecm', 'predictor')
        fission_q : dict, optional
            Dictionary of nuclides and their fission Q values [eV].
            If not given, values will be pulled from the ``chain_file``.
        **kwargs
            Keyword arguments passed to integration function (e.g.,
            :func:`openmc.deplete.integrator.cecm`)

        """
        # Import the depletion module.  This is done here rather than the module
        # header to delay importing openmc.lib (through openmc.deplete) which
        # can be tough to install properly.
        import openmc.deplete as dep

        # Create OpenMC transport operator
        op = dep.Operator(
            self.geometry,
            self.settings,
            chain_file,
            fission_q=fission_q,
        )

        # Perform depletion
        check_value('method', method, ('cecm', 'predictor', 'cf4', 'epc_rk4',
                                       'si_celi', 'si_leqi', 'celi', 'leqi'))
        getattr(dep.integrator, method)(op, timesteps, **kwargs)
Ejemplo n.º 31
0
    def from_geometry(cls, geometry, basis='xy', slice_coord=0.):
        """Return plot that encompasses a geometry.

        Parameters
        ----------
        geometry : openmc.Geometry
            The geometry the base the plot off of
        basis : {'xy', 'xz', 'yz'}
            The basis directions for the plot
        slice_coord : float
            The level at which the slice plot should be plotted. For example, if
            the basis is 'xy', this would indicate the z value used in the
            origin.

        """
        cv.check_type('geometry', geometry, openmc.Geometry)
        cv.check_value('basis', basis, _BASES)

        # Decide which axes to keep
        if basis == 'xy':
            pick_index = (0, 1)
            slice_index = 2
        elif basis == 'yz':
            pick_index = (1, 2)
            slice_index = 0
        elif basis == 'xz':
            pick_index = (0, 2)
            slice_index = 1

        # Get lower-left and upper-right coordinates for desired axes
        lower_left, upper_right = geometry.bounding_box
        lower_left = lower_left[np.array(pick_index)]
        upper_right = upper_right[np.array(pick_index)]

        if np.any(np.isinf((lower_left, upper_right))):
            raise ValueError('The geometry does not appear to be bounded '
                             'in the {} plane.'.format(basis))

        plot = cls()
        plot.origin = np.insert((lower_left + upper_right)/2,
                                slice_index, slice_coord)
        plot.width = upper_right - lower_left
        return plot
Ejemplo n.º 32
0
    def set_chi_mgxs(self, chi, nuclide='total', xs_type='macro'):
        """This method allows for an openmc.mgxs.Chi
        to be used to set chi for this XSdata object.

        Parameters
        ----------
        chi: openmc.mgxs.Chi
            MGXS Object containing chi for the domain of interest.
        nuclide : str
            Individual nuclide (or 'total' if obtaining material-wise data)
            to gather data for.  Defaults to 'total'.
        xs_type: {'macro', 'micro'}
            Provide the macro or micro cross section in units of cm^-1 or
            barns. Defaults to 'macro'.

        See also
        --------
        openmc.mgxs.Library.create_mg_library()
        openmc.mgxs.Library.get_xsdata

        """

        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)

        check_type('chi', chi, openmc.mgxs.Chi)
        check_value('energy_groups', chi.energy_groups, [self.energy_groups])
        check_value('domain_type', chi.domain_type,
                    ['universe', 'cell', 'material'])

        if self.representation is 'isotropic':
            self._chi = chi.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)

        if self.use_chi is not None:
            self.use_chi = True
Ejemplo n.º 33
0
    def set_scatter_mgxs(self, scatter, nuclide='total', xs_type='macro'):
        """This method allows for an openmc.mgxs.ScatterMatrixXS
        to be used to set the scatter matrix cross section for this XSdata
        object.  If the XSdata.order attribute has not yet been set, then
        it will be set based on the properties of scatter.

        Parameters
        ----------
        scatter: openmc.mgxs.ScatterMatrixXS
            MGXS Object containing the scatter matrix cross section
            for the domain of interest.
        nuclide : str
            Individual nuclide (or 'total' if obtaining material-wise data)
            to gather data for.  Defaults to 'total'.
        xs_type: {'macro', 'micro'}
            Provide the macro or micro cross section in units of cm^-1 or
            barns. Defaults to 'macro'.

        See also
        --------
        openmc.mgxs.Library.create_mg_library()
        openmc.mgxs.Library.get_xsdata

        """

        check_type('scatter', scatter, openmc.mgxs.ScatterMatrixXS)
        check_value('energy_groups', scatter.energy_groups,
                    [self.energy_groups])
        check_value('domain_type', scatter.domain_type,
                    ['universe', 'cell', 'material'])

        if self.scatt_type != 'legendre':
            msg = 'Anisotropic scattering representations other than ' \
                  'Legendre expansions have not yet been implemented in ' \
                  'openmc.mgxs.'
            raise ValueError(msg)

        # If the user has not defined XSdata.order, then we will set
        # the order based on the data within scatter.
        # Otherwise, we will check to see that XSdata.order to match
        # the order of scatter
        if self.order is None:
            self.order = scatter.legendre_order
        else:
            check_value('legendre_order', scatter.legendre_order,
                        [self.order])

        if self.representation is 'isotropic':
            # Get the scattering orders in the outermost dimension
            self._scatter = np.zeros((self.num_orders,
                                      self.energy_groups.num_groups,
                                      self.energy_groups.num_groups))
            for moment in range(self.num_orders):
                self._scatter[moment, :, :] = scatter.get_xs(nuclides=nuclide,
                                                             xs_type=xs_type,
                                                             moment=moment)

        elif self.representation is 'angle':
            msg = 'Angular-Dependent MGXS have not yet been implemented'
            raise ValueError(msg)
Ejemplo n.º 34
0
    def set_source_energy(self, stype, params=[]):
        """Defined the energy distribution of the external/starting source.

        Parameters
        ----------
        stype : str
            The type of energy distribution. Valid options are "monoenergetic",
            "watt", and "maxwell". The "monoenergetic" option produces source
            sites at a single energy. The "watt" option produces source sites
            whose energy is sampled from a Watt fission spectrum. The "maxwell"
            option produce source sites whose energy is sampled from a Maxwell
            fission spectrum.
        params : Iterable of float
            For a "monoenergetic" energy distribution, ``params`` should be
            given as the energy in MeV of the source sites.

            For a "watt" energy distribution, ``params`` should be given as two
            real numbers :math:`a` and :math:`b` that parameterize the
            distribution :math:`p(E) dE = c e^{-E/a} \sinh \sqrt{b \, E} dE`.

            For a "maxwell" energy distribution, ``params`` should be given as
            one real number :math:`a` that parameterizes the distribution
            :math:`p(E) dE = c E e^{-E/a} dE`.

        """

        check_type('source energy type', stype, basestring)
        check_value('source energy type', stype,
                    ['monoenergetic', 'watt', 'maxwell'])
        check_type('source energy parameters', params, Iterable, Real)
        if stype in ['monoenergetic', 'maxwell']:
            check_length(
                'source energy parameters for a monoenergetic '
                'or Maxwell source', params, 1)
        elif stype == 'watt':
            check_length('source energy parameters for a Watt source', params,
                         2)

        self._source_energy_type = stype
        self._source_energy_params = params
Ejemplo n.º 35
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
Ejemplo n.º 36
0
    def set_source_energy(self, stype, params=[]):
        """Defined the energy distribution of the external/starting source.

        Parameters
        ----------
        stype : str
            The type of energy distribution. Valid options are "monoenergetic",
            "watt", and "maxwell". The "monoenergetic" option produces source
            sites at a single energy. The "watt" option produces source sites
            whose energy is sampled from a Watt fission spectrum. The "maxwell"
            option produce source sites whose energy is sampled from a Maxwell
            fission spectrum.
        params : Iterable of float
            For a "monoenergetic" energy distribution, ``params`` should be
            given as the energy in MeV of the source sites.

            For a "watt" energy distribution, ``params`` should be given as two
            real numbers :math:`a` and :math:`b` that parameterize the
            distribution :math:`p(E) dE = c e^{-E/a} \sinh \sqrt{b \, E} dE`.

            For a "maxwell" energy distribution, ``params`` should be given as
            one real number :math:`a` that parameterizes the distribution
            :math:`p(E) dE = c E e^{-E/a} dE`.

        """

        check_type('source energy type', stype, basestring)
        check_value('source energy type', stype,
                    ['monoenergetic', 'watt', 'maxwell'])
        check_type('source energy parameters', params, Iterable, Real)
        if stype in ['monoenergetic', 'maxwell']:
            check_length('source energy parameters for a monoenergetic '
                         'or Maxwell source', params, 1)
        elif stype == 'watt':
            check_length('source energy parameters for a Watt source',
                         params, 2)

        self._source_energy_type = stype
        self._source_energy_params = params
Ejemplo n.º 37
0
 def resonance_scattering(self, res):
     cv.check_type('resonance scattering settings', res, Mapping)
     keys = ('enable', 'method', 'energy_min', 'energy_max', 'nuclides')
     for key, value in res.items():
         cv.check_value('resonance scattering dictionary key', key, keys)
         if key == 'enable':
             cv.check_type('resonance scattering enable', value, bool)
         elif key == 'method':
             cv.check_value('resonance scattering method', value,
                            _RES_SCAT_METHODS)
         elif key == 'energy_min':
             name = 'resonance scattering minimum energy'
             cv.check_type(name, value, Real)
             cv.check_greater_than(name, value, 0)
         elif key == 'energy_max':
             name = 'resonance scattering minimum energy'
             cv.check_type(name, value, Real)
             cv.check_greater_than(name, value, 0)
         elif key == 'nuclides':
             cv.check_type('resonance scattering nuclides', value, Iterable,
                           string_types)
     self._resonance_scattering = res
Ejemplo n.º 38
0
 def resonance_scattering(self, res):
     cv.check_type('resonance scattering settings', res, Mapping)
     keys = ('enable', 'method', 'energy_min', 'energy_max', 'nuclides')
     for key, value in res.items():
         cv.check_value('resonance scattering dictionary key', key, keys)
         if key == 'enable':
             cv.check_type('resonance scattering enable', value, bool)
         elif key == 'method':
             cv.check_value('resonance scattering method', value,
                            _RES_SCAT_METHODS)
         elif key == 'energy_min':
             name = 'resonance scattering minimum energy'
             cv.check_type(name, value, Real)
             cv.check_greater_than(name, value, 0)
         elif key == 'energy_max':
             name = 'resonance scattering minimum energy'
             cv.check_type(name, value, Real)
             cv.check_greater_than(name, value, 0)
         elif key == 'nuclides':
             cv.check_type('resonance scattering nuclides', value,
                           Iterable, string_types)
     self._resonance_scattering = res
Ejemplo n.º 39
0
    def set_source_space(self, stype, params):
        """Defined the spatial bounds of the external/starting source.

        Parameters
        ----------
        stype : str
            The type of spatial distribution. Valid options are "box",
            "fission", and "point". A "box" spatial distribution has coordinates
            sampled uniformly in a parallelepiped. A "fission" spatial
            distribution samples locations from a "box" distribution but only
            locations in fissionable materials are accepted. A "point" spatial
            distribution has coordinates specified by a triplet.
        params : Iterable of float
            For a "box" or "fission" spatial distribution, ``params`` should be
            given as six real numbers, the first three of which specify the
            lower-left corner of a parallelepiped and the last three of which
            specify the upper-right corner. Source sites are sampled uniformly
            through that parallelepiped.

            For a "point" spatial distribution, ``params`` should be given as
            three real numbers which specify the (x,y,z) location of an
            isotropic point source

        """

        check_type('source space type', stype, basestring)
        check_value('source space type', stype, ['box', 'fission', 'point'])
        check_type('source space parameters', params, Iterable, Real)
        if stype in ['box', 'fission']:
            check_length(
                'source space parameters for a '
                'box/fission distribution', params, 6)
        elif stype == 'point':
            check_length('source space parameters for a point source', params,
                         3)

        self._source_space_type = stype
        self._source_space_params = params
Ejemplo n.º 40
0
    def set_source_angle(self, stype, params=[]):
        """Defined the angular distribution of the external/starting source.

        Parameters
        ----------
        stype : str
            The type of angular distribution. Valid options are "isotropic" and
            "monodirectional". The angle of the particle emitted from a source
            site is isotropic if the "isotropic" option is given. The angle of
            the particle emitted from a source site is the direction specified
            in ``params`` if the "monodirectional" option is given.
        params : Iterable of float
            For an "isotropic" angular distribution, ``params`` should not
            be specified.

            For a "monodirectional" angular distribution, ``params`` should
            be given as three floats which specify the angular cosines
            with respect to each axis.

        """

        check_type('source angle type', stype, basestring)
        check_value('source angle type', stype,
                    ['isotropic', 'monodirectional'])
        check_type('source angle parameters', params, Iterable, Real)
        if stype == 'isotropic' and params is not None:
            msg = 'Unable to set source angle parameters since they are not ' \
                  'it is not supported for isotropic type sources'
            raise ValueError(msg)
        elif stype == 'monodirectional':
            check_length(
                'source angle parameters for a monodirectional '
                'source', params, 3)

        self._source_angle_type = stype
        self._source_angle_params = params
Ejemplo n.º 41
0
    def mix_materials(cls, materials, fracs, percent_type='ao', name=None):
        """Mix materials together based on atom, weight, or volume fractions

        .. versionadded:: 0.12

        Parameters
        ----------
        materials : Iterable of openmc.Material
            Materials to combine
        fracs : Iterable of float
            Fractions of each material to be combined
        percent_type : {'ao', 'wo', 'vo'}
            Type of percentage, must be one of 'ao', 'wo', or 'vo', to signify atom
            percent (molar percent), weight percent, or volume percent,
            optional. Defaults to 'ao'
        name : str
            The name for the new material, optional. Defaults to concatenated
            names of input materials with percentages indicated inside
            parentheses.

        Returns
        -------
        openmc.Material
            Mixture of the materials

        """

        cv.check_type('materials', materials, Iterable, Material)
        cv.check_type('fracs', fracs, Iterable, Real)
        cv.check_value('percent type', percent_type, {'ao', 'wo', 'vo'})

        fracs = np.asarray(fracs)
        void_frac = 1. - np.sum(fracs)

        # Warn that fractions don't add to 1, set remainder to void, or raise
        # an error if percent_type isn't 'vo'
        if not np.isclose(void_frac, 0.):
            if percent_type in ('ao', 'wo'):
                msg = ('A non-zero void fraction is not acceptable for '
                       'percent_type: {}'.format(percent_type))
                raise ValueError(msg)
            else:
                msg = ('Warning: sum of fractions do not add to 1, void '
                       'fraction set to {}'.format(void_frac))
                warnings.warn(msg)

        # Calculate appropriate weights which are how many cc's of each
        # material are found in 1cc of the composite material
        amms = np.asarray([mat.average_molar_mass for mat in materials])
        mass_dens = np.asarray([mat.get_mass_density() for mat in materials])
        if percent_type == 'ao':
            wgts = fracs * amms / mass_dens
            wgts /= np.sum(wgts)
        elif percent_type == 'wo':
            wgts = fracs / mass_dens
            wgts /= np.sum(wgts)
        elif percent_type == 'vo':
            wgts = fracs

        # If any of the involved materials contain S(a,b) tables raise an error
        sab_names = set(sab[0] for mat in materials for sab in mat._sab)
        if sab_names:
            msg = ('Currently we do not support mixing materials containing '
                   'S(a,b) tables')
            raise NotImplementedError(msg)

        # Add nuclide densities weighted by appropriate fractions
        nuclides_per_cc = defaultdict(float)
        mass_per_cc = defaultdict(float)
        for mat, wgt in zip(materials, wgts):
            for nuc, atoms_per_bcm in mat.get_nuclide_atom_densities().values(
            ):
                nuc_per_cc = wgt * 1.e24 * atoms_per_bcm
                nuclides_per_cc[nuc] += nuc_per_cc
                mass_per_cc[nuc] += nuc_per_cc*openmc.data.atomic_mass(nuc) / \
                                    openmc.data.AVOGADRO

        # Create the new material with the desired name
        if name is None:
            name = '-'.join(
                ['{}({})'.format(m.name, f) for m, f in zip(materials, fracs)])
        new_mat = openmc.Material(name=name)

        # Compute atom fractions of nuclides and add them to the new material
        tot_nuclides_per_cc = np.sum(
            [dens for dens in nuclides_per_cc.values()])
        for nuc, atom_dens in nuclides_per_cc.items():
            new_mat.add_nuclide(nuc, atom_dens / tot_nuclides_per_cc, 'ao')

        # Compute mass density for the new material and set it
        new_density = np.sum([dens for dens in mass_per_cc.values()])
        new_mat.set_density('g/cm3', new_density)

        # If any of the involved materials is depletable, the new material is
        # depletable
        new_mat.depletable = any(mat.depletable for mat in materials)

        return new_mat
Ejemplo n.º 42
0
    def get_atoms(self, mat, nuc, nuc_units="atoms", time_units="s"):
        """Get number of nuclides over time from a single material

        .. note::
            Initial values for some isotopes that do not appear in
            initial concentrations may be non-zero, depending on the
            value of :class:`openmc.deplete.Operator` ``dilute_initial``.
            The :class:`openmc.deplete.Operator` adds isotopes according
            to this setting, which can be set to zero.

        Parameters
        ----------
        mat : str
            Material name to evaluate
        nuc : str
            Nuclide name to evaluate
        nuc_units : {"atoms", "atom/b-cm", "atom/cm3"}, optional
            Units for the returned concentration. Default is ``"atoms"``

            .. versionadded:: 0.12
        time_units : {"s", "min", "h", "d"}, optional
            Units for the returned time array. Default is ``"s"`` to
            return the value in seconds.

            .. versionadded:: 0.12

        Returns
        -------
        times : numpy.ndarray
            Array of times in units of ``time_units``
        concentrations : numpy.ndarray
            Concentration of specified nuclide in units of ``nuc_units``

        """
        cv.check_value("time_units", time_units, {"s", "d", "min", "h"})
        cv.check_value("nuc_units", nuc_units,
                    {"atoms", "atom/b-cm", "atom/cm3"})

        times = np.empty_like(self, dtype=float)
        concentrations = np.empty_like(self, dtype=float)

        # Evaluate value in each region
        for i, result in enumerate(self):
            times[i] = result.time[0]
            concentrations[i] = result[0, mat, nuc]

        # Unit conversions
        if time_units == "d":
            times /= (60 * 60 * 24)
        elif time_units == "h":
            times /= (60 * 60)
        elif time_units == "min":
            times /= 60

        if nuc_units != "atoms":
            # Divide by volume to get density
            concentrations /= self[0].volume[mat]
            if nuc_units == "atom/b-cm":
                # 1 barn = 1e-24 cm^2
                concentrations *= 1e-24

        return times, concentrations
Ejemplo n.º 43
0
    def add_element(self,
                    element,
                    percent,
                    percent_type='ao',
                    enrichment=None):
        """Add a natural element to the material

        Parameters
        ----------
        element : str
            Element to add, e.g., 'Zr'
        percent : float
            Atom or weight percent
        percent_type : {'ao', 'wo'}, optional
            'ao' for atom percent and 'wo' for weight percent. Defaults to atom
            percent.
        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).

        """
        cv.check_type('nuclide', element, str)
        cv.check_type('percent', percent, Real)
        cv.check_value('percent type', percent_type, {'ao', 'wo'})

        if self._macroscopic is not None:
            msg = 'Unable to add an Element to Material ID="{}" as a ' \
                  'macroscopic data-set has already been added'.format(self._id)
            raise ValueError(msg)

        if enrichment is not None:
            if not isinstance(enrichment, Real):
                msg = 'Unable to add an Element to Material ID="{}" with a ' \
                      'non-floating point enrichment value "{}"'\
                      .format(self._id, enrichment)
                raise ValueError(msg)

            elif element != 'U':
                msg = 'Unable to use enrichment for element {} which is not ' \
                      'uranium for Material ID="{}"'.format(element, self._id)
                raise ValueError(msg)

            # Check that the enrichment is in the valid range
            cv.check_less_than('enrichment', enrichment, 100. / 1.008)
            cv.check_greater_than('enrichment', enrichment, 0., equality=True)

            if enrichment > 5.0:
                msg = 'A uranium enrichment of {} was given for Material ID='\
                      '"{}". OpenMC assumes the U234/U235 mass ratio is '\
                      'constant at 0.008, which is only valid at low ' \
                      'enrichments. Consider setting the isotopic ' \
                      'composition manually for enrichments over 5%.'.\
                      format(enrichment, self._id)
                warnings.warn(msg)

        # Make sure element name is just that
        if not element.isalpha():
            raise ValueError("Element name should be given by the "
                             "element's symbol, e.g., 'Zr'")

        # Add naturally-occuring isotopes
        element = openmc.Element(element)
        for nuclide in element.expand(percent, percent_type, enrichment):
            self.add_nuclide(*nuclide)
Ejemplo n.º 44
0
 def type(self, meshtype):
     cv.check_type('type for mesh ID="{0}"'.format(self._id),
                meshtype, basestring)
     cv.check_value('type for mesh ID="{0}"'.format(self._id),
                 meshtype, ['regular'])
     self._type = meshtype
Ejemplo n.º 45
0
 def type(self, meshtype):
     cv.check_type('type for mesh ID="{0}"'.format(self._id), meshtype,
                   string_types)
     cv.check_value('type for mesh ID="{0}"'.format(self._id), meshtype,
                    ['regular'])
     self._type = meshtype
Ejemplo n.º 46
0
    def build_cells(self, bc=['reflective'] * 6):
        """Generates a lattice of universes with the same dimensionality
        as the mesh object.  The individual cells/universes produced
        will not have material definitions applied and so downstream code
        will have to apply that information.

        Parameters
        ----------
        bc : iterable of {'reflective', 'periodic', 'transmission', or 'vacuum'}
            Boundary conditions for each of the four faces of a rectangle
            (if aplying to a 2D mesh) or six faces of a parallelepiped
            (if applying to a 3D mesh) provided in the following order:
            [x min, x max, y min, y max, z min, z max].  2-D cells do not
            contain the z min and z max entries.

        Returns
        -------
        root_cell : openmc.Cell
            The cell containing the lattice representing the mesh geometry;
            this cell is a single parallelepiped with boundaries matching
            the outermost mesh boundary with the boundary conditions from bc
            applied.
        cells : iterable of openmc.Cell
            The list of cells within each lattice position mimicking the mesh
            geometry.

        """

        cv.check_length('bc', bc, length_min=4, length_max=6)
        for entry in bc:
            cv.check_value(
                'bc', entry,
                ['transmission', 'vacuum', 'reflective', 'periodic'])

        # Build the cell which will contain the lattice
        xplanes = [
            openmc.XPlane(x0=self.lower_left[0], boundary_type=bc[0]),
            openmc.XPlane(x0=self.upper_right[0], boundary_type=bc[1])
        ]
        if len(self.dimension) == 1:
            yplanes = [
                openmc.YPlane(y0=-1e10, boundary_type='reflective'),
                openmc.YPlane(y0=1e10, boundary_type='reflective')
            ]
        else:
            yplanes = [
                openmc.YPlane(y0=self.lower_left[1], boundary_type=bc[2]),
                openmc.YPlane(y0=self.upper_right[1], boundary_type=bc[3])
            ]

        if len(self.dimension) <= 2:
            # Would prefer to have the z ranges be the max supported float, but
            # these values are apparently different between python and Fortran.
            # Choosing a safe and sane default.
            # Values of +/-1e10 are used here as there seems to be an
            # inconsistency between what numpy uses as the max float and what
            # Fortran expects for a real(8), so this avoids code complication
            # and achieves the same goal.
            zplanes = [
                openmc.ZPlane(z0=-1e10, boundary_type='reflective'),
                openmc.ZPlane(z0=1e10, boundary_type='reflective')
            ]
        else:
            zplanes = [
                openmc.ZPlane(z0=self.lower_left[2], boundary_type=bc[4]),
                openmc.ZPlane(z0=self.upper_right[2], boundary_type=bc[5])
            ]
        root_cell = openmc.Cell()
        root_cell.region = ((+xplanes[0] & -xplanes[1]) &
                            (+yplanes[0] & -yplanes[1]) &
                            (+zplanes[0] & -zplanes[1]))

        # Build the universes which will be used for each of the [i,j,k]
        # locations within the mesh.
        # We will concurrently build cells to assign to these universes
        cells = []
        universes = []
        for [i, j, k] in self.cell_generator():
            cells.append(openmc.Cell())
            universes.append(openmc.Universe())
            universes[-1].add_cell(cells[-1])

        lattice = openmc.RectLattice()
        lattice.lower_left = self.lower_left

        # Assign the universe and rotate to match the indexing expected for
        # the lattice
        lattice.universes = np.rot90(np.reshape(universes, self.dimension))

        if self.width is not None:
            lattice.pitch = self.width
        else:
            dx = ((self.upper_right[0] - self.lower_left[0]) /
                  self.dimension[0])

            if len(self.dimension) == 1:
                lattice.pitch = [dx]
            elif len(self.dimension) == 2:
                dy = ((self.upper_right[1] - self.lower_left[1]) /
                      self.dimension[1])
                lattice.pitch = [dx, dy]
            else:
                dy = ((self.upper_right[1] - self.lower_left[1]) /
                      self.dimension[1])
                dz = ((self.upper_right[2] - self.lower_left[2]) /
                      self.dimension[2])
                lattice.pitch = [dx, dy, dz]

        # Fill Cell with the Lattice
        root_cell.fill = lattice

        return root_cell, cells
Ejemplo n.º 47
0
 def display(self, display):
     check_type('CMFD display', display, string_types)
     check_value('CMFD display', display,
                 ['balance', 'dominance', 'entropy', 'source'])
     self._display = display
Ejemplo n.º 48
0
 def formalism(self, formalism):
     if formalism is not None:
         cv.check_type('formalism', formalism, string_types)
         cv.check_value('formalism', formalism, ('MLBW', 'RM'))
     self._formalism = formalism
Ejemplo n.º 49
0
 def map(self, meshmap):
     check_type('CMFD mesh map', meshmap, Iterable, Integral)
     for m in meshmap:
         check_value('CMFD mesh map', m, [1, 2])
     self._map = meshmap
Ejemplo n.º 50
0
 def variable(self, var):
     if var is not None:
         cv.check_type('derivative variable', var, string_types)
         cv.check_value('derivative variable', var,
                        ('density', 'nuclide_density', 'temperature'))
     self._variable = var
Ejemplo n.º 51
0
 def color_by(self, color_by):
     cv.check_value('plot color_by', color_by, ['cell', 'material'])
     self._color_by = color_by
Ejemplo n.º 52
0
 def type(self, plottype):
     cv.check_value('plot type', plottype, ['slice', 'voxel'])
     self._type = plottype
Ejemplo n.º 53
0
 def basis(self, basis):
     cv.check_value('plot basis', basis, _BASES)
     self._basis = basis
Ejemplo n.º 54
0
    def add_element(self,
                    element,
                    percent,
                    percent_type='ao',
                    enrichment=None,
                    enrichment_target=None,
                    enrichment_type=None):
        """Add a natural element to the material

        Parameters
        ----------
        element : str
            Element to add, e.g., 'Zr' or 'Zirconium'
        percent : float
            Atom or weight percent
        percent_type : {'ao', 'wo'}, optional
            'ao' for atom percent and 'wo' for weight percent. Defaults to atom
            percent.
        enrichment : float, optional
            Enrichment of an enrichment_taget nuclide in percent (ao or wo).
            If enrichment_taget is not supplied then it is enrichment for U235
            in weight percent. For example, input 4.95 for 4.95 weight percent
            enriched U.
            Default is None (natural composition).
        enrichment_target: str, optional
            Single nuclide name to enrich from a natural composition (e.g., 'O16')

            .. versionadded:: 0.12
        enrichment_type: {'ao', 'wo'}, optional
            'ao' for enrichment as atom percent and 'wo' for weight percent.
            Default is: 'ao' for two-isotope enrichment; 'wo' for U enrichment

            .. versionadded:: 0.12

        Notes
        -----
        General enrichment procedure is allowed only for elements composed of
        two isotopes. If `enrichment_target` is given without `enrichment`
        natural composition is added to the material.

        """

        cv.check_type('nuclide', element, str)
        cv.check_type('percent', percent, Real)
        cv.check_value('percent type', percent_type, {'ao', 'wo'})

        # Make sure element name is just that
        if not element.isalpha():
            raise ValueError(
                "Element name should be given by the "
                "element's symbol or name, e.g., 'Zr', 'zirconium'")

        # Allow for element identifier to be given as a symbol or name
        if len(element) > 2:
            el = element.lower()
            element = openmc.data.ELEMENT_SYMBOL.get(el)
            if element is None:
                msg = 'Element name "{}" not recognised'.format(el)
                raise ValueError(msg)
        else:
            if element[0].islower():
                msg = 'Element name "{}" should start with an uppercase ' \
                      'letter'.format(element)
                raise ValueError(msg)
            if len(element) == 2 and element[1].isupper():
                msg = 'Element name "{}" should end with a lowercase ' \
                      'letter'.format(element)
                raise ValueError(msg)
            # skips the first entry of ATOMIC_SYMBOL which is n for neutron
            if element not in list(openmc.data.ATOMIC_SYMBOL.values())[1:]:
                msg = 'Element name "{}" not recognised'.format(element)
                raise ValueError(msg)

        if self._macroscopic is not None:
            msg = 'Unable to add an Element to Material ID="{}" as a ' \
                  'macroscopic data-set has already been added'.format(self._id)
            raise ValueError(msg)

        if enrichment is not None and enrichment_target is None:
            if not isinstance(enrichment, Real):
                msg = 'Unable to add an Element to Material ID="{}" with a ' \
                      'non-floating point enrichment value "{}"'\
                      .format(self._id, enrichment)
                raise ValueError(msg)

            elif element != 'U':
                msg = 'Unable to use enrichment for element {} which is not ' \
                      'uranium for Material ID="{}"'.format(element, self._id)
                raise ValueError(msg)

            # Check that the enrichment is in the valid range
            cv.check_less_than('enrichment', enrichment, 100. / 1.008)
            cv.check_greater_than('enrichment', enrichment, 0., equality=True)

            if enrichment > 5.0:
                msg = 'A uranium enrichment of {} was given for Material ID='\
                      '"{}". OpenMC assumes the U234/U235 mass ratio is '\
                      'constant at 0.008, which is only valid at low ' \
                      'enrichments. Consider setting the isotopic ' \
                      'composition manually for enrichments over 5%.'.\
                      format(enrichment, self._id)
                warnings.warn(msg)

        # Add naturally-occuring isotopes
        element = openmc.Element(element)
        for nuclide in element.expand(percent, percent_type, enrichment,
                                      enrichment_target, enrichment_type):
            self.add_nuclide(*nuclide)
Ejemplo n.º 55
0
 def interpolation(self, interpolation):
     cv.check_value('interpolation', interpolation, [2, 5])
     self._interpolation = interpolation
Ejemplo n.º 56
0
def get_metadata(zaid, metastable_scheme='nndc'):
    """Return basic identifying data for a nuclide with a given ZAID.

    Parameters
    ----------
    zaid : int
        ZAID (1000*Z + A) obtained from a library
    metastable_scheme : {'nndc', 'mcnp'}
        Determine how ZAID identifiers are to be interpreted in the case of
        a metastable nuclide. Because the normal ZAID (=1000*Z + A) does not
        encode metastable information, different conventions are used among
        different libraries. In MCNP libraries, the convention is to add 400
        for a metastable nuclide except for Am242m, for which 95242 is
        metastable and 95642 (or 1095242 in newer libraries) is the ground
        state. For NNDC libraries, ZAID is given as 1000*Z + A + 100*m.

    Returns
    -------
    name : str
        Name of the table
    element : str
        The atomic symbol of the isotope in the table; e.g., Zr.
    Z : int
        Number of protons in the nucleus
    mass_number : int
        Number of nucleons in the nucleus
    metastable : int
        Metastable state of the nucleus. A value of zero indicates ground state.

    """

    cv.check_type('zaid', zaid, int)
    cv.check_value('metastable_scheme', metastable_scheme, ['nndc', 'mcnp'])

    Z = zaid // 1000
    mass_number = zaid % 1000

    if metastable_scheme == 'mcnp':
        if zaid > 1000000:
            # New SZA format
            Z = Z % 1000
            if zaid == 1095242:
                metastable = 0
            else:
                metastable = zaid // 1000000
        else:
            if zaid == 95242:
                metastable = 1
            elif zaid == 95642:
                metastable = 0
            else:
                metastable = 1 if mass_number > 300 else 0
    elif metastable_scheme == 'nndc':
        metastable = 1 if mass_number > 300 else 0

    while mass_number > 3 * Z:
        mass_number -= 100

    # Determine name
    element = ATOMIC_SYMBOL[Z]
    name = gnd_name(Z, mass_number, metastable)

    return (name, element, Z, mass_number, metastable)
Ejemplo n.º 57
0
 def interpolation(self, interpolation):
     cv.check_value('interpolation', interpolation, _INTERPOLATION_SCHEMES)
     self._interpolation = interpolation