5. Materials and Cross-Section Data
In OpenSn, a “material” is represented by assigning a multi-group cross-section object to one or more mesh block ids. The two main elements are:
a
pyopensn.xs.MultiGroupXSobject containing the macroscopic cross-section data, andan
xs_mapentry that associates that object with a list ofblock_ids.
This section describes how to create and load cross-section data, how block id mapping works in transport inputs, how OpenMC and native OpenSn cross-section files are used, and how cross sections can be combined and inspected from Python.
5.1. Overview
The Python MuliGroupXS API has the following methods:
The most common workflow is:
Create or load one or more
pyopensn.xs.MultiGroupXSobjects.Assign them to mesh block ids with
xs_map.Pass that mapping directly to a transport problem, or update the problem
later using
pyopensn.solver.LBSProblem.SetXSMap().
Note
OpenSn’s Python interface works with macroscopic multi-group cross sections. If you combine two cross sections, the resulting object is another macroscopic cross section with density-weighted data.
5.2. Materials, Block IDs, and xs_map
Mesh cells in OpenSn carry integer block ids. The transport problem uses those block ids to decide which cross section applies in each cell.
Each entry in xs_map is a dictionary with:
block_ids: a list of mesh block idsxs: apyopensn.xs.MultiGroupXSobject
Example:
from pyopensn.mesh import OrthogonalMeshGenerator
from pyopensn.xs import MultiGroupXS
from pyopensn.aquad import GLCProductQuadrature2DXY
from pyopensn.solver import DiscreteOrdinatesProblem
meshgen = OrthogonalMeshGenerator(node_sets=[[0.0, 1.0, 2.0], [0.0, 1.0]])
grid = meshgen.Execute()
# Sets the block id for each cell to 0
grid.SetUniformBlockID(0)
xs_fuel = MultiGroupXS()
xs_fuel.CreateSimpleOneGroup(sigma_t=1.0, c=0.7, velocity=1.0)
problem = DiscreteOrdinatesProblem(
mesh=grid,
num_groups=1,
groupsets=[
{
"groups_from_to": (0, 0),
"angular_quadrature": GLCProductQuadrature2DXY(
n_polar=2,
n_azimuthal=4,
scattering_order=0,
),
},
],
xs_map=[
{"block_ids": [0], "xs": xs_fuel},
],
)
If multiple block ids should use the same material, put them in the same
block_ids list:
xs_map = [
{"block_ids": [0, 3, 7], "xs": xs_fuel},
]
If you need to replace the material assignment after problem construction, use
pyopensn.solver.LBSProblem.SetXSMap() with the same xs_map
structure.
Note
block_ids are mesh labels, not material names. A common and simple
pattern is to assign one block id per material region when building the
mesh, then map each region to its corresponding
pyopensn.xs.MultiGroupXS object.
5.3. Creating a Simple One-Group Cross Section
For small tests, manufactured problems, and simple transients,
pyopensn.xs.MultiGroupXS.CreateSimpleOneGroup() is the quickest way to
build a cross section.
from pyopensn.xs import MultiGroupXS
xs = MultiGroupXS()
xs.CreateSimpleOneGroup(sigma_t=1.0, c=0.8, velocity=2.0)
This creates a one-group material with:
sigma_t = 1.0isotropic within-group scattering ratio
c = 0.8absorption implied by
sigma_a = sigma_t * (1 - c)inverse velocity populated from
1 / velocitywhenvelocity > 0
This method is intentionally minimal. It is useful when you want a small, explicit test problem without maintaining a cross-section file.
5.4. Inspecting a MultiGroupXS Object
The following properties and methods are available from Python for inspecting cross section data:
num_groupsscattering_ordernum_precursorsis_fissionableGetScaleFactor()sigma_tsigma_asigma_fchinu_sigma_fnu_prompt_sigma_fnu_delayed_sigma_finv_velocityhas_custom_xs(name)get_custom_xs(name)custom_xs_names()
Example:
print(xs.num_groups)
print(xs.sigma_t)
print(xs.inv_velocity)
Note
The Python getters expose the data that the solver will actually use. This
makes them useful both for debugging file imports and for checking the
results of operations such as pyopensn.xs.MultiGroupXS.Combine() and
pyopensn.xs.MultiGroupXS.Scale().
5.5. Loading OpenSn Cross-Section Files
Use pyopensn.xs.MultiGroupXS.LoadFromOpenSn() to load OpenSn’s native
text cross-section format:
xs = MultiGroupXS()
xs.LoadFromOpenSn("fuel.cxs")
This is often the most convenient format when:
you want a small, readable input file under version control,
you are defining benchmark or regression materials by hand, or
you want direct control over prompt and delayed fission data.
Note
The native OpenSn format is the best choice when you want an input file that can be edited and reviewed directly. OpenMC MGXS files are better when the data already exists in an HDF5 library and should be imported as-is.
5.5.1. Minimal OpenSn Format
At minimum, an OpenSn cross-section file defines the number of groups and one or more group-dependent cross sections. A small one-group example looks like:
NUM_GROUPS 1
NUM_MOMENTS 1
SIGMA_T_BEGIN
0 1.0
SIGMA_T_END
SIGMA_A_BEGIN
0 0.2
SIGMA_A_END
TRANSFER_MOMENTS_BEGIN
M_GFROM_GTO_VAL 0 0 0 0.8
TRANSFER_MOMENTS_END
For most transport materials, the most important top-level sections are:
NUM_GROUPSNUM_MOMENTSGROUP_STRUCTURE_BEGIN…GROUP_STRUCTURE_END(optional)SIGMA_T_BEGIN…SIGMA_T_ENDSIGMA_A_BEGIN…SIGMA_A_END(optional)TRANSFER_MOMENTS_BEGIN…TRANSFER_MOMENTS_END(optional)INV_VELOCITY_BEGIN…INV_VELOCITY_ENDorVELOCITY_BEGIN…VELOCITY_END(optional)
Important details:
NUM_MOMENTSis the number of scattering moments, not the maximum Legendre order. For example,NUM_MOMENTS 1means isotropic scattering only.If
SIGMA_Ais omitted, OpenSn will infer absorption from the total cross section and the zeroth transfer matrix when possible.The transfer matrix entries use
M_GFROM_GTO_VAL moment g_from g_to value.
Note
A practical rule is to keep the native file explicit when possible. Even if OpenSn can infer some quantities, files that provide the intended data directly are easier to review and less ambiguous.
5.5.2. Fission Data in OpenSn Files
For fissionable materials, OpenSn supports two main styles of input.
For prompt-only or steady-state fission data, the usual path is:
SIGMA_Feither
NUwithCHI, orNU_SIGMA_Ftogether with enough data to infer the remaining quantities
For delayed-neutron problems, the file may additionally provide:
NUM_PRECURSORSNU_PROMPTNU_DELAYEDCHI_PROMPTCHI_DELAYEDPRECURSOR_DECAY_CONSTANTSPRECURSOR_FRACTIONAL_YIELDS
OpenSn also supports an alternative PRODUCTION_MATRIX representation for
fission production. This is useful for advanced data preparation, but most user
inputs are clearer when written in terms of SIGMA_F, NU or
NU_PROMPT/NU_DELAYED, and the corresponding spectra.
5.6. Loading OpenMC MGXS Files
Use pyopensn.xs.MultiGroupXS.LoadFromOpenMC() to load cross sections
from an OpenMC multi-group HDF5 library.
xs_uo2 = MultiGroupXS()
xs_uo2.LoadFromOpenMC(
file_name="mgxs.h5",
dataset_name="set1",
temperature=294.0,
)
Parameters:
file_name: the OpenMC MGXS HDF5 filedataset_name: the material or dataset group to loadtemperature: the requested temperature in kelvinextra_xs_names: an optional list of additional named one-dimensional datasets to import as custom XS
Example:
xs_hdpe = MultiGroupXS()
xs_hdpe.LoadFromOpenMC(
file_name="HDPE.h5",
dataset_name="set1",
temperature=294.0,
extra_xs_names=["absorption"],
)
Note
When importing from OpenMC, OpenSn recomputes absorption from the imported total cross section and transfer matrix rather than trusting the OpenMC absorption dataset directly. This makes the imported data less sensitive to small inconsistencies or statistical noise.
5.6.1. What OpenMC Import Expects
The Python interface expects an OpenMC MGXS HDF5 file with:
filetype = "mgxs"a dataset group matching
dataset_namea temperature subgroup such as
294K
The imported object may include:
total cross section
transfer matrices
inverse velocity
fission cross section
fission production data
fission spectrum
any requested named custom one-dimensional XS in
extra_xs_names
If the requested dataset or temperature is not present, the load fails with an error.
5.7. Custom Cross Sections
OpenSn’s Python API supports named custom one-dimensional cross sections through OpenMC import. These are useful when a dataset should be carried alongside the standard transport data for later inspection, combination, scaling, or use in derived field functions.
Load them by name with extra_xs_names:
xs = MultiGroupXS()
xs.LoadFromOpenMC(
"HDPE.h5",
"set1",
294.0,
extra_xs_names=["absorption", "heating"],
)
Inspect them with:
print(xs.custom_xs_names())
print(xs.has_custom_xs("heating"))
print(xs.get_custom_xs("heating"))
Important behavior:
custom XS are stored as named one-dimensional vectors
they are preserved by
pyopensn.xs.MultiGroupXS.Combine()they are scaled by
pyopensn.xs.MultiGroupXS.Scale()
Note
The Python API currently supports loading and reading custom XS, but it does not expose a direct Python method for creating or modifying custom XS entries by hand. In practice, custom XS are an import-and-use feature rather than a full custom-data authoring interface.
5.8. Combining Cross Sections
Use pyopensn.xs.MultiGroupXS.Combine() to build a new cross section by
combining existing ones with density weights.
xs_1 = MultiGroupXS()
xs_1.CreateSimpleOneGroup(sigma_t=1.0, c=0.5)
xs_2 = MultiGroupXS()
xs_2.CreateSimpleOneGroup(sigma_t=2.0, c=1.0 / 3.0)
xs_mix = MultiGroupXS.Combine([
(xs_1, 0.5),
(xs_2, 3.0),
])
Combine returns a new pyopensn.xs.MultiGroupXS object and does
not modify its inputs.
Combination semantics are:
standard one-dimensional XS such as total, absorption, and fission are added with the supplied densities as linear weights
transfer matrices are combined with the same density weighting
custom one-dimensional XS are combined with the same density weighting
fission spectra and precursor fractional yields are weighted so that they remain normalized in the combined material
Important restrictions:
all inputs must have the same number of groups
if inverse velocity is present, all inputs must have the same group-wise inverse velocity
Note
Combine is intended for macroscopic mixing. The density values are
weights in the macroscopic combination formula, not a request to renormalize
the final material back to unit density.
Combining is often useful in transient tests where a composite material needs to be built from two pre-existing macroscopic states.
5.9. Scaling Cross Sections
Use pyopensn.xs.MultiGroupXS.Scale() to scale the current cross
section in place:
xs.Scale(2.5)
Important behavior:
scaling does not compound
each call rescales from the original baseline data
named custom XS are scaled together with the standard one-dimensional XS
The current factor can be queried with GetScaleFactor().
Note
Non-compounding scaling is deliberate. It makes repeated parameter studies
easier because Scale(0.5) followed later by Scale(2.0) means “scale
relative to the original material” each time, not “multiply the current
state again.”
5.10. Choosing Between OpenSn and OpenMC Inputs
As a practical guideline:
use
pyopensn.xs.MultiGroupXS.CreateSimpleOneGroup()for very small analytic or regression-style problemsuse
pyopensn.xs.MultiGroupXS.LoadFromOpenSn()when you want a small, readable, hand-maintained transport fileuse
pyopensn.xs.MultiGroupXS.LoadFromOpenMC()when the source data already exists in an OpenMC MGXS libraryuse
pyopensn.xs.MultiGroupXS.Combine()when you need a new macroscopic material formed from existing macroscopic materials
5.11. Practical Example
The following example shows a common pattern with two materials and two mesh regions:
from pyopensn.xs import MultiGroupXS
from pyopensn.aquad import GLCProductQuadrature2DXY
from pyopensn.solver import DiscreteOrdinatesProblem
# Assume the mesh already has block ids 0 and 1 on its cells.
grid = ...
xs_air = MultiGroupXS()
xs_air.LoadFromOpenSn("Air.cxs")
xs_poly = MultiGroupXS()
xs_poly.LoadFromOpenMC("HDPE.h5", "set1", 294.0, extra_xs_names=["absorption"])
problem = DiscreteOrdinatesProblem(
mesh=grid,
num_groups=xs_air.num_groups,
groupsets=[
{
"groups_from_to": (0, xs_air.num_groups - 1),
"angular_quadrature": GLCProductQuadrature2DXY(
n_polar=2,
n_azimuthal=4,
scattering_order=1,
),
},
],
xs_map=[
{"block_ids": [0], "xs": xs_air},
{"block_ids": [1], "xs": xs_poly},
],
)
This pattern covers most transport inputs:
each material region gets a block id
each block id is mapped to a
pyopensn.xs.MultiGroupXSthe cross sections can come from either OpenSn files, OpenMC libraries, or a combined/simple source
5.12. Cautions and Best Practices
Reuse the same
pyopensn.xs.MultiGroupXSobject for multiple block ids when the material is truly identical.Use distinct objects when materials will be changed independently later with
pyopensn.solver.LBSProblem.SetXSMap().Keep the number of groups, scattering order, and fission model consistent with the solver setup.
When combining cross sections, ensure that group-wise inverse velocities match exactly if they are present.
When importing from OpenMC, request only the extra named datasets that you actually need as custom XS.
Note
MultiGroupXS objects are mutable Python handles to shared C++ objects.
If the same object is reused in multiple places, later mutation of that
object affects every place that shares it.