From 7dd7af6dfa87676190bd7043b050a9f79f0652a8 Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Mon, 2 Mar 2020 18:54:03 +0000 Subject: [PATCH 01/13] Checks for -ve volume and adds it to Cell.__repl_ --- openmc/cell.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/openmc/cell.py b/openmc/cell.py index e01cb8613..792f152be 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -4,6 +4,7 @@ from copy import deepcopy from math import cos, sin, pi from numbers import Real from xml.etree import ElementTree as ET +from uncertainties import UFloat import sys import warnings @@ -134,6 +135,7 @@ class Cell(IDManagerMixin): string += '\t{0: <15}=\t{1}\n'.format('Temperature', self.temperature) string += '{: <16}=\t{}\n'.format('\tTranslation', self.translation) + string += '{: <16}=\t{}\n'.format('\tVolume', self.volume) return string @@ -285,9 +287,18 @@ class Cell(IDManagerMixin): @volume.setter def volume(self, volume): if volume is not None: - cv.check_type('cell volume', volume, Real) + try: + cv.check_type('cell volume', volume, Real) + except TypeError: + cv.check_type('cell volume', volume, UFloat) + cv.check_greater_than('cell volume', volume, 0.0) self._volume = volume + # Forget now invalid info about atoms content + # (sice volume has just changed) + if self._atoms is not None: + self._atoms = None + def add_volume_information(self, volume_calc): """Add volume information to a cell. From c0f7459ff39c5735dd873cfb658a8885b363a603 Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Mon, 2 Mar 2020 19:41:56 +0000 Subject: [PATCH 02/13] Implement getter for Cell.atoms Make type checking in Cell.volume more compact --- openmc/cell.py | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 792f152be..3ecab7ba1 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -184,6 +184,35 @@ class Cell(IDManagerMixin): def volume(self): return self._volume + @property + def atoms(self): + if self._atoms is None: + if self._volume is None: + msg = 'Cannot calculate atoms content becouse no volume '\ + 'is set. Use Cell.volume to provide it or perform '\ + 'stochastic volume calculation.' + raise ValueError(msg) + + elif self._fill is None: + msg = 'Cell is filled with void. It contains no atoms.' + raise ValueError(msg) + + elif isinstance(self._fill, (openmc.Universe, openmc.Lattice)): + msg = 'Universe and Lattice cells can contain multiple '\ + 'materials. Atoms content must be calculated with '\ + 'stochastic volume calculation' + raise ValueError(msg) + + elif isinstance(self._fill, openmc.Material): + # Get atomic Densities + self._atoms = self._fill.get_nuclide_atom_densities() + + # Convert to total number of atoms + for key, nuclide in self._atoms.items(): + self._atoms[key] = (nuclide[0], nuclide[1] * self._volume) + + return self._atoms + @property def paths(self): if self._paths is None: @@ -287,14 +316,11 @@ class Cell(IDManagerMixin): @volume.setter def volume(self, volume): if volume is not None: - try: - cv.check_type('cell volume', volume, Real) - except TypeError: - cv.check_type('cell volume', volume, UFloat) + cv.check_type('cell volume', volume, (Real, UFloat)) cv.check_greater_than('cell volume', volume, 0.0) self._volume = volume - # Forget now invalid info about atoms content + # Info about atoms content can now be invalid # (sice volume has just changed) if self._atoms is not None: self._atoms = None From 36512e30968f1c46f29736c20b59719a26f5b10c Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Tue, 3 Mar 2020 15:54:28 +0000 Subject: [PATCH 03/13] Add tests for Cell.atoms and Cell.volume Remove unnecessary 'if' blocks Print volume in __repr__ only if its set to preserve regression Make shure that _atoms is forgotten for volume/fill changes --- openmc/cell.py | 52 +++++++++++------ tests/unit_tests/test_cell.py | 102 +++++++++++++++++++++++++++++++++- 2 files changed, 136 insertions(+), 18 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 3ecab7ba1..67c224de5 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -135,7 +135,10 @@ class Cell(IDManagerMixin): string += '\t{0: <15}=\t{1}\n'.format('Temperature', self.temperature) string += '{: <16}=\t{}\n'.format('\tTranslation', self.translation) - string += '{: <16}=\t{}\n'.format('\tVolume', self.volume) + + # Print Volume only when its set to avoid breaking regression + if self._volume is not None: + string += '{: <16}=\t{}\n'.format('\tVolume', self.volume) return string @@ -188,28 +191,33 @@ class Cell(IDManagerMixin): def atoms(self): if self._atoms is None: if self._volume is None: - msg = 'Cannot calculate atoms content becouse no volume '\ - 'is set. Use Cell.volume to provide it or perform '\ - 'stochastic volume calculation.' + msg = ('Cannot calculate atoms content becouse no volume ' + 'is set. Use Cell.volume to provide it or perform ' + 'stochastic volume calculation.') raise ValueError(msg) - elif self._fill is None: - msg = 'Cell is filled with void. It contains no atoms.' + elif self.fill_type == 'void': + msg = ('Cell is filled with void. It contains no atoms. ' + 'Material must be set to calculate atoms content.') raise ValueError(msg) - elif isinstance(self._fill, (openmc.Universe, openmc.Lattice)): - msg = 'Universe and Lattice cells can contain multiple '\ - 'materials. Atoms content must be calculated with '\ - 'stochastic volume calculation' + elif self.fill_type != 'material': + msg = ('Universe, Lattice and Distributed Material cells can ' + 'contain multiple materials. Atoms content must be ' + 'calculated with stochastic volume calculation') raise ValueError(msg) - elif isinstance(self._fill, openmc.Material): + elif self.fill_type == 'material': # Get atomic Densities self._atoms = self._fill.get_nuclide_atom_densities() # Convert to total number of atoms for key, nuclide in self._atoms.items(): - self._atoms[key] = (nuclide[0], nuclide[1] * self._volume) + atom_num = nuclide[1] * self._volume * 1.0E+24 + self._atoms[key] = (nuclide[0], atom_num) + else: + msg = 'Unrecognised fill_type:{}'.format(self.fill_type) + raise ValueError(msg) return self._atoms @@ -254,12 +262,16 @@ class Cell(IDManagerMixin): elif not isinstance(fill, (openmc.Material, openmc.Lattice, openmc.Universe)): - msg = 'Unable to set Cell ID="{0}" to use a non-Material or ' \ - 'Universe fill "{1}"'.format(self._id, fill) + msg = ('Unable to set Cell ID="{0}" to use a non-Material or ' + 'Universe fill "{1}"'.format(self._id, fill)) raise ValueError(msg) self._fill = fill + # Info about atoms content can now be invalid + # (sice fill has just changed) + self._atoms = None + @rotation.setter def rotation(self, rotation): cv.check_length('cell rotation', rotation, 3) @@ -317,13 +329,19 @@ class Cell(IDManagerMixin): def volume(self, volume): if volume is not None: cv.check_type('cell volume', volume, (Real, UFloat)) - cv.check_greater_than('cell volume', volume, 0.0) + + # Note that ufloat(0.0, 0.1) >= 0.0 is False + # we need special treatment for UFloat input + val = volume + if isinstance(val, UFloat): + val = volume.nominal_value + cv.check_greater_than('cell volume', val, 0.0) + self._volume = volume # Info about atoms content can now be invalid # (sice volume has just changed) - if self._atoms is not None: - self._atoms = None + self._atoms = None def add_volume_information(self, volume_calc): """Add volume information to a cell. diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 6ac4ae9c0..03b03c6e9 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -1,10 +1,16 @@ import xml.etree. ElementTree as ET import numpy as np +import uncertainties as u import openmc import pytest + from tests.unit_tests import assert_unbounded +from openmc.data import atomic_mass, AVOGADRO + +# Relative tolerance for float comparison +TOL = 1e-9 def test_contains(): @@ -29,6 +35,14 @@ def test_repr(cell_with_lattice): c = openmc.Cell() repr(c) + # Empty cell with Volume + c.volume = 3.0 + repr(c) + + # Empty cell with Uncertain Volume + c.volume = u.ufloat(3.0, 0.2) + repr(c) + def test_bounding_box(): zcyl = openmc.ZCylinder() @@ -112,6 +126,92 @@ def test_get_nuclides(uo2): assert nucs == ['U235', 'O16'] +def test_volume_setting(): + c = openmc.Cell() + + # Test ordinary volume and uncertain volume + c.volume = 3 + c.volume = u.ufloat(3, 0.7) + + # Test errors for -ve and 0 volume + with pytest.raises(ValueError): + c.volume = 0.0 + with pytest.raises(ValueError): + c.volume = -1.0 + with pytest.raises(ValueError): + c.volume = u.ufloat(0.0, 0.1) + with pytest.raises(ValueError): + c.volume = u.ufloat(-0.05, 0.1) + + +def test_atoms_of_material_cell(uo2, water): + """ Test if correct number of atoms is returned. + Also check if Cell.atoms still works after volume/material was changed + """ + c = openmc.Cell(fill=uo2) + c.volume = 2.0 + expected_nucs = ['U235', 'O16'] + + # Precalculate the expected number of atoms + molarMass = ((atomic_mass('U235') + 2 * atomic_mass('O16'))/3) + expected_atoms = list() + expected_atoms.append(1/3 * uo2.density/molarMass * AVOGADRO * 2.0) # U235 + expected_atoms.append(2/3 * uo2.density/molarMass * AVOGADRO * 2.0) # O16 + + tuples = list(c.atoms.values()) + for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): + assert nuc == t[0] + assert atom_num == t[1] + + # Change volume and check if OK + c.volume = 3.0 + expected_atoms = list() + expected_atoms.append(1/3 * uo2.density/molarMass * AVOGADRO * 3.0) # U235 + expected_atoms.append(2/3 * uo2.density/molarMass * AVOGADRO * 3.0) # O16 + + tuples = list(c.atoms.values()) + for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): + assert nuc == t[0] + assert atom_num == pytest.approx(t[1], rel=TOL) + + # Change material and check if OK + c.fill = water + expected_nucs = ['H1', 'O16'] + molarMass = ((2 * atomic_mass('H1') + atomic_mass('O16'))/3) + expected_atoms = list() + expected_atoms.append(2/3 * water.density/molarMass * AVOGADRO * 3.0) # H1 + expected_atoms.append(1/3 * water.density/molarMass * AVOGADRO * 3.0) # O16 + + tuples = list(c.atoms.values()) + for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): + assert nuc == t[0] + assert atom_num == pytest.approx(t[1], rel=TOL) + + +def test_atoms_errors(cell_with_lattice): + cells, mats, univ, lattice = cell_with_lattice + + # Distributed Material + with pytest.raises(ValueError): + cells[0].volume = 2 + cells[0].atoms + + # Material Cell with no Volume + with pytest.raises(ValueError): + cells[1].atoms + + # Cell with lattice + with pytest.raises(ValueError): + cells[2].volume = 3 + cells[2].atoms + + # Cell with volume but with Void fill + with pytest.raises(ValueError): + cells[1].volume = 2 + cells[1].fill = None + cells[1].atoms + + def test_nuclide_densities(uo2): c = openmc.Cell(fill=uo2) expected_nucs = ['U235', 'O16'] @@ -119,7 +219,7 @@ def test_nuclide_densities(uo2): tuples = list(c.get_nuclide_densities().values()) for nuc, density, t in zip(expected_nucs, expected_density, tuples): assert nuc == t[0] - assert density == t[1] + assert density == pytest.approx(t[1], rel=TOL) # Empty cell c = openmc.Cell() From 023f9e46900629ff36d6b13e33b39dda60846072 Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Tue, 3 Mar 2020 19:02:54 +0000 Subject: [PATCH 04/13] Add support for 'distribmat' cells to Cell.atoms Provide missing atoms entry in Cell Attributes Create docstring for Cell.atoms --- openmc/cell.py | 49 ++++++++++++++++++++++++++++----- tests/unit_tests/test_cell.py | 52 +++++++++++++++++++++++------------ 2 files changed, 77 insertions(+), 24 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 67c224de5..f2884e494 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -86,7 +86,12 @@ class Cell(IDManagerMixin): volume : float Volume of the cell in cm^3. This can either be set manually or calculated in a stochastic volume calculation and added via the - :meth:`Cell.add_volume_information` method. + :meth:`Cell.add_volume_information` method. For 'distribmat' cells + it is a total volume of all instances. + atoms : dict + Mapping of nuclides to total number of atoms for each nuclide present + in the cell, or all its instances for 'sdistribmat' fill. For example, + {'U235': 1.0e22, 'U238': 5.0e22, ...}. """ @@ -189,6 +194,21 @@ class Cell(IDManagerMixin): @property def atoms(self): + """ Get total number of atoms of each nuclide in the cell + + Returns + ------- + atoms: collections.OrderedDict + Dictionary which keys are nuclides and values the number of atoms. + For example, {'H1':1.0e22, 'O16':0.5e22, ...} + + Raises + ------ + ValueError + If total volume of the cell is not set + ValueError + If cell is filled with Universe, Lattice or Void + """ if self._atoms is None: if self._volume is None: msg = ('Cannot calculate atoms content becouse no volume ' @@ -201,10 +221,10 @@ class Cell(IDManagerMixin): 'Material must be set to calculate atoms content.') raise ValueError(msg) - elif self.fill_type != 'material': - msg = ('Universe, Lattice and Distributed Material cells can ' - 'contain multiple materials. Atoms content must be ' - 'calculated with stochastic volume calculation') + elif self.fill_type in ['lattice', 'universe']: + msg = ('Universe and Lattice cells can contain multiple ' + 'materials in diffrent proportions. Atoms content must ' + 'be calculated with stochastic volume calculation') raise ValueError(msg) elif self.fill_type == 'material': @@ -213,8 +233,23 @@ class Cell(IDManagerMixin): # Convert to total number of atoms for key, nuclide in self._atoms.items(): - atom_num = nuclide[1] * self._volume * 1.0E+24 - self._atoms[key] = (nuclide[0], atom_num) + atom = nuclide[1] * self._volume * 1.0e+24 + self._atoms[key] = atom + + elif self.fill_type == 'distribmat': + # Assumes that volume is total volume of all instances + # Also assumes that all instances have the same volume + partial_volume = self.volume / len(self.fill) + self._atoms = OrderedDict() + for mat in self.fill: + for key, nuclide in mat.get_nuclide_atom_densities().items(): + # To account for overlap of nuclides between distribmat + # we need to append new atoms # to any existing value + # hence it is necessary to ask for default. + atom = self._atoms.setdefault(key, 0) + atom += nuclide[1] * partial_volume * 1.0e+24 + self._atoms[key] = atom + else: msg = 'Unrecognised fill_type:{}'.format(self.fill_type) raise ValueError(msg) diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 03b03c6e9..d682c29c7 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -144,7 +144,7 @@ def test_volume_setting(): c.volume = u.ufloat(-0.05, 0.1) -def test_atoms_of_material_cell(uo2, water): +def test_atoms_material_cell(uo2, water): """ Test if correct number of atoms is returned. Also check if Cell.atoms still works after volume/material was changed """ @@ -153,12 +153,12 @@ def test_atoms_of_material_cell(uo2, water): expected_nucs = ['U235', 'O16'] # Precalculate the expected number of atoms - molarMass = ((atomic_mass('U235') + 2 * atomic_mass('O16'))/3) + M = ((atomic_mass('U235') + 2 * atomic_mass('O16'))/3) expected_atoms = list() - expected_atoms.append(1/3 * uo2.density/molarMass * AVOGADRO * 2.0) # U235 - expected_atoms.append(2/3 * uo2.density/molarMass * AVOGADRO * 2.0) # O16 + expected_atoms.append(1/3 * uo2.density/M * AVOGADRO * 2.0) # U235 + expected_atoms.append(2/3 * uo2.density/M * AVOGADRO * 2.0) # O16 - tuples = list(c.atoms.values()) + tuples = list(c.atoms.items()) for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] assert atom_num == t[1] @@ -166,10 +166,10 @@ def test_atoms_of_material_cell(uo2, water): # Change volume and check if OK c.volume = 3.0 expected_atoms = list() - expected_atoms.append(1/3 * uo2.density/molarMass * AVOGADRO * 3.0) # U235 - expected_atoms.append(2/3 * uo2.density/molarMass * AVOGADRO * 3.0) # O16 + expected_atoms.append(1/3 * uo2.density/M * AVOGADRO * 3.0) # U235 + expected_atoms.append(2/3 * uo2.density/M * AVOGADRO * 3.0) # O16 - tuples = list(c.atoms.values()) + tuples = list(c.atoms.items()) for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] assert atom_num == pytest.approx(t[1], rel=TOL) @@ -177,12 +177,35 @@ def test_atoms_of_material_cell(uo2, water): # Change material and check if OK c.fill = water expected_nucs = ['H1', 'O16'] - molarMass = ((2 * atomic_mass('H1') + atomic_mass('O16'))/3) + M = ((2 * atomic_mass('H1') + atomic_mass('O16'))/3) expected_atoms = list() - expected_atoms.append(2/3 * water.density/molarMass * AVOGADRO * 3.0) # H1 - expected_atoms.append(1/3 * water.density/molarMass * AVOGADRO * 3.0) # O16 + expected_atoms.append(2/3 * water.density/M * AVOGADRO * 3.0) # H1 + expected_atoms.append(1/3 * water.density/M * AVOGADRO * 3.0) # O16 - tuples = list(c.atoms.values()) + tuples = list(c.atoms.items()) + for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): + assert nuc == t[0] + assert atom_num == pytest.approx(t[1], rel=TOL) + + +def test_atoms_distribmat_cell(uo2, water): + """ Test if correct number of atoms is returned for a cell with + 'distribmat' fill + """ + c = openmc.Cell(fill=[uo2, water]) + c.volume = 6.0 + + # Calculate the expected number of atoms + expected_nucs = ['U235', 'O16', 'H1'] + M_uo2 = ((atomic_mass('U235') + 2 * atomic_mass('O16'))/3) + M_water = ((2 * atomic_mass('H1') + atomic_mass('O16'))/3) + expected_atoms = list() + expected_atoms.append(1/3 * uo2.density/M_uo2 * AVOGADRO * 3.0) # U235 + expected_atoms.append(2/3 * uo2.density/M_uo2 * AVOGADRO * 3.0 + + 1/3 * water.density/M_water * AVOGADRO * 3.0) # O16 + expected_atoms.append(2/3 * water.density/M_water * AVOGADRO * 3.0) # H1 + + tuples = list(c.atoms.items()) for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] assert atom_num == pytest.approx(t[1], rel=TOL) @@ -191,11 +214,6 @@ def test_atoms_of_material_cell(uo2, water): def test_atoms_errors(cell_with_lattice): cells, mats, univ, lattice = cell_with_lattice - # Distributed Material - with pytest.raises(ValueError): - cells[0].volume = 2 - cells[0].atoms - # Material Cell with no Volume with pytest.raises(ValueError): cells[1].atoms From 275512bb0e964a6f6c385e4df18699aae26f637a Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Wed, 11 Mar 2020 18:40:51 +0000 Subject: [PATCH 05/13] Add documentation for atoms calculations via cell --- docs/source/usersguide/geometry.rst | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index dc7dd978e..be2c92a12 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -183,9 +183,13 @@ the :class:`openmc.Cell` class:: fuel.fill = uo2 fuel.region = pellet + # This cell will be filled with void on export to XML + gap = openmc.Cell(region=pellet_gap) + In this example, an instance of :class:`openmc.Material` is assigned to the :attr:`Cell.fill` attribute. One can also fill a cell with a :ref:`universe -` or :ref:`lattice `. +` or :ref:`lattice `. If you provide +no fill to a cell, it will be filled with void on export to XML. The classes :class:`Halfspace`, :class:`Intersection`, :class:`Union`, and :class:`Complement` and all instances of :class:`openmc.Region` and can be @@ -434,3 +438,30 @@ named ``dagmc.h5m``) when initializing a simulation. If a `geometry.xml `_. Future implementations of DAGMC geometry will support small volume overlaps and un-merged surfaces. + +------------------------- +Calculating Atoms Content +------------------------- + +If the total volume occupied by all instances of a cell in a geometry is known +by a user, it is possible to assign it to a cell without a stochastic volume +calculation:: + + from uncertainties import ufloat + + # Set known total volume in [cc] + cell = openmc.Cell() + cell.volume = 17.0 + + # Set volume if it is known with some uncertainty + cell.volume = ufloat(17.0, 0.1) + +Once a volume is set and a cell is filled with a material or distributed +materials. It is possible to use :func:`~openmc.Cell.atoms` method to obtain +a dictionary that maps nuclides to a total number of atoms in all instances +of a cell (e.g. ``{'H1':1.0e22, 'O16':0.5e22, ...}``):: + + cell = openmc.Cell(fill = u02) + cell.volume = 17.0 + + O16_atoms = cell.atoms['O16'] From a6076f07558e25ab5c56ce83c0374946b86b6dff Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Mon, 16 Mar 2020 14:31:24 +0000 Subject: [PATCH 06/13] Address comments by @ChasingNeutrons --- openmc/cell.py | 24 ++++++++++++------------ tests/unit_tests/test_cell.py | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index f2884e494..9a8bce2cc 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -141,7 +141,7 @@ class Cell(IDManagerMixin): self.temperature) string += '{: <16}=\t{}\n'.format('\tTranslation', self.translation) - # Print Volume only when its set to avoid breaking regression + # Print volume only when it is set to avoid breaking regression if self._volume is not None: string += '{: <16}=\t{}\n'.format('\tVolume', self.volume) @@ -199,8 +199,8 @@ class Cell(IDManagerMixin): Returns ------- atoms: collections.OrderedDict - Dictionary which keys are nuclides and values the number of atoms. - For example, {'H1':1.0e22, 'O16':0.5e22, ...} + Dictionary in which keys are nuclides and values the number of + atoms. For example, {'H1':1.0e22, 'O16':0.5e22, ...} Raises ------ @@ -211,24 +211,24 @@ class Cell(IDManagerMixin): """ if self._atoms is None: if self._volume is None: - msg = ('Cannot calculate atoms content becouse no volume ' + msg = ('Cannot calculate atom content becouse no volume ' 'is set. Use Cell.volume to provide it or perform ' - 'stochastic volume calculation.') + 'a stochastic volume calculation.') raise ValueError(msg) elif self.fill_type == 'void': msg = ('Cell is filled with void. It contains no atoms. ' - 'Material must be set to calculate atoms content.') + 'Material must be set to calculate atom content.') raise ValueError(msg) elif self.fill_type in ['lattice', 'universe']: msg = ('Universe and Lattice cells can contain multiple ' - 'materials in diffrent proportions. Atoms content must ' + 'materials in diffrent proportions. Atom content must ' 'be calculated with stochastic volume calculation') raise ValueError(msg) elif self.fill_type == 'material': - # Get atomic Densities + # Get atomic densities self._atoms = self._fill.get_nuclide_atom_densities() # Convert to total number of atoms @@ -303,8 +303,8 @@ class Cell(IDManagerMixin): self._fill = fill - # Info about atoms content can now be invalid - # (sice fill has just changed) + # Info about atom content can now be invalid + # (since fill has just changed) self._atoms = None @rotation.setter @@ -366,7 +366,7 @@ class Cell(IDManagerMixin): cv.check_type('cell volume', volume, (Real, UFloat)) # Note that ufloat(0.0, 0.1) >= 0.0 is False - # we need special treatment for UFloat input + # We need special treatment for UFloat input val = volume if isinstance(val, UFloat): val = volume.nominal_value @@ -374,7 +374,7 @@ class Cell(IDManagerMixin): self._volume = volume - # Info about atoms content can now be invalid + # Info about atom content can now be invalid # (sice volume has just changed) self._atoms = None diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index d682c29c7..30eb82ca1 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -35,11 +35,11 @@ def test_repr(cell_with_lattice): c = openmc.Cell() repr(c) - # Empty cell with Volume + # Empty cell with volume c.volume = 3.0 repr(c) - # Empty cell with Uncertain Volume + # Empty cell with uncertain volume c.volume = u.ufloat(3.0, 0.2) repr(c) @@ -214,7 +214,7 @@ def test_atoms_distribmat_cell(uo2, water): def test_atoms_errors(cell_with_lattice): cells, mats, univ, lattice = cell_with_lattice - # Material Cell with no Volume + # Material Cell with no volume with pytest.raises(ValueError): cells[1].atoms @@ -223,7 +223,7 @@ def test_atoms_errors(cell_with_lattice): cells[2].volume = 3 cells[2].atoms - # Cell with volume but with Void fill + # Cell with volume but with void fill with pytest.raises(ValueError): cells[1].volume = 2 cells[1].fill = None From 9a782c80675f392c85c93c60401f88d826e2bf3c Mon Sep 17 00:00:00 2001 From: Mikolaj-A-Kowalski <32641577+Mikolaj-A-Kowalski@users.noreply.github.com> Date: Tue, 17 Mar 2020 18:56:36 +0000 Subject: [PATCH 07/13] Apply suggestions from code review Co-Authored-By: Simon Richards --- docs/source/usersguide/geometry.rst | 10 +++++----- openmc/cell.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index be2c92a12..4b925c448 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -443,8 +443,8 @@ named ``dagmc.h5m``) when initializing a simulation. If a `geometry.xml Calculating Atoms Content ------------------------- -If the total volume occupied by all instances of a cell in a geometry is known -by a user, it is possible to assign it to a cell without a stochastic volume +If the total volume occupied by all instances of a cell in the geometry is known +by the user, it is possible to assign this volume to a cell without performing a stochastic volume calculation:: from uncertainties import ufloat @@ -456,9 +456,9 @@ calculation:: # Set volume if it is known with some uncertainty cell.volume = ufloat(17.0, 0.1) -Once a volume is set and a cell is filled with a material or distributed -materials. It is possible to use :func:`~openmc.Cell.atoms` method to obtain -a dictionary that maps nuclides to a total number of atoms in all instances +Once a volume is set, and a cell is filled with a material or distributed +materials, it is possible to use the :func:`~openmc.Cell.atoms` method to obtain +a dictionary of nuclides and their total number of atoms in all instances of a cell (e.g. ``{'H1':1.0e22, 'O16':0.5e22, ...}``):: cell = openmc.Cell(fill = u02) diff --git a/openmc/cell.py b/openmc/cell.py index 9a8bce2cc..9b16c36e3 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -87,10 +87,10 @@ class Cell(IDManagerMixin): Volume of the cell in cm^3. This can either be set manually or calculated in a stochastic volume calculation and added via the :meth:`Cell.add_volume_information` method. For 'distribmat' cells - it is a total volume of all instances. + it is the total volume of all instances. atoms : dict - Mapping of nuclides to total number of atoms for each nuclide present - in the cell, or all its instances for 'sdistribmat' fill. For example, + Mapping of nuclides to the total number of atoms for each nuclide present + in the cell, or in all of its instances for a 'distribmat' fill. For example, {'U235': 1.0e22, 'U238': 5.0e22, ...}. """ From 7ee102795f643f047826cc0a7dbe012fd9aca87f Mon Sep 17 00:00:00 2001 From: Mikolaj-A-Kowalski <32641577+Mikolaj-A-Kowalski@users.noreply.github.com> Date: Tue, 17 Mar 2020 19:15:09 +0000 Subject: [PATCH 08/13] Remove non-default tolerance from test_cell.py --- tests/unit_tests/test_cell.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 30eb82ca1..1a01a0f6c 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -9,9 +9,6 @@ import pytest from tests.unit_tests import assert_unbounded from openmc.data import atomic_mass, AVOGADRO -# Relative tolerance for float comparison -TOL = 1e-9 - def test_contains(): # Cell with specified region @@ -172,7 +169,7 @@ def test_atoms_material_cell(uo2, water): tuples = list(c.atoms.items()) for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] - assert atom_num == pytest.approx(t[1], rel=TOL) + assert atom_num == pytest.approx(t[1]) # Change material and check if OK c.fill = water @@ -185,7 +182,7 @@ def test_atoms_material_cell(uo2, water): tuples = list(c.atoms.items()) for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] - assert atom_num == pytest.approx(t[1], rel=TOL) + assert atom_num == pytest.approx(t[1]) def test_atoms_distribmat_cell(uo2, water): @@ -208,7 +205,7 @@ def test_atoms_distribmat_cell(uo2, water): tuples = list(c.atoms.items()) for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] - assert atom_num == pytest.approx(t[1], rel=TOL) + assert atom_num == pytest.approx(t[1]) def test_atoms_errors(cell_with_lattice): @@ -237,7 +234,7 @@ def test_nuclide_densities(uo2): tuples = list(c.get_nuclide_densities().values()) for nuc, density, t in zip(expected_nucs, expected_density, tuples): assert nuc == t[0] - assert density == pytest.approx(t[1], rel=TOL) + assert density == pytest.approx(t[1]) # Empty cell c = openmc.Cell() From 06ffd256bc492f671e10f864ffeabaedf696a305 Mon Sep 17 00:00:00 2001 From: Mikolaj-A-Kowalski <32641577+Mikolaj-A-Kowalski@users.noreply.github.com> Date: Thu, 19 Mar 2020 11:23:12 +0000 Subject: [PATCH 09/13] Apply suggestions from code review Co-Authored-By: Patrick Shriwise --- openmc/cell.py | 10 +++++----- tests/unit_tests/test_cell.py | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index 9b16c36e3..0173ac495 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -88,7 +88,7 @@ class Cell(IDManagerMixin): calculated in a stochastic volume calculation and added via the :meth:`Cell.add_volume_information` method. For 'distribmat' cells it is the total volume of all instances. - atoms : dict + atoms : collections.OrderedDict Mapping of nuclides to the total number of atoms for each nuclide present in the cell, or in all of its instances for a 'distribmat' fill. For example, {'U235': 1.0e22, 'U238': 5.0e22, ...}. @@ -199,7 +199,7 @@ class Cell(IDManagerMixin): Returns ------- atoms: collections.OrderedDict - Dictionary in which keys are nuclides and values the number of + Dictionary in which keys are nuclides and values are the number of atoms. For example, {'H1':1.0e22, 'O16':0.5e22, ...} Raises @@ -224,7 +224,7 @@ class Cell(IDManagerMixin): elif self.fill_type in ['lattice', 'universe']: msg = ('Universe and Lattice cells can contain multiple ' 'materials in diffrent proportions. Atom content must ' - 'be calculated with stochastic volume calculation') + 'be calculated with stochastic volume calculation.') raise ValueError(msg) elif self.fill_type == 'material': @@ -244,14 +244,14 @@ class Cell(IDManagerMixin): for mat in self.fill: for key, nuclide in mat.get_nuclide_atom_densities().items(): # To account for overlap of nuclides between distribmat - # we need to append new atoms # to any existing value + # we need to append new atoms to any existing value # hence it is necessary to ask for default. atom = self._atoms.setdefault(key, 0) atom += nuclide[1] * partial_volume * 1.0e+24 self._atoms[key] = atom else: - msg = 'Unrecognised fill_type:{}'.format(self.fill_type) + msg = 'Unrecognised fill_type: {}'.format(self.fill_type) raise ValueError(msg) return self._atoms diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 1a01a0f6c..e5ab58201 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -150,7 +150,7 @@ def test_atoms_material_cell(uo2, water): expected_nucs = ['U235', 'O16'] # Precalculate the expected number of atoms - M = ((atomic_mass('U235') + 2 * atomic_mass('O16'))/3) + M = (atomic_mass('U235') + 2 * atomic_mass('O16')) / 3 expected_atoms = list() expected_atoms.append(1/3 * uo2.density/M * AVOGADRO * 2.0) # U235 expected_atoms.append(2/3 * uo2.density/M * AVOGADRO * 2.0) # O16 @@ -174,7 +174,7 @@ def test_atoms_material_cell(uo2, water): # Change material and check if OK c.fill = water expected_nucs = ['H1', 'O16'] - M = ((2 * atomic_mass('H1') + atomic_mass('O16'))/3) + M = (2 * atomic_mass('H1') + atomic_mass('O16')) / 3 expected_atoms = list() expected_atoms.append(2/3 * water.density/M * AVOGADRO * 3.0) # H1 expected_atoms.append(1/3 * water.density/M * AVOGADRO * 3.0) # O16 @@ -194,8 +194,8 @@ def test_atoms_distribmat_cell(uo2, water): # Calculate the expected number of atoms expected_nucs = ['U235', 'O16', 'H1'] - M_uo2 = ((atomic_mass('U235') + 2 * atomic_mass('O16'))/3) - M_water = ((2 * atomic_mass('H1') + atomic_mass('O16'))/3) + M_uo2 = (atomic_mass('U235') + 2 * atomic_mass('O16')) / 3 + M_water = (2 * atomic_mass('H1') + atomic_mass('O16')) / 3 expected_atoms = list() expected_atoms.append(1/3 * uo2.density/M_uo2 * AVOGADRO * 3.0) # U235 expected_atoms.append(2/3 * uo2.density/M_uo2 * AVOGADRO * 3.0 + From ec102212193ca5fa683dd736ca52452e8fb0923d Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Thu, 19 Mar 2020 12:04:44 +0000 Subject: [PATCH 10/13] Address comments by @pshriwise --- docs/source/usersguide/geometry.rst | 4 ++-- openmc/cell.py | 19 +++++-------------- .../distribmat/results_true.dat | 1 + .../multipole/results_true.dat | 1 + tests/unit_tests/test_cell.py | 10 +++++----- 5 files changed, 14 insertions(+), 21 deletions(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index 4b925c448..f95a1ff1c 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -188,8 +188,8 @@ the :class:`openmc.Cell` class:: In this example, an instance of :class:`openmc.Material` is assigned to the :attr:`Cell.fill` attribute. One can also fill a cell with a :ref:`universe -` or :ref:`lattice `. If you provide -no fill to a cell, it will be filled with void on export to XML. +` or :ref:`lattice `. If no fill +is provided to a cell, it will be filled with void by default. The classes :class:`Halfspace`, :class:`Intersection`, :class:`Union`, and :class:`Complement` and all instances of :class:`openmc.Region` and can be diff --git a/openmc/cell.py b/openmc/cell.py index 0173ac495..0b6bd4427 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -89,9 +89,9 @@ class Cell(IDManagerMixin): :meth:`Cell.add_volume_information` method. For 'distribmat' cells it is the total volume of all instances. atoms : collections.OrderedDict - Mapping of nuclides to the total number of atoms for each nuclide present - in the cell, or in all of its instances for a 'distribmat' fill. For example, - {'U235': 1.0e22, 'U238': 5.0e22, ...}. + Mapping of nuclides to the total number of atoms for each nuclide + present in the cell, or in all of its instances for a 'distribmat' + fill. For example, {'U235': 1.0e22, 'U238': 5.0e22, ...}. """ @@ -140,10 +140,7 @@ class Cell(IDManagerMixin): string += '\t{0: <15}=\t{1}\n'.format('Temperature', self.temperature) string += '{: <16}=\t{}\n'.format('\tTranslation', self.translation) - - # Print volume only when it is set to avoid breaking regression - if self._volume is not None: - string += '{: <16}=\t{}\n'.format('\tVolume', self.volume) + string += '{: <16}=\t{}\n'.format('\tVolume', self.volume) return string @@ -364,13 +361,7 @@ class Cell(IDManagerMixin): def volume(self, volume): if volume is not None: cv.check_type('cell volume', volume, (Real, UFloat)) - - # Note that ufloat(0.0, 0.1) >= 0.0 is False - # We need special treatment for UFloat input - val = volume - if isinstance(val, UFloat): - val = volume.nominal_value - cv.check_greater_than('cell volume', val, 0.0) + cv.check_greater_than('cell volume', volume, 0.0, equality=True) self._volume = volume diff --git a/tests/regression_tests/distribmat/results_true.dat b/tests/regression_tests/distribmat/results_true.dat index e0143f0ff..5cf99d6ba 100644 --- a/tests/regression_tests/distribmat/results_true.dat +++ b/tests/regression_tests/distribmat/results_true.dat @@ -7,3 +7,4 @@ Cell Region = -9 Rotation = None Translation = None + Volume = None diff --git a/tests/regression_tests/multipole/results_true.dat b/tests/regression_tests/multipole/results_true.dat index 890e47efd..2273c03fd 100644 --- a/tests/regression_tests/multipole/results_true.dat +++ b/tests/regression_tests/multipole/results_true.dat @@ -39,3 +39,4 @@ Cell Rotation = None Temperature = [500. 700. 0. 800.] Translation = None + Volume = None diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index e5ab58201..4ab596250 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -130,13 +130,13 @@ def test_volume_setting(): c.volume = 3 c.volume = u.ufloat(3, 0.7) - # Test errors for -ve and 0 volume - with pytest.raises(ValueError): - c.volume = 0.0 + # Allow volume to be set to 0.0 + c.volume = 0.0 + c.volume = u.ufloat(0.0, 0.1) + + # Test errors for -ve volume with pytest.raises(ValueError): c.volume = -1.0 - with pytest.raises(ValueError): - c.volume = u.ufloat(0.0, 0.1) with pytest.raises(ValueError): c.volume = u.ufloat(-0.05, 0.1) From 2debfc0d8a56e969c76af97ac377232a2d69e744 Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Thu, 19 Mar 2020 15:40:27 +0000 Subject: [PATCH 11/13] Address comments by @paulromano --- docs/source/usersguide/geometry.rst | 10 +++++----- openmc/cell.py | 15 --------------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index f95a1ff1c..22158c821 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -183,13 +183,13 @@ the :class:`openmc.Cell` class:: fuel.fill = uo2 fuel.region = pellet - # This cell will be filled with void on export to XML - gap = openmc.Cell(region=pellet_gap) - In this example, an instance of :class:`openmc.Material` is assigned to the :attr:`Cell.fill` attribute. One can also fill a cell with a :ref:`universe ` or :ref:`lattice `. If no fill -is provided to a cell, it will be filled with void by default. +is provided to a cell, it will be filled with void by default:: + + # This cell will be filled with void on export to XML + gap = openmc.Cell(region=pellet_gap) The classes :class:`Halfspace`, :class:`Intersection`, :class:`Union`, and :class:`Complement` and all instances of :class:`openmc.Region` and can be @@ -459,7 +459,7 @@ calculation:: Once a volume is set, and a cell is filled with a material or distributed materials, it is possible to use the :func:`~openmc.Cell.atoms` method to obtain a dictionary of nuclides and their total number of atoms in all instances -of a cell (e.g. ``{'H1':1.0e22, 'O16':0.5e22, ...}``):: +of a cell (e.g. ``{'H1': 1.0e22, 'O16': 0.5e22, ...}``):: cell = openmc.Cell(fill = u02) cell.volume = 17.0 diff --git a/openmc/cell.py b/openmc/cell.py index 0b6bd4427..4fe7ae3a4 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -191,21 +191,6 @@ class Cell(IDManagerMixin): @property def atoms(self): - """ Get total number of atoms of each nuclide in the cell - - Returns - ------- - atoms: collections.OrderedDict - Dictionary in which keys are nuclides and values are the number of - atoms. For example, {'H1':1.0e22, 'O16':0.5e22, ...} - - Raises - ------ - ValueError - If total volume of the cell is not set - ValueError - If cell is filled with Universe, Lattice or Void - """ if self._atoms is None: if self._volume is None: msg = ('Cannot calculate atom content becouse no volume ' From 671c90235039d0f4a97103bd5ba6af2803c4327c Mon Sep 17 00:00:00 2001 From: Mikolaj-A-Kowalski <32641577+Mikolaj-A-Kowalski@users.noreply.github.com> Date: Thu, 19 Mar 2020 15:43:20 +0000 Subject: [PATCH 12/13] Apply suggestions from code review Co-Authored-By: Paul Romano --- docs/source/usersguide/geometry.rst | 4 +- openmc/cell.py | 2 +- tests/unit_tests/test_cell.py | 58 +++++++++++++++-------------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index 22158c821..f550327b2 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -444,8 +444,8 @@ Calculating Atoms Content ------------------------- If the total volume occupied by all instances of a cell in the geometry is known -by the user, it is possible to assign this volume to a cell without performing a stochastic volume -calculation:: +by the user, it is possible to assign this volume to a cell without performing a +:ref:`stochastic volume ` calculation:: from uncertainties import ufloat diff --git a/openmc/cell.py b/openmc/cell.py index 4fe7ae3a4..426a502e0 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -233,7 +233,7 @@ class Cell(IDManagerMixin): self._atoms[key] = atom else: - msg = 'Unrecognised fill_type: {}'.format(self.fill_type) + msg = 'Unrecognized fill_type: {}'.format(self.fill_type) raise ValueError(msg) return self._atoms diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 4ab596250..b3c33410c 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -1,7 +1,7 @@ import xml.etree. ElementTree as ET import numpy as np -import uncertainties as u +from uncertainties import ufloat import openmc import pytest @@ -37,7 +37,7 @@ def test_repr(cell_with_lattice): repr(c) # Empty cell with uncertain volume - c.volume = u.ufloat(3.0, 0.2) + c.volume = ufloat(3.0, 0.2) repr(c) @@ -128,17 +128,17 @@ def test_volume_setting(): # Test ordinary volume and uncertain volume c.volume = 3 - c.volume = u.ufloat(3, 0.7) + c.volume = ufloat(3, 0.7) # Allow volume to be set to 0.0 c.volume = 0.0 - c.volume = u.ufloat(0.0, 0.1) + c.volume = ufloat(0.0, 0.1) - # Test errors for -ve volume + # Test errors for negative volume with pytest.raises(ValueError): c.volume = -1.0 with pytest.raises(ValueError): - c.volume = u.ufloat(-0.05, 0.1) + c.volume = ufloat(-0.05, 0.1) def test_atoms_material_cell(uo2, water): @@ -151,22 +151,24 @@ def test_atoms_material_cell(uo2, water): # Precalculate the expected number of atoms M = (atomic_mass('U235') + 2 * atomic_mass('O16')) / 3 - expected_atoms = list() - expected_atoms.append(1/3 * uo2.density/M * AVOGADRO * 2.0) # U235 - expected_atoms.append(2/3 * uo2.density/M * AVOGADRO * 2.0) # O16 + expected_atoms = [ + 1/3 * uo2.density/M * AVOGADRO * 2.0, # U235 + 2/3 * uo2.density/M * AVOGADRO * 2.0 # O16 + ] - tuples = list(c.atoms.items()) + tuples = c.atoms.items() for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] assert atom_num == t[1] # Change volume and check if OK c.volume = 3.0 - expected_atoms = list() - expected_atoms.append(1/3 * uo2.density/M * AVOGADRO * 3.0) # U235 - expected_atoms.append(2/3 * uo2.density/M * AVOGADRO * 3.0) # O16 + expected_atoms = [ + 1/3 * uo2.density/M * AVOGADRO * 3.0, # U235 + 2/3 * uo2.density/M * AVOGADRO * 3.0 # O16 + ] - tuples = list(c.atoms.items()) + tuples = c.atoms.items() for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] assert atom_num == pytest.approx(t[1]) @@ -175,11 +177,12 @@ def test_atoms_material_cell(uo2, water): c.fill = water expected_nucs = ['H1', 'O16'] M = (2 * atomic_mass('H1') + atomic_mass('O16')) / 3 - expected_atoms = list() - expected_atoms.append(2/3 * water.density/M * AVOGADRO * 3.0) # H1 - expected_atoms.append(1/3 * water.density/M * AVOGADRO * 3.0) # O16 + expected_atoms = [ + 2/3 * water.density/M * AVOGADRO * 3.0, # H1 + 1/3 * water.density/M * AVOGADRO * 3.0 # O16 + ] - tuples = list(c.atoms.items()) + tuples = c.atoms.items() for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] assert atom_num == pytest.approx(t[1]) @@ -196,13 +199,14 @@ def test_atoms_distribmat_cell(uo2, water): expected_nucs = ['U235', 'O16', 'H1'] M_uo2 = (atomic_mass('U235') + 2 * atomic_mass('O16')) / 3 M_water = (2 * atomic_mass('H1') + atomic_mass('O16')) / 3 - expected_atoms = list() - expected_atoms.append(1/3 * uo2.density/M_uo2 * AVOGADRO * 3.0) # U235 - expected_atoms.append(2/3 * uo2.density/M_uo2 * AVOGADRO * 3.0 + - 1/3 * water.density/M_water * AVOGADRO * 3.0) # O16 - expected_atoms.append(2/3 * water.density/M_water * AVOGADRO * 3.0) # H1 + expected_atoms = [ + 1/3 * uo2.density/M_uo2 * AVOGADRO * 3.0, # U235 + (2/3 * uo2.density/M_uo2 * AVOGADRO * 3.0 + + 1/3 * water.density/M_water * AVOGADRO * 3.0), # O16 + 2/3 * water.density/M_water * AVOGADRO * 3.0 # H1 + ] - tuples = list(c.atoms.items()) + tuples = c.atoms.items() for nuc, atom_num, t in zip(expected_nucs, expected_atoms, tuples): assert nuc == t[0] assert atom_num == pytest.approx(t[1]) @@ -216,14 +220,14 @@ def test_atoms_errors(cell_with_lattice): cells[1].atoms # Cell with lattice + cells[2].volume = 3 with pytest.raises(ValueError): - cells[2].volume = 3 cells[2].atoms # Cell with volume but with void fill + cells[1].volume = 2 + cells[1].fill = None with pytest.raises(ValueError): - cells[1].volume = 2 - cells[1].fill = None cells[1].atoms From 9c8e22add86b84f334999e7a160dbbe0ad1caa9c Mon Sep 17 00:00:00 2001 From: Mikolaj Adam Kowalski Date: Thu, 19 Mar 2020 16:08:42 +0000 Subject: [PATCH 13/13] Add missing suggestion by @paulromano --- docs/source/usersguide/geometry.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index f550327b2..f83af0b2f 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -185,8 +185,10 @@ the :class:`openmc.Cell` class:: In this example, an instance of :class:`openmc.Material` is assigned to the :attr:`Cell.fill` attribute. One can also fill a cell with a :ref:`universe -` or :ref:`lattice `. If no fill -is provided to a cell, it will be filled with void by default:: +` or :ref:`lattice `. If you provide +no fill to a cell or assign a value of `None`, it will be treated as a "void" +cell with no material within. Particles are allowed to stream through the cell but +will undergo no collisions:: # This cell will be filled with void on export to XML gap = openmc.Cell(region=pellet_gap)