예제 #1
0
def create_mats(mat_spec):
    """Create materials for study and returns the materials.
    """

    # Define the material
    iso = mat_spec.name
    dens = mat_spec.dens

    # Instantiate Nuclides
    candidate = openmc.Nuclide(iso)
    he3 = openmc.Nuclide('He3')

    # Create materials
    fuel = openmc.Material(name=iso)
    fuel.set_density('g/cm3', dens)
    fuel.add_nuclide(candidate, 1.0)

    air = openmc.Material(name='air')
    air.set_density('g/cm3', 0.001225)
    air.add_nuclide(he3, 1.0)

    materials_file = openmc.Materials((fuel, air))
    materials_file.default_xs = '71c'
    materials_file.export_to_xml()

    return fuel, air
    def _build_inputs(self):

        # The summary.h5 file needs to be created to read in the tallies
        self._input_set.settings.output = {'summary': True}

        # Initialize the nuclides
        u235 = openmc.Nuclide('U-235')
        u238 = openmc.Nuclide('U-238')
        pu239 = openmc.Nuclide('Pu-239')

        # Initialize the filters
        energy_filter = openmc.Filter(type='energy',
                                      bins=[0.0, 0.253e-6, 1.0e-3, 1.0, 20.0])
        distrib_filter = openmc.Filter(type='distribcell', bins=[60])

        # Initialized the tallies
        tally = openmc.Tally(name='distribcell tally')
        tally.filters = [energy_filter, distrib_filter]
        tally.scores = ['nu-fission', 'total']
        tally.nuclides = [u235, u238, pu239]
        tallies_file = openmc.Tallies([tally])

        # Export tallies to file
        self._input_set.tallies = tallies_file
        super(TallyAggregationTestHarness, self)._build_inputs()
예제 #3
0
    def get_nuclide_densities(self):
        """Return all nuclides contained in the cell and their densities

        Returns
        -------
        nuclides : collections.OrderedDict
            Dictionary whose keys are nuclide names and values are 2-tuples of
            (nuclide, density)

        """

        nuclides = OrderedDict()

        if self.fill_type == 'material':
            nuclides.update(self.fill.get_nuclide_densities())
        elif self.fill_type == 'void':
            pass
        else:
            if self._atoms is not None:
                volume = self.volume
                for name, atoms in self._atoms.items():
                    nuclide = openmc.Nuclide(name)
                    density = 1.0e-24 * atoms[
                        0] / volume  # density in atoms/b-cm
                    nuclides[name] = (nuclide, density)
            else:
                raise RuntimeError(
                    'Volume information is needed to calculate microscopic cross '
                    'sections for cell {}. This can be done by running a '
                    'stochastic volume calculation via the '
                    'openmc.VolumeCalculation object'.format(self.id))

        return nuclides
예제 #4
0
    def get_nuclide_densities(self):
        """Return all nuclides contained in the universe

        Returns
        -------
        nuclides : collections.OrderedDict
            Dictionary whose keys are nuclide names and values are 2-tuples of
            (nuclide, density)

        """
        nuclides = OrderedDict()

        if self._atoms is not None:
            volume = self.volume
            for name, atoms in self._atoms.items():
                nuclide = openmc.Nuclide(name)
                density = 1.0e-24 * atoms.n / volume  # density in atoms/b-cm
                nuclides[name] = (nuclide, density)
        else:
            raise RuntimeError(
                'Volume information is needed to calculate microscopic cross '
                f'sections for universe {self.id}. This can be done by running '
                'a stochastic volume calculation via the '
                'openmc.VolumeCalculation object')

        return nuclides
예제 #5
0
    def density_dictionary_to_openmc_mat(self, m_id):
        """ Generates an OpenMC material from a cell ID and self.number_density.

        Parameters
        ----------
        m_id : int
            Cell ID.

        Returns
        -------
        openmc.Material
            The OpenMC material filled with nuclides.
        """

        mat = openmc.Material(material_id=m_id)
        total = 0.0
        for key in self.number_density[m_id]:
            nuc = openmc.Nuclide(key)
            if type(self.number_density[m_id][key]) is zernike.ZernikePolynomial:
                nuc.poly_coeffs = self.number_density[m_id][key].openmc_form(radial_only=False)
                nuc.poly_type = "zernike"
                mat.add_nuclide(nuc, self.number_density[m_id][key].coeffs[0])
                total += self.number_density[m_id][key].coeffs[0]
            else:
                mat.add_nuclide(nuc, self.number_density[m_id][key])
                total += self.number_density[m_id][key]
        mat.set_density('atom/cm3', total)
        return mat
예제 #6
0
    def _build_inputs(self):

        # The summary.h5 file needs to be created to read in the tallies
        self._input_set.settings.output = {'summary': True}

        # Initialize the tallies file
        tallies_file = openmc.Tallies()

        # Initialize the nuclides
        u235 = openmc.Nuclide('U-235')
        u238 = openmc.Nuclide('U-238')
        pu239 = openmc.Nuclide('Pu-239')

        # Initialize Mesh
        mesh = openmc.Mesh(mesh_id=1)
        mesh.type = 'regular'
        mesh.dimension = [2, 2, 2]
        mesh.lower_left = [-160.0, -160.0, -183.0]
        mesh.upper_right = [160.0, 160.0, 183.0]

        # Initialize the filters
        energy_filter = openmc.Filter(type='energy',
                                      bins=(0.0, 0.253e-6, 1.0e-3, 1.0, 20.0))
        material_filter = openmc.Filter(type='material', bins=(1, 3))
        distrib_filter = openmc.Filter(type='distribcell', bins=(60))
        mesh_filter = openmc.Filter(type='mesh')
        mesh_filter.mesh = mesh

        # Initialized the tallies
        tally = openmc.Tally(name='tally 1')
        tally.filters = [material_filter, energy_filter, distrib_filter]
        tally.scores = ['nu-fission', 'total']
        tally.nuclides = [u235, pu239]
        tallies_file.append(tally)

        tally = openmc.Tally(name='tally 2')
        tally.filters = [energy_filter, mesh_filter]
        tally.scores = ['total', 'fission']
        tally.nuclides = [u238, u235]
        tallies_file.append(tally)

        # Export tallies to file
        self._input_set.tallies = tallies_file
        super(TallyArithmeticTestHarness, self)._build_inputs()
예제 #7
0
    def _build_inputs(self):
        mat1 = openmc.Material(material_id=1, temperature=294)
        mat1.set_density('g/cm3', 4.5)
        mat1.add_nuclide(openmc.Nuclide('U235'), 1.0)
        materials = openmc.Materials([mat1])
        materials.export_to_xml()

        sphere = openmc.Sphere(surface_id=1, r=10.0, boundary_type='vacuum')
        inside_sphere = openmc.Cell(cell_id=1)
        inside_sphere.region = -sphere
        inside_sphere.fill = mat1

        root = openmc.Universe(universe_id=0)
        root.add_cell(inside_sphere)
        geometry = openmc.Geometry()
        geometry.root_universe = root
        geometry.export_to_xml()

        # Create an array of different sources
        x_dist = openmc.stats.Uniform(-3., 3.)
        y_dist = openmc.stats.Discrete([-4., -1., 3.], [0.2, 0.3, 0.5])
        z_dist = openmc.stats.Tabular([-2., 0., 2.], [0.2, 0.3, 0.2])
        spatial1 = openmc.stats.CartesianIndependent(x_dist, y_dist, z_dist)
        spatial2 = openmc.stats.Box([-4., -4., -4.], [4., 4., 4.])
        spatial3 = openmc.stats.Point([1.2, -2.3, 0.781])

        mu_dist = openmc.stats.Discrete([-1., 0., 1.], [0.5, 0.25, 0.25])
        phi_dist = openmc.stats.Uniform(0., 6.28318530718)
        angle1 = openmc.stats.PolarAzimuthal(mu_dist, phi_dist)
        angle2 = openmc.stats.Monodirectional(reference_uvw=[0., 1., 0.])
        angle3 = openmc.stats.Isotropic()

        E = np.logspace(0, 7)
        p = np.sin(np.linspace(0., pi))
        p /= sum(np.diff(E) * p[:-1])
        energy1 = openmc.stats.Maxwell(1.2895e6)
        energy2 = openmc.stats.Watt(0.988e6, 2.249e-6)
        energy3 = openmc.stats.Tabular(E, p, interpolation='histogram')

        source1 = openmc.Source(spatial1, angle1, energy1, strength=0.5)
        source2 = openmc.Source(spatial2, angle2, energy2, strength=0.3)
        source3 = openmc.Source(spatial3, angle3, energy3, strength=0.2)

        settings = openmc.Settings()
        settings.batches = 10
        settings.inactive = 5
        settings.particles = 1000
        settings.source = [source1, source2, source3]
        settings.export_to_xml()
예제 #8
0
    def _read_materials(self):
        self.n_materials = self._f['n_materials'].value

        # Initialize dictionary for each Material
        # Keys     - Material keys
        # Values   - Material objects
        self.materials = {}

        for key in self._f['materials'].keys():
            if key == 'n_materials':
                continue

            material_id = int(key.lstrip('material '))
            index = self._f['materials'][key]['index'].value
            name = self._f['materials'][key]['name'].value.decode()
            density = self._f['materials'][key]['atom_density'].value
            nuc_densities = self._f['materials'][key]['nuclide_densities'][...]
            nuclides = self._f['materials'][key]['nuclides'].value

            # Create the Material
            material = openmc.Material(material_id=material_id, name=name)

            # Read the names of the S(a,b) tables for this Material and add them
            if 'sab_names' in self._f['materials'][key]:
                sab_tables = self._f['materials'][key]['sab_names'].value
                for sab_table in sab_tables:
                    name, xs = sab_table.decode().split('.')
                    material.add_s_alpha_beta(name, xs)

            # Set the Material's density to atom/b-cm as used by OpenMC
            material.set_density(density=density, units='atom/b-cm')

            # Add all nuclides to the Material
            for fullname, density in zip(nuclides, nuc_densities):
                fullname = fullname.decode().strip()
                name, xs = fullname.split('.')

                if 'nat' in name:
                    material.add_element(openmc.Element(name=name, xs=xs),
                                         percent=density,
                                         percent_type='ao')
                else:
                    material.add_nuclide(openmc.Nuclide(name=name, xs=xs),
                                         percent=density,
                                         percent_type='ao')

            # Add the Material to the global dictionary of all Materials
            self.materials[index] = material
예제 #9
0
    def generate_materials_xml(self):
        """ Creates materials.xml from self.number_density.

        Iterates through each cell in self.number_density and creates the
        openmc material object to generate materials.xml.
        """
        openmc.reset_auto_material_id()

        mat = []
        i = 0

        for key_mat in self.number_density:
            mat.append(openmc.Material(material_id=key_mat))

            mat_name = self.mat_name[key_mat]

            total = 0.0
            for key_nuc in self.number_density[key_mat]:
                # Check if in participating nuclides
                if key_nuc in self.participating_nuclides:
                    nuc = openmc.Nuclide(key_nuc,
                                         xs=self.materials.library[mat_name])
                    if type(self.number_density[key_mat][key_nuc]) is zernike.ZernikePolynomial:
                        
                        nuc.poly_coeffs = self.number_density[key_mat][key_nuc].openmc_form(radial_only=False)
                        self.total_number[key_mat][key_nuc] = self.number_density[key_mat][key_nuc] * self.volume[key_mat]
                        nuc.poly_type = "zernike"

                        mat[i].add_nuclide(nuc,
                                           self.number_density[key_mat][key_nuc].coeffs[0])
                        total += self.number_density[key_mat][key_nuc].coeffs[0]
                    else:
                        mat[i].add_nuclide(nuc,
                                           self.number_density[key_mat][key_nuc])
                        total += self.number_density[key_mat][key_nuc]
            mat[i].set_density('atom/cm3', total)

            if mat_name in self.materials.sab:
                mat[i].add_s_alpha_beta(self.materials.sab[mat_name],
                                        self.materials.library_sab[mat_name])

            i += 1

        materials_file = openmc.Materials()
        materials_file.add_materials(mat)
        materials_file.export_to_xml()
예제 #10
0
    def expand(self):
        """Expand natural element into its naturally-occurring isotopes.

        Returns
        -------
        isotopes : list
            Naturally-occurring isotopes of the element. Each item of the list
            is a tuple consisting of an openmc.Nuclide instance and the natural
            abundance of the isotope.

        """

        isotopes = []
        for isotope, abundance in sorted(natural_abundance.items()):
            if isotope.startswith(self.name + '-'):
                nuc = openmc.Nuclide(isotope, self.xs)
                isotopes.append((nuc, abundance))
        return isotopes
예제 #11
0
    def remove_nuclide(self, nuclide):
        """Remove a nuclide from the material

        Parameters
        ----------
        nuclide : openmc.Nuclide
            Nuclide to remove

        """
        cv.check_type('nuclide', nuclide, string_types + (openmc.Nuclide, ))

        if isinstance(nuclide, string_types):
            nuclide = openmc.Nuclide(nuclide)

        # If the Material contains the Nuclide, delete it
        for nuc in self._nuclides:
            if nuclide == nuc[0]:
                self._nuclides.remove(nuc)
                break
예제 #12
0
    def add_nuclide(self, nuclide, percent, percent_type='ao'):
        """Add a nuclide to the material

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

        """

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

        if not isinstance(nuclide, (openmc.Nuclide, basestring)):
            msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \
                  'non-Nuclide value "{1}"'.format(self._id, nuclide)
            raise ValueError(msg)

        elif not isinstance(percent, Real):
            msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \
                  'non-floating point value "{1}"'.format(self._id, percent)
            raise ValueError(msg)

        elif percent_type not in ['ao', 'wo', 'at/g-cm']:
            msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \
                  'percent type "{1}"'.format(self._id, percent_type)
            raise ValueError(msg)

        if isinstance(nuclide, openmc.Nuclide):
            # Copy this Nuclide to separate it from the Nuclide in
            # other Materials
            nuclide = deepcopy(nuclide)
        else:
            nuclide = openmc.Nuclide(nuclide)

        self._nuclides.append((nuclide, percent, percent_type))
예제 #13
0
    def add_nuclide(self, nuclide, percent, percent_type='ao'):
        """Add a nuclide to the material

        Parameters
        ----------
        nuclide : str or openmc.nuclide.Nuclide
            Nuclide to add
        percent : float
            Atom or weight percent
        percent_type : str
            'ao' for atom percent and 'wo' for weight percent

        """

        if not isinstance(nuclide, (openmc.Nuclide, str)):
            msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \
                  'non-Nuclide value "{1}"'.format(self._id, nuclide)
            raise ValueError(msg)

        elif not isinstance(percent, Real):
            msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \
                  'non-floating point value "{1}"'.format(self._id, percent)
            raise ValueError(msg)

        elif percent_type not in ['ao', 'wo', 'at/g-cm']:
            msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \
                  'percent type "{1}"'.format(self._id, percent_type)
            raise ValueError(msg)

        if isinstance(nuclide, openmc.Nuclide):
            # Copy this Nuclide to separate it from the Nuclide in
            # other Materials
            nuclide = deepcopy(nuclide)
        else:
            nuclide = openmc.Nuclide(nuclide)

        self._nuclides[nuclide._name] = (nuclide, percent, percent_type)
예제 #14
0
###############################################################################
#                      Simulation Input File Parameters
###############################################################################

# OpenMC simulation parameters
batches = 100
inactive = 10
particles = 100000


###############################################################################
#                 Exporting to OpenMC materials.xml File
###############################################################################

# Instantiate some Nuclides
h1 = openmc.Nuclide('H-1')
he4 = openmc.Nuclide('He-4')
b10 = openmc.Nuclide('B-10')
b11 = openmc.Nuclide('B-11')
o16 = openmc.Nuclide('O-16')
fe56 = openmc.Nuclide('Fe-56')
zr90 = openmc.Nuclide('Zr-90')
u235 = openmc.Nuclide('U-235')
u238 = openmc.Nuclide('U-238')

# Instantiate some Materials and register the appropriate Nuclides
uo2 = openmc.Material(name='UO2 Fuel')
uo2.set_density('g/cm3', 10.29769)
uo2.add_nuclide(u235, 5.5815e-4)
uo2.add_nuclide(u238, 2.2408e-2)
uo2.add_nuclide(o16, 4.5829e-2)
    def _build_inputs(self):
        # Materials
        mat = openmc.Material(material_id=1)
        mat.set_density('g/cc', 1.0)
        mat.add_nuclide('U-238', 1.0)
        mat.add_nuclide('U-235', 0.02)
        mat.add_nuclide('Pu-239', 0.02)
        mat.add_nuclide('H-1', 20.0)

        mats_file = openmc.Materials([mat])
        mats_file.default_xs = '71c'
        mats_file.export_to_xml()

        # Geometry
        dumb_surface = openmc.XPlane(x0=100)
        dumb_surface.boundary_type = 'reflective'

        c1 = openmc.Cell(cell_id=1)
        c1.fill = mat
        c1.region = -dumb_surface

        root_univ = openmc.Universe(universe_id=0)
        root_univ.add_cell(c1)

        geometry = openmc.Geometry()
        geometry.root_universe = root_univ
        geometry.export_to_xml()

        # Settings
        nuclide = openmc.Nuclide('U-238', '71c')
        nuclide.zaid = 92238
        res_scatt_dbrc = openmc.ResonanceScattering()
        res_scatt_dbrc.nuclide = nuclide
        res_scatt_dbrc.nuclide_0K = nuclide  # This is a bad idea! Just for tests
        res_scatt_dbrc.method = 'DBRC'
        res_scatt_dbrc.E_min = 1e-6
        res_scatt_dbrc.E_max = 210e-6

        nuclide = openmc.Nuclide('U-235', '71c')
        nuclide.zaid = 92235
        res_scatt_wcm = openmc.ResonanceScattering()
        res_scatt_wcm.nuclide = nuclide
        res_scatt_wcm.nuclide_0K = nuclide
        res_scatt_wcm.method = 'WCM'
        res_scatt_wcm.E_min = 1e-6
        res_scatt_wcm.E_max = 210e-6

        nuclide = openmc.Nuclide('Pu-239', '71c')
        nuclide.zaid = 94239
        res_scatt_ares = openmc.ResonanceScattering()
        res_scatt_ares.nuclide = nuclide
        res_scatt_ares.nuclide_0K = nuclide
        res_scatt_ares.method = 'ARES'
        res_scatt_ares.E_min = 1e-6
        res_scatt_ares.E_max = 210e-6

        sets_file = openmc.Settings()
        sets_file.batches = 10
        sets_file.inactive = 5
        sets_file.particles = 1000
        sets_file.source = openmc.source.Source(
            space=openmc.stats.Box([-4, -4, -4], [4, 4, 4]))
        sets_file.resonance_scattering = [
            res_scatt_dbrc, res_scatt_wcm, res_scatt_ares
        ]
        sets_file.export_to_xml()
예제 #16
0
mgdata = lib.get_xsdata(ru, "U235-fission", nuclide="U235")
micro_xs = mgdata.fission[
    0] / 1712E-6  # TODO: Correctly calculate number density

efilt = sp.filters[1]
etal = sp.get_tally(scores=["flux"], filters=[efilt])

talvals = np.array(etal.mean).squeeze()
stdvals = np.array(etal.std_dev).squeeze()

print(talvals)
print(stdvals)
print(efilt.bins)
bins = efilt.bins[:-1]

fig = openmc.plot_xs(openmc.Nuclide("U235"), ['fission'], temperature=600)
#fig = openmc.plot_xs(openmc.Nuclide("U238"), ['capture'], temperature=600)
ax = fig.gca()
ax.step(bins, talvals, label="$\phi(E)$", color="blue")
#ax.step(bins, talvals+stdvals, color="salmon", label="$\pm\sigma$")
#ax.step(bins, talvals-stdvals, color="salmon")
#ax.step([0, 2E7], [micro_xs]*2, color="red")
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlabel("$E$")
ax.set_ylabel("$\phi(E)$")

plt.legend(["U235 fission", "$\phi(E)$", "$\sigma_g(E)$"])
plt.title("Light Water")
plt.show()
예제 #17
0
    def tallies(self):
        if self.tallies_present and not self._tallies_read:
            # Read the number of tallies
            tallies_group = self._f['tallies']
            n_tallies = tallies_group.attrs['n_tallies']

            # Read a list of the IDs for each Tally
            if n_tallies > 0:
                # Tally user-defined IDs
                tally_ids = tallies_group.attrs['ids']
            else:
                tally_ids = []

            # Ignore warnings about duplicate IDs
            with warnings.catch_warnings():
                warnings.simplefilter('ignore', openmc.IDWarning)

                # Iterate over all tallies
                for tally_id in tally_ids:
                    group = tallies_group['tally {}'.format(tally_id)]

                    # Read the number of realizations
                    n_realizations = group['n_realizations'].value

                    # Create Tally object and assign basic properties
                    tally = openmc.Tally(tally_id)
                    tally._sp_filename = self._f.filename
                    tally.name = group['name'].value.decode(
                    ) if 'name' in group else ''
                    tally.estimator = group['estimator'].value.decode()
                    tally.num_realizations = n_realizations

                    # Read derivative information.
                    if 'derivative' in group:
                        deriv_id = group['derivative'].value
                        tally.derivative = self.tally_derivatives[deriv_id]

                    # Read all filters
                    n_filters = group['n_filters'].value
                    if n_filters > 0:
                        filter_ids = group['filters'].value
                        filters_group = self._f['tallies/filters']
                        for filter_id in filter_ids:
                            filter_group = filters_group['filter {}'.format(
                                filter_id)]
                            new_filter = openmc.Filter.from_hdf5(
                                filter_group, meshes=self.meshes)
                            tally.filters.append(new_filter)

                    # Read nuclide bins
                    nuclide_names = group['nuclides'].value

                    # Add all nuclides to the Tally
                    for name in nuclide_names:
                        nuclide = openmc.Nuclide(name.decode().strip())
                        tally.nuclides.append(nuclide)

                    scores = group['score_bins'].value
                    n_score_bins = group['n_score_bins'].value

                    # Compute and set the filter strides
                    for i in range(n_filters):
                        tally_filter = tally.filters[i]
                        tally_filter.stride = n_score_bins * len(nuclide_names)

                        for j in range(i + 1, n_filters):
                            tally_filter.stride *= tally.filters[j].num_bins

                    # Read scattering moment order strings (e.g., P3, Y1,2, etc.)
                    moments = group['moment_orders'].value

                    # Add the scores to the Tally
                    for j, score in enumerate(scores):
                        score = score.decode()

                        # If this is a moment, use generic moment order
                        pattern = r'-n$|-pn$|-yn$'
                        score = re.sub(pattern, '-' + moments[j].decode(),
                                       score)

                        tally.scores.append(score)

                    # Add Tally to the global dictionary of all Tallies
                    tally.sparse = self.sparse
                    self._tallies[tally_id] = tally

            self._tallies_read = True

        return self._tallies
예제 #18
0
    def link_with_summary(self, summary):
        """Links Tallies and Filters with Summary model information.

        This routine retrieves model information (materials, geometry) from a
        Summary object populated with an HDF5 'summary.h5' file and inserts it
        into the Tally objects. This can be helpful when viewing and
        manipulating large scale Tally data. Note that it is necessary to link
        against a summary to populate the Tallies with any user-specified "name"
        XML tags.

        Parameters
        ----------
        summary : Summary
             A Summary object.

        Raises
        ------
        ValueError
            An error when the argument passed to the 'summary' parameter is not
            an openmc.Summary object.

        """

        if not isinstance(summary, openmc.summary.Summary):
            msg = 'Unable to link statepoint with "{0}" which ' \
                  'is not a Summary object'.format(summary)
            raise ValueError(msg)

        for tally_id, tally in self.tallies.items():
            # Get the Tally name from the summary file
            tally.name = summary.tallies[tally_id].name
            tally.with_summary = True

            nuclide_zaids = copy.deepcopy(tally.nuclides)

            for nuclide_zaid in nuclide_zaids:
                tally.remove_nuclide(nuclide_zaid)
                if nuclide_zaid == -1:
                    tally.add_nuclide(openmc.Nuclide('total'))
                else:
                    tally.add_nuclide(summary.nuclides[nuclide_zaid])

            for filter in tally.filters:
                if filter.type == 'surface':
                    surface_ids = []
                    for bin in filter.bins:
                        surface_ids.append(summary.surfaces[bin].id)
                    filter.bins = surface_ids

                if filter.type in ['cell', 'distribcell']:
                    distribcell_ids = []
                    for bin in filter.bins:
                        distribcell_ids.append(summary.cells[bin].id)
                    filter.bins = distribcell_ids

                if filter.type == 'universe':
                    universe_ids = []
                    for bin in filter.bins:
                        universe_ids.append(summary.universes[bin].id)
                    filter.bins = universe_ids

                if filter.type == 'material':
                    material_ids = []
                    for bin in filter.bins:
                        material_ids.append(summary.materials[bin].id)
                    filter.bins = material_ids

        self._with_summary = True
예제 #19
0
    def __init__(self, boron_ppm=c.nominalBoronPPM, is_symmetric=False, is_2d=False):
        """ We build the entire geometry in memory in the constructor """

        # TODO: make the control rod bank insertion heights attributes

        # Setup the materials
        self.mats = openmc_materials(ppm=boron_ppm)

        self.pincells = Pincells(self.mats)
        self.assemblies = Assemblies(self.pincells, self.mats)
        self.baffle = Baffle(self.assemblies, self.mats)
        self.core = Core(self.pincells, self.assemblies, self.baffle, is_symmetric=is_symmetric)
        self.main_universe = UniverseZero(self.core, self.mats, is_2d=is_2d)

        self.openmc_geometry = openmc.Geometry(self.main_universe)

        self.settings_batches = 10
        self.settings_inactive = 5
        self.settings_particles = 1000
        baffle_flat = 7.5*c.latticePitch
        if is_2d:
            self.settings_sourcebox = [-baffle_flat, -baffle_flat, c.struct_LowestExtent_2d,
                                       baffle_flat, baffle_flat, c.struct_HighestExtent_2d]
        else:
            self.settings_sourcebox = [-baffle_flat, -baffle_flat, c.fuel_Rod_bot,
                                       baffle_flat, baffle_flat, c.fuel_Rod_top]
        self.settings_output_tallies = False
        self.settings_summary = True
        self.settings_output_distribmats = False

        self.tally_meshes = []
        self.tallies = []

        self.dd_mesh_dimension = None
        self.dd_mesh_lower_left = None
        self.dd_mesh_upper_right = None
        self.dd_nodemap = None
        self.dd_truncate = False
        self.dd_interactions = False

        # These were not chosen with any application in mind: tailor them to your needs!
        self.depletion_nuclides = [
                    'Ag107', 'Ag109', 'Ag111', 'Am241', 'Am243', 'As75',
                    'Au197', 'Ba134', 'Ba135', 'Ba136', 'Ba137', 'Ba138',
                    'Ba140', 'Br79', 'Br81', 'Cd108', 'Cd110', 'Cd111',
                    'Cd112', 'Cd113', 'Cd114', 'Cd116', 'Ce140',
                    'Ce141', 'Ce142', 'Ce143', 'Ce144', 'Cm244', 'Co59',
                    'Cs133', 'Cs134', 'Cs135', 'Cs136', 'Cs137', 'Dy160',
                    'Dy161', 'Dy162', 'Dy163', 'Dy164', 'Er166', 'Er167',
                    'Eu151', 'Eu152', 'Eu153', 'Eu154', 'Eu155', 'Eu156',
                    'Eu157', 'Gd154', 'Gd155', 'Gd156', 'Gd157', 'Gd158',
                    'Gd160', 'Ge72', 'Ge73', 'Ge74', 'Ge76', 'Ho165',
                    'I127', 'I129', 'I130', 'I131', 'I135', 'In113',
                    'In115', 'Kr80', 'Kr82', 'Kr83', 'Kr84', 'Kr85',
                    'Kr86', 'La139', 'La140', 'Lu175', 'Lu176', 'Mo100',
                    'Mo94', 'Mo95', 'Mo96', 'Mo97', 'Mo98', 'Mo99',
                    'Nb93', 'Nb94', 'Nb95', 'Nd142', 'Nd143', 'Nd144',
                    'Nd145', 'Nd146', 'Nd147', 'Nd148', 'Nd150', 'Np237',
                    'Pa233', 'Pd104', 'Pd105', 'Pd106', 'Pd107', 'Pd108',
                    'Pd110', 'Pm147', 'Pm148', 'Pm149', 'Pm151', 'Pr141',
                    'Pr142', 'Pr143', 'Pu238', 'Pu239', 'Pu240', 'Pu241',
                    'Pu242', 'Rb85', 'Rb86', 'Rb87', 'Re185', 'Re187',
                    'Rh103', 'Rh105', 'Ru100', 'Ru101', 'Ru102', 'Ru103',
                    'Ru104', 'Ru105', 'Ru106', 'Ru99', 'Sb121', 'Sb123',
                    'Sb124', 'Sb125', 'Sb126', 'Se76', 'Se77', 'Se78',
                    'Se80', 'Se82', 'Sm147', 'Sm148', 'Sm149', 'Sm150',
                    'Sm151', 'Sm152', 'Sm153', 'Sm154', 'Sn115', 'Sn116',
                    'Sn117', 'Sn118', 'Sn119', 'Sn120', 'Sn122', 'Sn123',
                    'Sn124', 'Sn125', 'Sn126', 'Sr86', 'Sr87', 'Sr88',
                    'Sr89', 'Sr90', 'Ta181', 'Tb159', 'Tb160', 'Tc99',
                    'Te122', 'Te123', 'Te124', 'Te125', 'Te126',
                    'Te128', 'Te130', 'Te132', 'Th232', 'U233',
                    'U234', 'U235', 'U236', 'U238', 'W182', 'W183',
                    'W184', 'W186', 'Xe128', 'Xe129', 'Xe130', 'Xe131',
                    'Xe132', 'Xe133', 'Xe134', 'Xe135', 'Xe136', 'Y89',
                    'Y90', 'Y91', 'Zr90', 'Zr91', 'Zr92', 'Zr93', 'Zr94',
                    'Zr95', 'Zr96']
        nuclides = []
        for nuc in self.depletion_nuclides:
            nuclides.append(openmc.Nuclide(nuc))
        self.depletion_nuclides = nuclides
예제 #20
0
###############################################################################
#                      Simulation Input File Parameters
###############################################################################

# OpenMC simulation parameters
batches = 20
inactive = 10
particles = 10000

###############################################################################
#                 Exporting to OpenMC materials.xml File
###############################################################################

# Instantiate some Nuclides
h1 = openmc.Nuclide('H-1')
o16 = openmc.Nuclide('O-16')
u235 = openmc.Nuclide('U-235')

# Instantiate some Materials and register the appropriate Nuclides
fuel = openmc.Material(material_id=1, name='fuel')
fuel.set_density('g/cc', 4.5)
fuel.add_nuclide(u235, 1.)

moderator = openmc.Material(material_id=2, name='moderator')
moderator.set_density('g/cc', 1.0)
moderator.add_nuclide(h1, 2.)
moderator.add_nuclide(o16, 1.)
moderator.add_s_alpha_beta('HH2O', '71t')

# Instantiate a MaterialsFile, register all Materials, and export to XML
예제 #21
0
###############################################################################
#                      Simulation Input File Parameters
###############################################################################

# OpenMC simulation parameters
batches = 100
inactive = 10
particles = 10000

###############################################################################
#                 Exporting to OpenMC materials.xml File
###############################################################################

# Instantiate some Nuclides
h1 = openmc.Nuclide('H-1')
b10 = openmc.Nuclide('B-10')
b11 = openmc.Nuclide('B-11')
o16 = openmc.Nuclide('O-16')
u235 = openmc.Nuclide('U-235')
u238 = openmc.Nuclide('U-238')
zr90 = openmc.Nuclide('Zr-90')
zr91 = openmc.Nuclide('Zr-91')
zr92 = openmc.Nuclide('Zr-92')
zr94 = openmc.Nuclide('Zr-94')
zr96 = openmc.Nuclide('Zr-96')

# Instantiate some Materials and register the appropriate Nuclides
fuel = openmc.Material(name='3.1 w/o enriched UO2')
fuel.set_density('sum')
fuel.add_nuclide(
예제 #22
0
###############################################################################
#                      Simulation Input File Parameters
###############################################################################

# OpenMC simulation parameters
batches = 100
inactive = 10
particles = 1000

###############################################################################
#                 Exporting to OpenMC materials.xml File
###############################################################################

# Instantiate some Nuclides
h1 = openmc.Nuclide('H-1')
h2 = openmc.Nuclide('H-2')
he4 = openmc.Nuclide('He-4')
b10 = openmc.Nuclide('B-10')
b11 = openmc.Nuclide('B-11')
o16 = openmc.Nuclide('O-16')
o17 = openmc.Nuclide('O-17')
cr50 = openmc.Nuclide('Cr-50')
cr52 = openmc.Nuclide('Cr-52')
cr53 = openmc.Nuclide('Cr-53')
cr54 = openmc.Nuclide('Cr-54')
fe54 = openmc.Nuclide('Fe-54')
fe56 = openmc.Nuclide('Fe-56')
fe57 = openmc.Nuclide('Fe-57')
fe58 = openmc.Nuclide('Fe-58')
zr90 = openmc.Nuclide('Zr-90')
예제 #23
0
    def tallies(self):
        if not self._tallies_read:
            # Initialize dictionary for tallies
            self._tallies = {}

            # Read the number of tallies
            n_tallies = self._f['tallies/n_tallies'].value

            # Read a list of the IDs for each Tally
            if n_tallies > 0:
                # OpenMC Tally IDs (redefined internally from user definitions)
                tally_keys = self._f['tallies/keys'].value
            else:
                tally_keys = []

            base = 'tallies/tally '

            # Iterate over all Tallies
            for tally_key in tally_keys:

                # Read the Tally size specifications
                n_realizations = \
                    self._f['{0}{1}/n_realizations'.format(base, tally_key)].value

                # Create Tally object and assign basic properties
                tally = openmc.Tally(tally_id=tally_key)
                tally._sp_filename = self._f.filename
                tally.estimator = self._f['{0}{1}/estimator'.format(
                    base, tally_key)].value.decode()
                tally.num_realizations = n_realizations

                # Read the number of Filters
                n_filters = \
                    self._f['{0}{1}/n_filters'.format(base, tally_key)].value

                subbase = '{0}{1}/filter '.format(base, tally_key)

                # Initialize all Filters
                for j in range(1, n_filters + 1):

                    # Read the Filter type
                    filter_type = \
                        self._f['{0}{1}/type'.format(subbase, j)].value.decode()

                    n_bins = self._f['{0}{1}/n_bins'.format(subbase, j)].value

                    # Read the bin values
                    bins = self._f['{0}{1}/bins'.format(subbase, j)].value

                    # Create Filter object
                    new_filter = openmc.Filter(filter_type, bins)
                    new_filter.num_bins = n_bins

                    if filter_type == 'mesh':
                        mesh_ids = self._f['tallies/meshes/ids'].value
                        mesh_keys = self._f['tallies/meshes/keys'].value

                        key = mesh_keys[mesh_ids == bins][0]
                        new_filter.mesh = self.meshes[key]

                    # Add Filter to the Tally
                    tally.filters.append(new_filter)

                # Read Nuclide bins
                nuclide_names = \
                    self._f['{0}{1}/nuclides'.format(base, tally_key)].value

                # Add all Nuclides to the Tally
                for name in nuclide_names:
                    nuclide = openmc.Nuclide(name.decode().strip())
                    tally.nuclides.append(nuclide)

                scores = self._f['{0}{1}/score_bins'.format(base,
                                                            tally_key)].value
                n_score_bins = self._f['{0}{1}/n_score_bins'.format(
                    base, tally_key)].value

                # Compute and set the filter strides
                for i in range(n_filters):
                    tally_filter = tally.filters[i]
                    tally_filter.stride = n_score_bins * len(nuclide_names)

                    for j in range(i + 1, n_filters):
                        tally_filter.stride *= tally.filters[j].num_bins

                # Read scattering moment order strings (e.g., P3, Y1,2, etc.)
                moments = self._f['{0}{1}/moment_orders'.format(
                    base, tally_key)].value

                # Add the scores to the Tally
                for j, score in enumerate(scores):
                    score = score.decode()

                    # If this is a moment, use generic moment order
                    pattern = r'-n$|-pn$|-yn$'
                    score = re.sub(pattern, '-' + moments[j].decode(), score)

                    tally.scores.append(score)

                # Add Tally to the global dictionary of all Tallies
                tally.sparse = self.sparse
                self._tallies[tally_key] = tally

            self._tallies_read = True

        return self._tallies
예제 #24
0
    def expand(self,
               percent,
               percent_type,
               enrichment=None,
               cross_sections=None):
        """Expand natural element into its naturally-occurring isotopes.

        An optional cross_sections argument or the OPENMC_CROSS_SECTIONS
        environment variable is used to specify a cross_sections.xml file.
        If the cross_sections.xml file is found, the element is expanded only
        into the isotopes/nuclides present in cross_sections.xml. If no
        cross_sections.xml file is found, the element is expanded based on its
        naturally occurring isotopes.

        Parameters
        ----------
        percent : float
            Atom or weight percent
        percent_type : {'ao', 'wo'}
            'ao' for atom percent and 'wo' for weight 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).
        cross_sections : str, optional
            Location of cross_sections.xml file. Default is None.

        Returns
        -------
        isotopes : list
            Naturally-occurring isotopes of the element. Each item of the list
            is a tuple consisting of an openmc.Nuclide instance and the natural
            abundance of the isotope.

        """

        # Get the nuclides present in nature
        natural_nuclides = set()
        for nuclide in sorted(NATURAL_ABUNDANCE.keys()):
            if re.match(r'{}\d+'.format(self.name), nuclide):
                natural_nuclides.add(nuclide)

        # Create dict to store the expanded nuclides and abundances
        abundances = OrderedDict()

        # If cross_sections is None, get the cross sections from the
        # OPENMC_CROSS_SECTIONS environment variable
        if cross_sections is None:
            cross_sections = os.environ.get('OPENMC_CROSS_SECTIONS')

        # If a cross_sections library is present, check natural nuclides
        # against the nuclides in the library
        if cross_sections is not None:

            library_nuclides = set()
            tree = ET.parse(cross_sections)
            root = tree.getroot()
            for child in root:
                nuclide = child.attrib['materials']
                if re.match(r'{}\d+'.format(self.name), nuclide) and \
                   '_m' not in nuclide:
                    library_nuclides.add(nuclide)

            # Get a set of the mutual and absent nuclides. Convert to lists
            # and sort to avoid different ordering between Python 2 and 3.
            mutual_nuclides = natural_nuclides.intersection(library_nuclides)
            absent_nuclides = natural_nuclides.difference(mutual_nuclides)
            mutual_nuclides = sorted(list(mutual_nuclides))
            absent_nuclides = sorted(list(absent_nuclides))

            # If all natural nuclides are present in the library, expand element
            # using all natural nuclides
            if len(absent_nuclides) == 0:
                for nuclide in mutual_nuclides:
                    abundances[nuclide] = NATURAL_ABUNDANCE[nuclide]

            # If no natural elements are present in the library, check if the
            # 0 nuclide is present. If so, set the abundance to 1 for this
            # nuclide. Else, raise an error.
            elif len(mutual_nuclides) == 0:
                nuclide_0 = self.name + '0'
                if nuclide_0 in library_nuclides:
                    abundances[nuclide_0] = 1.0
                else:
                    msg = 'Unable to expand element {0} because the cross '\
                          'section library provided does not contain any of '\
                          'the natural isotopes for that element.'\
                          .format(self.name)
                    raise ValueError(msg)

            # If some, but not all, natural nuclides are in the library, add
            # the mutual nuclides. For the absent nuclides, add them based on
            # our knowledge of the common cross section libraries
            # (ENDF, JEFF, and JENDL)
            else:

                # Add the mutual isotopes
                for nuclide in mutual_nuclides:
                    abundances[nuclide] = NATURAL_ABUNDANCE[nuclide]

                # Adjust the abundances for the absent nuclides
                for nuclide in absent_nuclides:

                    if nuclide in ['O17', 'O18'] and 'O16' in mutual_nuclides:
                        abundances['O16'] += NATURAL_ABUNDANCE[nuclide]
                    elif nuclide == 'Ta180' and 'Ta181' in mutual_nuclides:
                        abundances['Ta181'] += NATURAL_ABUNDANCE[nuclide]
                    elif nuclide == 'W180' and 'W182' in mutual_nuclides:
                        abundances['W182'] += NATURAL_ABUNDANCE[nuclide]
                    else:
                        msg = 'Unsure how to partition natural abundance of ' \
                              'isotope {0} into other natural isotopes of ' \
                              'this element that are present in the cross ' \
                              'section library provided. Consider adding ' \
                              'the isotopes of this element individually.'
                        raise ValueError(msg)

        # If a cross_section library is not present, expand the element into
        # its natural nuclides
        else:
            for nuclide in natural_nuclides:
                abundances[nuclide] = NATURAL_ABUNDANCE[nuclide]

        # Modify mole fractions if enrichment provided
        if enrichment is not None:

            # Calculate the mass fractions of isotopes
            abundances['U234'] = 0.008 * enrichment
            abundances['U235'] = enrichment
            abundances['U238'] = 100.0 - 1.008 * enrichment

            # Convert the mass fractions to mole fractions
            for nuclide in abundances.keys():
                abundances[nuclide] /= atomic_mass(nuclide)

            # Normalize the mole fractions to one
            sum_abundances = sum(abundances.values())
            for nuclide in abundances.keys():
                abundances[nuclide] /= sum_abundances

        # Compute the ratio of the nuclide atomic masses to the element
        # atomic mass
        if percent_type == 'wo':

            # Compute the element atomic mass
            element_am = 0.
            for nuclide in abundances.keys():
                element_am += atomic_mass(nuclide) * abundances[nuclide]

            # Convert the molar fractions to mass fractions
            for nuclide in abundances.keys():
                abundances[nuclide] *= atomic_mass(nuclide) / element_am

            # Normalize the mass fractions to one
            sum_abundances = sum(abundances.values())
            for nuclide in abundances.keys():
                abundances[nuclide] /= sum_abundances

        # Create a list of the isotopes in this element
        isotopes = []
        for nuclide, abundance in abundances.items():
            nuc = openmc.Nuclide(nuclide)
            nuc.scattering = self.scattering
            isotopes.append((nuc, percent * abundance, percent_type))

        return isotopes
예제 #25
0
###############################################################################
#                      Simulation Input File Parameters
###############################################################################

# OpenMC simulation parameters
batches = 500
inactive = 10
particles = 10000


###############################################################################
#                 Exporting to OpenMC materials.xml File
###############################################################################

# Instantiate a Nuclides
u235 = openmc.Nuclide('U-235')

# Instantiate a Material and register the Nuclide
fuel = openmc.Material(material_id=1, name='fuel')
fuel.set_density('g/cc', 4.5)
fuel.add_nuclide(u235, 1.)

# Instantiate a MaterialsFile, register Material, and export to XML
materials_file = openmc.MaterialsFile()
materials_file.default_xs = '71c'
materials_file.add_material(fuel)
materials_file.export_to_xml()


###############################################################################
#                 Exporting to OpenMC geometry.xml File
예제 #26
0
    def tallies(self):
        if self.tallies_present and not self._tallies_read:
            # Read the number of tallies
            tallies_group = self._f['tallies']
            n_tallies = tallies_group.attrs['n_tallies']

            # Read a list of the IDs for each Tally
            if n_tallies > 0:
                # Tally user-defined IDs
                tally_ids = tallies_group.attrs['ids']
            else:
                tally_ids = []

            # Ignore warnings about duplicate IDs
            with warnings.catch_warnings():
                warnings.simplefilter('ignore', openmc.IDWarning)

                # Iterate over all tallies
                for tally_id in tally_ids:
                    group = tallies_group['tally {}'.format(tally_id)]

                    # Check if tally is internal and therefore has no data
                    if group.attrs.get("internal"):
                        continue

                    # Create Tally object and assign basic properties
                    tally = openmc.Tally(tally_id)
                    tally._sp_filename = self._f.filename
                    tally.name = group['name'][(
                    )].decode() if 'name' in group else ''

                    # Read the number of realizations
                    n_realizations = group['n_realizations'][()]

                    tally.estimator = group['estimator'][()].decode()
                    tally.num_realizations = n_realizations

                    # Read derivative information.
                    if 'derivative' in group:
                        deriv_id = group['derivative'][()]
                        tally.derivative = self.tally_derivatives[deriv_id]

                    # Read all filters
                    n_filters = group['n_filters'][()]
                    if n_filters > 0:
                        filter_ids = group['filters'][()]
                        filters_group = self._f['tallies/filters']
                        for filter_id in filter_ids:
                            filter_group = filters_group['filter {}'.format(
                                filter_id)]
                            new_filter = openmc.Filter.from_hdf5(
                                filter_group, meshes=self.meshes)
                            tally.filters.append(new_filter)

                    # Read nuclide bins
                    nuclide_names = group['nuclides'][()]

                    # Add all nuclides to the Tally
                    for name in nuclide_names:
                        nuclide = openmc.Nuclide(name.decode().strip())
                        tally.nuclides.append(nuclide)

                    scores = group['score_bins'][()]
                    n_score_bins = group['n_score_bins'][()]

                    # Add the scores to the Tally
                    for j, score in enumerate(scores):
                        score = score.decode()

                        tally.scores.append(score)

                    # Add Tally to the global dictionary of all Tallies
                    tally.sparse = self.sparse
                    self._tallies[tally_id] = tally

            self._tallies_read = True

        return self._tallies
예제 #27
0
def slab_mg(reps=None, as_macro=True):
    """Create a one-group, 1D slab model.

    Parameters
    ----------
    reps : list, optional
        List of angular representations. Each item corresponds to materials and
        dictates the angular representation of the multi-group cross
        sections---isotropic ('iso') or angle-dependent ('ang'), and if Legendre
        scattering or tabular scattering ('mu') is used. Thus, items can be
        'ang', 'ang_mu', 'iso', or 'iso_mu'.

    as_macro : bool, optional
        Whether :class:`openmc.Macroscopic` is used

    Returns
    -------
    model : openmc.model.Model
        One-group, 1D slab model

    """
    model = openmc.model.Model()

    # Define materials needed for 1D/1G slab problem
    mat_names = ['uo2', 'clad', 'lwtr']
    mgxs_reps = ['ang', 'ang_mu', 'iso', 'iso_mu']

    if reps is None:
        reps = mgxs_reps

    xs = []
    i = 0
    for mat in mat_names:
        for rep in reps:
            i += 1
            if as_macro:
                xs.append(openmc.Macroscopic(mat + '_' + rep))
                m = openmc.Material(name=str(i))
                m.set_density('macro', 1.)
                m.add_macroscopic(xs[-1])
            else:
                xs.append(openmc.Nuclide(mat + '_' + rep))
                m = openmc.Material(name=str(i))
                m.set_density('atom/b-cm', 1.)
                m.add_nuclide(xs[-1].name, 1.0, 'ao')
            model.materials.append(m)

    # Define the materials file
    model.xs_data = xs
    model.materials.cross_sections = "../1d_mgxs.h5"

    # Define surfaces.
    # Assembly/Problem Boundary
    left = openmc.XPlane(x0=0.0, boundary_type='reflective')
    right = openmc.XPlane(x0=10.0, boundary_type='reflective')
    bottom = openmc.YPlane(y0=0.0, boundary_type='reflective')
    top = openmc.YPlane(y0=10.0, boundary_type='reflective')

    # for each material add a plane
    planes = [openmc.ZPlane(z0=0.0, boundary_type='reflective')]
    dz = round(5. / float(len(model.materials)), 4)
    for i in range(len(model.materials) - 1):
        planes.append(openmc.ZPlane(z0=dz * float(i + 1)))
    planes.append(openmc.ZPlane(z0=5.0, boundary_type='reflective'))

    # Define cells for each material
    model.geometry.root_universe = openmc.Universe(name='root universe')
    xy = +left & -right & +bottom & -top
    for i, mat in enumerate(model.materials):
        c = openmc.Cell(fill=mat, region=xy & +planes[i] & -planes[i + 1])
        model.geometry.root_universe.add_cell(c)

    model.settings.batches = 10
    model.settings.inactive = 5
    model.settings.particles = 100
    model.settings.source = openmc.Source(space=openmc.stats.Box(
        [0.0, 0.0, 0.0], [10.0, 10.0, 5.]))
    model.settings.energy_mode = "multi-group"

    plot = openmc.Plot()
    plot.filename = 'mat'
    plot.origin = (5.0, 5.0, 2.5)
    plot.width = (2.5, 2.5)
    plot.basis = 'xz'
    plot.pixels = (3000, 3000)
    plot.color_by = 'material'
    model.plots.append(plot)

    return model