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. We recommend using Pandas >v0.15.0 or later since OpenMC's Python API leverages the multi-indexing feature included in the most recent releases of Pandas.

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
from openmc.source import Source
from openmc.stats import Box
import openmoc
from openmoc.compatible import get_openmoc_geometry
import pyne.ace

%matplotlib inline


/usr/local/lib/python2.7/dist-packages/matplotlib/__init__.py:1318: 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/ipykernel/__main__.py:11: QAWarning: pyne.rxname is not yet QA compliant.
/usr/local/lib/python2.7/dist-packages/ipykernel/__main__.py:11: 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 MaterialsFile object that can be exported to an actual XML file.


In [4]:
# Instantiate a MaterialsFile, add Materials
materials_file = openmc.MaterialsFile()
materials_file.add_material(fuel)
materials_file.add_material(water)
materials_file.add_material(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, put the geometry into a GeometryFile object, and export it to XML.


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

# Instantiate a GeometryFile
geometry_file = openmc.GeometryFile()
geometry_file.geometry = openmc_geometry

# Export to "geometry.xml"
geometry_file.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 SettingsFile
settings_file = openmc.SettingsFile()
settings_file.batches = batches
settings_file.inactive = inactive
settings_file.particles = particles
settings_file.output = {'tallies': True, 'summary': True}
bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]
settings_file.source = Source(space=Box(
        bounds[:3], bounds[3:], only_fissionable=True))

# 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 TalliesFile
tallies_file = openmc.TalliesFile()

# 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 type to the cell
        xs_library[cell.id][rxn_type].domain = cell
        xs_library[cell.id][rxn_type].domain_type = '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.add_tally(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
executor = openmc.Executor()
executor.run_simulation(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-2015 Massachusetts Institute of Technology
      License:        http://mit-crpg.github.io/openmc/license.html
      Version:        0.7.1
      Git SHA1:       ea9fb637f63f9374c7436456141afa850b84acf9
      Date/Time:      2016-01-14 08:03:40

 ===========================================================================
 ========================>     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.22593                       
        2/1    1.24245                       
        3/1    1.24545                       
        4/1    1.21868                       
        5/1    1.22429                       
        6/1    1.22607                       
        7/1    1.21456                       
        8/1    1.23816                       
        9/1    1.25060                       
       10/1    1.22806                       
       11/1    1.19821                       
       12/1    1.19897    1.19859 +/- 0.00038
       13/1    1.22119    1.20612 +/- 0.00754
       14/1    1.20701    1.20634 +/- 0.00533
       15/1    1.24784    1.21464 +/- 0.00927
       16/1    1.22413    1.21622 +/- 0.00773
       17/1    1.25050    1.22112 +/- 0.00817
       18/1    1.22006    1.22099 +/- 0.00707
       19/1    1.22813    1.22178 +/- 0.00629
       20/1    1.22791    1.22239 +/- 0.00566
       21/1    1.22729    1.22284 +/- 0.00514
       22/1    1.19867    1.22083 +/- 0.00510
       23/1    1.23796    1.22214 +/- 0.00488
       24/1    1.22412    1.22228 +/- 0.00452
       25/1    1.22638    1.22256 +/- 0.00421
       26/1    1.22181    1.22251 +/- 0.00394
       27/1    1.19055    1.22063 +/- 0.00415
       28/1    1.20683    1.21986 +/- 0.00399
       29/1    1.21689    1.21971 +/- 0.00378
       30/1    1.23670    1.22056 +/- 0.00368
       31/1    1.21396    1.22024 +/- 0.00352
       32/1    1.21389    1.21995 +/- 0.00337
       33/1    1.24649    1.22111 +/- 0.00342
       34/1    1.23204    1.22156 +/- 0.00330
       35/1    1.20768    1.22101 +/- 0.00322
       36/1    1.22271    1.22107 +/- 0.00309
       37/1    1.21796    1.22096 +/- 0.00298
       38/1    1.23842    1.22158 +/- 0.00293
       39/1    1.23080    1.22190 +/- 0.00285
       40/1    1.23572    1.22236 +/- 0.00279
       41/1    1.21691    1.22218 +/- 0.00271
       42/1    1.24616    1.22293 +/- 0.00272
       43/1    1.21903    1.22282 +/- 0.00264
       44/1    1.22967    1.22302 +/- 0.00257
       45/1    1.22053    1.22295 +/- 0.00250
       46/1    1.24087    1.22344 +/- 0.00248
       47/1    1.20251    1.22288 +/- 0.00248
       48/1    1.20331    1.22236 +/- 0.00246
       49/1    1.22724    1.22249 +/- 0.00240
       50/1    1.24798    1.22313 +/- 0.00243
 Triggers unsatisfied, max unc./thresh. is 1.32110 for scatter-p1 in tally 10054
 The estimated number of batches is 80
 Creating state point statepoint.050.h5...
       51/1    1.22253    1.22311 +/- 0.00237
       52/1    1.24330    1.22359 +/- 0.00236
       53/1    1.23251    1.22380 +/- 0.00231
       54/1    1.21133    1.22352 +/- 0.00228
       55/1    1.24503    1.22399 +/- 0.00228
       56/1    1.22013    1.22391 +/- 0.00223
       57/1    1.23877    1.22423 +/- 0.00220
       58/1    1.23793    1.22451 +/- 0.00218
       59/1    1.21018    1.22422 +/- 0.00215
       60/1    1.22417    1.22422 +/- 0.00211
       61/1    1.23094    1.22435 +/- 0.00207
       62/1    1.23310    1.22452 +/- 0.00204
       63/1    1.22488    1.22453 +/- 0.00200
       64/1    1.22702    1.22457 +/- 0.00196
       65/1    1.18834    1.22391 +/- 0.00204
       66/1    1.23112    1.22404 +/- 0.00200
       67/1    1.21611    1.22390 +/- 0.00197
       68/1    1.22513    1.22392 +/- 0.00194
       69/1    1.21741    1.22381 +/- 0.00191
       70/1    1.22484    1.22383 +/- 0.00188
       71/1    1.19662    1.22338 +/- 0.00190
       72/1    1.23315    1.22354 +/- 0.00187
       73/1    1.22796    1.22361 +/- 0.00185
       74/1    1.21417    1.22346 +/- 0.00182
       75/1    1.21020    1.22326 +/- 0.00181
       76/1    1.23413    1.22343 +/- 0.00179
       77/1    1.22184    1.22340 +/- 0.00176
       78/1    1.20309    1.22310 +/- 0.00176
       79/1    1.23458    1.22327 +/- 0.00174
       80/1    1.20724    1.22304 +/- 0.00173
 Triggers satisfied for batch 80
 Creating state point statepoint.080.h5...

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


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

 Total time for initialization     =  3.8300E-01 seconds
   Reading cross sections          =  1.0700E-01 seconds
 Total time in simulation          =  2.5629E+02 seconds
   Time in transport only          =  2.5623E+02 seconds
   Time in inactive batches        =  1.5743E+01 seconds
   Time in active batches          =  2.4055E+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       =  1.0000E-03 seconds
 Total time for finalization       =  7.0000E-03 seconds
 Total time elapsed                =  2.5674E+02 seconds
 Calculation Rate (inactive)       =  6352.03 neutrons/second
 Calculation Rate (active)         =  1662.87 neutrons/second

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

 k-effective (Collision)     =  1.22327 +/-  0.00148
 k-effective (Track-length)  =  1.22304 +/-  0.00173
 k-effective (Absorption)    =  1.22407 +/-  0.00129
 Combined k-effective        =  1.22373 +/-  0.00113
 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.080.h5')

In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. This is necessary for the openmc.mgxs module to properly process the tally data. We first create a Summary object and link it with the statepoint.


In [16]:
# Load the summary file and link it with the statepoint
su = openmc.Summary('summary.h5')
sp.link_with_summary(su)

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 [17]:
# 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 [18]:
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.31e+00 +/- 1.88e-01%
            Group 2 [0.00553    - 0.821     MeV]:	3.97e+00 +/- 1.24e-01%
            Group 3 [4e-06      - 0.00553   MeV]:	5.50e+01 +/- 2.02e-01%
            Group 4 [6.25e-07   - 4e-06     MeV]:	8.83e+01 +/- 3.56e-01%
            Group 5 [2.8e-07    - 6.25e-07  MeV]:	2.90e+02 +/- 4.54e-01%
            Group 6 [1.4e-07    - 2.8e-07   MeV]:	4.49e+02 +/- 4.10e-01%
            Group 7 [5.8e-08    - 1.4e-07   MeV]:	6.87e+02 +/- 2.56e-01%
            Group 8 [0.0        - 5.8e-08   MeV]:	1.44e+03 +/- 2.82e-01%

	Nuclide        =	U-238
	Cross Sections [barns]:
            Group 1 [0.821      - 20.0      MeV]:	1.06e+00 +/- 2.30e-01%
            Group 2 [0.00553    - 0.821     MeV]:	1.21e-03 +/- 2.25e-01%
            Group 3 [4e-06      - 0.00553   MeV]:	5.82e-04 +/- 3.09e+00%
            Group 4 [6.25e-07   - 4e-06     MeV]:	6.54e-06 +/- 3.27e-01%
            Group 5 [2.8e-07    - 6.25e-07  MeV]:	1.07e-05 +/- 4.39e-01%
            Group 6 [1.4e-07    - 2.8e-07   MeV]:	1.55e-05 +/- 4.12e-01%
            Group 7 [5.8e-08    - 1.4e-07   MeV]:	2.30e-05 +/- 2.57e-01%
            Group 8 [0.0        - 5.8e-08   MeV]:	4.24e-05 +/- 2.81e-01%



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


In [19]:
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.19e-01%
            Group 2 [0.00553    - 0.821     MeV]:	1.51e-03 +/- 1.22e-01%
            Group 3 [4e-06      - 0.00553   MeV]:	2.06e-02 +/- 2.02e-01%
            Group 4 [6.25e-07   - 4e-06     MeV]:	3.31e-02 +/- 3.56e-01%
            Group 5 [2.8e-07    - 6.25e-07  MeV]:	1.09e-01 +/- 4.54e-01%
            Group 6 [1.4e-07    - 2.8e-07   MeV]:	1.69e-01 +/- 4.10e-01%
            Group 7 [5.8e-08    - 1.4e-07   MeV]:	2.58e-01 +/- 2.56e-01%
            Group 8 [0.0        - 5.8e-08   MeV]:	5.40e-01 +/- 2.82e-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 [20]:
nuscatter = xs_library[moderator_cell.id]['nu-scatter']
df = nuscatter.get_pandas_dataframe(xs_type='micro')
df.head(10)


/usr/local/lib/python2.7/dist-packages/numpy/lib/shape_base.py:872: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  return c.reshape(shape_out)
/usr/local/lib/python2.7/dist-packages/numpy/lib/shape_base.py:872: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  return c.reshape(shape_out)
Out[20]:
cell group in group out nuclide mean std. dev.
126 10002 1 1 H-1 0.234022 0.003645
127 10002 1 1 O-16 1.560305 0.006280
124 10002 1 2 H-1 1.588025 0.002815
125 10002 1 2 O-16 0.285147 0.001392
122 10002 1 3 H-1 0.010776 0.000186
123 10002 1 3 O-16 0.000000 0.000000
120 10002 1 4 H-1 0.000023 0.000010
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 [21]:
# 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 [22]:
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.81e-03 +/- 4.75e-01%
            Group 2 [0.0        - 6.25e-07  MeV]:	1.82e-01 +/- 1.89e-01%

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

	Nuclide        =	O-16
	Cross Sections [cm^-1]:
            Group 1 [6.25e-07   - 20.0      MeV]:	1.45e-01 +/- 1.50e-01%
            Group 2 [0.0        - 6.25e-07  MeV]:	1.74e-01 +/- 2.66e-01%




In [23]:
df = condensed_xs.get_pandas_dataframe(xs_type='micro')
df


/usr/local/lib/python2.7/dist-packages/numpy/lib/shape_base.py:872: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  return c.reshape(shape_out)
/usr/local/lib/python2.7/dist-packages/numpy/lib/shape_base.py:872: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  return c.reshape(shape_out)
Out[23]:
cell group in nuclide mean std. dev.
3 10000 1 U-235 20.828127 0.098842
4 10000 1 U-238 9.582295 0.012550
5 10000 1 O-16 3.157358 0.004725
0 10000 2 U-235 485.217649 0.916465
1 10000 2 U-238 11.176081 0.023196
2 10000 2 O-16 3.788167 0.010090

Verification with OpenMOC

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


In [24]:
# Create an OpenMOC Geometry from the OpenCG Geometry
openmoc_geometry = get_openmoc_geometry(su.opencg_geometry)

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


In [25]:
# 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 [26]:
# Generate tracks for OpenMOC
openmoc_geometry.initializeFlatSourceRegions()
track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=128, spacing=0.1)
track_generator.generateTracks()

# Run OpenMOC
solver = openmoc.CPUSolver(track_generator)
solver.computeEigenvalue()


[  NORMAL ]  Ray tracing for track segmentation...
[  NORMAL ]  Dumping tracks to file...
[  NORMAL ]  Computing the eigenvalue...
[  NORMAL ]  Iteration 0:	k_eff = 0.574633	res = 0.000E+00
[  NORMAL ]  Iteration 1:	k_eff = 0.679931	res = 4.254E-01
[  NORMAL ]  Iteration 2:	k_eff = 0.660910	res = 1.832E-01
[  NORMAL ]  Iteration 3:	k_eff = 0.658975	res = 2.798E-02
[  NORMAL ]  Iteration 4:	k_eff = 0.642976	res = 2.927E-03
[  NORMAL ]  Iteration 5:	k_eff = 0.625710	res = 2.428E-02
[  NORMAL ]  Iteration 6:	k_eff = 0.606520	res = 2.685E-02
[  NORMAL ]  Iteration 7:	k_eff = 0.587277	res = 3.067E-02
[  NORMAL ]  Iteration 8:	k_eff = 0.568777	res = 3.173E-02
[  NORMAL ]  Iteration 9:	k_eff = 0.551415	res = 3.150E-02
[  NORMAL ]  Iteration 10:	k_eff = 0.535708	res = 3.052E-02
[  NORMAL ]  Iteration 11:	k_eff = 0.521916	res = 2.849E-02
[  NORMAL ]  Iteration 12:	k_eff = 0.510221	res = 2.575E-02
[  NORMAL ]  Iteration 13:	k_eff = 0.500691	res = 2.241E-02
[  NORMAL ]  Iteration 14:	k_eff = 0.493392	res = 1.868E-02
[  NORMAL ]  Iteration 15:	k_eff = 0.488318	res = 1.458E-02
[  NORMAL ]  Iteration 16:	k_eff = 0.485438	res = 1.028E-02
[  NORMAL ]  Iteration 17:	k_eff = 0.484705	res = 5.896E-03
[  NORMAL ]  Iteration 18:	k_eff = 0.486046	res = 1.510E-03
[  NORMAL ]  Iteration 19:	k_eff = 0.489362	res = 2.766E-03
[  NORMAL ]  Iteration 20:	k_eff = 0.494546	res = 6.824E-03
[  NORMAL ]  Iteration 21:	k_eff = 0.501481	res = 1.059E-02
[  NORMAL ]  Iteration 22:	k_eff = 0.510042	res = 1.402E-02
[  NORMAL ]  Iteration 23:	k_eff = 0.520095	res = 1.707E-02
[  NORMAL ]  Iteration 24:	k_eff = 0.531508	res = 1.971E-02
[  NORMAL ]  Iteration 25:	k_eff = 0.544144	res = 2.194E-02
[  NORMAL ]  Iteration 26:	k_eff = 0.557872	res = 2.378E-02
[  NORMAL ]  Iteration 27:	k_eff = 0.572557	res = 2.523E-02
[  NORMAL ]  Iteration 28:	k_eff = 0.588073	res = 2.632E-02
[  NORMAL ]  Iteration 29:	k_eff = 0.604293	res = 2.710E-02
[  NORMAL ]  Iteration 30:	k_eff = 0.621101	res = 2.758E-02
[  NORMAL ]  Iteration 31:	k_eff = 0.638382	res = 2.781E-02
[  NORMAL ]  Iteration 32:	k_eff = 0.656032	res = 2.782E-02
[  NORMAL ]  Iteration 33:	k_eff = 0.673950	res = 2.765E-02
[  NORMAL ]  Iteration 34:	k_eff = 0.692043	res = 2.731E-02
[  NORMAL ]  Iteration 35:	k_eff = 0.710227	res = 2.685E-02
[  NORMAL ]  Iteration 36:	k_eff = 0.728423	res = 2.628E-02
[  NORMAL ]  Iteration 37:	k_eff = 0.746558	res = 2.562E-02
[  NORMAL ]  Iteration 38:	k_eff = 0.764569	res = 2.490E-02
[  NORMAL ]  Iteration 39:	k_eff = 0.782396	res = 2.412E-02
[  NORMAL ]  Iteration 40:	k_eff = 0.799990	res = 2.332E-02
[  NORMAL ]  Iteration 41:	k_eff = 0.817301	res = 2.249E-02
[  NORMAL ]  Iteration 42:	k_eff = 0.834292	res = 2.164E-02
[  NORMAL ]  Iteration 43:	k_eff = 0.850928	res = 2.079E-02
[  NORMAL ]  Iteration 44:	k_eff = 0.867178	res = 1.994E-02
[  NORMAL ]  Iteration 45:	k_eff = 0.883018	res = 1.910E-02
[  NORMAL ]  Iteration 46:	k_eff = 0.898427	res = 1.827E-02
[  NORMAL ]  Iteration 47:	k_eff = 0.913390	res = 1.745E-02
[  NORMAL ]  Iteration 48:	k_eff = 0.927892	res = 1.665E-02
[  NORMAL ]  Iteration 49:	k_eff = 0.941926	res = 1.588E-02
[  NORMAL ]  Iteration 50:	k_eff = 0.955484	res = 1.512E-02
[  NORMAL ]  Iteration 51:	k_eff = 0.968563	res = 1.439E-02
[  NORMAL ]  Iteration 52:	k_eff = 0.981162	res = 1.369E-02
[  NORMAL ]  Iteration 53:	k_eff = 0.993283	res = 1.301E-02
[  NORMAL ]  Iteration 54:	k_eff = 1.004929	res = 1.235E-02
[  NORMAL ]  Iteration 55:	k_eff = 1.016105	res = 1.172E-02
[  NORMAL ]  Iteration 56:	k_eff = 1.026818	res = 1.112E-02
[  NORMAL ]  Iteration 57:	k_eff = 1.037075	res = 1.054E-02
[  NORMAL ]  Iteration 58:	k_eff = 1.046885	res = 9.989E-03
[  NORMAL ]  Iteration 59:	k_eff = 1.056259	res = 9.459E-03
[  NORMAL ]  Iteration 60:	k_eff = 1.065206	res = 8.954E-03
[  NORMAL ]  Iteration 61:	k_eff = 1.073740	res = 8.471E-03
[  NORMAL ]  Iteration 62:	k_eff = 1.081872	res = 8.012E-03
[  NORMAL ]  Iteration 63:	k_eff = 1.089614	res = 7.573E-03
[  NORMAL ]  Iteration 64:	k_eff = 1.096980	res = 7.156E-03
[  NORMAL ]  Iteration 65:	k_eff = 1.103981	res = 6.760E-03
[  NORMAL ]  Iteration 66:	k_eff = 1.110631	res = 6.382E-03
[  NORMAL ]  Iteration 67:	k_eff = 1.116944	res = 6.024E-03
[  NORMAL ]  Iteration 68:	k_eff = 1.122932	res = 5.684E-03
[  NORMAL ]  Iteration 69:	k_eff = 1.128608	res = 5.361E-03
[  NORMAL ]  Iteration 70:	k_eff = 1.133985	res = 5.055E-03
[  NORMAL ]  Iteration 71:	k_eff = 1.139076	res = 4.764E-03
[  NORMAL ]  Iteration 72:	k_eff = 1.143892	res = 4.490E-03
[  NORMAL ]  Iteration 73:	k_eff = 1.148447	res = 4.228E-03
[  NORMAL ]  Iteration 74:	k_eff = 1.152753	res = 3.982E-03
[  NORMAL ]  Iteration 75:	k_eff = 1.156819	res = 3.749E-03
[  NORMAL ]  Iteration 76:	k_eff = 1.160659	res = 3.528E-03
[  NORMAL ]  Iteration 77:	k_eff = 1.164283	res = 3.319E-03
[  NORMAL ]  Iteration 78:	k_eff = 1.167701	res = 3.122E-03
[  NORMAL ]  Iteration 79:	k_eff = 1.170923	res = 2.936E-03
[  NORMAL ]  Iteration 80:	k_eff = 1.173960	res = 2.759E-03
[  NORMAL ]  Iteration 81:	k_eff = 1.176822	res = 2.594E-03
[  NORMAL ]  Iteration 82:	k_eff = 1.179516	res = 2.437E-03
[  NORMAL ]  Iteration 83:	k_eff = 1.182052	res = 2.289E-03
[  NORMAL ]  Iteration 84:	k_eff = 1.184438	res = 2.150E-03
[  NORMAL ]  Iteration 85:	k_eff = 1.186682	res = 2.018E-03
[  NORMAL ]  Iteration 86:	k_eff = 1.188792	res = 1.895E-03
[  NORMAL ]  Iteration 87:	k_eff = 1.190775	res = 1.778E-03
[  NORMAL ]  Iteration 88:	k_eff = 1.192639	res = 1.668E-03
[  NORMAL ]  Iteration 89:	k_eff = 1.194389	res = 1.565E-03
[  NORMAL ]  Iteration 90:	k_eff = 1.196032	res = 1.468E-03
[  NORMAL ]  Iteration 91:	k_eff = 1.197575	res = 1.375E-03
[  NORMAL ]  Iteration 92:	k_eff = 1.199023	res = 1.290E-03
[  NORMAL ]  Iteration 93:	k_eff = 1.200381	res = 1.209E-03
[  NORMAL ]  Iteration 94:	k_eff = 1.201654	res = 1.133E-03
[  NORMAL ]  Iteration 95:	k_eff = 1.202848	res = 1.061E-03
[  NORMAL ]  Iteration 96:	k_eff = 1.203968	res = 9.941E-04
[  NORMAL ]  Iteration 97:	k_eff = 1.205016	res = 9.308E-04
[  NORMAL ]  Iteration 98:	k_eff = 1.205999	res = 8.707E-04
[  NORMAL ]  Iteration 99:	k_eff = 1.206921	res = 8.159E-04
[  NORMAL ]  Iteration 100:	k_eff = 1.207783	res = 7.635E-04
[  NORMAL ]  Iteration 101:	k_eff = 1.208590	res = 7.145E-04
[  NORMAL ]  Iteration 102:	k_eff = 1.209345	res = 6.684E-04
[  NORMAL ]  Iteration 103:	k_eff = 1.210053	res = 6.250E-04
[  NORMAL ]  Iteration 104:	k_eff = 1.210714	res = 5.848E-04
[  NORMAL ]  Iteration 105:	k_eff = 1.211333	res = 5.466E-04
[  NORMAL ]  Iteration 106:	k_eff = 1.211913	res = 5.115E-04
[  NORMAL ]  Iteration 107:	k_eff = 1.212453	res = 4.784E-04
[  NORMAL ]  Iteration 108:	k_eff = 1.212960	res = 4.462E-04
[  NORMAL ]  Iteration 109:	k_eff = 1.213433	res = 4.175E-04
[  NORMAL ]  Iteration 110:	k_eff = 1.213875	res = 3.901E-04
[  NORMAL ]  Iteration 111:	k_eff = 1.214288	res = 3.643E-04
[  NORMAL ]  Iteration 112:	k_eff = 1.214674	res = 3.404E-04
[  NORMAL ]  Iteration 113:	k_eff = 1.215036	res = 3.181E-04
[  NORMAL ]  Iteration 114:	k_eff = 1.215372	res = 2.972E-04
[  NORMAL ]  Iteration 115:	k_eff = 1.215686	res = 2.772E-04
[  NORMAL ]  Iteration 116:	k_eff = 1.215980	res = 2.586E-04
[  NORMAL ]  Iteration 117:	k_eff = 1.216255	res = 2.416E-04
[  NORMAL ]  Iteration 118:	k_eff = 1.216511	res = 2.258E-04
[  NORMAL ]  Iteration 119:	k_eff = 1.216749	res = 2.105E-04
[  NORMAL ]  Iteration 120:	k_eff = 1.216973	res = 1.963E-04
[  NORMAL ]  Iteration 121:	k_eff = 1.217181	res = 1.834E-04
[  NORMAL ]  Iteration 122:	k_eff = 1.217375	res = 1.710E-04
[  NORMAL ]  Iteration 123:	k_eff = 1.217556	res = 1.595E-04
[  NORMAL ]  Iteration 124:	k_eff = 1.217725	res = 1.488E-04
[  NORMAL ]  Iteration 125:	k_eff = 1.217883	res = 1.389E-04
[  NORMAL ]  Iteration 126:	k_eff = 1.218030	res = 1.296E-04
[  NORMAL ]  Iteration 127:	k_eff = 1.218167	res = 1.208E-04
[  NORMAL ]  Iteration 128:	k_eff = 1.218294	res = 1.128E-04
[  NORMAL ]  Iteration 129:	k_eff = 1.218414	res = 1.041E-04
[  NORMAL ]  Iteration 130:	k_eff = 1.218525	res = 9.793E-05
[  NORMAL ]  Iteration 131:	k_eff = 1.218628	res = 9.128E-05
[  NORMAL ]  Iteration 132:	k_eff = 1.218725	res = 8.502E-05
[  NORMAL ]  Iteration 133:	k_eff = 1.218815	res = 7.903E-05
[  NORMAL ]  Iteration 134:	k_eff = 1.218899	res = 7.376E-05
[  NORMAL ]  Iteration 135:	k_eff = 1.218976	res = 6.888E-05
[  NORMAL ]  Iteration 136:	k_eff = 1.219049	res = 6.362E-05
[  NORMAL ]  Iteration 137:	k_eff = 1.219117	res = 5.979E-05
[  NORMAL ]  Iteration 138:	k_eff = 1.219180	res = 5.591E-05
[  NORMAL ]  Iteration 139:	k_eff = 1.219239	res = 5.181E-05
[  NORMAL ]  Iteration 140:	k_eff = 1.219294	res = 4.824E-05
[  NORMAL ]  Iteration 141:	k_eff = 1.219345	res = 4.496E-05
[  NORMAL ]  Iteration 142:	k_eff = 1.219392	res = 4.197E-05
[  NORMAL ]  Iteration 143:	k_eff = 1.219437	res = 3.871E-05
[  NORMAL ]  Iteration 144:	k_eff = 1.219478	res = 3.666E-05
[  NORMAL ]  Iteration 145:	k_eff = 1.219516	res = 3.373E-05
[  NORMAL ]  Iteration 146:	k_eff = 1.219552	res = 3.112E-05
[  NORMAL ]  Iteration 147:	k_eff = 1.219585	res = 2.941E-05
[  NORMAL ]  Iteration 148:	k_eff = 1.219616	res = 2.711E-05
[  NORMAL ]  Iteration 149:	k_eff = 1.219645	res = 2.542E-05
[  NORMAL ]  Iteration 150:	k_eff = 1.219671	res = 2.369E-05
[  NORMAL ]  Iteration 151:	k_eff = 1.219696	res = 2.207E-05
[  NORMAL ]  Iteration 152:	k_eff = 1.219720	res = 2.049E-05
[  NORMAL ]  Iteration 153:	k_eff = 1.219741	res = 1.903E-05
[  NORMAL ]  Iteration 154:	k_eff = 1.219761	res = 1.770E-05
[  NORMAL ]  Iteration 155:	k_eff = 1.219780	res = 1.639E-05
[  NORMAL ]  Iteration 156:	k_eff = 1.219797	res = 1.533E-05
[  NORMAL ]  Iteration 157:	k_eff = 1.219813	res = 1.396E-05
[  NORMAL ]  Iteration 158:	k_eff = 1.219828	res = 1.319E-05
[  NORMAL ]  Iteration 159:	k_eff = 1.219842	res = 1.216E-05
[  NORMAL ]  Iteration 160:	k_eff = 1.219854	res = 1.152E-05
[  NORMAL ]  Iteration 161:	k_eff = 1.219867	res = 1.049E-05
[  NORMAL ]  Iteration 162:	k_eff = 1.219878	res = 1.005E-05

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


In [27]:
# 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.223729
openmoc keff = 1.219878
bias [pcm]: -385.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 [28]:
openmoc_geometry = get_openmoc_geometry(su.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 [29]:
# Generate tracks for OpenMOC
openmoc_geometry.initializeFlatSourceRegions()
track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=128, 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.495594	res = 0.000E+00
[  NORMAL ]  Iteration 1:	k_eff = 0.557313	res = 5.044E-01
[  NORMAL ]  Iteration 2:	k_eff = 0.518115	res = 1.245E-01
[  NORMAL ]  Iteration 3:	k_eff = 0.509017	res = 7.033E-02
[  NORMAL ]  Iteration 4:	k_eff = 0.496280	res = 1.756E-02
[  NORMAL ]  Iteration 5:	k_eff = 0.488358	res = 2.502E-02
[  NORMAL ]  Iteration 6:	k_eff = 0.482660	res = 1.596E-02
[  NORMAL ]  Iteration 7:	k_eff = 0.479524	res = 1.167E-02
[  NORMAL ]  Iteration 8:	k_eff = 0.478569	res = 6.497E-03
[  NORMAL ]  Iteration 9:	k_eff = 0.479591	res = 1.992E-03
[  NORMAL ]  Iteration 10:	k_eff = 0.482389	res = 2.136E-03
[  NORMAL ]  Iteration 11:	k_eff = 0.486774	res = 5.834E-03
[  NORMAL ]  Iteration 12:	k_eff = 0.492576	res = 9.091E-03
[  NORMAL ]  Iteration 13:	k_eff = 0.499632	res = 1.192E-02
[  NORMAL ]  Iteration 14:	k_eff = 0.507800	res = 1.433E-02
[  NORMAL ]  Iteration 15:	k_eff = 0.516944	res = 1.635E-02
[  NORMAL ]  Iteration 16:	k_eff = 0.526942	res = 1.801E-02
[  NORMAL ]  Iteration 17:	k_eff = 0.537682	res = 1.934E-02
[  NORMAL ]  Iteration 18:	k_eff = 0.549061	res = 2.038E-02
[  NORMAL ]  Iteration 19:	k_eff = 0.560985	res = 2.116E-02
[  NORMAL ]  Iteration 20:	k_eff = 0.573368	res = 2.172E-02
[  NORMAL ]  Iteration 21:	k_eff = 0.586133	res = 2.207E-02
[  NORMAL ]  Iteration 22:	k_eff = 0.599208	res = 2.226E-02
[  NORMAL ]  Iteration 23:	k_eff = 0.612528	res = 2.231E-02
[  NORMAL ]  Iteration 24:	k_eff = 0.626035	res = 2.223E-02
[  NORMAL ]  Iteration 25:	k_eff = 0.639676	res = 2.205E-02
[  NORMAL ]  Iteration 26:	k_eff = 0.653402	res = 2.179E-02
[  NORMAL ]  Iteration 27:	k_eff = 0.667171	res = 2.146E-02
[  NORMAL ]  Iteration 28:	k_eff = 0.680942	res = 2.107E-02
[  NORMAL ]  Iteration 29:	k_eff = 0.694681	res = 2.064E-02
[  NORMAL ]  Iteration 30:	k_eff = 0.708356	res = 2.018E-02
[  NORMAL ]  Iteration 31:	k_eff = 0.721940	res = 1.969E-02
[  NORMAL ]  Iteration 32:	k_eff = 0.735407	res = 1.918E-02
[  NORMAL ]  Iteration 33:	k_eff = 0.748734	res = 1.865E-02
[  NORMAL ]  Iteration 34:	k_eff = 0.761904	res = 1.812E-02
[  NORMAL ]  Iteration 35:	k_eff = 0.774897	res = 1.759E-02
[  NORMAL ]  Iteration 36:	k_eff = 0.787700	res = 1.705E-02
[  NORMAL ]  Iteration 37:	k_eff = 0.800299	res = 1.652E-02
[  NORMAL ]  Iteration 38:	k_eff = 0.812684	res = 1.599E-02
[  NORMAL ]  Iteration 39:	k_eff = 0.824844	res = 1.548E-02
[  NORMAL ]  Iteration 40:	k_eff = 0.836773	res = 1.496E-02
[  NORMAL ]  Iteration 41:	k_eff = 0.848462	res = 1.446E-02
[  NORMAL ]  Iteration 42:	k_eff = 0.859908	res = 1.397E-02
[  NORMAL ]  Iteration 43:	k_eff = 0.871105	res = 1.349E-02
[  NORMAL ]  Iteration 44:	k_eff = 0.882052	res = 1.302E-02
[  NORMAL ]  Iteration 45:	k_eff = 0.892745	res = 1.257E-02
[  NORMAL ]  Iteration 46:	k_eff = 0.903184	res = 1.212E-02
[  NORMAL ]  Iteration 47:	k_eff = 0.913368	res = 1.169E-02
[  NORMAL ]  Iteration 48:	k_eff = 0.923296	res = 1.128E-02
[  NORMAL ]  Iteration 49:	k_eff = 0.932972	res = 1.087E-02
[  NORMAL ]  Iteration 50:	k_eff = 0.942394	res = 1.048E-02
[  NORMAL ]  Iteration 51:	k_eff = 0.951567	res = 1.010E-02
[  NORMAL ]  Iteration 52:	k_eff = 0.960491	res = 9.733E-03
[  NORMAL ]  Iteration 53:	k_eff = 0.969168	res = 9.378E-03
[  NORMAL ]  Iteration 54:	k_eff = 0.977604	res = 9.035E-03
[  NORMAL ]  Iteration 55:	k_eff = 0.985801	res = 8.704E-03
[  NORMAL ]  Iteration 56:	k_eff = 0.993762	res = 8.384E-03
[  NORMAL ]  Iteration 57:	k_eff = 1.001491	res = 8.076E-03
[  NORMAL ]  Iteration 58:	k_eff = 1.008992	res = 7.778E-03
[  NORMAL ]  Iteration 59:	k_eff = 1.016271	res = 7.490E-03
[  NORMAL ]  Iteration 60:	k_eff = 1.023329	res = 7.214E-03
[  NORMAL ]  Iteration 61:	k_eff = 1.030174	res = 6.945E-03
[  NORMAL ]  Iteration 62:	k_eff = 1.036809	res = 6.689E-03
[  NORMAL ]  Iteration 63:	k_eff = 1.043238	res = 6.441E-03
[  NORMAL ]  Iteration 64:	k_eff = 1.049466	res = 6.200E-03
[  NORMAL ]  Iteration 65:	k_eff = 1.055498	res = 5.970E-03
[  NORMAL ]  Iteration 66:	k_eff = 1.061338	res = 5.748E-03
[  NORMAL ]  Iteration 67:	k_eff = 1.066993	res = 5.533E-03
[  NORMAL ]  Iteration 68:	k_eff = 1.072465	res = 5.328E-03
[  NORMAL ]  Iteration 69:	k_eff = 1.077760	res = 5.128E-03
[  NORMAL ]  Iteration 70:	k_eff = 1.082882	res = 4.937E-03
[  NORMAL ]  Iteration 71:	k_eff = 1.087836	res = 4.753E-03
[  NORMAL ]  Iteration 72:	k_eff = 1.092627	res = 4.575E-03
[  NORMAL ]  Iteration 73:	k_eff = 1.097260	res = 4.404E-03
[  NORMAL ]  Iteration 74:	k_eff = 1.101737	res = 4.240E-03
[  NORMAL ]  Iteration 75:	k_eff = 1.106065	res = 4.080E-03
[  NORMAL ]  Iteration 76:	k_eff = 1.110247	res = 3.929E-03
[  NORMAL ]  Iteration 77:	k_eff = 1.114288	res = 3.781E-03
[  NORMAL ]  Iteration 78:	k_eff = 1.118191	res = 3.639E-03
[  NORMAL ]  Iteration 79:	k_eff = 1.121961	res = 3.502E-03
[  NORMAL ]  Iteration 80:	k_eff = 1.125602	res = 3.372E-03
[  NORMAL ]  Iteration 81:	k_eff = 1.129119	res = 3.245E-03
[  NORMAL ]  Iteration 82:	k_eff = 1.132513	res = 3.124E-03
[  NORMAL ]  Iteration 83:	k_eff = 1.135790	res = 3.006E-03
[  NORMAL ]  Iteration 84:	k_eff = 1.138954	res = 2.894E-03
[  NORMAL ]  Iteration 85:	k_eff = 1.142008	res = 2.786E-03
[  NORMAL ]  Iteration 86:	k_eff = 1.144954	res = 2.681E-03
[  NORMAL ]  Iteration 87:	k_eff = 1.147797	res = 2.580E-03
[  NORMAL ]  Iteration 88:	k_eff = 1.150539	res = 2.483E-03
[  NORMAL ]  Iteration 89:	k_eff = 1.153185	res = 2.389E-03
[  NORMAL ]  Iteration 90:	k_eff = 1.155738	res = 2.300E-03
[  NORMAL ]  Iteration 91:	k_eff = 1.158201	res = 2.214E-03
[  NORMAL ]  Iteration 92:	k_eff = 1.160575	res = 2.130E-03
[  NORMAL ]  Iteration 93:	k_eff = 1.162865	res = 2.050E-03
[  NORMAL ]  Iteration 94:	k_eff = 1.165074	res = 1.973E-03
[  NORMAL ]  Iteration 95:	k_eff = 1.167202	res = 1.899E-03
[  NORMAL ]  Iteration 96:	k_eff = 1.169255	res = 1.827E-03
[  NORMAL ]  Iteration 97:	k_eff = 1.171235	res = 1.759E-03
[  NORMAL ]  Iteration 98:	k_eff = 1.173142	res = 1.693E-03
[  NORMAL ]  Iteration 99:	k_eff = 1.174981	res = 1.629E-03
[  NORMAL ]  Iteration 100:	k_eff = 1.176753	res = 1.568E-03
[  NORMAL ]  Iteration 101:	k_eff = 1.178461	res = 1.508E-03
[  NORMAL ]  Iteration 102:	k_eff = 1.180108	res = 1.452E-03
[  NORMAL ]  Iteration 103:	k_eff = 1.181694	res = 1.397E-03
[  NORMAL ]  Iteration 104:	k_eff = 1.183223	res = 1.344E-03
[  NORMAL ]  Iteration 105:	k_eff = 1.184696	res = 1.294E-03
[  NORMAL ]  Iteration 106:	k_eff = 1.186115	res = 1.245E-03
[  NORMAL ]  Iteration 107:	k_eff = 1.187482	res = 1.198E-03
[  NORMAL ]  Iteration 108:	k_eff = 1.188800	res = 1.152E-03
[  NORMAL ]  Iteration 109:	k_eff = 1.190069	res = 1.110E-03
[  NORMAL ]  Iteration 110:	k_eff = 1.191290	res = 1.067E-03
[  NORMAL ]  Iteration 111:	k_eff = 1.192469	res = 1.026E-03
[  NORMAL ]  Iteration 112:	k_eff = 1.193602	res = 9.889E-04
[  NORMAL ]  Iteration 113:	k_eff = 1.194694	res = 9.503E-04
[  NORMAL ]  Iteration 114:	k_eff = 1.195747	res = 9.154E-04
[  NORMAL ]  Iteration 115:	k_eff = 1.196759	res = 8.808E-04
[  NORMAL ]  Iteration 116:	k_eff = 1.197735	res = 8.464E-04
[  NORMAL ]  Iteration 117:	k_eff = 1.198674	res = 8.155E-04
[  NORMAL ]  Iteration 118:	k_eff = 1.199579	res = 7.845E-04
[  NORMAL ]  Iteration 119:	k_eff = 1.200450	res = 7.550E-04
[  NORMAL ]  Iteration 120:	k_eff = 1.201289	res = 7.263E-04
[  NORMAL ]  Iteration 121:	k_eff = 1.202097	res = 6.984E-04
[  NORMAL ]  Iteration 122:	k_eff = 1.202875	res = 6.728E-04
[  NORMAL ]  Iteration 123:	k_eff = 1.203623	res = 6.470E-04
[  NORMAL ]  Iteration 124:	k_eff = 1.204344	res = 6.220E-04
[  NORMAL ]  Iteration 125:	k_eff = 1.205037	res = 5.994E-04
[  NORMAL ]  Iteration 126:	k_eff = 1.205706	res = 5.757E-04
[  NORMAL ]  Iteration 127:	k_eff = 1.206349	res = 5.551E-04
[  NORMAL ]  Iteration 128:	k_eff = 1.206968	res = 5.328E-04
[  NORMAL ]  Iteration 129:	k_eff = 1.207565	res = 5.132E-04
[  NORMAL ]  Iteration 130:	k_eff = 1.208138	res = 4.944E-04
[  NORMAL ]  Iteration 131:	k_eff = 1.208690	res = 4.749E-04
[  NORMAL ]  Iteration 132:	k_eff = 1.209221	res = 4.566E-04
[  NORMAL ]  Iteration 133:	k_eff = 1.209733	res = 4.395E-04
[  NORMAL ]  Iteration 134:	k_eff = 1.210226	res = 4.232E-04
[  NORMAL ]  Iteration 135:	k_eff = 1.210700	res = 4.076E-04
[  NORMAL ]  Iteration 136:	k_eff = 1.211156	res = 3.916E-04
[  NORMAL ]  Iteration 137:	k_eff = 1.211595	res = 3.767E-04
[  NORMAL ]  Iteration 138:	k_eff = 1.212017	res = 3.628E-04
[  NORMAL ]  Iteration 139:	k_eff = 1.212423	res = 3.486E-04
[  NORMAL ]  Iteration 140:	k_eff = 1.212814	res = 3.350E-04
[  NORMAL ]  Iteration 141:	k_eff = 1.213191	res = 3.227E-04
[  NORMAL ]  Iteration 142:	k_eff = 1.213554	res = 3.107E-04
[  NORMAL ]  Iteration 143:	k_eff = 1.213902	res = 2.989E-04
[  NORMAL ]  Iteration 144:	k_eff = 1.214238	res = 2.869E-04
[  NORMAL ]  Iteration 145:	k_eff = 1.214561	res = 2.770E-04
[  NORMAL ]  Iteration 146:	k_eff = 1.214872	res = 2.659E-04
[  NORMAL ]  Iteration 147:	k_eff = 1.215171	res = 2.558E-04
[  NORMAL ]  Iteration 148:	k_eff = 1.215458	res = 2.458E-04
[  NORMAL ]  Iteration 149:	k_eff = 1.215735	res = 2.361E-04
[  NORMAL ]  Iteration 150:	k_eff = 1.216002	res = 2.281E-04
[  NORMAL ]  Iteration 151:	k_eff = 1.216258	res = 2.194E-04
[  NORMAL ]  Iteration 152:	k_eff = 1.216505	res = 2.110E-04
[  NORMAL ]  Iteration 153:	k_eff = 1.216742	res = 2.028E-04
[  NORMAL ]  Iteration 154:	k_eff = 1.216970	res = 1.952E-04
[  NORMAL ]  Iteration 155:	k_eff = 1.217191	res = 1.876E-04
[  NORMAL ]  Iteration 156:	k_eff = 1.217402	res = 1.809E-04
[  NORMAL ]  Iteration 157:	k_eff = 1.217605	res = 1.734E-04
[  NORMAL ]  Iteration 158:	k_eff = 1.217800	res = 1.673E-04
[  NORMAL ]  Iteration 159:	k_eff = 1.217988	res = 1.602E-04
[  NORMAL ]  Iteration 160:	k_eff = 1.218169	res = 1.546E-04
[  NORMAL ]  Iteration 161:	k_eff = 1.218344	res = 1.485E-04
[  NORMAL ]  Iteration 162:	k_eff = 1.218511	res = 1.429E-04
[  NORMAL ]  Iteration 163:	k_eff = 1.218672	res = 1.378E-04
[  NORMAL ]  Iteration 164:	k_eff = 1.218828	res = 1.323E-04
[  NORMAL ]  Iteration 165:	k_eff = 1.218977	res = 1.273E-04
[  NORMAL ]  Iteration 166:	k_eff = 1.219121	res = 1.225E-04
[  NORMAL ]  Iteration 167:	k_eff = 1.219259	res = 1.182E-04
[  NORMAL ]  Iteration 168:	k_eff = 1.219392	res = 1.131E-04
[  NORMAL ]  Iteration 169:	k_eff = 1.219520	res = 1.090E-04
[  NORMAL ]  Iteration 170:	k_eff = 1.219643	res = 1.050E-04
[  NORMAL ]  Iteration 171:	k_eff = 1.219761	res = 1.008E-04
[  NORMAL ]  Iteration 172:	k_eff = 1.219876	res = 9.712E-05
[  NORMAL ]  Iteration 173:	k_eff = 1.219985	res = 9.360E-05
[  NORMAL ]  Iteration 174:	k_eff = 1.220090	res = 8.946E-05
[  NORMAL ]  Iteration 175:	k_eff = 1.220191	res = 8.611E-05
[  NORMAL ]  Iteration 176:	k_eff = 1.220288	res = 8.299E-05
[  NORMAL ]  Iteration 177:	k_eff = 1.220382	res = 7.977E-05
[  NORMAL ]  Iteration 178:	k_eff = 1.220472	res = 7.682E-05
[  NORMAL ]  Iteration 179:	k_eff = 1.220560	res = 7.421E-05
[  NORMAL ]  Iteration 180:	k_eff = 1.220643	res = 7.140E-05
[  NORMAL ]  Iteration 181:	k_eff = 1.220724	res = 6.824E-05
[  NORMAL ]  Iteration 182:	k_eff = 1.220801	res = 6.591E-05
[  NORMAL ]  Iteration 183:	k_eff = 1.220875	res = 6.353E-05
[  NORMAL ]  Iteration 184:	k_eff = 1.220946	res = 6.092E-05
[  NORMAL ]  Iteration 185:	k_eff = 1.221015	res = 5.826E-05
[  NORMAL ]  Iteration 186:	k_eff = 1.221081	res = 5.613E-05
[  NORMAL ]  Iteration 187:	k_eff = 1.221145	res = 5.433E-05
[  NORMAL ]  Iteration 188:	k_eff = 1.221206	res = 5.230E-05
[  NORMAL ]  Iteration 189:	k_eff = 1.221266	res = 5.025E-05
[  NORMAL ]  Iteration 190:	k_eff = 1.221322	res = 4.833E-05
[  NORMAL ]  Iteration 191:	k_eff = 1.221376	res = 4.642E-05
[  NORMAL ]  Iteration 192:	k_eff = 1.221429	res = 4.437E-05
[  NORMAL ]  Iteration 193:	k_eff = 1.221479	res = 4.286E-05
[  NORMAL ]  Iteration 194:	k_eff = 1.221528	res = 4.123E-05
[  NORMAL ]  Iteration 195:	k_eff = 1.221574	res = 3.993E-05
[  NORMAL ]  Iteration 196:	k_eff = 1.221619	res = 3.785E-05
[  NORMAL ]  Iteration 197:	k_eff = 1.221662	res = 3.669E-05
[  NORMAL ]  Iteration 198:	k_eff = 1.221704	res = 3.547E-05
[  NORMAL ]  Iteration 199:	k_eff = 1.221743	res = 3.387E-05
[  NORMAL ]  Iteration 200:	k_eff = 1.221781	res = 3.243E-05
[  NORMAL ]  Iteration 201:	k_eff = 1.221818	res = 3.127E-05
[  NORMAL ]  Iteration 202:	k_eff = 1.221854	res = 3.018E-05
[  NORMAL ]  Iteration 203:	k_eff = 1.221888	res = 2.924E-05
[  NORMAL ]  Iteration 204:	k_eff = 1.221921	res = 2.786E-05
[  NORMAL ]  Iteration 205:	k_eff = 1.221952	res = 2.677E-05
[  NORMAL ]  Iteration 206:	k_eff = 1.221982	res = 2.579E-05
[  NORMAL ]  Iteration 207:	k_eff = 1.222011	res = 2.468E-05
[  NORMAL ]  Iteration 208:	k_eff = 1.222039	res = 2.377E-05
[  NORMAL ]  Iteration 209:	k_eff = 1.222066	res = 2.288E-05
[  NORMAL ]  Iteration 210:	k_eff = 1.222093	res = 2.204E-05
[  NORMAL ]  Iteration 211:	k_eff = 1.222118	res = 2.117E-05
[  NORMAL ]  Iteration 212:	k_eff = 1.222141	res = 2.044E-05
[  NORMAL ]  Iteration 213:	k_eff = 1.222165	res = 1.954E-05
[  NORMAL ]  Iteration 214:	k_eff = 1.222187	res = 1.899E-05
[  NORMAL ]  Iteration 215:	k_eff = 1.222208	res = 1.797E-05
[  NORMAL ]  Iteration 216:	k_eff = 1.222229	res = 1.745E-05
[  NORMAL ]  Iteration 217:	k_eff = 1.222248	res = 1.686E-05
[  NORMAL ]  Iteration 218:	k_eff = 1.222267	res = 1.623E-05
[  NORMAL ]  Iteration 219:	k_eff = 1.222286	res = 1.568E-05
[  NORMAL ]  Iteration 220:	k_eff = 1.222304	res = 1.508E-05
[  NORMAL ]  Iteration 221:	k_eff = 1.222320	res = 1.458E-05
[  NORMAL ]  Iteration 222:	k_eff = 1.222337	res = 1.387E-05
[  NORMAL ]  Iteration 223:	k_eff = 1.222353	res = 1.337E-05
[  NORMAL ]  Iteration 224:	k_eff = 1.222368	res = 1.286E-05
[  NORMAL ]  Iteration 225:	k_eff = 1.222382	res = 1.230E-05
[  NORMAL ]  Iteration 226:	k_eff = 1.222396	res = 1.201E-05
[  NORMAL ]  Iteration 227:	k_eff = 1.222409	res = 1.131E-05
[  NORMAL ]  Iteration 228:	k_eff = 1.222422	res = 1.082E-05
[  NORMAL ]  Iteration 229:	k_eff = 1.222435	res = 1.051E-05
[  NORMAL ]  Iteration 230:	k_eff = 1.222447	res = 1.015E-05

In [30]:
# 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.223729
openmoc keff = 1.222447
bias [pcm]: -128.2

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 [31]:
# 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 [32]:
# 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[32]:
(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 [33]:
# 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)


/usr/local/lib/python2.7/dist-packages/numpy/lib/shape_base.py:872: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  return c.reshape(shape_out)
/usr/local/lib/python2.7/dist-packages/numpy/lib/shape_base.py:872: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  return c.reshape(shape_out)

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


In [34]:
# 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()