StatePoint Files in OpenMC

What you'll learn

First pin cell · 10 / 1110 min read
  • Open a statepoint and pull out k-effective with its uncertainty.
  • Retrieve a tally by name and convert it to a pandas dataframe.
  • Judge whether a result has converged, using relative error and k by generation.

Before you start

Reading a statepoint back

A statepoint (statepoint.<batch>.h5) is the file model.run() writes, holding every tally's mean and standard deviation, k-effective for an eigenvalue run, and enough of the model to make sense of it. Open it and read out what you need — nothing here needs recomputing.

python
with openmc.StatePoint(statepoint_path) as sp:
    keff = sp.keff
    print(f"k-effective = {keff.nominal_value:.5f} ± {keff.std_dev:.5f}")

    tally = sp.get_tally(name='fuel_flux')   # the name must match a tally you defined
    mean = tally.mean
    rel_err = tally.std_dev / tally.mean

    df = tally.get_pandas_dataframe()   # full breakdown by filter bin, score, and nuclide

Tutorial snippet — no separate file in examples repo

get_pandas_dataframe() is the useful form once a tally carries more than one filter or score — it gives you one row per bin with columns for every filter, the score name, the mean, and the standard deviation, instead of the plain arrays that tally.mean returns.

Two independent checks decide whether a result is trustworthy. Relative error — std_dev / mean — falls as one over the square root of active histories, and should be comfortably under a percent or two for anything you plan to report. Separately, sp.k_generation gives k-effective batch by batch; plotted against batch number, it should look like noise scattered around a flat mean once the inactive batches have passed, not a value still drifting in one direction — a persistent trend past that point means the inactive count in Settings was too low.

The pin cell's statepoint

The pin cell's three named tallies — fuel_flux, clad_flux, and water_flux — come back out exactly as they were named going in. This is the same fragment that appears on Example: Pin Cell, which also works through the sanity checks — on k-effective, on the fuel's nu-fission-to-absorption ratio, and on relative error — that decide whether this particular run is one to trust.

python
with openmc.StatePoint(statepoint_path) as sp:
    keff = sp.keff

    fuel_flux = sp.get_tally(name='fuel_flux')
    clad_flux = sp.get_tally(name='clad_flux')
    water_flux = sp.get_tally(name='water_flux')

    nu_fission_rate = fuel_flux.get_slice(scores=['nu-fission'])
    absorption_rate = fuel_flux.get_slice(scores=['absorption'])

Tutorial snippet — no separate file in examples repo

One thing to try

Plot sp.k_generation against batch number, with a vertical line marking the end of the 20 inactive batches. Predict what the two halves of the plot will look like before you run it — the segment before the line is the fission source still settling from its starting guess, and the segment after is what the relative-error check above is actually measuring the noise of.

python
import matplotlib.pyplot as plt

keff_by_gen = sp.k_generation
batches = range(1, len(keff_by_gen) + 1)

plt.figure()
plt.axvline(20, linestyle='--', color='gray', label='end of inactive batches')
plt.plot(batches, keff_by_gen, 'o-')
plt.xlabel('Batch')
plt.ylabel('k-effective')
plt.legend()
plt.show()

Tutorial snippet — no separate file in examples repo

Check yourself

  • Open a statepoint and pull out k-effective with its uncertainty?
  • Retrieve a tally by name and convert it to a pandas dataframe?
  • Judge whether a result has converged, using relative error and k by generation?