Add support for 'distribmat' cells to Cell.atoms

Provide missing atoms entry in Cell Attributes
Create docstring for Cell.atoms
This commit is contained in:
Mikolaj Adam Kowalski 2020-03-03 19:02:54 +00:00
parent 36512e3096
commit 023f9e4690
2 changed files with 77 additions and 24 deletions

View file

@ -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)

View file

@ -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