1{
2 "cells": [
3  {
4   "cell_type": "markdown",
5   "metadata": {},
6   "source": [
7    "# Modeling a Pin-Cell\n",
8    "This notebook is intended to demonstrate the basic features of the Python API for constructing input files and running OpenMC. In it, we will show how to create a basic reflective pin-cell model that is equivalent to modeling an infinite array of fuel pins. If you have never used OpenMC, this can serve as a good starting point to learn the Python API. We highly recommend having a copy of the [Python API reference documentation](https://docs.openmc.org/en/stable/pythonapi/index.html) open in another browser tab that you can refer to."
9   ]
10  },
11  {
12   "cell_type": "code",
13   "execution_count": 1,
14   "metadata": {},
15   "outputs": [],
16   "source": [
17    "%matplotlib inline\n",
18    "import openmc"
19   ]
20  },
21  {
22   "cell_type": "markdown",
23   "metadata": {},
24   "source": [
25    "## Defining Materials\n",
26    "\n",
27    "Materials in OpenMC are defined as a set of nuclides with specified atom/weight fractions. To begin, we will create a material by making an instance of the `Material` class. In OpenMC, many objects, including materials, are identified by a \"unique ID\" that is simply just a positive integer. These IDs are used when exporting XML files that the solver reads in. They also appear in the output and can be used for identification. Since an integer ID is not very useful by itself, you can also give a material a `name` as well."
28   ]
29  },
30  {
31   "cell_type": "code",
32   "execution_count": 2,
33   "metadata": {},
34   "outputs": [
35    {
36     "name": "stdout",
37     "output_type": "stream",
38     "text": [
39      "Material\n",
40      "\tID             =\t1\n",
41      "\tName           =\tuo2\n",
42      "\tTemperature    =\tNone\n",
43      "\tDensity        =\tNone [sum]\n",
44      "\tS(a,b) Tables  \n",
45      "\tNuclides       \n",
46      "\n"
47     ]
48    }
49   ],
50   "source": [
51    "uo2 = openmc.Material(1, \"uo2\")\n",
52    "print(uo2)"
53   ]
54  },
55  {
56   "cell_type": "markdown",
57   "metadata": {},
58   "source": [
59    "On the XML side, you have no choice but to supply an ID. However, in the Python API, if you don't give an ID, one will be automatically generated for you:"
60   ]
61  },
62  {
63   "cell_type": "code",
64   "execution_count": 3,
65   "metadata": {},
66   "outputs": [
67    {
68     "name": "stdout",
69     "output_type": "stream",
70     "text": [
71      "Material\n",
72      "\tID             =\t2\n",
73      "\tName           =\t\n",
74      "\tTemperature    =\tNone\n",
75      "\tDensity        =\tNone [sum]\n",
76      "\tS(a,b) Tables  \n",
77      "\tNuclides       \n",
78      "\n"
79     ]
80    }
81   ],
82   "source": [
83    "mat = openmc.Material()\n",
84    "print(mat)"
85   ]
86  },
87  {
88   "cell_type": "markdown",
89   "metadata": {},
90   "source": [
91    "We see that an ID of 2 was automatically assigned. Let's now move on to adding nuclides to our `uo2` material. The `Material` object has a method `add_nuclide()` whose first argument is the name of the nuclide and second argument is the atom or weight fraction."
92   ]
93  },
94  {
95   "cell_type": "code",
96   "execution_count": 4,
97   "metadata": {},
98   "outputs": [
99    {
100     "name": "stdout",
101     "output_type": "stream",
102     "text": [
103      "Help on method add_nuclide in module openmc.material:\n",
104      "\n",
105      "add_nuclide(nuclide, percent, percent_type='ao') method of openmc.material.Material instance\n",
106      "    Add a nuclide to the material\n",
107      "    \n",
108      "    Parameters\n",
109      "    ----------\n",
110      "    nuclide : str\n",
111      "        Nuclide to add, e.g., 'Mo95'\n",
112      "    percent : float\n",
113      "        Atom or weight percent\n",
114      "    percent_type : {'ao', 'wo'}\n",
115      "        'ao' for atom percent and 'wo' for weight percent\n",
116      "\n"
117     ]
118    }
119   ],
120   "source": [
121    "help(uo2.add_nuclide)"
122   ]
123  },
124  {
125   "cell_type": "markdown",
126   "metadata": {},
127   "source": [
128    "We see that by default it assumes we want an atom fraction."
129   ]
130  },
131  {
132   "cell_type": "code",
133   "execution_count": 5,
134   "metadata": {},
135   "outputs": [],
136   "source": [
137    "# Add nuclides to uo2\n",
138    "uo2.add_nuclide('U235', 0.03)\n",
139    "uo2.add_nuclide('U238', 0.97)\n",
140    "uo2.add_nuclide('O16', 2.0)"
141   ]
142  },
143  {
144   "cell_type": "markdown",
145   "metadata": {},
146   "source": [
147    "Now we need to assign a total density to the material. We'll use the `set_density` for this."
148   ]
149  },
150  {
151   "cell_type": "code",
152   "execution_count": 6,
153   "metadata": {},
154   "outputs": [],
155   "source": [
156    "uo2.set_density('g/cm3', 10.0)"
157   ]
158  },
159  {
160   "cell_type": "markdown",
161   "metadata": {},
162   "source": [
163    "You may sometimes be given a material specification where all the nuclide densities are in units of atom/b-cm. In this case, you just want the density to be the sum of the constituents. In that case, you can simply run `mat.set_density('sum')`.\n",
164    "\n",
165    "With UO2 finished, let's now create materials for the clad and coolant. Note the use of `add_element()` for zirconium."
166   ]
167  },
168  {
169   "cell_type": "code",
170   "execution_count": 7,
171   "metadata": {},
172   "outputs": [],
173   "source": [
174    "zirconium = openmc.Material(name=\"zirconium\")\n",
175    "zirconium.add_element('Zr', 1.0)\n",
176    "zirconium.set_density('g/cm3', 6.6)\n",
177    "\n",
178    "water = openmc.Material(name=\"h2o\")\n",
179    "water.add_nuclide('H1', 2.0)\n",
180    "water.add_nuclide('O16', 1.0)\n",
181    "water.set_density('g/cm3', 1.0)"
182   ]
183  },
184  {
185   "cell_type": "markdown",
186   "metadata": {},
187   "source": [
188    "An astute observer might now point out that this water material we just created will only use free-atom cross sections. We need to tell it to use an $S(\\alpha,\\beta)$ table so that the bound atom cross section is used at thermal energies. To do this, there's an `add_s_alpha_beta()` method. Note the use of the GND-style name \"c_H_in_H2O\"."
189   ]
190  },
191  {
192   "cell_type": "code",
193   "execution_count": 8,
194   "metadata": {},
195   "outputs": [],
196   "source": [
197    "water.add_s_alpha_beta('c_H_in_H2O')"
198   ]
199  },
200  {
201   "cell_type": "markdown",
202   "metadata": {},
203   "source": [
204    "When we go to run the transport solver in OpenMC, it is going to look for a `materials.xml` file. Thus far, we have only created objects in memory. To actually create a `materials.xml` file, we need to instantiate a `Materials` collection and export it to XML."
205   ]
206  },
207  {
208   "cell_type": "code",
209   "execution_count": 9,
210   "metadata": {},
211   "outputs": [],
212   "source": [
213    "materials = openmc.Materials([uo2, zirconium, water])"
214   ]
215  },
216  {
217   "cell_type": "markdown",
218   "metadata": {},
219   "source": [
220    "Note that `Materials` is actually a subclass of Python's built-in `list`, so we can use methods like `append()`, `insert()`, `pop()`, etc."
221   ]
222  },
223  {
224   "cell_type": "code",
225   "execution_count": 10,
226   "metadata": {},
227   "outputs": [
228    {
229     "data": {
230      "text/plain": [
231       "True"
232      ]
233     },
234     "execution_count": 10,
235     "metadata": {},
236     "output_type": "execute_result"
237    }
238   ],
239   "source": [
240    "materials = openmc.Materials()\n",
241    "materials.append(uo2)\n",
242    "materials += [zirconium, water]\n",
243    "isinstance(materials, list)"
244   ]
245  },
246  {
247   "cell_type": "markdown",
248   "metadata": {},
249   "source": [
250    "Finally, we can create the XML file with the `export_to_xml()` method. In a Jupyter notebook, we can run a shell command by putting `!` before it, so in this case we are going to display the `materials.xml` file that we created."
251   ]
252  },
253  {
254   "cell_type": "code",
255   "execution_count": 11,
256   "metadata": {},
257   "outputs": [
258    {
259     "name": "stdout",
260     "output_type": "stream",
261     "text": [
262      "<?xml version='1.0' encoding='utf-8'?>\r\n",
263      "<materials>\r\n",
264      "  <material depletable=\"true\" id=\"1\" name=\"uo2\">\r\n",
265      "    <density units=\"g/cm3\" value=\"10.0\" />\r\n",
266      "    <nuclide ao=\"0.03\" name=\"U235\" />\r\n",
267      "    <nuclide ao=\"0.97\" name=\"U238\" />\r\n",
268      "    <nuclide ao=\"2.0\" name=\"O16\" />\r\n",
269      "  </material>\r\n",
270      "  <material id=\"3\" name=\"zirconium\">\r\n",
271      "    <density units=\"g/cm3\" value=\"6.6\" />\r\n",
272      "    <nuclide ao=\"0.5145\" name=\"Zr90\" />\r\n",
273      "    <nuclide ao=\"0.1122\" name=\"Zr91\" />\r\n",
274      "    <nuclide ao=\"0.1715\" name=\"Zr92\" />\r\n",
275      "    <nuclide ao=\"0.1738\" name=\"Zr94\" />\r\n",
276      "    <nuclide ao=\"0.028\" name=\"Zr96\" />\r\n",
277      "  </material>\r\n",
278      "  <material id=\"4\" name=\"h2o\">\r\n",
279      "    <density units=\"g/cm3\" value=\"1.0\" />\r\n",
280      "    <nuclide ao=\"2.0\" name=\"H1\" />\r\n",
281      "    <nuclide ao=\"1.0\" name=\"O16\" />\r\n",
282      "    <sab name=\"c_H_in_H2O\" />\r\n",
283      "  </material>\r\n",
284      "</materials>\r\n"
285     ]
286    }
287   ],
288   "source": [
289    "materials.export_to_xml()\n",
290    "!cat materials.xml"
291   ]
292  },
293  {
294   "cell_type": "markdown",
295   "metadata": {},
296   "source": [
297    "### Element Expansion\n",
298    "\n",
299    "Did you notice something really cool that happened to our Zr element? OpenMC automatically turned it into a list of nuclides when it exported it! The way this feature works is as follows:\n",
300    "\n",
301    "- First, it checks whether `Materials.cross_sections` has been set, indicating the path to a `cross_sections.xml` file.\n",
302    "- If `Materials.cross_sections` isn't set, it looks for the `OPENMC_CROSS_SECTIONS` environment variable.\n",
303    "- If either of these are found, it scans the file to see what nuclides are actually available and will expand elements accordingly.\n",
304    "\n",
305    "Let's see what happens if we change O16 in water to elemental O."
306   ]
307  },
308  {
309   "cell_type": "code",
310   "execution_count": 12,
311   "metadata": {},
312   "outputs": [
313    {
314     "name": "stdout",
315     "output_type": "stream",
316     "text": [
317      "<?xml version='1.0' encoding='utf-8'?>\r\n",
318      "<materials>\r\n",
319      "  <material depletable=\"true\" id=\"1\" name=\"uo2\">\r\n",
320      "    <density units=\"g/cm3\" value=\"10.0\" />\r\n",
321      "    <nuclide ao=\"0.03\" name=\"U235\" />\r\n",
322      "    <nuclide ao=\"0.97\" name=\"U238\" />\r\n",
323      "    <nuclide ao=\"2.0\" name=\"O16\" />\r\n",
324      "  </material>\r\n",
325      "  <material id=\"3\" name=\"zirconium\">\r\n",
326      "    <density units=\"g/cm3\" value=\"6.6\" />\r\n",
327      "    <nuclide ao=\"0.5145\" name=\"Zr90\" />\r\n",
328      "    <nuclide ao=\"0.1122\" name=\"Zr91\" />\r\n",
329      "    <nuclide ao=\"0.1715\" name=\"Zr92\" />\r\n",
330      "    <nuclide ao=\"0.1738\" name=\"Zr94\" />\r\n",
331      "    <nuclide ao=\"0.028\" name=\"Zr96\" />\r\n",
332      "  </material>\r\n",
333      "  <material id=\"4\" name=\"h2o\">\r\n",
334      "    <density units=\"g/cm3\" value=\"1.0\" />\r\n",
335      "    <nuclide ao=\"2.0\" name=\"H1\" />\r\n",
336      "    <nuclide ao=\"0.999621\" name=\"O16\" />\r\n",
337      "    <nuclide ao=\"0.000379\" name=\"O17\" />\r\n",
338      "    <sab name=\"c_H_in_H2O\" />\r\n",
339      "  </material>\r\n",
340      "</materials>\r\n"
341     ]
342    }
343   ],
344   "source": [
345    "water.remove_nuclide('O16')\n",
346    "water.add_element('O', 1.0)\n",
347    "\n",
348    "materials.export_to_xml()\n",
349    "!cat materials.xml"
350   ]
351  },
352  {
353   "cell_type": "markdown",
354   "metadata": {},
355   "source": [
356    "We see that now O16 and O17 were automatically added. O18 is missing because our cross sections file (which is based on ENDF/B-VII.1) doesn't have O18. If OpenMC didn't know about the cross sections file, it would have assumed that all isotopes exist."
357   ]
358  },
359  {
360   "cell_type": "markdown",
361   "metadata": {},
362   "source": [
363    "### The `cross_sections.xml` file\n",
364    "\n",
365    "The `cross_sections.xml` tells OpenMC where it can find nuclide cross sections and $S(\\alpha,\\beta)$ tables. It serves the same purpose as MCNP's `xsdir` file and Serpent's `xsdata` file. As we mentioned, this can be set either by the `OPENMC_CROSS_SECTIONS` environment variable or the `Materials.cross_sections` attribute.\n",
366    "\n",
367    "Let's have a look at what's inside this file:"
368   ]
369  },
370  {
371   "cell_type": "code",
372   "execution_count": 13,
373   "metadata": {},
374   "outputs": [
375    {
376     "name": "stdout",
377     "output_type": "stream",
378     "text": [
379      "<?xml version='1.0' encoding='utf-8'?>\n",
380      "<cross_sections>\n",
381      "  <library materials=\"H1\" path=\"H1.h5\" type=\"neutron\" />\n",
382      "  <library materials=\"H2\" path=\"H2.h5\" type=\"neutron\" />\n",
383      "  <library materials=\"H3\" path=\"H3.h5\" type=\"neutron\" />\n",
384      "  <library materials=\"He3\" path=\"He3.h5\" type=\"neutron\" />\n",
385      "  <library materials=\"He4\" path=\"He4.h5\" type=\"neutron\" />\n",
386      "  <library materials=\"Li6\" path=\"Li6.h5\" type=\"neutron\" />\n",
387      "  <library materials=\"Li7\" path=\"Li7.h5\" type=\"neutron\" />\n",
388      "  <library materials=\"Be7\" path=\"Be7.h5\" type=\"neutron\" />\n",
389      "    ...\n",
390      "  <library materials=\"Cf253\" path=\"wmp/098253.h5\" type=\"wmp\" />\n",
391      "  <library materials=\"Cf254\" path=\"wmp/098254.h5\" type=\"wmp\" />\n",
392      "  <library materials=\"Es251\" path=\"wmp/099251.h5\" type=\"wmp\" />\n",
393      "  <library materials=\"Es252\" path=\"wmp/099252.h5\" type=\"wmp\" />\n",
394      "  <library materials=\"Es253\" path=\"wmp/099253.h5\" type=\"wmp\" />\n",
395      "  <library materials=\"Es254\" path=\"wmp/099254.h5\" type=\"wmp\" />\n",
396      "  <library materials=\"Es254_m1\" path=\"wmp/099254m1.h5\" type=\"wmp\" />\n",
397      "  <library materials=\"Es255\" path=\"wmp/099255.h5\" type=\"wmp\" />\n",
398      "  <library materials=\"Fm255\" path=\"wmp/100255.h5\" type=\"wmp\" />\n",
399      "</cross_sections>\n"
400     ]
401    }
402   ],
403   "source": [
404    "!cat $OPENMC_CROSS_SECTIONS | head -n 10\n",
405    "print('    ...')\n",
406    "!cat $OPENMC_CROSS_SECTIONS | tail -n 10"
407   ]
408  },
409  {
410   "cell_type": "markdown",
411   "metadata": {},
412   "source": [
413    "### Enrichment\n",
414    "\n",
415    "Note that the `add_element()` method has a special argument `enrichment` that can be used for Uranium. For example, if we know that we want to create 3% enriched UO2, the following would work:"
416   ]
417  },
418  {
419   "cell_type": "code",
420   "execution_count": 14,
421   "metadata": {},
422   "outputs": [],
423   "source": [
424    "uo2_three = openmc.Material()\n",
425    "uo2_three.add_element('U', 1.0, enrichment=3.0)\n",
426    "uo2_three.add_element('O', 2.0)\n",
427    "uo2_three.set_density('g/cc', 10.0)"
428   ]
429  },
430  {
431   "cell_type": "markdown",
432   "metadata": {},
433   "source": [
434    "### Mixtures\n",
435    "\n",
436    "In OpenMC it is also possible to define materials by mixing existing materials. For example, if we wanted to create MOX fuel out of a mixture of UO2 (97 wt%) and PuO2 (3 wt%) we could do the following:"
437   ]
438  },
439  {
440   "cell_type": "code",
441   "execution_count": 15,
442   "metadata": {},
443   "outputs": [],
444   "source": [
445    "# Create PuO2 material\n",
446    "puo2 = openmc.Material()\n",
447    "puo2.add_nuclide('Pu239', 0.94)\n",
448    "puo2.add_nuclide('Pu240', 0.06)\n",
449    "puo2.add_nuclide('O16', 2.0)\n",
450    "puo2.set_density('g/cm3', 11.5)\n",
451    "\n",
452    "# Create the mixture\n",
453    "mox = openmc.Material.mix_materials([uo2, puo2], [0.97, 0.03], 'wo')"
454   ]
455  },
456  {
457   "cell_type": "markdown",
458   "metadata": {},
459   "source": [
460    "The 'wo' argument in the `mix_materials()` method specifies that the fractions are weight fractions. Materials can also be mixed by atomic and volume fractions with 'ao' and 'vo', respectively. For 'ao' and 'wo' the fractions must sum to one. For 'vo', if fractions do not sum to one, the remaining fraction is set as void."
461   ]
462  },
463  {
464   "cell_type": "markdown",
465   "metadata": {},
466   "source": [
467    "## Defining Geometry\n",
468    "\n",
469    "At this point, we have three materials defined, exported to XML, and ready to be used in our model. To finish our model, we need to define the geometric arrangement of materials. OpenMC represents physical volumes using constructive solid geometry (CSG), also known as combinatorial geometry. The object that allows us to assign a material to a region of space is called a `Cell` (same concept in MCNP, for those familiar). In order to define a region that we can assign to a cell, we must first define surfaces which bound the region. A *surface* is a locus of zeros of a function of Cartesian coordinates $x$, $y$, and $z$, e.g.\n",
470    "\n",
471    "- A plane perpendicular to the x axis: $x - x_0 = 0$\n",
472    "- A cylinder parallel to the z axis: $(x - x_0)^2 + (y - y_0)^2 - R^2 = 0$\n",
473    "- A sphere: $(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 - R^2 = 0$\n",
474    "\n",
475    "Between those three classes of surfaces (planes, cylinders, spheres), one can construct a wide variety of models. It is also possible to define cones and general second-order surfaces (tori are not currently supported).\n",
476    "\n",
477    "Note that defining a surface is not sufficient to specify a volume -- in order to define an actual volume, one must reference the half-space of a surface. A surface *half-space* is the region whose points satisfy a positive or negative inequality of the surface equation. For example, for a sphere of radius one centered at the origin, the surface equation is $f(x,y,z) = x^2 + y^2 + z^2 - 1 = 0$. Thus, we say that the negative half-space of the sphere, is defined as the collection of points satisfying $f(x,y,z) < 0$, which one can reason is the inside of the sphere. Conversely, the positive half-space of the sphere would correspond to all points outside of the sphere.\n",
478    "\n",
479    "Let's go ahead and create a sphere and confirm that what we've told you is true."
480   ]
481  },
482  {
483   "cell_type": "code",
484   "execution_count": 16,
485   "metadata": {},
486   "outputs": [],
487   "source": [
488    "sphere = openmc.Sphere(r=1.0)"
489   ]
490  },
491  {
492   "cell_type": "markdown",
493   "metadata": {},
494   "source": [
495    "Note that by default the sphere is centered at the origin so we didn't have to supply `x0`, `y0`, or `z0` arguments. Strictly speaking, we could have omitted `R` as well since it defaults to one. To get the negative or positive half-space, we simply need to apply the `-` or `+` unary operators, respectively.\n",
496    "\n",
497    "(NOTE: Those unary operators are defined by special methods: `__pos__` and `__neg__` in this case)."
498   ]
499  },
500  {
501   "cell_type": "code",
502   "execution_count": 17,
503   "metadata": {},
504   "outputs": [],
505   "source": [
506    "inside_sphere = -sphere\n",
507    "outside_sphere = +sphere"
508   ]
509  },
510  {
511   "cell_type": "markdown",
512   "metadata": {},
513   "source": [
514    "Now let's see if `inside_sphere` actually contains points inside the sphere:"
515   ]
516  },
517  {
518   "cell_type": "code",
519   "execution_count": 18,
520   "metadata": {},
521   "outputs": [
522    {
523     "name": "stdout",
524     "output_type": "stream",
525     "text": [
526      "True False\n",
527      "False True\n"
528     ]
529    }
530   ],
531   "source": [
532    "print((0,0,0) in inside_sphere, (0,0,2) in inside_sphere)\n",
533    "print((0,0,0) in outside_sphere, (0,0,2) in outside_sphere)"
534   ]
535  },
536  {
537   "cell_type": "markdown",
538   "metadata": {},
539   "source": [
540    "Everything works as expected! Now that we understand how to create half-spaces, we can create more complex volumes by combining half-spaces using Boolean operators: `&` (intersection), `|` (union), and `~` (complement). For example, let's say we want to define a region that is the top part of the sphere (all points inside the sphere that have $z > 0$."
541   ]
542  },
543  {
544   "cell_type": "code",
545   "execution_count": 19,
546   "metadata": {},
547   "outputs": [],
548   "source": [
549    "z_plane = openmc.ZPlane(z0=0)\n",
550    "northern_hemisphere = -sphere & +z_plane"
551   ]
552  },
553  {
554   "cell_type": "markdown",
555   "metadata": {},
556   "source": [
557    "For many regions, OpenMC can automatically determine a bounding box. To get the bounding box, we use the `bounding_box` property of a region, which returns a tuple of the lower-left and upper-right Cartesian coordinates for the bounding box:"
558   ]
559  },
560  {
561   "cell_type": "code",
562   "execution_count": 20,
563   "metadata": {},
564   "outputs": [
565    {
566     "data": {
567      "text/plain": [
568       "(array([-1., -1.,  0.]), array([1., 1., 1.]))"
569      ]
570     },
571     "execution_count": 20,
572     "metadata": {},
573     "output_type": "execute_result"
574    }
575   ],
576   "source": [
577    "northern_hemisphere.bounding_box"
578   ]
579  },
580  {
581   "cell_type": "markdown",
582   "metadata": {},
583   "source": [
584    "Now that we see how to create volumes, we can use them to create a cell."
585   ]
586  },
587  {
588   "cell_type": "code",
589   "execution_count": 21,
590   "metadata": {},
591   "outputs": [],
592   "source": [
593    "cell = openmc.Cell()\n",
594    "cell.region = northern_hemisphere\n",
595    "\n",
596    "# or...\n",
597    "cell = openmc.Cell(region=northern_hemisphere)"
598   ]
599  },
600  {
601   "cell_type": "markdown",
602   "metadata": {},
603   "source": [
604    "By default, the cell is not filled by any material (void). In order to assign a material, we set the `fill` property of a `Cell`."
605   ]
606  },
607  {
608   "cell_type": "code",
609   "execution_count": 22,
610   "metadata": {},
611   "outputs": [],
612   "source": [
613    "cell.fill = water"
614   ]
615  },
616  {
617   "cell_type": "markdown",
618   "metadata": {},
619   "source": [
620    "### Universes and in-line plotting"
621   ]
622  },
623  {
624   "cell_type": "markdown",
625   "metadata": {},
626   "source": [
627    "A collection of cells is known as a universe (again, this will be familiar to MCNP/Serpent users) and can be used as a repeatable unit when creating a model. Although we don't need it yet, the benefit of creating a universe is that we can visualize our geometry while we're creating it."
628   ]
629  },
630  {
631   "cell_type": "code",
632   "execution_count": 23,
633   "metadata": {},
634   "outputs": [],
635   "source": [
636    "universe = openmc.Universe()\n",
637    "universe.add_cell(cell)\n",
638    "\n",
639    "# this also works\n",
640    "universe = openmc.Universe(cells=[cell])"
641   ]
642  },
643  {
644   "cell_type": "markdown",
645   "metadata": {},
646   "source": [
647    "The `Universe` object has a `plot` method that will display our the universe as current constructed:"
648   ]
649  },
650  {
651   "cell_type": "code",
652   "execution_count": 24,
653   "metadata": {},
654   "outputs": [
655    {
656     "data": {
657      "text/plain": [
658       "<matplotlib.image.AxesImage at 0x7f7df827b250>"
659      ]
660     },
661     "execution_count": 24,
662     "metadata": {},
663     "output_type": "execute_result"
664    },
665    {
666     "data": {
667      "image/png": "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\n",
668      "text/plain": [
669       "<Figure size 432x288 with 1 Axes>"
670      ]
671     },
672     "metadata": {
673      "needs_background": "light"
674     },
675     "output_type": "display_data"
676    }
677   ],
678   "source": [
679    "universe.plot(width=(2.0, 2.0))"
680   ]
681  },
682  {
683   "cell_type": "markdown",
684   "metadata": {},
685   "source": [
686    "By default, the plot will appear in the $x$-$y$ plane. We can change that with the `basis` argument."
687   ]
688  },
689  {
690   "cell_type": "code",
691   "execution_count": 25,
692   "metadata": {},
693   "outputs": [
694    {
695     "data": {
696      "text/plain": [
697       "<matplotlib.image.AxesImage at 0x7f7df8112100>"
698      ]
699     },
700     "execution_count": 25,
701     "metadata": {},
702     "output_type": "execute_result"
703    },
704    {
705     "data": {
706      "image/png": "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\n",
707      "text/plain": [
708       "<Figure size 432x288 with 1 Axes>"
709      ]
710     },
711     "metadata": {
712      "needs_background": "light"
713     },
714     "output_type": "display_data"
715    }
716   ],
717   "source": [
718    "universe.plot(width=(2.0, 2.0), basis='xz')"
719   ]
720  },
721  {
722   "cell_type": "markdown",
723   "metadata": {},
724   "source": [
725    "If we have particular fondness for, say, fuchsia, we can tell the `plot()` method to make our cell that color."
726   ]
727  },
728  {
729   "cell_type": "code",
730   "execution_count": 26,
731   "metadata": {},
732   "outputs": [
733    {
734     "data": {
735      "text/plain": [
736       "<matplotlib.image.AxesImage at 0x7f7df80edd30>"
737      ]
738     },
739     "execution_count": 26,
740     "metadata": {},
741     "output_type": "execute_result"
742    },
743    {
744     "data": {
745      "image/png": "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\n",
746      "text/plain": [
747       "<Figure size 432x288 with 1 Axes>"
748      ]
749     },
750     "metadata": {
751      "needs_background": "light"
752     },
753     "output_type": "display_data"
754    }
755   ],
756   "source": [
757    "universe.plot(width=(2.0, 2.0), basis='xz',\n",
758    "              colors={cell: 'fuchsia'})"
759   ]
760  },
761  {
762   "cell_type": "markdown",
763   "metadata": {},
764   "source": [
765    "### Pin cell geometry\n",
766    "\n",
767    "We now have enough knowledge to create our pin-cell. We need three surfaces to define the fuel and clad:\n",
768    "\n",
769    "1. The outer surface of the fuel -- a cylinder parallel to the z axis\n",
770    "2. The inner surface of the clad -- same as above\n",
771    "3. The outer surface of the clad -- same as above\n",
772    "\n",
773    "These three surfaces will all be instances of `openmc.ZCylinder`, each with a different radius according to the specification."
774   ]
775  },
776  {
777   "cell_type": "code",
778   "execution_count": 27,
779   "metadata": {},
780   "outputs": [],
781   "source": [
782    "fuel_outer_radius = openmc.ZCylinder(r=0.39)\n",
783    "clad_inner_radius = openmc.ZCylinder(r=0.40)\n",
784    "clad_outer_radius = openmc.ZCylinder(r=0.46)"
785   ]
786  },
787  {
788   "cell_type": "markdown",
789   "metadata": {},
790   "source": [
791    "With the surfaces created, we can now take advantage of the built-in operators on surfaces to create regions for the fuel, the gap, and the clad:"
792   ]
793  },
794  {
795   "cell_type": "code",
796   "execution_count": 28,
797   "metadata": {},
798   "outputs": [],
799   "source": [
800    "fuel_region = -fuel_outer_radius\n",
801    "gap_region = +fuel_outer_radius & -clad_inner_radius\n",
802    "clad_region = +clad_inner_radius & -clad_outer_radius"
803   ]
804  },
805  {
806   "cell_type": "markdown",
807   "metadata": {},
808   "source": [
809    "Now we can create corresponding cells that assign materials to these regions. As with materials, cells have unique IDs that are assigned either manually or automatically. Note that the gap cell doesn't have any material assigned (it is void by default)."
810   ]
811  },
812  {
813   "cell_type": "code",
814   "execution_count": 29,
815   "metadata": {},
816   "outputs": [],
817   "source": [
818    "fuel = openmc.Cell(name='fuel')\n",
819    "fuel.fill = uo2\n",
820    "fuel.region = fuel_region\n",
821    "\n",
822    "gap = openmc.Cell(name='air gap')\n",
823    "gap.region = gap_region\n",
824    "\n",
825    "clad = openmc.Cell(name='clad')\n",
826    "clad.fill = zirconium\n",
827    "clad.region = clad_region"
828   ]
829  },
830  {
831   "cell_type": "markdown",
832   "metadata": {},
833   "source": [
834    "Finally, we need to handle the coolant outside of our fuel pin. To do this, we create x- and y-planes that bound the geometry."
835   ]
836  },
837  {
838   "cell_type": "code",
839   "execution_count": 30,
840   "metadata": {},
841   "outputs": [],
842   "source": [
843    "pitch = 1.26\n",
844    "left = openmc.XPlane(x0=-pitch/2, boundary_type='reflective')\n",
845    "right = openmc.XPlane(x0=pitch/2, boundary_type='reflective')\n",
846    "bottom = openmc.YPlane(y0=-pitch/2, boundary_type='reflective')\n",
847    "top = openmc.YPlane(y0=pitch/2, boundary_type='reflective')"
848   ]
849  },
850  {
851   "cell_type": "markdown",
852   "metadata": {},
853   "source": [
854    "The water region is going to be everything outside of the clad outer radius and within the box formed as the intersection of four half-spaces."
855   ]
856  },
857  {
858   "cell_type": "code",
859   "execution_count": 31,
860   "metadata": {},
861   "outputs": [],
862   "source": [
863    "water_region = +left & -right & +bottom & -top & +clad_outer_radius\n",
864    "\n",
865    "moderator = openmc.Cell(name='moderator')\n",
866    "moderator.fill = water\n",
867    "moderator.region = water_region"
868   ]
869  },
870  {
871   "cell_type": "markdown",
872   "metadata": {},
873   "source": [
874    "OpenMC also includes a factory function that generates a rectangular prism that could have made our lives easier."
875   ]
876  },
877  {
878   "cell_type": "code",
879   "execution_count": 32,
880   "metadata": {},
881   "outputs": [
882    {
883     "data": {
884      "text/plain": [
885       "openmc.region.Intersection"
886      ]
887     },
888     "execution_count": 32,
889     "metadata": {},
890     "output_type": "execute_result"
891    }
892   ],
893   "source": [
894    "box = openmc.rectangular_prism(width=pitch, height=pitch,\n",
895    "                               boundary_type='reflective')\n",
896    "type(box)"
897   ]
898  },
899  {
900   "cell_type": "markdown",
901   "metadata": {},
902   "source": [
903    "Pay attention here -- the object that was returned is NOT a surface. It is actually the intersection of four surface half-spaces, just like we created manually before. Thus, we don't need to apply the unary operator (`-box`). Instead, we can directly combine it with `+clad_or`."
904   ]
905  },
906  {
907   "cell_type": "code",
908   "execution_count": 33,
909   "metadata": {},
910   "outputs": [],
911   "source": [
912    "water_region = box & +clad_outer_radius"
913   ]
914  },
915  {
916   "cell_type": "markdown",
917   "metadata": {},
918   "source": [
919    "The final step is to assign the cells we created to a universe and tell OpenMC that this universe is the \"root\" universe in our geometry. The `Geometry` is the final object that is actually exported to XML."
920   ]
921  },
922  {
923   "cell_type": "code",
924   "execution_count": 34,
925   "metadata": {},
926   "outputs": [
927    {
928     "name": "stdout",
929     "output_type": "stream",
930     "text": [
931      "<?xml version='1.0' encoding='utf-8'?>\r\n",
932      "<geometry>\r\n",
933      "  <cell id=\"3\" material=\"1\" name=\"fuel\" region=\"-3\" universe=\"3\" />\r\n",
934      "  <cell id=\"4\" material=\"void\" name=\"air gap\" region=\"3 -4\" universe=\"3\" />\r\n",
935      "  <cell id=\"5\" material=\"3\" name=\"clad\" region=\"4 -5\" universe=\"3\" />\r\n",
936      "  <cell id=\"6\" material=\"4\" name=\"moderator\" region=\"6 -7 8 -9 5\" universe=\"3\" />\r\n",
937      "  <surface coeffs=\"0.0 0.0 0.39\" id=\"3\" type=\"z-cylinder\" />\r\n",
938      "  <surface coeffs=\"0.0 0.0 0.4\" id=\"4\" type=\"z-cylinder\" />\r\n",
939      "  <surface coeffs=\"0.0 0.0 0.46\" id=\"5\" type=\"z-cylinder\" />\r\n",
940      "  <surface boundary=\"reflective\" coeffs=\"-0.63\" id=\"6\" type=\"x-plane\" />\r\n",
941      "  <surface boundary=\"reflective\" coeffs=\"0.63\" id=\"7\" type=\"x-plane\" />\r\n",
942      "  <surface boundary=\"reflective\" coeffs=\"-0.63\" id=\"8\" type=\"y-plane\" />\r\n",
943      "  <surface boundary=\"reflective\" coeffs=\"0.63\" id=\"9\" type=\"y-plane\" />\r\n",
944      "</geometry>\r\n"
945     ]
946    }
947   ],
948   "source": [
949    "root_universe = openmc.Universe(cells=(fuel, gap, clad, moderator))\n",
950    "\n",
951    "geometry = openmc.Geometry()\n",
952    "geometry.root_universe = root_universe\n",
953    "\n",
954    "# or...\n",
955    "geometry = openmc.Geometry(root_universe)\n",
956    "geometry.export_to_xml()\n",
957    "!cat geometry.xml"
958   ]
959  },
960  {
961   "cell_type": "markdown",
962   "metadata": {},
963   "source": [
964    "## Starting source and settings\n",
965    "\n",
966    "The Python API has a module ``openmc.stats`` with various univariate and multivariate probability distributions. We can use these distributions to create a starting source using the ``openmc.Source`` object."
967   ]
968  },
969  {
970   "cell_type": "code",
971   "execution_count": 35,
972   "metadata": {},
973   "outputs": [],
974   "source": [
975    "# Create a point source\n",
976    "point = openmc.stats.Point((0, 0, 0))\n",
977    "source = openmc.Source(space=point)"
978   ]
979  },
980  {
981   "cell_type": "markdown",
982   "metadata": {},
983   "source": [
984    "Now let's create a `Settings` object and give it the source we created along with specifying how many batches and particles we want to run."
985   ]
986  },
987  {
988   "cell_type": "code",
989   "execution_count": 36,
990   "metadata": {},
991   "outputs": [],
992   "source": [
993    "settings = openmc.Settings()\n",
994    "settings.source = source\n",
995    "settings.batches = 100\n",
996    "settings.inactive = 10\n",
997    "settings.particles = 1000"
998   ]
999  },
1000  {
1001   "cell_type": "code",
1002   "execution_count": 37,
1003   "metadata": {},
1004   "outputs": [
1005    {
1006     "name": "stdout",
1007     "output_type": "stream",
1008     "text": [
1009      "<?xml version='1.0' encoding='utf-8'?>\r\n",
1010      "<settings>\r\n",
1011      "  <run_mode>eigenvalue</run_mode>\r\n",
1012      "  <particles>1000</particles>\r\n",
1013      "  <batches>100</batches>\r\n",
1014      "  <inactive>10</inactive>\r\n",
1015      "  <source strength=\"1.0\">\r\n",
1016      "    <space type=\"point\">\r\n",
1017      "      <parameters>0 0 0</parameters>\r\n",
1018      "    </space>\r\n",
1019      "  </source>\r\n",
1020      "</settings>\r\n"
1021     ]
1022    }
1023   ],
1024   "source": [
1025    "settings.export_to_xml()\n",
1026    "!cat settings.xml"
1027   ]
1028  },
1029  {
1030   "cell_type": "markdown",
1031   "metadata": {},
1032   "source": [
1033    "## User-defined tallies\n",
1034    "\n",
1035    "We actually have all the *required* files needed to run a simulation. Before we do that though, let's give a quick example of how to create tallies. We will show how one would tally the total, fission, absorption, and (n,$\\gamma$) reaction rates for $^{235}$U in the cell containing fuel. Recall that filters allow us to specify *where* in phase-space we want events to be tallied and scores tell us *what* we want to tally:\n",
1036    "\n",
1037    "$$X = \\underbrace{\\int d\\mathbf{r} \\int d\\mathbf{\\Omega} \\int dE}_{\\text{filters}} \\; \\underbrace{f(\\mathbf{r},\\mathbf{\\Omega},E)}_{\\text{scores}} \\psi (\\mathbf{r},\\mathbf{\\Omega},E)$$\n",
1038    "\n",
1039    "In this case, the *where* is \"the fuel cell\". So, we will create a cell filter specifying the fuel cell."
1040   ]
1041  },
1042  {
1043   "cell_type": "code",
1044   "execution_count": 38,
1045   "metadata": {},
1046   "outputs": [],
1047   "source": [
1048    "cell_filter = openmc.CellFilter(fuel)\n",
1049    "\n",
1050    "tally = openmc.Tally(1)\n",
1051    "tally.filters = [cell_filter]"
1052   ]
1053  },
1054  {
1055   "cell_type": "markdown",
1056   "metadata": {},
1057   "source": [
1058    "The *what* is the total, fission, absorption, and (n,$\\gamma$) reaction rates in $^{235}$U. By default, if we only specify what reactions, it will gives us tallies over all nuclides. We can use the `nuclides` attribute to name specific nuclides we're interested in."
1059   ]
1060  },
1061  {
1062   "cell_type": "code",
1063   "execution_count": 39,
1064   "metadata": {},
1065   "outputs": [],
1066   "source": [
1067    "tally.nuclides = ['U235']\n",
1068    "tally.scores = ['total', 'fission', 'absorption', '(n,gamma)']"
1069   ]
1070  },
1071  {
1072   "cell_type": "markdown",
1073   "metadata": {},
1074   "source": [
1075    "Similar to the other files, we need to create a `Tallies` collection and export it to XML."
1076   ]
1077  },
1078  {
1079   "cell_type": "code",
1080   "execution_count": 40,
1081   "metadata": {},
1082   "outputs": [
1083    {
1084     "name": "stdout",
1085     "output_type": "stream",
1086     "text": [
1087      "<?xml version='1.0' encoding='utf-8'?>\r\n",
1088      "<tallies>\r\n",
1089      "  <filter id=\"1\" type=\"cell\">\r\n",
1090      "    <bins>3</bins>\r\n",
1091      "  </filter>\r\n",
1092      "  <tally id=\"1\">\r\n",
1093      "    <filters>1</filters>\r\n",
1094      "    <nuclides>U235</nuclides>\r\n",
1095      "    <scores>total fission absorption (n,gamma)</scores>\r\n",
1096      "  </tally>\r\n",
1097      "</tallies>\r\n"
1098     ]
1099    }
1100   ],
1101   "source": [
1102    "tallies = openmc.Tallies([tally])\n",
1103    "tallies.export_to_xml()\n",
1104    "!cat tallies.xml"
1105   ]
1106  },
1107  {
1108   "cell_type": "markdown",
1109   "metadata": {},
1110   "source": [
1111    "## Running OpenMC\n",
1112    "\n",
1113    "Running OpenMC from Python can be done using the `openmc.run()` function. This function allows you to set the number of MPI processes and OpenMP threads, if need be."
1114   ]
1115  },
1116  {
1117   "cell_type": "code",
1118   "execution_count": 41,
1119   "metadata": {
1120    "scrolled": true
1121   },
1122   "outputs": [
1123    {
1124     "name": "stdout",
1125     "output_type": "stream",
1126     "text": [
1127      "                                %%%%%%%%%%%%%%%\n",
1128      "                           %%%%%%%%%%%%%%%%%%%%%%%%\n",
1129      "                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
1130      "                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
1131      "                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
1132      "                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
1133      "                                    %%%%%%%%%%%%%%%%%%%%%%%%\n",
1134      "                                     %%%%%%%%%%%%%%%%%%%%%%%%\n",
1135      "                 ###############      %%%%%%%%%%%%%%%%%%%%%%%%\n",
1136      "                ##################     %%%%%%%%%%%%%%%%%%%%%%%\n",
1137      "                ###################     %%%%%%%%%%%%%%%%%%%%%%%\n",
1138      "                ####################     %%%%%%%%%%%%%%%%%%%%%%\n",
1139      "                #####################     %%%%%%%%%%%%%%%%%%%%%\n",
1140      "                ######################     %%%%%%%%%%%%%%%%%%%%\n",
1141      "                #######################     %%%%%%%%%%%%%%%%%%\n",
1142      "                 #######################     %%%%%%%%%%%%%%%%%\n",
1143      "                 ######################     %%%%%%%%%%%%%%%%%\n",
1144      "                  ####################     %%%%%%%%%%%%%%%%%\n",
1145      "                    #################     %%%%%%%%%%%%%%%%%\n",
1146      "                     ###############     %%%%%%%%%%%%%%%%\n",
1147      "                       ############     %%%%%%%%%%%%%%%\n",
1148      "                          ########     %%%%%%%%%%%%%%\n",
1149      "                                      %%%%%%%%%%%\n",
1150      "\n",
1151      "                   | The OpenMC Monte Carlo Code\n",
1152      "         Copyright | 2011-2020 MIT and OpenMC contributors\n",
1153      "           License | https://docs.openmc.org/en/latest/license.html\n",
1154      "           Version | 0.12.0\n",
1155      "          Git SHA1 | 3d90a9f857ec72eae897e054d4225180f1fa4d93\n",
1156      "         Date/Time | 2020-08-25 14:58:51\n",
1157      "    OpenMP Threads | 4\n",
1158      "\n",
1159      " Reading settings XML file...\n",
1160      " Reading cross sections XML file...\n",
1161      " Reading materials XML file...\n",
1162      " Reading geometry XML file...\n",
1163      " Reading U235 from /home/master/data/nuclear/endfb71_hdf5/U235.h5\n",
1164      " Reading U238 from /home/master/data/nuclear/endfb71_hdf5/U238.h5\n",
1165      " Reading O16 from /home/master/data/nuclear/endfb71_hdf5/O16.h5\n",
1166      " Reading Zr90 from /home/master/data/nuclear/endfb71_hdf5/Zr90.h5\n",
1167      " Reading Zr91 from /home/master/data/nuclear/endfb71_hdf5/Zr91.h5\n",
1168      " Reading Zr92 from /home/master/data/nuclear/endfb71_hdf5/Zr92.h5\n",
1169      " Reading Zr94 from /home/master/data/nuclear/endfb71_hdf5/Zr94.h5\n",
1170      " Reading Zr96 from /home/master/data/nuclear/endfb71_hdf5/Zr96.h5\n",
1171      " Reading H1 from /home/master/data/nuclear/endfb71_hdf5/H1.h5\n",
1172      " Reading O17 from /home/master/data/nuclear/endfb71_hdf5/O17.h5\n",
1173      " Reading c_H_in_H2O from /home/master/data/nuclear/endfb71_hdf5/c_H_in_H2O.h5\n",
1174      " Minimum neutron data temperature: 294.000000 K\n",
1175      " Maximum neutron data temperature: 294.000000 K\n",
1176      " Reading tallies XML file...\n",
1177      " Preparing distributed cell instances...\n",
1178      " Writing summary.h5 file...\n",
1179      " Maximum neutron transport energy: 20000000.000000 eV for U235\n",
1180      " Initializing source particles...\n",
1181      "\n",
1182      " ====================>     K EIGENVALUE SIMULATION     <====================\n",
1183      "\n",
1184      "  Bat./Gen.      k            Average k\n",
1185      "  =========   ========   ====================\n",
1186      "        1/1    1.42066\n",
1187      "        2/1    1.39831\n",
1188      "        3/1    1.46207\n",
1189      "        4/1    1.44888\n",
1190      "        5/1    1.42595\n",
1191      "        6/1    1.35549\n",
1192      "        7/1    1.36717\n",
1193      "        8/1    1.45095\n",
1194      "        9/1    1.36061\n",
1195      "       10/1    1.36554\n",
1196      "       11/1    1.36973\n",
1197      "       12/1    1.44276    1.40625 +/- 0.03652\n",
1198      "       13/1    1.35512    1.38920 +/- 0.02711\n",
1199      "       14/1    1.54216    1.42744 +/- 0.04277\n",
1200      "       15/1    1.39353    1.42066 +/- 0.03382\n",
1201      "       16/1    1.38650    1.41497 +/- 0.02820\n",
1202      "       17/1    1.38760    1.41106 +/- 0.02415\n",
1203      "       18/1    1.38413    1.40769 +/- 0.02118\n",
1204      "       19/1    1.39088    1.40582 +/- 0.01877\n",
1205      "       20/1    1.47468    1.41271 +/- 0.01815\n",
1206      "       21/1    1.45695    1.41673 +/- 0.01690\n",
1207      "       22/1    1.40308    1.41559 +/- 0.01547\n",
1208      "       23/1    1.40821    1.41503 +/- 0.01424\n",
1209      "       24/1    1.32301    1.40845 +/- 0.01473\n",
1210      "       25/1    1.36702    1.40569 +/- 0.01399\n",
1211      "       26/1    1.30968    1.39969 +/- 0.01440\n",
1212      "       27/1    1.38099    1.39859 +/- 0.01357\n",
1213      "       28/1    1.42103    1.39984 +/- 0.01285\n",
1214      "       29/1    1.39741    1.39971 +/- 0.01216\n",
1215      "       30/1    1.36548    1.39800 +/- 0.01166\n",
1216      "       31/1    1.41573    1.39884 +/- 0.01112\n",
1217      "       32/1    1.39788    1.39880 +/- 0.01061\n",
1218      "       33/1    1.35942    1.39709 +/- 0.01028\n",
1219      "       34/1    1.40483    1.39741 +/- 0.00985\n",
1220      "       35/1    1.39418    1.39728 +/- 0.00944\n",
1221      "       36/1    1.41492    1.39796 +/- 0.00910\n",
1222      "       37/1    1.49392    1.40151 +/- 0.00945\n",
1223      "       38/1    1.45114    1.40329 +/- 0.00928\n",
1224      "       39/1    1.42619    1.40408 +/- 0.00899\n",
1225      "       40/1    1.35249    1.40236 +/- 0.00885\n",
1226      "       41/1    1.35401    1.40080 +/- 0.00870\n",
1227      "       42/1    1.40220    1.40084 +/- 0.00842\n",
1228      "       43/1    1.36437    1.39974 +/- 0.00824\n",
1229      "       44/1    1.33642    1.39787 +/- 0.00821\n",
1230      "       45/1    1.36953    1.39706 +/- 0.00801\n",
1231      "       46/1    1.30034    1.39438 +/- 0.00824\n",
1232      "       47/1    1.44097    1.39564 +/- 0.00811\n",
1233      "       48/1    1.37981    1.39522 +/- 0.00790\n",
1234      "       49/1    1.34870    1.39403 +/- 0.00779\n",
1235      "       50/1    1.41247    1.39449 +/- 0.00761\n",
1236      "       51/1    1.33382    1.39301 +/- 0.00756\n",
1237      "       52/1    1.37043    1.39247 +/- 0.00740\n",
1238      "       53/1    1.38754    1.39236 +/- 0.00723\n",
1239      "       54/1    1.40160    1.39257 +/- 0.00707\n",
1240      "       55/1    1.37511    1.39218 +/- 0.00692\n",
1241      "       56/1    1.38589    1.39204 +/- 0.00677\n",
1242      "       57/1    1.40630    1.39234 +/- 0.00663\n",
1243      "       58/1    1.29944    1.39041 +/- 0.00677\n",
1244      "       59/1    1.40019    1.39061 +/- 0.00663\n",
1245      "       60/1    1.42384    1.39127 +/- 0.00653\n",
1246      "       61/1    1.36502    1.39076 +/- 0.00643\n",
1247      "       62/1    1.37042    1.39037 +/- 0.00631\n",
1248      "       63/1    1.42295    1.39098 +/- 0.00622\n",
1249      "       64/1    1.40042    1.39116 +/- 0.00611\n",
1250      "       65/1    1.36382    1.39066 +/- 0.00602\n",
1251      "       66/1    1.31659    1.38934 +/- 0.00606\n",
1252      "       67/1    1.36101    1.38884 +/- 0.00597\n",
1253      "       68/1    1.46359    1.39013 +/- 0.00601\n",
1254      "       69/1    1.41012    1.39047 +/- 0.00591\n",
1255      "       70/1    1.27411    1.38853 +/- 0.00613\n",
1256      "       71/1    1.45399    1.38960 +/- 0.00612\n",
1257      "       72/1    1.40455    1.38984 +/- 0.00603\n",
1258      "       73/1    1.33020    1.38890 +/- 0.00601\n",
1259      "       74/1    1.44599    1.38979 +/- 0.00598\n",
1260      "       75/1    1.34985    1.38917 +/- 0.00592\n",
1261      "       76/1    1.36183    1.38876 +/- 0.00584\n",
1262      "       77/1    1.41080    1.38909 +/- 0.00576\n",
1263      "       78/1    1.43991    1.38984 +/- 0.00573\n",
1264      "       79/1    1.35613    1.38935 +/- 0.00566\n",
1265      "       80/1    1.31659    1.38831 +/- 0.00568\n",
1266      "       81/1    1.51344    1.39007 +/- 0.00587\n",
1267      "       82/1    1.38404    1.38999 +/- 0.00579\n",
1268      "       83/1    1.39613    1.39007 +/- 0.00571\n",
1269      "       84/1    1.43037    1.39061 +/- 0.00566\n",
1270      "       85/1    1.47316    1.39172 +/- 0.00569\n",
1271      "       86/1    1.39220    1.39172 +/- 0.00561\n",
1272      "       87/1    1.44400    1.39240 +/- 0.00558\n",
1273      "       88/1    1.42419    1.39281 +/- 0.00552\n",
1274      "       89/1    1.30930    1.39175 +/- 0.00556\n",
1275      "       90/1    1.46976    1.39273 +/- 0.00557\n",
1276      "       91/1    1.38334    1.39261 +/- 0.00550\n",
1277      "       92/1    1.35260    1.39212 +/- 0.00546\n",
1278      "       93/1    1.38505    1.39204 +/- 0.00539\n",
1279      "       94/1    1.38290    1.39193 +/- 0.00533\n",
1280      "       95/1    1.42597    1.39233 +/- 0.00528\n",
1281      "       96/1    1.41624    1.39261 +/- 0.00523\n",
1282      "       97/1    1.42053    1.39293 +/- 0.00518\n",
1283      "       98/1    1.36268    1.39258 +/- 0.00513\n",
1284      "       99/1    1.39175    1.39258 +/- 0.00507\n",
1285      "      100/1    1.38148    1.39245 +/- 0.00502\n",
1286      " Creating state point statepoint.100.h5...\n",
1287      "\n",
1288      " =======================>     TIMING STATISTICS     <=======================\n",
1289      "\n",
1290      " Total time for initialization     = 6.9022e-01 seconds\n",
1291      "   Reading cross sections          = 6.7913e-01 seconds\n",
1292      " Total time in simulation          = 1.7892e+00 seconds\n",
1293      "   Time in transport only          = 1.7650e+00 seconds\n",
1294      "   Time in inactive batches        = 1.5005e-01 seconds\n",
1295      "   Time in active batches          = 1.6391e+00 seconds\n",
1296      "   Time synchronizing fission bank = 4.2308e-03 seconds\n",
1297      "     Sampling source sites         = 3.4593e-03 seconds\n",
1298      "     SEND/RECV source sites        = 6.2601e-04 seconds\n",
1299      "   Time accumulating tallies       = 9.5555e-05 seconds\n",
1300      " Total time for finalization       = 7.4948e-05 seconds\n",
1301      " Total time elapsed                = 2.4836e+00 seconds\n",
1302      " Calculation Rate (inactive)       = 66645.8 particles/second\n",
1303      " Calculation Rate (active)         = 54907.5 particles/second\n",
1304      "\n",
1305      " ============================>     RESULTS     <============================\n",
1306      "\n",
1307      " k-effective (Collision)     = 1.39516 +/- 0.00457\n",
1308      " k-effective (Track-length)  = 1.39245 +/- 0.00502\n",
1309      " k-effective (Absorption)    = 1.40443 +/- 0.00333\n",
1310      " Combined k-effective        = 1.40145 +/- 0.00319\n",
1311      " Leakage Fraction            = 0.00000 +/- 0.00000\n",
1312      "\n"
1313     ]
1314    }
1315   ],
1316   "source": [
1317    "openmc.run()"
1318   ]
1319  },
1320  {
1321   "cell_type": "markdown",
1322   "metadata": {},
1323   "source": [
1324    "Great! OpenMC already told us our k-effective. It also spit out a file called `tallies.out` that shows our tallies. This is a very basic method to look at tally data; for more sophisticated methods, see other example notebooks."
1325   ]
1326  },
1327  {
1328   "cell_type": "code",
1329   "execution_count": 42,
1330   "metadata": {},
1331   "outputs": [
1332    {
1333     "name": "stdout",
1334     "output_type": "stream",
1335     "text": [
1336      " ============================>     TALLY 1     <============================\r\n",
1337      "\r\n",
1338      " Cell 3\r\n",
1339      "   U235\r\n",
1340      "     Total Reaction Rate                  0.726151 +/- 0.00251702\r\n",
1341      "     Fission Rate                         0.543836 +/- 0.00205084\r\n",
1342      "     Absorption Rate                      0.652874 +/- 0.002424\r\n",
1343      "     (n,gamma)                            0.10904 +/- 0.000385793\r\n"
1344     ]
1345    }
1346   ],
1347   "source": [
1348    "!cat tallies.out"
1349   ]
1350  },
1351  {
1352   "cell_type": "markdown",
1353   "metadata": {},
1354   "source": [
1355    "## Geometry plotting\n",
1356    "\n",
1357    "We saw before that we could call the `Universe.plot()` method to show a universe while we were creating our geometry. There is also a built-in plotter in the codebase that is much faster than the Python plotter and has more options. The interface looks somewhat similar to the `Universe.plot()` method. Instead though, we create `Plot` instances, assign them to a `Plots` collection, export it to XML, and then run OpenMC in geometry plotting mode. As an example, let's specify that we want the plot to be colored by material (rather than by cell) and we assign yellow to fuel and blue to water."
1358   ]
1359  },
1360  {
1361   "cell_type": "code",
1362   "execution_count": 43,
1363   "metadata": {},
1364   "outputs": [],
1365   "source": [
1366    "plot = openmc.Plot()\n",
1367    "plot.filename = 'pinplot'\n",
1368    "plot.width = (pitch, pitch)\n",
1369    "plot.pixels = (200, 200)\n",
1370    "plot.color_by = 'material'\n",
1371    "plot.colors = {uo2: 'yellow', water: 'blue'}"
1372   ]
1373  },
1374  {
1375   "cell_type": "markdown",
1376   "metadata": {},
1377   "source": [
1378    "With our plot created, we need to add it to a `Plots` collection which can be exported to XML."
1379   ]
1380  },
1381  {
1382   "cell_type": "code",
1383   "execution_count": 44,
1384   "metadata": {},
1385   "outputs": [
1386    {
1387     "name": "stdout",
1388     "output_type": "stream",
1389     "text": [
1390      "<?xml version='1.0' encoding='utf-8'?>\r\n",
1391      "<plots>\r\n",
1392      "  <plot basis=\"xy\" color_by=\"material\" filename=\"pinplot\" id=\"1\" type=\"slice\">\r\n",
1393      "    <origin>0.0 0.0 0.0</origin>\r\n",
1394      "    <width>1.26 1.26</width>\r\n",
1395      "    <pixels>200 200</pixels>\r\n",
1396      "    <color id=\"1\" rgb=\"255 255 0\" />\r\n",
1397      "    <color id=\"4\" rgb=\"0 0 255\" />\r\n",
1398      "  </plot>\r\n",
1399      "</plots>\r\n"
1400     ]
1401    }
1402   ],
1403   "source": [
1404    "plots = openmc.Plots([plot])\n",
1405    "plots.export_to_xml()\n",
1406    "!cat plots.xml"
1407   ]
1408  },
1409  {
1410   "cell_type": "markdown",
1411   "metadata": {},
1412   "source": [
1413    "Now we can run OpenMC in plotting mode by calling the `plot_geometry()` function. Under the hood this is calling `openmc --plot`."
1414   ]
1415  },
1416  {
1417   "cell_type": "code",
1418   "execution_count": 45,
1419   "metadata": {},
1420   "outputs": [
1421    {
1422     "name": "stdout",
1423     "output_type": "stream",
1424     "text": [
1425      "                                %%%%%%%%%%%%%%%\n",
1426      "                           %%%%%%%%%%%%%%%%%%%%%%%%\n",
1427      "                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
1428      "                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
1429      "                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
1430      "                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
1431      "                                    %%%%%%%%%%%%%%%%%%%%%%%%\n",
1432      "                                     %%%%%%%%%%%%%%%%%%%%%%%%\n",
1433      "                 ###############      %%%%%%%%%%%%%%%%%%%%%%%%\n",
1434      "                ##################     %%%%%%%%%%%%%%%%%%%%%%%\n",
1435      "                ###################     %%%%%%%%%%%%%%%%%%%%%%%\n",
1436      "                ####################     %%%%%%%%%%%%%%%%%%%%%%\n",
1437      "                #####################     %%%%%%%%%%%%%%%%%%%%%\n",
1438      "                ######################     %%%%%%%%%%%%%%%%%%%%\n",
1439      "                #######################     %%%%%%%%%%%%%%%%%%\n",
1440      "                 #######################     %%%%%%%%%%%%%%%%%\n",
1441      "                 ######################     %%%%%%%%%%%%%%%%%\n",
1442      "                  ####################     %%%%%%%%%%%%%%%%%\n",
1443      "                    #################     %%%%%%%%%%%%%%%%%\n",
1444      "                     ###############     %%%%%%%%%%%%%%%%\n",
1445      "                       ############     %%%%%%%%%%%%%%%\n",
1446      "                          ########     %%%%%%%%%%%%%%\n",
1447      "                                      %%%%%%%%%%%\n",
1448      "\n",
1449      "                   | The OpenMC Monte Carlo Code\n",
1450      "         Copyright | 2011-2020 MIT and OpenMC contributors\n",
1451      "           License | https://docs.openmc.org/en/latest/license.html\n",
1452      "           Version | 0.12.0\n",
1453      "          Git SHA1 | 3d90a9f857ec72eae897e054d4225180f1fa4d93\n",
1454      "         Date/Time | 2020-08-25 14:58:54\n",
1455      "    OpenMP Threads | 4\n",
1456      "\n",
1457      " Reading settings XML file...\n",
1458      " Reading cross sections XML file...\n",
1459      " Reading materials XML file...\n",
1460      " Reading geometry XML file...\n",
1461      " Reading tallies XML file...\n",
1462      " Preparing distributed cell instances...\n",
1463      " Reading plot XML file...\n",
1464      "\n",
1465      " =======================>     PLOTTING SUMMARY     <========================\n",
1466      "\n",
1467      "Plot ID: 1\n",
1468      "Plot file: pinplot.ppm\n",
1469      "Universe depth: -1\n",
1470      "Plot Type: Slice\n",
1471      "Origin: 0.0 0.0 0.0\n",
1472      "Width: 1.26 1.26\n",
1473      "Coloring: Materials\n",
1474      "Basis: XY\n",
1475      "Pixels: 200 200\n",
1476      "\n",
1477      " Processing plot 1: pinplot.ppm...\n"
1478     ]
1479    }
1480   ],
1481   "source": [
1482    "openmc.plot_geometry()"
1483   ]
1484  },
1485  {
1486   "cell_type": "markdown",
1487   "metadata": {},
1488   "source": [
1489    "OpenMC writes out a peculiar image with a `.ppm` extension. If you have ImageMagick installed, this can be converted into a more normal `.png` file."
1490   ]
1491  },
1492  {
1493   "cell_type": "code",
1494   "execution_count": 46,
1495   "metadata": {},
1496   "outputs": [],
1497   "source": [
1498    "!convert pinplot.ppm pinplot.png"
1499   ]
1500  },
1501  {
1502   "cell_type": "markdown",
1503   "metadata": {},
1504   "source": [
1505    "We can use functionality from IPython to display the image inline in our notebook:"
1506   ]
1507  },
1508  {
1509   "cell_type": "code",
1510   "execution_count": 47,
1511   "metadata": {
1512    "scrolled": false
1513   },
1514   "outputs": [
1515    {
1516     "data": {
1517      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAgMAAADQNkYNAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEUAAP9yEhL//////wAZPRNOAAAAAWJLR0QCZgt8ZAAAAAd0SU1FB+QIGQ86Nr0vrD0AAAI7SURBVGje7ZmxkcIwEEUhcAnuhxIIEIGvAwioxiU4QASU4GougA4gsM6SfNxh766sfx7N3Ix+zJv9X7KxtLtaZWVlZWWl1Fr12sQQpXLaRRMRTKFe2kbk+Na8POpNkbbmWlMqtkwxRsJllIotMxQ56F7neWX8LmrdGtNpPWc//Z4cLsbpfp6xN85XNRA904Sd2V/stXlJ16EFcL4O7Q/SnUPOrK/9xfzSvQ44K0dFhjLCmq0nRYYyvDPrq2rfka4RnVlfoyJ9GdGZ9XUdI89aWGYbpTITNUKYgvLlnXFhSsqXd7bjEcKXc8YhvYEjhdzY/Db9lUKebP4+/b6lkK7m8nNRhDAlE8WFoREuig/DpKej+DAbGmGiuDAUUsgItWR8ejZ/yaZ3+SmET+/zL4JIC8Ys2VpI7/JPkSKEbCnkyiNPCilDyI5A+AVzSzZFVAhRBCKssVvlBRB5W8iNwZCThDymiLyT5F5iSCsh3RSRN5/cfgwxoiikkpFmgqgwopZAPmTkcxnkKCO3BZDQs088/RhykpFHRjLyP5AE70uadz/Z/1iK/2TgYwF9klJ8K4GPeJrTBXDsSXMeS3O2RA69wNEaOMAD1wTgMgJceYCLVZobH3IVBS68wLUauLwDLQKgEYG0O4CmCtC6ARpEQBsKaXYBLTWgcQe0B4EmJNLqBBqqQNsWaA4jLWig0Q2005GmPTAaAAYQyJgDGKYgIxtgMISMn4AhFzJKAwZ2yFgQGT4iI86srKysrD/rC4LWcCSWwIp+AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTA4LTI1VDE0OjU4OjU0KzAxOjAwkH0c4gAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0wOC0yNVQxNDo1ODo1NCswMTowMOEgpF4AAAAASUVORK5CYII=\n",
1518      "text/plain": [
1519       "<IPython.core.display.Image object>"
1520      ]
1521     },
1522     "execution_count": 47,
1523     "metadata": {},
1524     "output_type": "execute_result"
1525    }
1526   ],
1527   "source": [
1528    "from IPython.display import Image\n",
1529    "Image(\"pinplot.png\")"
1530   ]
1531  },
1532  {
1533   "cell_type": "markdown",
1534   "metadata": {},
1535   "source": [
1536    "That was a little bit cumbersome. Thankfully, OpenMC provides us with a method on the `Plot` class that does all that \"boilerplate\" work."
1537   ]
1538  },
1539  {
1540   "cell_type": "code",
1541   "execution_count": 48,
1542   "metadata": {},
1543   "outputs": [
1544    {
1545     "data": {
1546      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAgMAAADQNkYNAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEUAAP9yEhL//////wAZPRNOAAAAAWJLR0QCZgt8ZAAAAAd0SU1FB+QIGQ86Nr0vrD0AAAI7SURBVGje7ZmxkcIwEEUhcAnuhxIIEIGvAwioxiU4QASU4GougA4gsM6SfNxh766sfx7N3Ix+zJv9X7KxtLtaZWVlZWWl1Fr12sQQpXLaRRMRTKFe2kbk+Na8POpNkbbmWlMqtkwxRsJllIotMxQ56F7neWX8LmrdGtNpPWc//Z4cLsbpfp6xN85XNRA904Sd2V/stXlJ16EFcL4O7Q/SnUPOrK/9xfzSvQ44K0dFhjLCmq0nRYYyvDPrq2rfka4RnVlfoyJ9GdGZ9XUdI89aWGYbpTITNUKYgvLlnXFhSsqXd7bjEcKXc8YhvYEjhdzY/Db9lUKebP4+/b6lkK7m8nNRhDAlE8WFoREuig/DpKej+DAbGmGiuDAUUsgItWR8ejZ/yaZ3+SmET+/zL4JIC8Ys2VpI7/JPkSKEbCnkyiNPCilDyI5A+AVzSzZFVAhRBCKssVvlBRB5W8iNwZCThDymiLyT5F5iSCsh3RSRN5/cfgwxoiikkpFmgqgwopZAPmTkcxnkKCO3BZDQs088/RhykpFHRjLyP5AE70uadz/Z/1iK/2TgYwF9klJ8K4GPeJrTBXDsSXMeS3O2RA69wNEaOMAD1wTgMgJceYCLVZobH3IVBS68wLUauLwDLQKgEYG0O4CmCtC6ARpEQBsKaXYBLTWgcQe0B4EmJNLqBBqqQNsWaA4jLWig0Q2005GmPTAaAAYQyJgDGKYgIxtgMISMn4AhFzJKAwZ2yFgQGT4iI86srKysrD/rC4LWcCSWwIp+AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTA4LTI1VDE0OjU4OjU0KzAxOjAwkH0c4gAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0wOC0yNVQxNDo1ODo1NCswMTowMOEgpF4AAAAASUVORK5CYII=\n",
1547      "text/plain": [
1548       "<IPython.core.display.Image object>"
1549      ]
1550     },
1551     "execution_count": 48,
1552     "metadata": {},
1553     "output_type": "execute_result"
1554    }
1555   ],
1556   "source": [
1557    "plot.to_ipython_image()"
1558   ]
1559  }
1560 ],
1561 "metadata": {
1562  "anaconda-cloud": {},
1563  "kernelspec": {
1564   "display_name": "Python 3",
1565   "language": "python",
1566   "name": "python3"
1567  },
1568  "language_info": {
1569   "codemirror_mode": {
1570    "name": "ipython",
1571    "version": 3
1572   },
1573   "file_extension": ".py",
1574   "mimetype": "text/x-python",
1575   "name": "python",
1576   "nbconvert_exporter": "python",
1577   "pygments_lexer": "ipython3",
1578   "version": "3.8.3"
1579  }
1580 },
1581 "nbformat": 4,
1582 "nbformat_minor": 1
1583}
1584