MGXS Part II: Advanced FeaturesΒΆ

mgxs-part-ii

This IPython Notebook illustrates the use of the openmc.mgxs module to calculate multi-group cross sections for a heterogeneous fuel pin cell geometry. In particular, this Notebook illustrates the following features:

  • Creation of multi-group cross sections on a heterogeneous geometry
  • Calculation of cross sections on a nuclide-by-nuclide basis
  • The use of tally precision triggers with multi-group cross sections
  • Built-in features for energy condensation in downstream data processing
  • The use of PyNE to plot continuous-energy vs. multi-group cross sections
  • Validation of multi-group cross sections with OpenMOC

Note: This Notebook was created using OpenMOC to verify the multi-group cross-sections generated by OpenMC. In order to run this Notebook in its entirety, you must have OpenMOC installed on your system, along with OpenCG to convert the OpenMC geometries into OpenMOC geometries. In addition, this Notebook illustrates the use of Pandas DataFrames to containerize multi-group cross section data.

Generate Input Files

In [1]:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

import openmc
import openmc.mgxs as mgxs
import openmoc
from openmoc.opencg_compatible import get_openmoc_geometry
import pyne.ace

%matplotlib inline
/usr/local/lib/python2.7/dist-packages/matplotlib-1.5.1+1178.ga40c9ec-py2.7-linux-x86_64.egg/matplotlib/__init__.py:884: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
/usr/local/lib/python2.7/dist-packages/matplotlib-1.5.1+1178.ga40c9ec-py2.7-linux-x86_64.egg/matplotlib/__init__.py:1362: UserWarning:  This call to matplotlib.use() has no effect
because the backend has already been chosen;
matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.

  warnings.warn(_use_error_msg)
/usr/local/lib/python2.7/dist-packages/IPython/kernel/__main__.py:9: QAWarning: pyne.rxname is not yet QA compliant.
/usr/local/lib/python2.7/dist-packages/IPython/kernel/__main__.py:9: QAWarning: pyne.ace is not yet QA compliant.

First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material.

In [2]:
# Instantiate some Nuclides
h1 = openmc.Nuclide('H-1')
o16 = openmc.Nuclide('O-16')
u235 = openmc.Nuclide('U-235')
u238 = openmc.Nuclide('U-238')
zr90 = openmc.Nuclide('Zr-90')

With the nuclides we defined, we will now create three distinct materials for water, clad and fuel.

In [3]:
# 1.6% enriched fuel
fuel = openmc.Material(name='1.6% Fuel')
fuel.set_density('g/cm3', 10.31341)
fuel.add_nuclide(u235, 3.7503e-4)
fuel.add_nuclide(u238, 2.2625e-2)
fuel.add_nuclide(o16, 4.6007e-2)

# borated water
water = openmc.Material(name='Borated Water')
water.set_density('g/cm3', 0.740582)
water.add_nuclide(h1, 4.9457e-2)
water.add_nuclide(o16, 2.4732e-2)

# zircaloy
zircaloy = openmc.Material(name='Zircaloy')
zircaloy.set_density('g/cm3', 6.55)
zircaloy.add_nuclide(zr90, 7.2758e-3)

With our materials, we can now create a Materials object that can be exported to an actual XML file.

In [4]:
# Instantiate a Materials collection
materials_file = openmc.Materials((fuel, water, zircaloy))
materials_file.default_xs = '71c'

# Export to "materials.xml"
materials_file.export_to_xml()

Now let's move on to the geometry. Our problem will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces -- in this case two cylinders and six reflective planes.

In [5]:
# Create cylinders for the fuel and clad
fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218)
clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720)

# Create boundary planes to surround the geometry
min_x = openmc.XPlane(x0=-0.63, boundary_type='reflective')
max_x = openmc.XPlane(x0=+0.63, boundary_type='reflective')
min_y = openmc.YPlane(y0=-0.63, boundary_type='reflective')
max_y = openmc.YPlane(y0=+0.63, boundary_type='reflective')
min_z = openmc.ZPlane(z0=-0.63, boundary_type='reflective')
max_z = openmc.ZPlane(z0=+0.63, boundary_type='reflective')

With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces.

In [6]:
# Create a Universe to encapsulate a fuel pin
pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin')

# Create fuel Cell
fuel_cell = openmc.Cell(name='1.6% Fuel')
fuel_cell.fill = fuel
fuel_cell.region = -fuel_outer_radius
pin_cell_universe.add_cell(fuel_cell)

# Create a clad Cell
clad_cell = openmc.Cell(name='1.6% Clad')
clad_cell.fill = zircaloy
clad_cell.region = +fuel_outer_radius & -clad_outer_radius
pin_cell_universe.add_cell(clad_cell)

# Create a moderator Cell
moderator_cell = openmc.Cell(name='1.6% Moderator')
moderator_cell.fill = water
moderator_cell.region = +clad_outer_radius
pin_cell_universe.add_cell(moderator_cell)

OpenMC requires that there is a "root" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe.

In [7]:
# Create root Cell
root_cell = openmc.Cell(name='root cell')
root_cell.region = +min_x & -max_x & +min_y & -max_y
root_cell.fill = pin_cell_universe

# Create root Universe
root_universe = openmc.Universe(universe_id=0, name='root universe')
root_universe.add_cell(root_cell)

We now must create a geometry that is assigned a root universe and export it to XML.

In [8]:
# Create Geometry and set root Universe
openmc_geometry = openmc.Geometry()
openmc_geometry.root_universe = root_universe

# Export to "geometry.xml"
openmc_geometry.export_to_xml()

Next, we must define simulation parameters. In this case, we will use 10 inactive batches and 190 active batches each with 10,000 particles.

In [9]:
# OpenMC simulation parameters
batches = 50
inactive = 10
particles = 10000

# Instantiate a Settings object
settings_file = openmc.Settings()
settings_file.batches = batches
settings_file.inactive = inactive
settings_file.particles = particles
settings_file.output = {'tallies': True}

# Create an initial uniform spatial source distribution over fissionable zones
bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]
uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)
settings_file.source = openmc.source.Source(space=uniform_dist)

# Activate tally precision triggers
settings_file.trigger_active = True
settings_file.trigger_max_batches = settings_file.batches * 4

# Export to "settings.xml"
settings_file.export_to_xml()

Now we are finally ready to make use of the openmc.mgxs module to generate multi-group cross sections! First, let's define "coarse" 2-group and "fine" 8-group structures using the built-in EnergyGroups class.

In [10]:
# Instantiate a "coarse" 2-group EnergyGroups object
coarse_groups = mgxs.EnergyGroups()
coarse_groups.group_edges = np.array([0., 0.625e-6, 20.])

# Instantiate a "fine" 8-group EnergyGroups object
fine_groups = mgxs.EnergyGroups()
fine_groups.group_edges = np.array([0., 0.058e-6, 0.14e-6, 0.28e-6,
                                    0.625e-6, 4.e-6, 5.53e-3, 821.e-3, 20.])

Now we will instantiate a variety of MGXS objects needed to run an OpenMOC simulation to verify the accuracy of our cross sections. In particular, we define transport, fission, nu-fission, nu-scatter and chi cross sections for each of the three cells in the fuel pin with the 8-group structure as our energy groups.

In [11]:
# Extract all Cells filled by Materials
openmc_cells = openmc_geometry.get_all_material_cells()

# Create dictionary to store multi-group cross sections for all cells
xs_library = {}

# Instantiate 8-group cross sections for each cell
for cell in openmc_cells:
    xs_library[cell.id] = {}
    xs_library[cell.id]['transport']  = mgxs.TransportXS(groups=fine_groups)
    xs_library[cell.id]['fission'] = mgxs.FissionXS(groups=fine_groups)
    xs_library[cell.id]['nu-fission'] = mgxs.NuFissionXS(groups=fine_groups)
    xs_library[cell.id]['nu-scatter'] = mgxs.NuScatterMatrixXS(groups=fine_groups)
    xs_library[cell.id]['chi'] = mgxs.Chi(groups=fine_groups)

Next, we showcase the use of OpenMC's tally precision trigger feature in conjunction with the openmc.mgxs module. In particular, we will assign a tally trigger of 1E-2 on the standard deviation for each of the tallies used to compute multi-group cross sections.

In [12]:
# Create a tally trigger for +/- 0.01 on each tally used to compute the multi-group cross sections
tally_trigger = openmc.Trigger('std_dev', 1E-2)

# Add the tally trigger to each of the multi-group cross section tallies
for cell in openmc_cells:
    for mgxs_type in xs_library[cell.id]:
        xs_library[cell.id][mgxs_type].tally_trigger = tally_trigger

Now, we must loop over all cells to set the cross section domains to the various cells - fuel, clad and moderator - included in the geometry. In addition, we will set each cross section to tally cross sections on a per-nuclide basis through the use of the MGXS class' boolean by_nuclide instance attribute.

In [13]:
# Instantiate an empty Tallies object
tallies_file = openmc.Tallies()

# Iterate over all cells and cross section types
for cell in openmc_cells:
    for rxn_type in xs_library[cell.id]:

        # Set the cross sections domain to the cell
        xs_library[cell.id][rxn_type].domain = cell
        
        # Tally cross sections by nuclide
        xs_library[cell.id][rxn_type].by_nuclide = True
                
        # Add OpenMC tallies to the tallies file for XML generation
        for tally in xs_library[cell.id][rxn_type].tallies.values():
            tallies_file.append(tally, merge=True)

# Export to "tallies.xml"
tallies_file.export_to_xml()

Now we a have a complete set of inputs, so we can go ahead and run our simulation.

In [14]:
# Run OpenMC
openmc.run(output=True)
       .d88888b.                             888b     d888  .d8888b.
      d88P" "Y88b                            8888b   d8888 d88P  Y88b
      888     888                            88888b.d88888 888    888
      888     888 88888b.   .d88b.  88888b.  888Y88888P888 888       
      888     888 888 "88b d8P  Y8b 888 "88b 888 Y888P 888 888       
      888     888 888  888 88888888 888  888 888  Y8P  888 888    888
      Y88b. .d88P 888 d88P Y8b.     888  888 888   "   888 Y88b  d88P
       "Y88888P"  88888P"   "Y8888  888  888 888       888  "Y8888P"
__________________888______________________________________________________
                  888
                  888

      Copyright:      2011-2016 Massachusetts Institute of Technology
      License:        http://openmc.readthedocs.io/en/latest/license.html
      Version:        0.7.1
      Git SHA1:       19feb55e6d5e8350398627f39fb55ee8e2e63011
      Date/Time:      2016-05-13 10:13:48
      MPI Processes:  1

 ===========================================================================
 ========================>     INITIALIZATION     <=========================
 ===========================================================================

 Reading settings XML file...
 Reading cross sections XML file...
 Reading geometry XML file...
 Reading materials XML file...
 Reading tallies XML file...
 Building neighboring cells lists for each surface...
 Loading ACE cross section table: 92235.71c
 Loading ACE cross section table: 92238.71c
 Loading ACE cross section table: 8016.71c
 Loading ACE cross section table: 1001.71c
 Loading ACE cross section table: 40090.71c
 Maximum neutron transport energy: 20.0000 MeV for 92235.71c
 Initializing source particles...

 ===========================================================================
 ====================>     K EIGENVALUE SIMULATION     <====================
 ===========================================================================

  Bat./Gen.      k            Average k         
  =========   ========   ====================   
        1/1    1.20332                       
        2/1    1.22209                       
        3/1    1.24309                       
        4/1    1.22833                       
        5/1    1.21786                       
        6/1    1.22005                       
        7/1    1.20894                       
        8/1    1.22071                       
        9/1    1.21279                       
       10/1    1.22198                       
       11/1    1.22287                       
       12/1    1.25490    1.23888 +/- 0.01602
       13/1    1.20224    1.22667 +/- 0.01532
       14/1    1.23375    1.22844 +/- 0.01098
       15/1    1.23068    1.22889 +/- 0.00851
       16/1    1.23073    1.22920 +/- 0.00696
       17/1    1.25364    1.23269 +/- 0.00684
       18/1    1.20820    1.22963 +/- 0.00667
       19/1    1.23138    1.22982 +/- 0.00588
       20/1    1.20682    1.22752 +/- 0.00574
       21/1    1.23580    1.22827 +/- 0.00525
       22/1    1.24190    1.22941 +/- 0.00492
       23/1    1.23125    1.22955 +/- 0.00453
       24/1    1.21606    1.22859 +/- 0.00430
       25/1    1.23653    1.22912 +/- 0.00404
       26/1    1.23850    1.22970 +/- 0.00383
       27/1    1.20986    1.22853 +/- 0.00378
       28/1    1.25277    1.22988 +/- 0.00381
       29/1    1.23334    1.23006 +/- 0.00361
       30/1    1.24345    1.23073 +/- 0.00349
       31/1    1.21565    1.23001 +/- 0.00339
       32/1    1.20555    1.22890 +/- 0.00342
       33/1    1.22995    1.22895 +/- 0.00327
       34/1    1.19763    1.22764 +/- 0.00339
       35/1    1.22645    1.22760 +/- 0.00325
       36/1    1.23900    1.22803 +/- 0.00316
       37/1    1.24305    1.22859 +/- 0.00309
       38/1    1.22484    1.22846 +/- 0.00298
       39/1    1.20986    1.22782 +/- 0.00294
       40/1    1.23764    1.22814 +/- 0.00286
       41/1    1.20476    1.22739 +/- 0.00287
       42/1    1.21652    1.22705 +/- 0.00280
       43/1    1.21279    1.22662 +/- 0.00275
       44/1    1.20210    1.22590 +/- 0.00276
       45/1    1.22644    1.22591 +/- 0.00268
       46/1    1.22907    1.22600 +/- 0.00261
       47/1    1.24057    1.22639 +/- 0.00257
       48/1    1.21610    1.22612 +/- 0.00251
       49/1    1.22199    1.22602 +/- 0.00245
       50/1    1.20860    1.22558 +/- 0.00243
 Triggers unsatisfied, max unc./thresh. is 1.25496 for flux in tally 10051
 The estimated number of batches is 73
 Creating state point statepoint.050.h5...
       51/1    1.21850    1.22541 +/- 0.00237
       52/1    1.22833    1.22548 +/- 0.00232
       53/1    1.20239    1.22494 +/- 0.00233
       54/1    1.24876    1.22548 +/- 0.00234
       55/1    1.20670    1.22506 +/- 0.00232
       56/1    1.24260    1.22545 +/- 0.00230
       57/1    1.21039    1.22512 +/- 0.00228
       58/1    1.23929    1.22542 +/- 0.00225
       59/1    1.21357    1.22518 +/- 0.00221
       60/1    1.23456    1.22537 +/- 0.00218
       61/1    1.23963    1.22565 +/- 0.00215
       62/1    1.24020    1.22593 +/- 0.00213
       63/1    1.22325    1.22587 +/- 0.00209
       64/1    1.22070    1.22578 +/- 0.00205
       65/1    1.22423    1.22575 +/- 0.00201
       66/1    1.22973    1.22582 +/- 0.00198
       67/1    1.21842    1.22569 +/- 0.00195
       68/1    1.19552    1.22517 +/- 0.00198
       69/1    1.21475    1.22500 +/- 0.00196
       70/1    1.21888    1.22489 +/- 0.00193
       71/1    1.19720    1.22444 +/- 0.00195
       72/1    1.23770    1.22465 +/- 0.00193
       73/1    1.23894    1.22488 +/- 0.00191
 Triggers unsatisfied, max unc./thresh. is 1.00243 for flux in tally 10051
 The estimated number of batches is 74
       74/1    1.22437    1.22487 +/- 0.00188
 Triggers satisfied for batch 74
 Creating state point statepoint.074.h5...

 ===========================================================================
 ======================>     SIMULATION FINISHED     <======================
 ===========================================================================


 =======================>     TIMING STATISTICS     <=======================

 Total time for initialization     =  5.7400E-01 seconds
   Reading cross sections          =  1.2600E-01 seconds
 Total time in simulation          =  2.6256E+02 seconds
   Time in transport only          =  2.6250E+02 seconds
   Time in inactive batches        =  2.2890E+01 seconds
   Time in active batches          =  2.3967E+02 seconds
   Time synchronizing fission bank =  3.4000E-02 seconds
     Sampling source sites         =  2.1000E-02 seconds
     SEND/RECV source sites        =  1.3000E-02 seconds
   Time accumulating tallies       =  0.0000E+00 seconds
 Total time for finalization       =  1.3000E-02 seconds
 Total time elapsed                =  2.6320E+02 seconds
 Calculation Rate (inactive)       =  4368.72 neutrons/second
 Calculation Rate (active)         =  1668.93 neutrons/second

 ============================>     RESULTS     <============================

 k-effective (Collision)     =  1.22358 +/-  0.00179
 k-effective (Track-length)  =  1.22487 +/-  0.00188
 k-effective (Absorption)    =  1.22300 +/-  0.00114
 Combined k-effective        =  1.22347 +/-  0.00106
 Leakage Fraction            =  0.00000 +/-  0.00000

Out[14]:
0

Tally Data Processing

Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a StatePoint object.

In [15]:
# Load the last statepoint file
sp = openmc.StatePoint('statepoint.074.h5')

The statepoint is now ready to be analyzed by our multi-group cross sections. We simply have to load the tallies from the StatePoint into each object as follows and our MGXS objects will compute the cross sections for us under-the-hood.

In [16]:
# Iterate over all cells and cross section types
for cell in openmc_cells:
    for rxn_type in xs_library[cell.id]:
        xs_library[cell.id][rxn_type].load_from_statepoint(sp)

That's it! Our multi-group cross sections are now ready for the big spotlight. This time we have cross sections in three distinct spatial zones - fuel, clad and moderator - on a per-nuclide basis.

Extracting and Storing MGXS Data

Let's first inspect one of our cross sections by printing it to the screen as a microscopic cross section in units of barns.

In [17]:
nufission = xs_library[fuel_cell.id]['nu-fission']
nufission.print_xs(xs_type='micro', nuclides=['U-235', 'U-238'])
Multi-Group XS
	Reaction Type  =	nu-fission
	Domain Type    =	cell
	Domain ID      =	10000
	Nuclide        =	U-235
	Cross Sections [barns]:
            Group 1 [0.821      - 20.0      MeV]:	3.30e+00 +/- 2.19e-01%
            Group 2 [0.00553    - 0.821     MeV]:	3.96e+00 +/- 1.32e-01%
            Group 3 [4e-06      - 0.00553   MeV]:	5.52e+01 +/- 2.31e-01%
            Group 4 [6.25e-07   - 4e-06     MeV]:	8.83e+01 +/- 2.96e-01%
            Group 5 [2.8e-07    - 6.25e-07  MeV]:	2.90e+02 +/- 4.64e-01%
            Group 6 [1.4e-07    - 2.8e-07   MeV]:	4.49e+02 +/- 4.22e-01%
            Group 7 [5.8e-08    - 1.4e-07   MeV]:	6.87e+02 +/- 2.97e-01%
            Group 8 [0.0        - 5.8e-08   MeV]:	1.44e+03 +/- 2.91e-01%

	Nuclide        =	U-238
	Cross Sections [barns]:
            Group 1 [0.821      - 20.0      MeV]:	1.06e+00 +/- 2.56e-01%
            Group 2 [0.00553    - 0.821     MeV]:	1.21e-03 +/- 2.55e-01%
            Group 3 [4e-06      - 0.00553   MeV]:	5.77e-04 +/- 3.67e+00%
            Group 4 [6.25e-07   - 4e-06     MeV]:	6.54e-06 +/- 2.74e-01%
            Group 5 [2.8e-07    - 6.25e-07  MeV]:	1.07e-05 +/- 4.55e-01%
            Group 6 [1.4e-07    - 2.8e-07   MeV]:	1.55e-05 +/- 4.25e-01%
            Group 7 [5.8e-08    - 1.4e-07   MeV]:	2.30e-05 +/- 2.97e-01%
            Group 8 [0.0        - 5.8e-08   MeV]:	4.24e-05 +/- 2.90e-01%



Our multi-group cross sections are capable of summing across all nuclides to provide us with macroscopic cross sections as well.

In [18]:
nufission = xs_library[fuel_cell.id]['nu-fission']
nufission.print_xs(xs_type='macro', nuclides='sum')
Multi-Group XS
	Reaction Type  =	nu-fission
	Domain Type    =	cell
	Domain ID      =	10000
	Cross Sections [cm^-1]:
            Group 1 [0.821      - 20.0      MeV]:	2.52e-02 +/- 2.44e-01%
            Group 2 [0.00553    - 0.821     MeV]:	1.51e-03 +/- 1.30e-01%
            Group 3 [4e-06      - 0.00553   MeV]:	2.07e-02 +/- 2.31e-01%
            Group 4 [6.25e-07   - 4e-06     MeV]:	3.31e-02 +/- 2.96e-01%
            Group 5 [2.8e-07    - 6.25e-07  MeV]:	1.09e-01 +/- 4.64e-01%
            Group 6 [1.4e-07    - 2.8e-07   MeV]:	1.69e-01 +/- 4.22e-01%
            Group 7 [5.8e-08    - 1.4e-07   MeV]:	2.58e-01 +/- 2.97e-01%
            Group 8 [0.0        - 5.8e-08   MeV]:	5.40e-01 +/- 2.91e-01%



Although a printed report is nice, it is not scalable or flexible. Let's extract the microscopic cross section data for the moderator as a Pandas DataFrame .

In [19]:
nuscatter = xs_library[moderator_cell.id]['nu-scatter']
df = nuscatter.get_pandas_dataframe(xs_type='micro')
df.head(10)
Out[19]:
cell group in group out nuclide mean std. dev.
126 10002 1 1 H-1 0.234115 0.003568
127 10002 1 1 O-16 1.563707 0.005953
124 10002 1 2 H-1 1.594129 0.002369
125 10002 1 2 O-16 0.285761 0.001676
122 10002 1 3 H-1 0.011089 0.000248
123 10002 1 3 O-16 0.000000 0.000000
120 10002 1 4 H-1 0.000000 0.000000
121 10002 1 4 O-16 0.000000 0.000000
118 10002 1 5 H-1 0.000000 0.000000
119 10002 1 5 O-16 0.000000 0.000000

Next, we illustate how one can easily take multi-group cross sections and condense them down to a coarser energy group structure. The MGXS class includes a get_condensed_xs(...) method which takes an EnergyGroups parameter with a coarse(r) group structure and returns a new MGXS condensed to the coarse groups. We illustrate this process below using the 2-group structure created earlier.

In [20]:
# Extract the 16-group transport cross section for the fuel
fine_xs = xs_library[fuel_cell.id]['transport']

# Condense to the 2-group structure
condensed_xs = fine_xs.get_condensed_xs(coarse_groups)

Group condensation is as simple as that! We now have a new coarse 2-group TransportXS in addition to our original 16-group TransportXS. Let's inspect the 2-group TransportXS by printing it to the screen and extracting a Pandas DataFrame as we have already learned how to do.

In [21]:
condensed_xs.print_xs()
Multi-Group XS
	Reaction Type  =	transport
	Domain Type    =	cell
	Domain ID      =	10000
	Nuclide        =	U-235
	Cross Sections [cm^-1]:
            Group 1 [6.25e-07   - 20.0      MeV]:	7.73e-03 +/- 5.06e-01%
            Group 2 [0.0        - 6.25e-07  MeV]:	1.82e-01 +/- 2.05e-01%

	Nuclide        =	U-238
	Cross Sections [cm^-1]:
            Group 1 [6.25e-07   - 20.0      MeV]:	2.17e-01 +/- 1.44e-01%
            Group 2 [0.0        - 6.25e-07  MeV]:	2.53e-01 +/- 2.57e-01%

	Nuclide        =	O-16
	Cross Sections [cm^-1]:
            Group 1 [6.25e-07   - 20.0      MeV]:	1.46e-01 +/- 1.60e-01%
            Group 2 [0.0        - 6.25e-07  MeV]:	1.75e-01 +/- 2.94e-01%



In [22]:
df = condensed_xs.get_pandas_dataframe(xs_type='micro')
df
Out[22]:
cell group in nuclide mean std. dev.
3 10000 1 U-235 20.611692 0.104237
4 10000 1 U-238 9.585358 0.013808
5 10000 1 O-16 3.164190 0.005049
0 10000 2 U-235 485.413426 0.996410
1 10000 2 U-238 11.190386 0.028731
2 10000 2 O-16 3.794859 0.011139

Verification with OpenMOC

Now, let's verify our cross sections using OpenMOC. First, we use OpenCG construct an equivalent OpenMOC geometry.

In [23]:
# Create an OpenMOC Geometry from the OpenCG Geometry
openmoc_geometry = get_openmoc_geometry(sp.summary.opencg_geometry)

Next, we we can inject the multi-group cross sections into the equivalent fuel pin cell OpenMOC geometry.

In [24]:
# Get all OpenMOC cells in the gometry
openmoc_cells = openmoc_geometry.getRootUniverse().getAllCells()

# Inject multi-group cross sections into OpenMOC Materials
for cell_id, cell in openmoc_cells.items():
    
    # Ignore the root cell
    if cell.getName() == 'root cell':
        continue
    
    # Get a reference to the Material filling this Cell
    openmoc_material = cell.getFillMaterial()
    
    # Set the number of energy groups for the Material
    openmoc_material.setNumEnergyGroups(fine_groups.num_groups)
    
    # Extract the appropriate cross section objects for this cell
    transport = xs_library[cell_id]['transport']
    nufission = xs_library[cell_id]['nu-fission']
    nuscatter = xs_library[cell_id]['nu-scatter']
    chi = xs_library[cell_id]['chi']
    
    # Inject NumPy arrays of cross section data into the Material
    # NOTE: Sum across nuclides to get macro cross sections needed by OpenMOC
    openmoc_material.setSigmaT(transport.get_xs(nuclides='sum').flatten())
    openmoc_material.setNuSigmaF(nufission.get_xs(nuclides='sum').flatten())
    openmoc_material.setSigmaS(nuscatter.get_xs(nuclides='sum').flatten())
    openmoc_material.setChi(chi.get_xs(nuclides='sum').flatten())

We are now ready to run OpenMOC to verify our cross-sections from OpenMC.

In [25]:
# Generate tracks for OpenMOC
track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=128, azim_spacing=0.1)
track_generator.generateTracks()

# Run OpenMOC
solver = openmoc.CPUSolver(track_generator)
solver.computeEigenvalue()
[  NORMAL ]  Importing ray tracing data from file...
[  NORMAL ]  Computing the eigenvalue...
[  NORMAL ]  Iteration 0:	k_eff = 0.574672	res = 0.000E+00
[  NORMAL ]  Iteration 1:	k_eff = 0.679815	res = 4.253E-01
[  NORMAL ]  Iteration 2:	k_eff = 0.660826	res = 1.830E-01
[  NORMAL ]  Iteration 3:	k_eff = 0.658940	res = 2.793E-02
[  NORMAL ]  Iteration 4:	k_eff = 0.643012	res = 2.853E-03
[  NORMAL ]  Iteration 5:	k_eff = 0.625810	res = 2.417E-02
[  NORMAL ]  Iteration 6:	k_eff = 0.606678	res = 2.675E-02
[  NORMAL ]  Iteration 7:	k_eff = 0.587485	res = 3.057E-02
[  NORMAL ]  Iteration 8:	k_eff = 0.569028	res = 3.164E-02
[  NORMAL ]  Iteration 9:	k_eff = 0.551707	res = 3.142E-02
[  NORMAL ]  Iteration 10:	k_eff = 0.536034	res = 3.044E-02
[  NORMAL ]  Iteration 11:	k_eff = 0.522274	res = 2.841E-02
[  NORMAL ]  Iteration 12:	k_eff = 0.510609	res = 2.567E-02
[  NORMAL ]  Iteration 13:	k_eff = 0.501105	res = 2.234E-02
[  NORMAL ]  Iteration 14:	k_eff = 0.493831	res = 1.861E-02
[  NORMAL ]  Iteration 15:	k_eff = 0.488780	res = 1.452E-02
[  NORMAL ]  Iteration 16:	k_eff = 0.485922	res = 1.023E-02
[  NORMAL ]  Iteration 17:	k_eff = 0.485209	res = 5.846E-03
[  NORMAL ]  Iteration 18:	k_eff = 0.486569	res = 1.467E-03
[  NORMAL ]  Iteration 19:	k_eff = 0.489903	res = 2.801E-03
[  NORMAL ]  Iteration 20:	k_eff = 0.495102	res = 6.853E-03
[  NORMAL ]  Iteration 21:	k_eff = 0.502053	res = 1.061E-02
[  NORMAL ]  Iteration 22:	k_eff = 0.510627	res = 1.404E-02
[  NORMAL ]  Iteration 23:	k_eff = 0.520692	res = 1.708E-02
[  NORMAL ]  Iteration 24:	k_eff = 0.532116	res = 1.971E-02
[  NORMAL ]  Iteration 25:	k_eff = 0.544763	res = 2.194E-02
[  NORMAL ]  Iteration 26:	k_eff = 0.558500	res = 2.377E-02
[  NORMAL ]  Iteration 27:	k_eff = 0.573195	res = 2.522E-02
[  NORMAL ]  Iteration 28:	k_eff = 0.588717	res = 2.631E-02
[  NORMAL ]  Iteration 29:	k_eff = 0.604945	res = 2.708E-02
[  NORMAL ]  Iteration 30:	k_eff = 0.621759	res = 2.756E-02
[  NORMAL ]  Iteration 31:	k_eff = 0.639046	res = 2.779E-02
[  NORMAL ]  Iteration 32:	k_eff = 0.656701	res = 2.780E-02
[  NORMAL ]  Iteration 33:	k_eff = 0.674624	res = 2.763E-02
[  NORMAL ]  Iteration 34:	k_eff = 0.692722	res = 2.729E-02
[  NORMAL ]  Iteration 35:	k_eff = 0.710909	res = 2.683E-02
[  NORMAL ]  Iteration 36:	k_eff = 0.729109	res = 2.626E-02
[  NORMAL ]  Iteration 37:	k_eff = 0.747248	res = 2.560E-02
[  NORMAL ]  Iteration 38:	k_eff = 0.765262	res = 2.488E-02
[  NORMAL ]  Iteration 39:	k_eff = 0.783093	res = 2.411E-02
[  NORMAL ]  Iteration 40:	k_eff = 0.800689	res = 2.330E-02
[  NORMAL ]  Iteration 41:	k_eff = 0.818004	res = 2.247E-02
[  NORMAL ]  Iteration 42:	k_eff = 0.834999	res = 2.163E-02
[  NORMAL ]  Iteration 43:	k_eff = 0.851638	res = 2.078E-02
[  NORMAL ]  Iteration 44:	k_eff = 0.867891	res = 1.993E-02
[  NORMAL ]  Iteration 45:	k_eff = 0.883735	res = 1.909E-02
[  NORMAL ]  Iteration 46:	k_eff = 0.899148	res = 1.826E-02
[  NORMAL ]  Iteration 47:	k_eff = 0.914114	res = 1.744E-02
[  NORMAL ]  Iteration 48:	k_eff = 0.928621	res = 1.664E-02
[  NORMAL ]  Iteration 49:	k_eff = 0.942659	res = 1.587E-02
[  NORMAL ]  Iteration 50:	k_eff = 0.956221	res = 1.512E-02
[  NORMAL ]  Iteration 51:	k_eff = 0.969305	res = 1.439E-02
[  NORMAL ]  Iteration 52:	k_eff = 0.981909	res = 1.368E-02
[  NORMAL ]  Iteration 53:	k_eff = 0.994034	res = 1.300E-02
[  NORMAL ]  Iteration 54:	k_eff = 1.005685	res = 1.235E-02
[  NORMAL ]  Iteration 55:	k_eff = 1.016866	res = 1.172E-02
[  NORMAL ]  Iteration 56:	k_eff = 1.027583	res = 1.112E-02
[  NORMAL ]  Iteration 57:	k_eff = 1.037845	res = 1.054E-02
[  NORMAL ]  Iteration 58:	k_eff = 1.047661	res = 9.986E-03
[  NORMAL ]  Iteration 59:	k_eff = 1.057040	res = 9.458E-03
[  NORMAL ]  Iteration 60:	k_eff = 1.065993	res = 8.952E-03
[  NORMAL ]  Iteration 61:	k_eff = 1.074533	res = 8.470E-03
[  NORMAL ]  Iteration 62:	k_eff = 1.082670	res = 8.011E-03
[  NORMAL ]  Iteration 63:	k_eff = 1.090418	res = 7.573E-03
[  NORMAL ]  Iteration 64:	k_eff = 1.097789	res = 7.156E-03
[  NORMAL ]  Iteration 65:	k_eff = 1.104796	res = 6.760E-03
[  NORMAL ]  Iteration 66:	k_eff = 1.111452	res = 6.383E-03
[  NORMAL ]  Iteration 67:	k_eff = 1.117770	res = 6.025E-03
[  NORMAL ]  Iteration 68:	k_eff = 1.123764	res = 5.685E-03
[  NORMAL ]  Iteration 69:	k_eff = 1.129445	res = 5.362E-03
[  NORMAL ]  Iteration 70:	k_eff = 1.134828	res = 5.056E-03
[  NORMAL ]  Iteration 71:	k_eff = 1.139924	res = 4.766E-03
[  NORMAL ]  Iteration 72:	k_eff = 1.144746	res = 4.491E-03
[  NORMAL ]  Iteration 73:	k_eff = 1.149306	res = 4.230E-03
[  NORMAL ]  Iteration 74:	k_eff = 1.153617	res = 3.984E-03
[  NORMAL ]  Iteration 75:	k_eff = 1.157689	res = 3.750E-03
[  NORMAL ]  Iteration 76:	k_eff = 1.161534	res = 3.530E-03
[  NORMAL ]  Iteration 77:	k_eff = 1.165163	res = 3.321E-03
[  NORMAL ]  Iteration 78:	k_eff = 1.168586	res = 3.124E-03
[  NORMAL ]  Iteration 79:	k_eff = 1.171813	res = 2.938E-03
[  NORMAL ]  Iteration 80:	k_eff = 1.174855	res = 2.762E-03
[  NORMAL ]  Iteration 81:	k_eff = 1.177721	res = 2.596E-03
[  NORMAL ]  Iteration 82:	k_eff = 1.180419	res = 2.439E-03
[  NORMAL ]  Iteration 83:	k_eff = 1.182960	res = 2.291E-03
[  NORMAL ]  Iteration 84:	k_eff = 1.185350	res = 2.152E-03
[  NORMAL ]  Iteration 85:	k_eff = 1.187598	res = 2.021E-03
[  NORMAL ]  Iteration 86:	k_eff = 1.189712	res = 1.897E-03
[  NORMAL ]  Iteration 87:	k_eff = 1.191699	res = 1.780E-03
[  NORMAL ]  Iteration 88:	k_eff = 1.193567	res = 1.670E-03
[  NORMAL ]  Iteration 89:	k_eff = 1.195320	res = 1.567E-03
[  NORMAL ]  Iteration 90:	k_eff = 1.196967	res = 1.469E-03
[  NORMAL ]  Iteration 91:	k_eff = 1.198513	res = 1.378E-03
[  NORMAL ]  Iteration 92:	k_eff = 1.199964	res = 1.292E-03
[  NORMAL ]  Iteration 93:	k_eff = 1.201326	res = 1.211E-03
[  NORMAL ]  Iteration 94:	k_eff = 1.202602	res = 1.134E-03
[  NORMAL ]  Iteration 95:	k_eff = 1.203800	res = 1.063E-03
[  NORMAL ]  Iteration 96:	k_eff = 1.204922	res = 9.955E-04
[  NORMAL ]  Iteration 97:	k_eff = 1.205974	res = 9.323E-04
[  NORMAL ]  Iteration 98:	k_eff = 1.206959	res = 8.730E-04
[  NORMAL ]  Iteration 99:	k_eff = 1.207883	res = 8.173E-04
[  NORMAL ]  Iteration 100:	k_eff = 1.208747	res = 7.649E-04
[  NORMAL ]  Iteration 101:	k_eff = 1.209557	res = 7.159E-04
[  NORMAL ]  Iteration 102:	k_eff = 1.210315	res = 6.698E-04
[  NORMAL ]  Iteration 103:	k_eff = 1.211024	res = 6.266E-04
[  NORMAL ]  Iteration 104:	k_eff = 1.211688	res = 5.861E-04
[  NORMAL ]  Iteration 105:	k_eff = 1.212309	res = 5.481E-04
[  NORMAL ]  Iteration 106:	k_eff = 1.212890	res = 5.125E-04
[  NORMAL ]  Iteration 107:	k_eff = 1.213433	res = 4.791E-04
[  NORMAL ]  Iteration 108:	k_eff = 1.213941	res = 4.479E-04
[  NORMAL ]  Iteration 109:	k_eff = 1.214416	res = 4.186E-04
[  NORMAL ]  Iteration 110:	k_eff = 1.214860	res = 3.912E-04
[  NORMAL ]  Iteration 111:	k_eff = 1.215275	res = 3.655E-04
[  NORMAL ]  Iteration 112:	k_eff = 1.215662	res = 3.414E-04
[  NORMAL ]  Iteration 113:	k_eff = 1.216024	res = 3.189E-04
[  NORMAL ]  Iteration 114:	k_eff = 1.216362	res = 2.979E-04
[  NORMAL ]  Iteration 115:	k_eff = 1.216678	res = 2.781E-04
[  NORMAL ]  Iteration 116:	k_eff = 1.216973	res = 2.597E-04
[  NORMAL ]  Iteration 117:	k_eff = 1.217249	res = 2.425E-04
[  NORMAL ]  Iteration 118:	k_eff = 1.217506	res = 2.263E-04
[  NORMAL ]  Iteration 119:	k_eff = 1.217746	res = 2.112E-04
[  NORMAL ]  Iteration 120:	k_eff = 1.217970	res = 1.971E-04
[  NORMAL ]  Iteration 121:	k_eff = 1.218179	res = 1.840E-04
[  NORMAL ]  Iteration 122:	k_eff = 1.218374	res = 1.716E-04
[  NORMAL ]  Iteration 123:	k_eff = 1.218556	res = 1.601E-04
[  NORMAL ]  Iteration 124:	k_eff = 1.218726	res = 1.494E-04
[  NORMAL ]  Iteration 125:	k_eff = 1.218884	res = 1.393E-04
[  NORMAL ]  Iteration 126:	k_eff = 1.219032	res = 1.299E-04
[  NORMAL ]  Iteration 127:	k_eff = 1.219170	res = 1.212E-04
[  NORMAL ]  Iteration 128:	k_eff = 1.219298	res = 1.130E-04
[  NORMAL ]  Iteration 129:	k_eff = 1.219418	res = 1.053E-04
[  NORMAL ]  Iteration 130:	k_eff = 1.219529	res = 9.821E-05
[  NORMAL ]  Iteration 131:	k_eff = 1.219633	res = 9.155E-05
[  NORMAL ]  Iteration 132:	k_eff = 1.219730	res = 8.534E-05
[  NORMAL ]  Iteration 133:	k_eff = 1.219821	res = 7.954E-05
[  NORMAL ]  Iteration 134:	k_eff = 1.219905	res = 7.412E-05
[  NORMAL ]  Iteration 135:	k_eff = 1.219984	res = 6.907E-05
[  NORMAL ]  Iteration 136:	k_eff = 1.220057	res = 6.436E-05
[  NORMAL ]  Iteration 137:	k_eff = 1.220125	res = 5.997E-05
[  NORMAL ]  Iteration 138:	k_eff = 1.220188	res = 5.587E-05
[  NORMAL ]  Iteration 139:	k_eff = 1.220248	res = 5.205E-05
[  NORMAL ]  Iteration 140:	k_eff = 1.220303	res = 4.848E-05
[  NORMAL ]  Iteration 141:	k_eff = 1.220354	res = 4.516E-05
[  NORMAL ]  Iteration 142:	k_eff = 1.220402	res = 4.206E-05
[  NORMAL ]  Iteration 143:	k_eff = 1.220446	res = 3.917E-05
[  NORMAL ]  Iteration 144:	k_eff = 1.220488	res = 3.648E-05
[  NORMAL ]  Iteration 145:	k_eff = 1.220526	res = 3.397E-05
[  NORMAL ]  Iteration 146:	k_eff = 1.220562	res = 3.163E-05
[  NORMAL ]  Iteration 147:	k_eff = 1.220596	res = 2.945E-05
[  NORMAL ]  Iteration 148:	k_eff = 1.220627	res = 2.742E-05
[  NORMAL ]  Iteration 149:	k_eff = 1.220656	res = 2.552E-05
[  NORMAL ]  Iteration 150:	k_eff = 1.220683	res = 2.376E-05
[  NORMAL ]  Iteration 151:	k_eff = 1.220708	res = 2.212E-05
[  NORMAL ]  Iteration 152:	k_eff = 1.220732	res = 2.059E-05
[  NORMAL ]  Iteration 153:	k_eff = 1.220753	res = 1.916E-05
[  NORMAL ]  Iteration 154:	k_eff = 1.220774	res = 1.783E-05
[  NORMAL ]  Iteration 155:	k_eff = 1.220792	res = 1.660E-05
[  NORMAL ]  Iteration 156:	k_eff = 1.220810	res = 1.545E-05
[  NORMAL ]  Iteration 157:	k_eff = 1.220826	res = 1.437E-05
[  NORMAL ]  Iteration 158:	k_eff = 1.220841	res = 1.337E-05
[  NORMAL ]  Iteration 159:	k_eff = 1.220856	res = 1.244E-05
[  NORMAL ]  Iteration 160:	k_eff = 1.220869	res = 1.158E-05
[  NORMAL ]  Iteration 161:	k_eff = 1.220881	res = 1.077E-05
[  NORMAL ]  Iteration 162:	k_eff = 1.220892	res = 1.002E-05

We report the eigenvalues computed by OpenMC and OpenMOC here together to summarize our results.

In [26]:
# Print report of keff and bias with OpenMC
openmoc_keff = solver.getKeff()
openmc_keff = sp.k_combined[0]
bias = (openmoc_keff - openmc_keff) * 1e5

print('openmc keff = {0:1.6f}'.format(openmc_keff))
print('openmoc keff = {0:1.6f}'.format(openmoc_keff))
print('bias [pcm]: {0:1.1f}'.format(bias))
openmc keff = 1.223474
openmoc keff = 1.220892
bias [pcm]: -258.1

As a sanity check, let's run a simulation with the coarse 2-group cross sections to ensure that they also produce a reasonable result.

In [27]:
openmoc_geometry = get_openmoc_geometry(sp.summary.opencg_geometry)
openmoc_cells = openmoc_geometry.getRootUniverse().getAllCells()

# Inject multi-group cross sections into OpenMOC Materials
for cell_id, cell in openmoc_cells.items():
    
    # Ignore the root cell
    if cell.getName() == 'root cell':
        continue
    
    openmoc_material = cell.getFillMaterial()
    openmoc_material.setNumEnergyGroups(coarse_groups.num_groups)
    
    # Extract the appropriate cross section objects for this cell
    transport = xs_library[cell_id]['transport']
    nufission = xs_library[cell_id]['nu-fission']
    nuscatter = xs_library[cell_id]['nu-scatter']
    chi = xs_library[cell_id]['chi']
    
    # Perform group condensation
    transport = transport.get_condensed_xs(coarse_groups)
    nufission = nufission.get_condensed_xs(coarse_groups)
    nuscatter = nuscatter.get_condensed_xs(coarse_groups)
    chi = chi.get_condensed_xs(coarse_groups)
    
    # Inject NumPy arrays of cross section data into the Material
    openmoc_material.setSigmaT(transport.get_xs(nuclides='sum').flatten())
    openmoc_material.setNuSigmaF(nufission.get_xs(nuclides='sum').flatten())
    openmoc_material.setSigmaS(nuscatter.get_xs(nuclides='sum').flatten())
    openmoc_material.setChi(chi.get_xs(nuclides='sum').flatten())
In [28]:
# Generate tracks for OpenMOC
track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=128, azim_spacing=0.1)
track_generator.generateTracks()

# Run OpenMOC
solver = openmoc.CPUSolver(track_generator)
solver.computeEigenvalue()
[  NORMAL ]  Importing ray tracing data from file...
[  NORMAL ]  Computing the eigenvalue...
[  NORMAL ]  Iteration 0:	k_eff = 0.495816	res = 0.000E+00
[  NORMAL ]  Iteration 1:	k_eff = 0.557477	res = 5.042E-01
[  NORMAL ]  Iteration 2:	k_eff = 0.518300	res = 1.244E-01
[  NORMAL ]  Iteration 3:	k_eff = 0.509211	res = 7.027E-02
[  NORMAL ]  Iteration 4:	k_eff = 0.496489	res = 1.754E-02
[  NORMAL ]  Iteration 5:	k_eff = 0.488581	res = 2.498E-02
[  NORMAL ]  Iteration 6:	k_eff = 0.482897	res = 1.593E-02
[  NORMAL ]  Iteration 7:	k_eff = 0.479775	res = 1.163E-02
[  NORMAL ]  Iteration 8:	k_eff = 0.478834	res = 6.465E-03
[  NORMAL ]  Iteration 9:	k_eff = 0.479871	res = 1.960E-03
[  NORMAL ]  Iteration 10:	k_eff = 0.482684	res = 2.166E-03
[  NORMAL ]  Iteration 11:	k_eff = 0.487084	res = 5.861E-03
[  NORMAL ]  Iteration 12:	k_eff = 0.492900	res = 9.116E-03
[  NORMAL ]  Iteration 13:	k_eff = 0.499971	res = 1.194E-02
[  NORMAL ]  Iteration 14:	k_eff = 0.508153	res = 1.435E-02
[  NORMAL ]  Iteration 15:	k_eff = 0.517312	res = 1.637E-02
[  NORMAL ]  Iteration 16:	k_eff = 0.527324	res = 1.802E-02
[  NORMAL ]  Iteration 17:	k_eff = 0.538079	res = 1.935E-02
[  NORMAL ]  Iteration 18:	k_eff = 0.549472	res = 2.039E-02
[  NORMAL ]  Iteration 19:	k_eff = 0.561410	res = 2.117E-02
[  NORMAL ]  Iteration 20:	k_eff = 0.573807	res = 2.173E-02
[  NORMAL ]  Iteration 21:	k_eff = 0.586585	res = 2.208E-02
[  NORMAL ]  Iteration 22:	k_eff = 0.599674	res = 2.227E-02
[  NORMAL ]  Iteration 23:	k_eff = 0.613007	res = 2.231E-02
[  NORMAL ]  Iteration 24:	k_eff = 0.626528	res = 2.223E-02
[  NORMAL ]  Iteration 25:	k_eff = 0.640181	res = 2.206E-02
[  NORMAL ]  Iteration 26:	k_eff = 0.653920	res = 2.179E-02
[  NORMAL ]  Iteration 27:	k_eff = 0.667700	res = 2.146E-02
[  NORMAL ]  Iteration 28:	k_eff = 0.681483	res = 2.107E-02
[  NORMAL ]  Iteration 29:	k_eff = 0.695234	res = 2.064E-02
[  NORMAL ]  Iteration 30:	k_eff = 0.708921	res = 2.018E-02
[  NORMAL ]  Iteration 31:	k_eff = 0.722515	res = 1.969E-02
[  NORMAL ]  Iteration 32:	k_eff = 0.735993	res = 1.918E-02
[  NORMAL ]  Iteration 33:	k_eff = 0.749331	res = 1.865E-02
[  NORMAL ]  Iteration 34:	k_eff = 0.762510	res = 1.812E-02
[  NORMAL ]  Iteration 35:	k_eff = 0.775514	res = 1.759E-02
[  NORMAL ]  Iteration 36:	k_eff = 0.788326	res = 1.705E-02
[  NORMAL ]  Iteration 37:	k_eff = 0.800934	res = 1.652E-02
[  NORMAL ]  Iteration 38:	k_eff = 0.813328	res = 1.599E-02
[  NORMAL ]  Iteration 39:	k_eff = 0.825497	res = 1.547E-02
[  NORMAL ]  Iteration 40:	k_eff = 0.837433	res = 1.496E-02
[  NORMAL ]  Iteration 41:	k_eff = 0.849131	res = 1.446E-02
[  NORMAL ]  Iteration 42:	k_eff = 0.860584	res = 1.397E-02
[  NORMAL ]  Iteration 43:	k_eff = 0.871789	res = 1.349E-02
[  NORMAL ]  Iteration 44:	k_eff = 0.882742	res = 1.302E-02
[  NORMAL ]  Iteration 45:	k_eff = 0.893442	res = 1.256E-02
[  NORMAL ]  Iteration 46:	k_eff = 0.903888	res = 1.212E-02
[  NORMAL ]  Iteration 47:	k_eff = 0.914078	res = 1.169E-02
[  NORMAL ]  Iteration 48:	k_eff = 0.924013	res = 1.127E-02
[  NORMAL ]  Iteration 49:	k_eff = 0.933694	res = 1.087E-02
[  NORMAL ]  Iteration 50:	k_eff = 0.943122	res = 1.048E-02
[  NORMAL ]  Iteration 51:	k_eff = 0.952299	res = 1.010E-02
[  NORMAL ]  Iteration 52:	k_eff = 0.961228	res = 9.731E-03
[  NORMAL ]  Iteration 53:	k_eff = 0.969911	res = 9.376E-03
[  NORMAL ]  Iteration 54:	k_eff = 0.978351	res = 9.033E-03
[  NORMAL ]  Iteration 55:	k_eff = 0.986552	res = 8.702E-03
[  NORMAL ]  Iteration 56:	k_eff = 0.994517	res = 8.382E-03
[  NORMAL ]  Iteration 57:	k_eff = 1.002250	res = 8.074E-03
[  NORMAL ]  Iteration 58:	k_eff = 1.009756	res = 7.776E-03
[  NORMAL ]  Iteration 59:	k_eff = 1.017037	res = 7.488E-03
[  NORMAL ]  Iteration 60:	k_eff = 1.024100	res = 7.211E-03
[  NORMAL ]  Iteration 61:	k_eff = 1.030948	res = 6.944E-03
[  NORMAL ]  Iteration 62:	k_eff = 1.037585	res = 6.687E-03
[  NORMAL ]  Iteration 63:	k_eff = 1.044017	res = 6.438E-03
[  NORMAL ]  Iteration 64:	k_eff = 1.050248	res = 6.199E-03
[  NORMAL ]  Iteration 65:	k_eff = 1.056282	res = 5.968E-03
[  NORMAL ]  Iteration 66:	k_eff = 1.062125	res = 5.746E-03
[  NORMAL ]  Iteration 67:	k_eff = 1.067782	res = 5.532E-03
[  NORMAL ]  Iteration 68:	k_eff = 1.073256	res = 5.325E-03
[  NORMAL ]  Iteration 69:	k_eff = 1.078553	res = 5.127E-03
[  NORMAL ]  Iteration 70:	k_eff = 1.083677	res = 4.935E-03
[  NORMAL ]  Iteration 71:	k_eff = 1.088633	res = 4.751E-03
[  NORMAL ]  Iteration 72:	k_eff = 1.093425	res = 4.573E-03
[  NORMAL ]  Iteration 73:	k_eff = 1.098059	res = 4.402E-03
[  NORMAL ]  Iteration 74:	k_eff = 1.102538	res = 4.238E-03
[  NORMAL ]  Iteration 75:	k_eff = 1.106867	res = 4.079E-03
[  NORMAL ]  Iteration 76:	k_eff = 1.111050	res = 3.926E-03
[  NORMAL ]  Iteration 77:	k_eff = 1.115091	res = 3.779E-03
[  NORMAL ]  Iteration 78:	k_eff = 1.118996	res = 3.638E-03
[  NORMAL ]  Iteration 79:	k_eff = 1.122767	res = 3.501E-03
[  NORMAL ]  Iteration 80:	k_eff = 1.126408	res = 3.370E-03
[  NORMAL ]  Iteration 81:	k_eff = 1.129925	res = 3.244E-03
[  NORMAL ]  Iteration 82:	k_eff = 1.133320	res = 3.122E-03
[  NORMAL ]  Iteration 83:	k_eff = 1.136598	res = 3.005E-03
[  NORMAL ]  Iteration 84:	k_eff = 1.139762	res = 2.892E-03
[  NORMAL ]  Iteration 85:	k_eff = 1.142815	res = 2.784E-03
[  NORMAL ]  Iteration 86:	k_eff = 1.145762	res = 2.679E-03
[  NORMAL ]  Iteration 87:	k_eff = 1.148605	res = 2.578E-03
[  NORMAL ]  Iteration 88:	k_eff = 1.151348	res = 2.482E-03
[  NORMAL ]  Iteration 89:	k_eff = 1.153995	res = 2.388E-03
[  NORMAL ]  Iteration 90:	k_eff = 1.156548	res = 2.299E-03
[  NORMAL ]  Iteration 91:	k_eff = 1.159010	res = 2.212E-03
[  NORMAL ]  Iteration 92:	k_eff = 1.161384	res = 2.129E-03
[  NORMAL ]  Iteration 93:	k_eff = 1.163674	res = 2.049E-03
[  NORMAL ]  Iteration 94:	k_eff = 1.165883	res = 1.972E-03
[  NORMAL ]  Iteration 95:	k_eff = 1.168012	res = 1.898E-03
[  NORMAL ]  Iteration 96:	k_eff = 1.170064	res = 1.826E-03
[  NORMAL ]  Iteration 97:	k_eff = 1.172043	res = 1.757E-03
[  NORMAL ]  Iteration 98:	k_eff = 1.173951	res = 1.691E-03
[  NORMAL ]  Iteration 99:	k_eff = 1.175790	res = 1.628E-03
[  NORMAL ]  Iteration 100:	k_eff = 1.177562	res = 1.566E-03
[  NORMAL ]  Iteration 101:	k_eff = 1.179270	res = 1.507E-03
[  NORMAL ]  Iteration 102:	k_eff = 1.180916	res = 1.450E-03
[  NORMAL ]  Iteration 103:	k_eff = 1.182502	res = 1.396E-03
[  NORMAL ]  Iteration 104:	k_eff = 1.184030	res = 1.343E-03
[  NORMAL ]  Iteration 105:	k_eff = 1.185503	res = 1.292E-03
[  NORMAL ]  Iteration 106:	k_eff = 1.186922	res = 1.244E-03
[  NORMAL ]  Iteration 107:	k_eff = 1.188289	res = 1.197E-03
[  NORMAL ]  Iteration 108:	k_eff = 1.189605	res = 1.152E-03
[  NORMAL ]  Iteration 109:	k_eff = 1.190874	res = 1.108E-03
[  NORMAL ]  Iteration 110:	k_eff = 1.192096	res = 1.066E-03
[  NORMAL ]  Iteration 111:	k_eff = 1.193273	res = 1.026E-03
[  NORMAL ]  Iteration 112:	k_eff = 1.194407	res = 9.873E-04
[  NORMAL ]  Iteration 113:	k_eff = 1.195498	res = 9.500E-04
[  NORMAL ]  Iteration 114:	k_eff = 1.196550	res = 9.141E-04
[  NORMAL ]  Iteration 115:	k_eff = 1.197563	res = 8.796E-04
[  NORMAL ]  Iteration 116:	k_eff = 1.198538	res = 8.464E-04
[  NORMAL ]  Iteration 117:	k_eff = 1.199477	res = 8.144E-04
[  NORMAL ]  Iteration 118:	k_eff = 1.200381	res = 7.836E-04
[  NORMAL ]  Iteration 119:	k_eff = 1.201252	res = 7.539E-04
[  NORMAL ]  Iteration 120:	k_eff = 1.202091	res = 7.254E-04
[  NORMAL ]  Iteration 121:	k_eff = 1.202898	res = 6.980E-04
[  NORMAL ]  Iteration 122:	k_eff = 1.203675	res = 6.715E-04
[  NORMAL ]  Iteration 123:	k_eff = 1.204423	res = 6.461E-04
[  NORMAL ]  Iteration 124:	k_eff = 1.205144	res = 6.217E-04
[  NORMAL ]  Iteration 125:	k_eff = 1.205837	res = 5.981E-04
[  NORMAL ]  Iteration 126:	k_eff = 1.206505	res = 5.755E-04
[  NORMAL ]  Iteration 127:	k_eff = 1.207148	res = 5.537E-04
[  NORMAL ]  Iteration 128:	k_eff = 1.207766	res = 5.327E-04
[  NORMAL ]  Iteration 129:	k_eff = 1.208362	res = 5.125E-04
[  NORMAL ]  Iteration 130:	k_eff = 1.208935	res = 4.931E-04
[  NORMAL ]  Iteration 131:	k_eff = 1.209487	res = 4.744E-04
[  NORMAL ]  Iteration 132:	k_eff = 1.210018	res = 4.564E-04
[  NORMAL ]  Iteration 133:	k_eff = 1.210529	res = 4.391E-04
[  NORMAL ]  Iteration 134:	k_eff = 1.211021	res = 4.225E-04
[  NORMAL ]  Iteration 135:	k_eff = 1.211495	res = 4.064E-04
[  NORMAL ]  Iteration 136:	k_eff = 1.211950	res = 3.910E-04
[  NORMAL ]  Iteration 137:	k_eff = 1.212389	res = 3.762E-04
[  NORMAL ]  Iteration 138:	k_eff = 1.212811	res = 3.619E-04
[  NORMAL ]  Iteration 139:	k_eff = 1.213217	res = 3.482E-04
[  NORMAL ]  Iteration 140:	k_eff = 1.213608	res = 3.349E-04
[  NORMAL ]  Iteration 141:	k_eff = 1.213984	res = 3.222E-04
[  NORMAL ]  Iteration 142:	k_eff = 1.214346	res = 3.100E-04
[  NORMAL ]  Iteration 143:	k_eff = 1.214695	res = 2.982E-04
[  NORMAL ]  Iteration 144:	k_eff = 1.215030	res = 2.869E-04
[  NORMAL ]  Iteration 145:	k_eff = 1.215353	res = 2.760E-04
[  NORMAL ]  Iteration 146:	k_eff = 1.215663	res = 2.655E-04
[  NORMAL ]  Iteration 147:	k_eff = 1.215962	res = 2.554E-04
[  NORMAL ]  Iteration 148:	k_eff = 1.216249	res = 2.457E-04
[  NORMAL ]  Iteration 149:	k_eff = 1.216526	res = 2.364E-04
[  NORMAL ]  Iteration 150:	k_eff = 1.216792	res = 2.274E-04
[  NORMAL ]  Iteration 151:	k_eff = 1.217048	res = 2.187E-04
[  NORMAL ]  Iteration 152:	k_eff = 1.217294	res = 2.104E-04
[  NORMAL ]  Iteration 153:	k_eff = 1.217531	res = 2.024E-04
[  NORMAL ]  Iteration 154:	k_eff = 1.217759	res = 1.947E-04
[  NORMAL ]  Iteration 155:	k_eff = 1.217979	res = 1.873E-04
[  NORMAL ]  Iteration 156:	k_eff = 1.218190	res = 1.802E-04
[  NORMAL ]  Iteration 157:	k_eff = 1.218393	res = 1.733E-04
[  NORMAL ]  Iteration 158:	k_eff = 1.218588	res = 1.667E-04
[  NORMAL ]  Iteration 159:	k_eff = 1.218776	res = 1.604E-04
[  NORMAL ]  Iteration 160:	k_eff = 1.218957	res = 1.543E-04
[  NORMAL ]  Iteration 161:	k_eff = 1.219131	res = 1.484E-04
[  NORMAL ]  Iteration 162:	k_eff = 1.219298	res = 1.427E-04
[  NORMAL ]  Iteration 163:	k_eff = 1.219459	res = 1.373E-04
[  NORMAL ]  Iteration 164:	k_eff = 1.219614	res = 1.321E-04
[  NORMAL ]  Iteration 165:	k_eff = 1.219763	res = 1.270E-04
[  NORMAL ]  Iteration 166:	k_eff = 1.219907	res = 1.222E-04
[  NORMAL ]  Iteration 167:	k_eff = 1.220045	res = 1.176E-04
[  NORMAL ]  Iteration 168:	k_eff = 1.220177	res = 1.131E-04
[  NORMAL ]  Iteration 169:	k_eff = 1.220305	res = 1.088E-04
[  NORMAL ]  Iteration 170:	k_eff = 1.220428	res = 1.046E-04
[  NORMAL ]  Iteration 171:	k_eff = 1.220546	res = 1.006E-04
[  NORMAL ]  Iteration 172:	k_eff = 1.220660	res = 9.680E-05
[  NORMAL ]  Iteration 173:	k_eff = 1.220769	res = 9.311E-05
[  NORMAL ]  Iteration 174:	k_eff = 1.220874	res = 8.956E-05
[  NORMAL ]  Iteration 175:	k_eff = 1.220975	res = 8.614E-05
[  NORMAL ]  Iteration 176:	k_eff = 1.221073	res = 8.286E-05
[  NORMAL ]  Iteration 177:	k_eff = 1.221166	res = 7.970E-05
[  NORMAL ]  Iteration 178:	k_eff = 1.221256	res = 7.666E-05
[  NORMAL ]  Iteration 179:	k_eff = 1.221343	res = 7.373E-05
[  NORMAL ]  Iteration 180:	k_eff = 1.221426	res = 7.092E-05
[  NORMAL ]  Iteration 181:	k_eff = 1.221506	res = 6.822E-05
[  NORMAL ]  Iteration 182:	k_eff = 1.221583	res = 6.562E-05
[  NORMAL ]  Iteration 183:	k_eff = 1.221658	res = 6.311E-05
[  NORMAL ]  Iteration 184:	k_eff = 1.221729	res = 6.070E-05
[  NORMAL ]  Iteration 185:	k_eff = 1.221797	res = 5.839E-05
[  NORMAL ]  Iteration 186:	k_eff = 1.221863	res = 5.616E-05
[  NORMAL ]  Iteration 187:	k_eff = 1.221927	res = 5.402E-05
[  NORMAL ]  Iteration 188:	k_eff = 1.221988	res = 5.196E-05
[  NORMAL ]  Iteration 189:	k_eff = 1.222047	res = 4.997E-05
[  NORMAL ]  Iteration 190:	k_eff = 1.222103	res = 4.807E-05
[  NORMAL ]  Iteration 191:	k_eff = 1.222158	res = 4.623E-05
[  NORMAL ]  Iteration 192:	k_eff = 1.222210	res = 4.447E-05
[  NORMAL ]  Iteration 193:	k_eff = 1.222260	res = 4.277E-05
[  NORMAL ]  Iteration 194:	k_eff = 1.222308	res = 4.114E-05
[  NORMAL ]  Iteration 195:	k_eff = 1.222355	res = 3.957E-05
[  NORMAL ]  Iteration 196:	k_eff = 1.222400	res = 3.805E-05
[  NORMAL ]  Iteration 197:	k_eff = 1.222443	res = 3.660E-05
[  NORMAL ]  Iteration 198:	k_eff = 1.222484	res = 3.520E-05
[  NORMAL ]  Iteration 199:	k_eff = 1.222524	res = 3.386E-05
[  NORMAL ]  Iteration 200:	k_eff = 1.222562	res = 3.257E-05
[  NORMAL ]  Iteration 201:	k_eff = 1.222599	res = 3.132E-05
[  NORMAL ]  Iteration 202:	k_eff = 1.222635	res = 3.013E-05
[  NORMAL ]  Iteration 203:	k_eff = 1.222669	res = 2.898E-05
[  NORMAL ]  Iteration 204:	k_eff = 1.222701	res = 2.787E-05
[  NORMAL ]  Iteration 205:	k_eff = 1.222733	res = 2.680E-05
[  NORMAL ]  Iteration 206:	k_eff = 1.222763	res = 2.578E-05
[  NORMAL ]  Iteration 207:	k_eff = 1.222792	res = 2.480E-05
[  NORMAL ]  Iteration 208:	k_eff = 1.222820	res = 2.385E-05
[  NORMAL ]  Iteration 209:	k_eff = 1.222847	res = 2.294E-05
[  NORMAL ]  Iteration 210:	k_eff = 1.222873	res = 2.206E-05
[  NORMAL ]  Iteration 211:	k_eff = 1.222898	res = 2.122E-05
[  NORMAL ]  Iteration 212:	k_eff = 1.222922	res = 2.041E-05
[  NORMAL ]  Iteration 213:	k_eff = 1.222945	res = 1.963E-05
[  NORMAL ]  Iteration 214:	k_eff = 1.222968	res = 1.888E-05
[  NORMAL ]  Iteration 215:	k_eff = 1.222989	res = 1.816E-05
[  NORMAL ]  Iteration 216:	k_eff = 1.223009	res = 1.746E-05
[  NORMAL ]  Iteration 217:	k_eff = 1.223029	res = 1.680E-05
[  NORMAL ]  Iteration 218:	k_eff = 1.223048	res = 1.615E-05
[  NORMAL ]  Iteration 219:	k_eff = 1.223067	res = 1.554E-05
[  NORMAL ]  Iteration 220:	k_eff = 1.223084	res = 1.494E-05
[  NORMAL ]  Iteration 221:	k_eff = 1.223101	res = 1.437E-05
[  NORMAL ]  Iteration 222:	k_eff = 1.223117	res = 1.382E-05
[  NORMAL ]  Iteration 223:	k_eff = 1.223133	res = 1.329E-05
[  NORMAL ]  Iteration 224:	k_eff = 1.223148	res = 1.279E-05
[  NORMAL ]  Iteration 225:	k_eff = 1.223162	res = 1.230E-05
[  NORMAL ]  Iteration 226:	k_eff = 1.223176	res = 1.183E-05
[  NORMAL ]  Iteration 227:	k_eff = 1.223190	res = 1.137E-05
[  NORMAL ]  Iteration 228:	k_eff = 1.223203	res = 1.094E-05
[  NORMAL ]  Iteration 229:	k_eff = 1.223215	res = 1.052E-05
[  NORMAL ]  Iteration 230:	k_eff = 1.223227	res = 1.012E-05
In [29]:
# Print report of keff and bias with OpenMC
openmoc_keff = solver.getKeff()
openmc_keff = sp.k_combined[0]
bias = (openmoc_keff - openmc_keff) * 1e5

print('openmc keff = {0:1.6f}'.format(openmc_keff))
print('openmoc keff = {0:1.6f}'.format(openmoc_keff))
print('bias [pcm]: {0:1.1f}'.format(bias))
openmc keff = 1.223474
openmoc keff = 1.223227
bias [pcm]: -24.7

There is a non-trivial bias in both the 2-group and 8-group cases. In the case of a pin cell, one can show that these biases do not converge to <100 pcm with more particle histories. For heterogeneous geometries, additional measures must be taken to address the following three sources of bias:

  • Appropriate transport-corrected cross sections
  • Spatial discretization of OpenMOC's mesh
  • Constant-in-angle multi-group cross sections

Visualizing MGXS Data

It is often insightful to generate visual depictions of multi-group cross sections. There are many different types of plots which may be useful for multi-group cross section visualization, only a few of which will be shown here for enrichment and inspiration.

One particularly useful visualization is a comparison of the continuous-energy and multi-group cross sections for a particular nuclide and reaction type. We illustrate one option for generating such plots with the use of the open source PyNE library to parse continuous-energy cross sections from the cross section data library provided with OpenMC. First, we instantiate a pyne.ace.Library object for U-235 as follows.

In [30]:
# Instantiate a PyNE ACE continuous-energy cross sections library
pyne_lib = pyne.ace.Library('../../../../data/nndc/293.6K/U_235_293.6K.ace')
pyne_lib.read('92235.71c')

# Extract the U-235 data from the library
u235 = pyne_lib.tables['92235.71c']

# Extract the continuous-energy U-235 fission cross section data
fission = u235.reactions[18]

Now, we use matplotlib and seaborn to plot the continuous-energy and multi-group cross sections on a single plot.

In [31]:
# Create a loglog plot of the U-235 continuous-energy fission cross section 
plt.loglog(u235.energy, fission.sigma, color='b', linewidth=1)

# Extract energy group bounds and MGXS values to plot
nufission = xs_library[fuel_cell.id]['fission']
energy_groups = nufission.energy_groups
x = energy_groups.group_edges
y = nufission.get_xs(nuclides=['U-235'], order_groups='decreasing', xs_type='micro')

# Fix low energy bound to the value defined by the ACE library
x[0] = u235.energy[0]

# Extend the mgxs values array for matplotlib's step plot
y = np.insert(y, 0, y[0])

# Create a step plot for the MGXS
plt.plot(x, y, drawstyle='steps', color='r', linewidth=3)

plt.title('U-235 Fission Cross Section')
plt.xlabel('Energy [MeV]')
plt.ylabel('Micro Fission XS')
plt.legend(['Continuous', 'Multi-Group'])
plt.xlim((x.min(), x.max()))
Out[31]:
(9.9999999999999994e-12, 20.0)

Another useful type of illustration is scattering matrix sparsity structures. First, we extract Pandas DataFrames for the H-1 and O-16 scattering matrices.

In [32]:
# Construct a Pandas DataFrame for the microscopic nu-scattering matrix
nuscatter = xs_library[moderator_cell.id]['nu-scatter']
df = nuscatter.get_pandas_dataframe(xs_type='micro')

# Slice DataFrame in two for each nuclide's mean values
h1 = df[df['nuclide'] == 'H-1']['mean']
o16 = df[df['nuclide'] == 'O-16']['mean']

# Cast DataFrames as NumPy arrays
h1 = h1.as_matrix()
o16 = o16.as_matrix()

# Reshape arrays to 2D matrix for plotting
h1.shape = (fine_groups.num_groups, fine_groups.num_groups)
o16.shape = (fine_groups.num_groups, fine_groups.num_groups)

Matplotlib's imshow routine can be used to plot the matrices to illustrate their sparsity structures.

In [33]:
# Create plot of the H-1 scattering matrix
fig = plt.subplot(121)
fig.imshow(h1, interpolation='nearest', cmap='jet')
plt.title('H-1 Scattering Matrix')
plt.xlabel('Group Out')
plt.ylabel('Group In')
plt.grid()

# Create plot of the O-16 scattering matrix
fig2 = plt.subplot(122)
fig2.imshow(o16, interpolation='nearest', cmap='jet')
plt.title('O-16 Scattering Matrix')
plt.xlabel('Group Out')
plt.ylabel('Group In')
plt.grid()

# Show the plot on screen
plt.show()
In [ ]: