diff --git a/docs/source/conf.py b/docs/source/conf.py index 8af607a4b..65ee4db6f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -28,7 +28,8 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.pngmath', 'sphinxcontrib.tikz', - 'sphinx_numfig'] + 'sphinx_numfig', + 'notebook_sphinxext'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/docs/source/pythonapi/examples/tally-arithmetic.ipynb b/docs/source/pythonapi/examples/tally-arithmetic.ipynb new file mode 100644 index 000000000..3223f23aa --- /dev/null +++ b/docs/source/pythonapi/examples/tally-arithmetic.ipynb @@ -0,0 +1,1512 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook shows the how tallies can be combined (added, subtracted, multiplied, etc.) using the Python API in order to create derived tallies. Since no covariance information is obtained, it is assumed that tallies are completely independent of one another when propagating uncertainties. The target problem is a simple pin cell.\n", + "\n", + "**Note:** that this Notebook was created using the latest Pandas v0.16.1. Everything in the Notebook will wun with older versions of Pandas, but the multi-indexing option in >v0.15.0 makes the tables look prettier." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import glob\n", + "from IPython.display import Image\n", + "import numpy as np\n", + "\n", + "import openmc\n", + "from openmc.statepoint import StatePoint\n", + "from openmc.summary import Summary\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate Input Files" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate some Nuclides\n", + "h1 = openmc.Nuclide('H-1')\n", + "b10 = openmc.Nuclide('B-10')\n", + "o16 = openmc.Nuclide('O-16')\n", + "u235 = openmc.Nuclide('U-235')\n", + "u238 = openmc.Nuclide('U-238')\n", + "zr90 = openmc.Nuclide('Zr-90')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the nuclides we defined, we will now create three materials for the fuel, water, and cladding of the fuel pin." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 1.6 enriched fuel\n", + "fuel = openmc.Material(name='1.6% Fuel')\n", + "fuel.set_density('g/cm3', 10.31341)\n", + "fuel.add_nuclide(u235, 3.7503e-4)\n", + "fuel.add_nuclide(u238, 2.2625e-2)\n", + "fuel.add_nuclide(o16, 4.6007e-2)\n", + "\n", + "# borated water\n", + "water = openmc.Material(name='Borated Water')\n", + "water.set_density('g/cm3', 0.740582)\n", + "water.add_nuclide(h1, 4.9457e-2)\n", + "water.add_nuclide(o16, 2.4732e-2)\n", + "water.add_nuclide(b10, 8.0042e-6)\n", + "\n", + "# zircaloy\n", + "zircaloy = openmc.Material(name='Zircaloy')\n", + "zircaloy.set_density('g/cm3', 6.55)\n", + "zircaloy.add_nuclide(zr90, 7.2758e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With our three materials, we can now create a materials file object that can be exported to an actual XML file." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a MaterialsFile, add Materials\n", + "materials_file = openmc.MaterialsFile()\n", + "materials_file.add_material(fuel)\n", + "materials_file.add_material(water)\n", + "materials_file.add_material(zircaloy)\n", + "materials_file.default_xs = '71c'\n", + "\n", + "# Export to \"materials.xml\"\n", + "materials_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create cylinders for the fuel and clad\n", + "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218)\n", + "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720)\n", + "\n", + "# Create boundary planes to surround the geometry\n", + "# Use both reflective and vacuum boundaries to make life interesting\n", + "min_x = openmc.XPlane(x0=-0.63, boundary_type='reflective')\n", + "max_x = openmc.XPlane(x0=+0.63, boundary_type='reflective')\n", + "min_y = openmc.YPlane(y0=-0.63, boundary_type='reflective')\n", + "max_y = openmc.YPlane(y0=+0.63, boundary_type='reflective')\n", + "min_z = openmc.ZPlane(z0=-0.63, boundary_type='reflective')\n", + "max_z = openmc.ZPlane(z0=+0.63, boundary_type='reflective')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create a Universe to encapsulate a fuel pin\n", + "pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin')\n", + "\n", + "# Create fuel Cell\n", + "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", + "fuel_cell.fill = fuel\n", + "fuel_cell.add_surface(fuel_outer_radius, halfspace=-1)\n", + "pin_cell_universe.add_cell(fuel_cell)\n", + "\n", + "# Create a clad Cell\n", + "clad_cell = openmc.Cell(name='1.6% Clad')\n", + "clad_cell.fill = zircaloy\n", + "clad_cell.add_surface(fuel_outer_radius, halfspace=+1)\n", + "clad_cell.add_surface(clad_outer_radius, halfspace=-1)\n", + "pin_cell_universe.add_cell(clad_cell)\n", + "\n", + "# Create a moderator Cell\n", + "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", + "moderator_cell.fill = water\n", + "moderator_cell.add_surface(clad_outer_radius, halfspace=+1)\n", + "pin_cell_universe.add_cell(moderator_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create root Cell\n", + "root_cell = openmc.Cell(name='root cell')\n", + "root_cell.fill = pin_cell_universe\n", + "\n", + "# Add boundary planes\n", + "root_cell.add_surface(min_x, halfspace=+1)\n", + "root_cell.add_surface(max_x, halfspace=-1)\n", + "root_cell.add_surface(min_y, halfspace=+1)\n", + "root_cell.add_surface(max_y, halfspace=-1)\n", + "root_cell.add_surface(min_z, halfspace=+1)\n", + "root_cell.add_surface(max_z, halfspace=-1)\n", + "\n", + "# Create root Universe\n", + "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", + "root_universe.add_cell(root_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now must create a geometry that is assigned a root universe, put the geometry into a geometry file, and export it to XML." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create Geometry and set root Universe\n", + "geometry = openmc.Geometry()\n", + "geometry.root_universe = root_universe" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a GeometryFile\n", + "geometry_file = openmc.GeometryFile()\n", + "geometry_file.geometry = geometry\n", + "\n", + "# Export to \"geometry.xml\"\n", + "geometry_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 5 inactive batches and 15 active batches each with 2500 particles." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# OpenMC simulation parameters\n", + "batches = 20\n", + "inactive = 5\n", + "particles = 2500\n", + "\n", + "# Instantiate a SettingsFile\n", + "settings_file = openmc.SettingsFile()\n", + "settings_file.batches = batches\n", + "settings_file.inactive = inactive\n", + "settings_file.particles = particles\n", + "settings_file.output = {'tallies': True, 'summary': True}\n", + "source_bounds = [-0.63, -0.63, -10, 0.63, 0.63, 10.]\n", + "settings_file.set_source_space('box', source_bounds)\n", + "\n", + "# Export to \"settings.xml\"\n", + "settings_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us also create a plot file that we can use to verify that our pin cell geometry was created successfully." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a Plot\n", + "plot = openmc.Plot(plot_id=1)\n", + "plot.filename = 'materials-xy'\n", + "plot.origin = [0, 0, 0]\n", + "plot.width = [1.26, 1.26]\n", + "plot.pixels = [250, 250]\n", + "plot.color = 'mat'\n", + "\n", + "# Instantiate a PlotsFile, add Plot, and export to \"plots.xml\"\n", + "plot_file = openmc.PlotsFile()\n", + "plot_file.add_plot(plot)\n", + "plot_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the plots.xml file, we can now generate and view the plot. OpenMC outputs plots in .ppm format, which can be converted into a compressed format like .png with the convert utility." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Run openmc in plotting mode\n", + "executor = openmc.Executor()\n", + "executor.plot_geometry(output=False)\n", + "\n", + "# Convert OpenMC's funky ppm to png\n", + "!convert materials-xy.ppm materials-xy.png" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAALKSURB\nVGje7dpLcqQwDAbgHHE2YeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmN\nP+HDhw8fPnz48Kf6VH9G+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4\nzPji99z0/AJ4n1lfvJ6fnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6\npA0wfln+ho/fwgYYn19C/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tN\nDbSGz7T0SBEWw4vLXzbQ6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X5\n8wZaxWd1+fMGiuFvir8bvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV\n873hB8UnM3xzANtf8nb4dwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7\nT/ppARBvp48UwJnelT5SACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4/\n/Jve+fhsH6Ctv7n8PTzjvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V\n32/o9+fl389Xnx+g5x/o+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6\n/4Le/6D3T/D9V67Y/ZsVQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/\ngPs/0P4TtP8F7r9J3AIO9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTu\nf4X7b+H+X7T/+BPuf3aM8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIw\nMTUtMDgtMDZUMTY6NDM6MTMrMDc6MDBtUQj+AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA4LTA2\nVDE2OjQzOjEzKzA3OjAwHAywQgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Display the materials plot inline\n", + "Image(filename='materials-xy.png')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see from the plot, we have a nice pin cell with fuel, cladding, and water! Before we run our simulation, we need to tell the code what we want to tally. The following code shows how to create a variety of tallies." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate an empty TalliesFile\n", + "tallies_file = openmc.TalliesFile()\n", + "tallies_file.tallies = []" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create Tallies to compute microscopic multi-group cross-sections\n", + "\n", + "# Instantiate energy filter for multi-group cross-section Tallies\n", + "energy_filter = openmc.Filter(type='energy', bins=[0., 0.625e-6, 20.])\n", + "\n", + "# Instantiate flux Tally in moderator and fuel\n", + "tally = openmc.Tally(name='flux')\n", + "tally.add_filter(openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id]))\n", + "tally.add_filter(energy_filter)\n", + "tally.add_score('flux')\n", + "tallies_file.add_tally(tally)\n", + "\n", + "# Instantiate reaction rate Tally in fuel\n", + "tally = openmc.Tally(name='fuel rxn rates')\n", + "tally.add_filter(openmc.Filter(type='cell', bins=[fuel_cell.id]))\n", + "tally.add_filter(energy_filter)\n", + "tally.add_score('nu-fission')\n", + "tally.add_score('scatter')\n", + "tally.add_nuclide(u238)\n", + "tally.add_nuclide(u235)\n", + "tallies_file.add_tally(tally)\n", + "\n", + "# Instantiate reaction rate Tally in moderator\n", + "tally = openmc.Tally(name='moderator rxn rates')\n", + "tally.add_filter(openmc.Filter(type='cell', bins=[moderator_cell.id]))\n", + "tally.add_filter(energy_filter)\n", + "tally.add_score('absorption')\n", + "tally.add_score('total')\n", + "tally.add_nuclide(o16)\n", + "tally.add_nuclide(h1)\n", + "tallies_file.add_tally(tally)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# K-Eigenvalue (infinity) tallies\n", + "fiss_rate = openmc.Tally(name='fiss. rate')\n", + "abs_rate = openmc.Tally(name='abs. rate')\n", + "fiss_rate.add_score('nu-fission')\n", + "abs_rate.add_score('absorption')\n", + "tallies_file.add_tally(fiss_rate)\n", + "tallies_file.add_tally(abs_rate)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Resonance Escape Probability tallies\n", + "therm_abs_rate = openmc.Tally(name='therm. abs. rate')\n", + "therm_abs_rate.add_score('absorption')\n", + "therm_abs_rate.add_filter(openmc.Filter(type='energy', bins=[0., 0.625]))\n", + "tallies_file.add_tally(therm_abs_rate)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Thermal Flux Utilization tallies\n", + "fuel_therm_abs_rate = openmc.Tally(name='fuel therm. abs. rate')\n", + "fuel_therm_abs_rate.add_score('absorption')\n", + "fuel_therm_abs_rate.add_filter(openmc.Filter(type='energy', bins=[0., 0.625]))\n", + "fuel_therm_abs_rate.add_filter(openmc.Filter(type='cell', bins=[fuel_cell.id]))\n", + "tallies_file.add_tally(fuel_therm_abs_rate)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Fast Fission Factor tallies\n", + "therm_fiss_rate = openmc.Tally(name='therm. fiss. rate')\n", + "tot_fiss_rate = openmc.Tally(name='tot. fiss. rate')\n", + "therm_fiss_rate.add_score('fission')\n", + "tot_fiss_rate.add_score('fission')\n", + "therm_fiss_rate.add_filter(openmc.Filter(type='energy', bins=[0., 0.625]))\n", + "tallies_file.add_tally(therm_fiss_rate)\n", + "tallies_file.add_tally(tot_fiss_rate)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate energy filter to illustrate Tally slicing\n", + "energy_filter = openmc.Filter(type='energy', bins=np.logspace(np.log10(1e-8), np.log10(20), 10))\n", + "\n", + "# Instantiate flux Tally in moderator and fuel\n", + "tally = openmc.Tally(name='need-to-slice')\n", + "tally.add_filter(openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id]))\n", + "tally.add_filter(energy_filter)\n", + "tally.add_score('nu-fission')\n", + "tally.add_score('scatter')\n", + "tally.add_nuclide(h1)\n", + "tally.add_nuclide(u238)\n", + "tallies_file.add_tally(tally)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Export to \"tallies.xml\"\n", + "tallies_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we a have a complete set of inputs, so we can go ahead and run our simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " .d88888b. 888b d888 .d8888b.\n", + " d88P\" \"Y88b 8888b d8888 d88P Y88b\n", + " 888 888 88888b.d88888 888 888\n", + " 888 888 88888b. .d88b. 88888b. 888Y88888P888 888 \n", + " 888 888 888 \"88b d8P Y8b 888 \"88b 888 Y888P 888 888 \n", + " 888 888 888 888 88888888 888 888 888 Y8P 888 888 888\n", + " Y88b. .d88P 888 d88P Y8b. 888 888 888 \" 888 Y88b d88P\n", + " \"Y88888P\" 88888P\" \"Y8888 888 888 888 888 \"Y8888P\"\n", + "__________________888______________________________________________________\n", + " 888\n", + " 888\n", + "\n", + " Copyright: 2011-2015 Massachusetts Institute of Technology\n", + " License: http://mit-crpg.github.io/openmc/license.html\n", + " Version: 0.6.2\n", + " Date/Time: 2015-08-07 11:12:08\n", + " MPI Processes: 4\n", + "\n", + " ===========================================================================\n", + " ========================> INITIALIZATION <=========================\n", + " ===========================================================================\n", + "\n", + " Reading settings XML file...\n", + " Reading cross sections XML file...\n", + " Reading geometry XML file...\n", + " Reading materials XML file...\n", + " Reading tallies XML file...\n", + " Building neighboring cells lists for each surface...\n", + " Loading ACE cross section table: 92238.71c\n", + " Loading ACE cross section table: 8016.71c\n", + " Loading ACE cross section table: 92235.71c\n", + " Loading ACE cross section table: 5010.71c\n", + " Loading ACE cross section table: 1001.71c\n", + " Loading ACE cross section table: 40090.71c\n", + " Initializing source particles...\n", + "\n", + " ===========================================================================\n", + " ====================> K EIGENVALUE SIMULATION <====================\n", + " ===========================================================================\n", + "\n", + " Bat./Gen. k Average k \n", + " ========= ======== ==================== \n", + " 1/1 1.04944 \n", + " 2/1 1.03451 \n", + " 3/1 1.06490 \n", + " 4/1 1.04020 \n", + " 5/1 1.03270 \n", + " 6/1 1.09507 \n", + " 7/1 1.06827 1.08167 +/- 0.01340\n", + " 8/1 1.06089 1.07474 +/- 0.01038\n", + " 9/1 1.03806 1.06557 +/- 0.01175\n", + " 10/1 1.05032 1.06252 +/- 0.00960\n", + " 11/1 1.03259 1.05753 +/- 0.00929\n", + " 12/1 1.02588 1.05301 +/- 0.00906\n", + " 13/1 1.03872 1.05123 +/- 0.00805\n", + " 14/1 1.05396 1.05153 +/- 0.00710\n", + " 15/1 1.03818 1.05019 +/- 0.00649\n", + " 16/1 1.05015 1.05019 +/- 0.00587\n", + " 17/1 1.01418 1.04719 +/- 0.00614\n", + " 18/1 1.07342 1.04921 +/- 0.00600\n", + " 19/1 1.03023 1.04785 +/- 0.00572\n", + " 20/1 1.05405 1.04827 +/- 0.00534\n", + " Creating state point statepoint.20.h5...\n", + "\n", + " ===========================================================================\n", + " ======================> SIMULATION FINISHED <======================\n", + " ===========================================================================\n", + "\n", + "\n", + " =======================> TIMING STATISTICS <=======================\n", + "\n", + " Total time for initialization = 9.0500E-01 seconds\n", + " Reading cross sections = 2.6500E-01 seconds\n", + " Total time in simulation = 8.9630E+00 seconds\n", + " Time in transport only = 8.1580E+00 seconds\n", + " Time in inactive batches = 1.0700E+00 seconds\n", + " Time in active batches = 7.8930E+00 seconds\n", + " Time synchronizing fission bank = 7.6400E-01 seconds\n", + " Sampling source sites = 4.0000E-03 seconds\n", + " SEND/RECV source sites = 1.0000E-03 seconds\n", + " Time accumulating tallies = 1.0000E-03 seconds\n", + " Total time for finalization = 2.0000E-03 seconds\n", + " Total time elapsed = 9.8710E+00 seconds\n", + " Calculation Rate (inactive) = 11682.2 neutrons/second\n", + " Calculation Rate (active) = 4751.05 neutrons/second\n", + "\n", + " ============================> RESULTS <============================\n", + "\n", + " k-effective (Collision) = 1.04399 +/- 0.00515\n", + " k-effective (Track-length) = 1.04827 +/- 0.00534\n", + " k-effective (Absorption) = 1.03932 +/- 0.00588\n", + " Combined k-effective = 1.04364 +/- 0.00533\n", + " Leakage Fraction = 0.00000 +/- 0.00000\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Remove old HDF5 (summary, statepoint) files\n", + "!rm statepoint.*\n", + "\n", + "# Run OpenMC with MPI!\n", + "executor.run_simulation(mpi_procs=4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tally Data Processing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our simulation ran successfully and created a statepoint file with all the tally data in it. We begin our analysis here loading the statepoint file and 'reading' the results. By default, the tally results are not read into memory because they might be large, even large enough to exceed the available memory on a computer." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "# Load the statepoint file\n", + "sp = StatePoint('statepoint.20.h5')\n", + "sp.read_results()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You may have also noticed we instructed OpenMC to create a summary file with lots of geometry information in it. This can help to produce more sensible output from the Python API, so we will use the summary file to link against." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "# Load the summary file and link with statepoint\n", + "su = Summary('summary.h5')\n", + "sp.link_with_summary(su)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have a tally of the total fission rate and the total absorption rate, so we can calculating k-infinity as:\n", + "$$k_\\infty = \\frac{\\nu \\Sigma_f \\phi}{\\Sigma_a \\phi}$$" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nuclidescoremeanstd. dev.
bin
0total(nu-fission / absorption)1.0420350.006584
\n", + "
" + ], + "text/plain": [ + " nuclide score mean std. dev.\n", + "bin \n", + "0 total (nu-fission / absorption) 1.042035 0.006584" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Compute k-infinity using tally arithmetic\n", + "fiss_rate = sp.get_tally(name='fiss. rate')\n", + "abs_rate = sp.get_tally(name='abs. rate')\n", + "keff = fiss_rate / abs_rate\n", + "keff.get_pandas_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that even though the neutron production rate and absorption rate are separate tallies, we still get a first-order estimate of the uncertainty on the quotient of them automatically!\n", + "\n", + "Now, let's analyze of few of the classic factors in the four-factor formula, starting with the resonance escape probability, which we'll define as $$p=\\frac{\\Sigma_{a,thermal}\\phi}{\\Sigma_a\\phi}$$" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nuclidescoremeanstd. dev.
bin
0totalabsorption0.9590670.00517
\n", + "
" + ], + "text/plain": [ + " nuclide score mean std. dev.\n", + "bin \n", + "0 total absorption 0.959067 0.00517" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Compute resonance escape probability using tally arithmetic\n", + "therm_abs_rate = sp.get_tally(name='therm. abs. rate')\n", + "res_esc = therm_abs_rate / abs_rate\n", + "res_esc.get_pandas_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The fast fission factor can be calculated as\n", + "$$\\epsilon=\\frac{\\Sigma_f\\phi}{\\Sigma_{f,thermal}\\phi}$$" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nuclidescoremeanstd. dev.
bin
0totalfission1.0801240.008126
\n", + "
" + ], + "text/plain": [ + " nuclide score mean std. dev.\n", + "bin \n", + "0 total fission 1.080124 0.008126" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Compute fast fission factor factor using tally arithmetic\n", + "therm_fiss_rate = sp.get_tally(name='therm. fiss. rate')\n", + "tot_fiss_rate = sp.get_tally(name='tot. fiss. rate')\n", + "fast_fiss = tot_fiss_rate / therm_fiss_rate\n", + "fast_fiss.get_pandas_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The thermal flux utilization is calculated as\n", + "$$f=\\frac{\\Sigma_{a,thermal}^F\\phi}{\\Sigma_a\\phi}$$\n", + "where $F$ denotes fuel." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nuclidescoremeanstd. dev.
bin
0totalabsorption0.7692630.004172
\n", + "
" + ], + "text/plain": [ + " nuclide score mean std. dev.\n", + "bin \n", + "0 total absorption 0.769263 0.004172" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Compute thermal flux utilization factor using tally arithmetic\n", + "fuel_therm_abs_rate = sp.get_tally(name='fuel therm. abs. rate')\n", + "therm_util = fuel_therm_abs_rate / abs_rate\n", + "therm_util.get_pandas_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's move on to a more complicated example now. Before we set up tallies to get reaction rates in the fuel and moderator in two energy groups for two different nuclides. We can use tally arithmetic to divide each of these reaction rates by the flux to get microscopic multi-group cross sections." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "# Compute microscopic multi-group cross-sections\n", + "flux = sp.get_tally(name='flux')\n", + "flux = flux.get_slice(filters=['cell'], filter_bins=[(fuel_cell.id,)])\n", + "fuel_rxn_rates = sp.get_tally(name='fuel rxn rates')\n", + "mod_rxn_rates = sp.get_tally(name='moderator rxn rates')" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellenergy [MeV]nuclidescoremeanstd. dev.
bin
0100000.0e+00 - 6.3e-07(U-238 / total)(nu-fission / flux)0.0000015.999638e-09
1100000.0e+00 - 6.3e-07(U-238 / total)(scatter / flux)0.2099851.975043e-03
2100000.0e+00 - 6.3e-07(U-235 / total)(nu-fission / flux)0.3556003.196431e-03
3100000.0e+00 - 6.3e-07(U-235 / total)(scatter / flux)0.0055555.223274e-05
4100006.3e-07 - 2.0e+01(U-238 / total)(nu-fission / flux)0.0072007.935962e-05
5100006.3e-07 - 2.0e+01(U-238 / total)(scatter / flux)0.2275348.747338e-04
6100006.3e-07 - 2.0e+01(U-235 / total)(nu-fission / flux)0.0080904.645182e-05
7100006.3e-07 - 2.0e+01(U-235 / total)(scatter / flux)0.0033701.274353e-05
\n", + "
" + ], + "text/plain": [ + " cell energy [MeV] nuclide score mean \\\n", + "bin \n", + "0 10000 0.0e+00 - 6.3e-07 (U-238 / total) (nu-fission / flux) 0.000001 \n", + "1 10000 0.0e+00 - 6.3e-07 (U-238 / total) (scatter / flux) 0.209985 \n", + "2 10000 0.0e+00 - 6.3e-07 (U-235 / total) (nu-fission / flux) 0.355600 \n", + "3 10000 0.0e+00 - 6.3e-07 (U-235 / total) (scatter / flux) 0.005555 \n", + "4 10000 6.3e-07 - 2.0e+01 (U-238 / total) (nu-fission / flux) 0.007200 \n", + "5 10000 6.3e-07 - 2.0e+01 (U-238 / total) (scatter / flux) 0.227534 \n", + "6 10000 6.3e-07 - 2.0e+01 (U-235 / total) (nu-fission / flux) 0.008090 \n", + "7 10000 6.3e-07 - 2.0e+01 (U-235 / total) (scatter / flux) 0.003370 \n", + "\n", + " std. dev. \n", + "bin \n", + "0 5.999638e-09 \n", + "1 1.975043e-03 \n", + "2 3.196431e-03 \n", + "3 5.223274e-05 \n", + "4 7.935962e-05 \n", + "5 8.747338e-04 \n", + "6 4.645182e-05 \n", + "7 1.274353e-05 " + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fuel_xs = fuel_rxn_rates / flux\n", + "fuel_xs.get_pandas_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We see that when the two tallies with multiple bins were divided, the derived tally contains the outer product of the combinations. If the filters/scores are the same, no outer product is needed. The `get_values(...)` method allows us to obtain a subset of tally scores. In the following example, we obtain just the neutron production microscopic cross sections." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[ 6.64202005e-07]\n", + " [ 3.55599908e-01]]\n", + "\n", + " [[ 7.20046753e-03]\n", + " [ 8.09041760e-03]]]\n" + ] + } + ], + "source": [ + "# Show how to use Tally.get_values(...) with a CrossScore\n", + "nu_fiss_xs = fuel_xs.get_values(scores=['(nu-fission / flux)'])\n", + "print(nu_fiss_xs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The same idea can be used not only for scores but also for filters and nuclides." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[ 0.00555494]]\n", + "\n", + " [[ 0.00337012]]]\n" + ] + } + ], + "source": [ + "# Show how to use Tally.get_values(...) with a CrossScore and CrossNuclide\n", + "u235_scatter_xs = fuel_xs.get_values(nuclides=['(U-235 / total)'], \n", + " scores=['(scatter / flux)'])\n", + "print(u235_scatter_xs)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[ 0.22753371]\n", + " [ 0.00337012]]]\n" + ] + } + ], + "source": [ + "# Show how to use Tally.get_values(...) with a CrossFilter and CrossScore\n", + "fast_scatter_xs = fuel_xs.get_values(filters=['energy'], \n", + " filter_bins=[((0.625e-6, 20.),)], \n", + " scores=['(scatter / flux)'])\n", + "print(fast_scatter_xs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A more advanced method is to use `get_slice(...)` to create a new derived tally that is a subset of an existing tally. This has the benefit that we can use `get_pandas_dataframe()` to see the tallies in a more human-readable format." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellenergy [MeV]nuclidescoremeanstd. dev.
bin
0100000.0e+00 - 6.3e-07U-238nu-fission0.0000029.952309e-09
1100000.0e+00 - 6.3e-07U-235nu-fission0.8719945.271360e-03
2100006.3e-07 - 2.0e+01U-238nu-fission0.0830068.813292e-04
3100006.3e-07 - 2.0e+01U-235nu-fission0.0932654.590785e-04
\n", + "
" + ], + "text/plain": [ + " cell energy [MeV] nuclide score mean std. dev.\n", + "bin \n", + "0 10000 0.0e+00 - 6.3e-07 U-238 nu-fission 0.000002 9.952309e-09\n", + "1 10000 0.0e+00 - 6.3e-07 U-235 nu-fission 0.871994 5.271360e-03\n", + "2 10000 6.3e-07 - 2.0e+01 U-238 nu-fission 0.083006 8.813292e-04\n", + "3 10000 6.3e-07 - 2.0e+01 U-235 nu-fission 0.093265 4.590785e-04" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# \"Slice\" the nu-fission data into a new derived Tally\n", + "nu_fission_rates = fuel_rxn_rates.get_slice(scores=['nu-fission'])\n", + "nu_fission_rates.get_pandas_dataframe()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellenergy [MeV]nuclidescoremeanstd. dev.
bin
0100021.0e-08 - 1.1e-07H-1scatter4.6695350.032937
1100021.1e-07 - 1.2e-06H-1scatter2.0347860.014311
2100021.2e-06 - 1.3e-05H-1scatter1.6644400.014963
3100021.3e-05 - 1.4e-04H-1scatter1.8754060.011341
4100021.4e-04 - 1.5e-03H-1scatter2.0650550.013958
5100021.5e-03 - 1.6e-02H-1scatter2.1444620.011313
6100021.6e-02 - 1.7e-01H-1scatter2.2065290.011302
7100021.7e-01 - 1.9e+00H-1scatter1.9923360.012023
8100021.9e+00 - 2.0e+01H-1scatter0.3774000.004341
\n", + "
" + ], + "text/plain": [ + " cell energy [MeV] nuclide score mean std. dev.\n", + "bin \n", + "0 10002 1.0e-08 - 1.1e-07 H-1 scatter 4.669535 0.032937\n", + "1 10002 1.1e-07 - 1.2e-06 H-1 scatter 2.034786 0.014311\n", + "2 10002 1.2e-06 - 1.3e-05 H-1 scatter 1.664440 0.014963\n", + "3 10002 1.3e-05 - 1.4e-04 H-1 scatter 1.875406 0.011341\n", + "4 10002 1.4e-04 - 1.5e-03 H-1 scatter 2.065055 0.013958\n", + "5 10002 1.5e-03 - 1.6e-02 H-1 scatter 2.144462 0.011313\n", + "6 10002 1.6e-02 - 1.7e-01 H-1 scatter 2.206529 0.011302\n", + "7 10002 1.7e-01 - 1.9e+00 H-1 scatter 1.992336 0.012023\n", + "8 10002 1.9e+00 - 2.0e+01 H-1 scatter 0.377400 0.004341" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# \"Slice\" the H-1 scatter data in the moderator Cell into a new derived Tally\n", + "need_to_slice = sp.get_tally(name='need-to-slice')\n", + "slice_test = need_to_slice.get_slice(scores=['scatter'], nuclides=['H-1'],\n", + " filters=['cell'], filter_bins=[(moderator_cell.id,)])\n", + "slice_test.get_pandas_dataframe()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/source/pythonapi/examples/tally-arithmetic.rst b/docs/source/pythonapi/examples/tally-arithmetic.rst new file mode 100644 index 000000000..5f3cf775e --- /dev/null +++ b/docs/source/pythonapi/examples/tally-arithmetic.rst @@ -0,0 +1,11 @@ +================ +Tally Arithmetic +================ + +.. only:: html + + .. notebook:: tally-arithmetic.ipynb + +.. only:: latex + + IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/pythonapi/index.rst b/docs/source/pythonapi/index.rst index f6c26557d..38314f4ea 100644 --- a/docs/source/pythonapi/index.rst +++ b/docs/source/pythonapi/index.rst @@ -4,9 +4,7 @@ Python API ========== --------- -Contents --------- +**API Documentation:** .. toctree:: :maxdepth: 1 @@ -30,3 +28,10 @@ Contents tallies trigger universe + +**Examples:** + +.. toctree:: + :maxdepth: 1 + + examples/tally-arithmetic diff --git a/docs/sphinxext/LICENSE b/docs/sphinxext/LICENSE new file mode 100644 index 000000000..2d508d2be --- /dev/null +++ b/docs/sphinxext/LICENSE @@ -0,0 +1,68 @@ +The file notebook_sphinxext.py was derived from code in PyNE and yt. + +PyNE has the following license: + +------------------------------------------------------------------------------- +Copyright 2011-2015, the PyNE Development Team. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE PYNE DEVELOPMENT TEAM ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of the stakeholders of the PyNE project or the employers of PyNE developers. +------------------------------------------------------------------------------- + +yt has the following license: + +------------------------------------------------------------------------------- +yt is licensed under the terms of the Modified BSD License (also known as New +or Revised BSD), as follows: + +Copyright (c) 2013-, yt Development Team +Copyright (c) 2006-2013, Matthew Turk + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +Neither the name of the yt Development Team nor the names of its +contributors may be used to endorse or promote products derived from this +software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------------------- diff --git a/docs/sphinxext/notebook_sphinxext.py b/docs/sphinxext/notebook_sphinxext.py new file mode 100644 index 000000000..a9d634a35 --- /dev/null +++ b/docs/sphinxext/notebook_sphinxext.py @@ -0,0 +1,120 @@ +import sys +import os.path +import re +import time +from docutils import io, nodes, statemachine, utils +try: + from docutils.utils.error_reporting import ErrorString # the new way +except ImportError: + from docutils.error_reporting import ErrorString # the old way +from docutils.parsers.rst import Directive, convert_directive_function +from docutils.parsers.rst import directives, roles, states +from docutils.parsers.rst.roles import set_classes +from docutils.transforms import misc + +try: + from IPython.nbconver.exporters import html +except ImportError: + from IPython.nbconvert import html + + +class Notebook(Directive): + """Use nbconvert to insert a notebook into the environment. + This is based on the Raw directive in docutils + """ + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = True + option_spec = {} + has_content = False + + def run(self): + # check if raw html is supported + if not self.state.document.settings.raw_enabled: + raise self.warning('"%s" directive disabled.' % self.name) + + # set up encoding + attributes = {'format': 'html'} + encoding = self.options.get( + 'encoding', self.state.document.settings.input_encoding) + e_handler = self.state.document.settings.input_encoding_error_handler + + # get path to notebook + source_dir = os.path.dirname( + os.path.abspath(self.state.document.current_source)) + nb_path = os.path.normpath(os.path.join(source_dir, + self.arguments[0])) + nb_path = utils.relative_path(None, nb_path) + + # convert notebook to html + exporter = html.HTMLExporter(template_file='full') + output, resources = exporter.from_filename(nb_path) + header = output.split('', 1)[1].split('',1)[0] + body = output.split('', 1)[1].split('',1)[0] + + # add HTML5 scoped attribute to header style tags + header = header.replace(''] + lines.append(header) + lines.append(body) + lines.append('') + text = '\n'.join(lines) + + # add dependency + self.state.document.settings.record_dependencies.add(nb_path) + attributes['source'] = nb_path + + # create notebook node + nb_node = notebook('', text, **attributes) + (nb_node.source, nb_node.line) = \ + self.state_machine.get_source_and_line(self.lineno) + + return [nb_node] + + +class notebook(nodes.raw): + pass + + +def visit_notebook_node(self, node): + self.visit_raw(node) + + +def depart_notebook_node(self, node): + self.depart_raw(node) + + +def setup(app): + app.add_node(notebook, + html=(visit_notebook_node, depart_notebook_node)) + + app.add_directive('notebook', Notebook)