Specifying Materials

Material specification forms a critical part of any analysis system. The OSCAR-5 provides functionality to specify material data required for neutronics calculations, as well as additional data required by other systems (e.g thermal hydraulics). All methods and data objects are contained in the core.material module. The material_library package also contains a number of pre-defined (built-in) materials.

Material Data

A core.material.Material instance is used to represent a composition of isotopes together with additional meta data. An instance can be created using the material.create_material method, for example,

>>> from core import *
>>> m = material.create_material()

The material container has the following parameters:

material.name

: string

!

Descriptive name for the material instance. Although this parameter has no real impact on any sub system, it does help in model visualization and documentation.

material.color

: tuple

Color used to identify the material during model visualization. Tuple of three integers denoting the red green blue (RGB) value of the color. Each integer value must fall between 0 and 255. The utilities.Palette class defines a number of colors. For example,

>>> from core import *
>>> print(utilities.Palette.Blue)
(0, 0, 255)
>>> print(utilities.Palette.DarkGray)
(169, 169, 169)
material.type

: material_tag

= generic

Material types is a mechanism used to conceptually group materials into units that best describe their purpose within a model. Types are also closely tied to the state perturbation mechanism. In particular, whenever a state change is triggered, all materials of the type the state is connected to will be altered. All material types are collected in material.tags. The following table lists available materials types, as well as the state parameters that will trigger a change in the material state.

Tag

Description

State Parameters

fuel

General fissionable material.

fuel_temperature

clad

Fuel cladding material.

clad_temperature

gap

Material filling the gap between clad and fuel.

moderator

Material used to moderate (thermalize) neutrons.

moderator_temperature moderator_density

structural

General structural material.

reflector

Material used to reflect neutrons.

reflector_temperature

control

Material used to absorb (remove) neutrons.

burnable_absorber

Material used to control initial reactivity.

soluble_absorber

Absorber solution.

moderator_temperature moderator_density poison_concentration

void

Very low density material.

moderator_and_structural_mixture

Mixture of moderator and structural materials. Usually used to approximate complex structures.

moderator_temperature moderator_density

self_cooled_channel

Material that will not be affected by core wide state perturbations.

material.temperature

: temperature

= 294 K

The material temperature. This parameter is usually set to some nominal value, but is frequently altered internally.

material.thermal_composition

: string

Sub composition within the material for which additional thermal scattering models are required. This must be one of the composition names defined in the configuration file.

material.thermal_isotope

: isotope

Isotope within the mixture which requires additional thermal scattering treatment.

Attention

If this parameter is set, the system will try to deduce which scattering library to use based on the isotope’s mass. This is not always reliable, since many isotopes occur in multiple thermal compositions. It is recommended to use material.thermal_composition instead.

This parameter is mostly for legacy support, and will likely be removed in future versions.

material.burnable

: bool

= False

Flag indicating if the material must be activated (depleted) during simulations. If False, the material will remain at it’s static composition. This flag is modified internally for materials managed in burnable bundles, but you can use it to flag stand alone materials as burnable.

Note

Burnable materials require material.volume to be set. The system will try to automatically calculate it based on the cells the material fill, but you can also manually specify it. Also, if you flag a material as burnable, make sure that it has a unique material.name.

material.volume

: volume

Volume this material fills. For burnable materials, the system will calculate it automatically. For most other materials, this parameter can be ignored.

Isotopes are added to the material mixture using the following function:

material.add(iso, number_density)

Adds an isotope to the material mixture.

Parameters:
  • iso (isotope) – Isotope to add.

  • number_density – Density of iso in the material. Must have number density dimensions.

Note

If iso has already been added to the mixture, it’s density will be increased by number_density.

Alternatively, the [] method can also be used. For example,

>>> from core import *
>>> m = material.create_material()
>>> m.name = 'MyMaterial'
>>> m.add('B-10', 1.0E-3 * units.number_density)
>>> m['B-11'] = 1.0E-2 * units.number_density
>>> print(m)
Material     : MyMaterial
Type         : generic
Mass density : 0.1994 g/cc
Isotope   Wt                  Nd (1/b/cm)
B-10      8.34      %         1.00000e-03
B-11      91.66     %         1.00000e-02
Total     100.00              1.10000e-02

Using material mixers

If the number density is not known (which is usually the case when building materials from engineering data), the MaterialMassFractionMixer or MaterialAtomicFractionMixer utilities can be used to mix compositions from weight or atomic fractions respectively. Both mixer classes are constructed by passing the total material density. This can be a quantity of either mass, atomic or number density units. Isotopic compositions are then specified using the add method. Finally, a complete material, with isotopic compositions in number densities, are returned using the mix method.

Note

The material returned by the mix method only contains isotopic compositions, so make sure to set some additional meta data (e.g material.name, material.color, material.type etc).

Mixing from mass fractions

material.create_mass_fraction_mixer(density, total=None)

Create a MaterialMassFractionMixer instance.

Parameters:
  • density – Total density of the final material. Usually a quantity with mass density dimensions.

  • total (float) – Value fractions should be normalized to. If None, the fractions will be normalized to their total.

Returns:

mixer

This call returns a MaterialMassFractionMixer instance, which is then used to add isotopes to the composition with the following methods:

mixer.add(iso, part)

Add an isotope to the mixture.

Parameters:
  • iso (isotope) – Isotope to add.

  • part (float) – Mass fraction of iso in the mixture. Fractions can be given either as percentages or fractions.

mixer.add_balance(iso)

Fill the remaining mass with the specified isotope.

Parameters:

iso (isotope) – Isotope to add.

Attention

This function requires that the total keyword was specified during the creation of the mixer.

Finally, a material is created using

mixer.mix()

Creates the material with the correct number densities for each isotope in the mixture.

Returns:

A material instance.

Return type:

material.Material

A typical mass fraction example,

>>> from core import *
>>> mixer = material.create_mass_fraction_mixer(density=2.71 * units.g / units.cc, total=100.0)
>>> mixer.add('Cu', 0.1)
>>> mixer.add('Si', 1.0)
>>> mixer.add_balance('Al-27')
>>> m = mixer.mix()
>>> m.name = 'Al'
>>> m.type = material.tags.structural
>>> print(m)
Material     : Al
Type         : structural
Mass density : 2.7100 g/cc
Isotope   Wt                  Nd (1/b/cm)
Al-27     98.90     %         5.98205e-02
Si-Nat    1.00      %         5.81073e-04
Cu-Nat    0.10      %         2.56822e-05
Total     100.00              6.04272e-02

Mixing from atomic fractions

material.create_atomic_fraction_mixer(density)

Create a MaterialAtomicFractionMixer instance.

Parameters:

density – Total density of the final material. A quantity with either mass, atomic or number density dimensions.

Returns:

mixer

The returned mixer is then used to add isotopes to the composition:

mixer.add(iso, part)

Add an isotope to the mixture.

Parameters:
  • iso (isotope) – Isotope to add.

  • part (float) – Atomic fraction (relative number of atoms) of iso in the mixture.

Finally, a material is created using:

mixer.mix()

Creates the material with the correct number densities for each isotope in the mixture.

Returns:

A material instance.

Return type:

material.Material

A typical atomic fraction example is:

>>> mixer = material.create_atomic_fraction_mixer(density=0.998 * units.g / units.cc)
>>> mixer.add('H-1', 2.0)
>>> mixer.add('O-16', 1.0)
>>> m = mixer.mix()
>>> m.name = 'H2O'
>>> m.type = material.tags.moderator
>>> print(m)
Material     : H2O
Type         : moderator
Mass density : 0.9980 g/cc
Isotope   Wt                  Nd (1/b/cm)
H-1       66.67     %         3.97562e-01
O-16      33.33     %         1.25250e-02
Total     100.00              4.10087e-01

Built-in materials

The material_library package contains a number of predefined materials. They are grouped into separate modules, which is listed in the following sections. Before using these materials in your model, you can check their content using the interpreter. For example:

>>> from material_library.moderators import LightWater
>>> from core.unit import units
>>> lwt = LightWater(pressure=1.8 * units.bar, temperature=20 * units.degC)
>>> print(lwt)
Material     : H2O
Type         : moderator
Mass density : 0.9982 g/cc
Isotope   Wt (%)    Nd (1/b/cm)
H-1       11.19     6.67559e-02
O-16      88.81     3.33779e-02
Total     100.00    1.00134e-01

Note

The material library is currently quite small, but expect it to grow in size and scope as thermal hydraulic modeling is added to the package.

Creating a material library for your model

The material module in the model package is intended to define common materials shared among multiple components. Although you can always build materials globally, the recommended method is to define a method for each material which return a unique instance of that material. The principle is best explained via an example:

from core import *

def al6082(mass_density = 2.71 * units.g / units.cc, color=(105, 105, 105)):
    """
    Aluminium 6082-T6 used in fuel assembly end adapters and other structural components.

    Args:
        mass_density: Material mass density.
        color : Set the material color for display purposes.

    Source:
        RR-FRM-0435 Rev 0.1

    Notes:
        - Missing mass fraction of 0.15% in composition
    """

    mixer = core.material.create_mass_fraction_mixer(mass_density,
                                                    total=100.0  # avoid auto re-normalization
                                                    )

    mixer.add('Al-27', 96.1)
    mixer.add('Cu-Nat', 0.1)
    mixer.add('Cr-Nat', 0.25)
    mixer.add('Mg-Nat', 0.9)
    mixer.add('Si-Nat', 1.0)
    mixer.add('Fe-Nat', 0.5)
    mixer.add('Mn-Nat', 0.7)
    mixer.add('Ti-Nat', 0.1)
    mixer.add('Zn-Nat', 0.2)

    m = mixer.mix()

    # Store additional meta data
    m.color = color
    m.type = material.tags.structural

    m.name = 'Al6082'

    m.__version__ = '2.0.0'
    m.__source__ = 'RR-FRM-0435 Rev 0.1'

    return m

In the above example the al6082 method returns an Al-6082 material instance. It accepts two arguments, the mass_density and color, with defaults 2.71 * units.g / units.cc and (105, 105, 105) respectively. Thus, the call al6082() will return an instance at the default density, and al6082(mass_density=2.8 * units.g / units.cc) at a modified density.

The comment block (delimited by opening and closing """) following the method declaration is a standard python document string, describing the method’s function, arguments, and any other information pertinent to the material. This information is useful for other users, and will be used by the documentation utility when creating model documentation.

The body of the method contains the material construction. Note how additional meta data is specified in the material returned by the mixer. Finally, the material is returned using the return statement.

Note

The arguments passed to a material build method frequently contain a density value. However, many fueled material specifications are given in terms of total mass. In this case, in order to calculate a density, a volume must also be passed. For example:

from core import *

def uranium_silicide(mass=17.89 * units.g,
               plate_volume=6.417*59.37*0.051 * units.cc,
               color=(244, 202, 22)):
    """
    Nominal meat specification for fresh LEU fuel plates

    Args:
        mass: Total plate U-235 mass
        plate_volume: Target plate volume
        color: Set the material color for display purposes

    """

    enrichment = 0.1975
    heavy_metal_fraction = 0.786

    # U-235 mass / fraction of U-235 / total volume
    mass_density = mass / (heavy_metal_fraction * enrichment) / plate_volume

    mixer = core.material.create_mass_fraction_mixer(mass_density)

    # Composition (mass fractions in %)
    mixer.add('U-235', 19.75 * heavy_metal_fraction)
    mixer.add('U-234', 0.24 * heavy_metal_fraction)
    mixer.add('U-236', 0.10 * heavy_metal_fraction)
    mixer.add('U-238', 79.91 * heavy_metal_fraction)

    mixer.add('Si-Nat', 6.4)
    mixer.add('Al-27', 15.0)

    m = mixer.mix()

    # Store additional meta data
    m.color = color
    m.type = material.tags.fuel

    m.name = 'U3Si-Al'
    m.__version__ = '2.0.0'
    m.__source__ = 'RR-FRM-0435 Rev 0.1'

    return m