mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Add methods on Material to get mass (if volume specified)
This commit is contained in:
parent
92697ec06e
commit
7622a1a394
6 changed files with 110 additions and 13 deletions
|
|
@ -36,6 +36,7 @@ Core Functions
|
|||
openmc.data.thin
|
||||
openmc.data.water_density
|
||||
openmc.data.write_compact_458_library
|
||||
openmc.data.zam
|
||||
|
||||
Angle-Energy Distributions
|
||||
--------------------------
|
||||
|
|
|
|||
|
|
@ -313,6 +313,26 @@ def water_density(temperature, pressure=0.1013):
|
|||
return coeff / pi / gamma1_pi
|
||||
|
||||
|
||||
def zam(name):
|
||||
"""Return tuple of (atomic number, mass number, metastable state)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Name of nuclide using GND convention, e.g., 'Am242m1'
|
||||
|
||||
Returns
|
||||
-------
|
||||
3-tuple of int
|
||||
Atomic number, mass number, and metastable state
|
||||
|
||||
"""
|
||||
symbol, A, state = re.match(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)',
|
||||
name).groups()
|
||||
metastable = int(state[2:]) if state else 0
|
||||
return (ATOMIC_NUMBER[symbol], int(A), metastable)
|
||||
|
||||
|
||||
# Values here are from the Committee on Data for Science and Technology
|
||||
# (CODATA) 2014 recommendation (doi:10.1103/RevModPhys.88.035009).
|
||||
|
||||
|
|
|
|||
|
|
@ -40,15 +40,6 @@ _REACTIONS = [
|
|||
]
|
||||
|
||||
|
||||
def _get_zai(s):
|
||||
"""Get ZAI value (10000*z + 10*A + metastable state) for sorting purposes"""
|
||||
symbol, A, state = re.match(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)', s).groups()
|
||||
Z = openmc.data.ATOMIC_NUMBER[symbol]
|
||||
A = int(A)
|
||||
state = int(state[2:]) if state else 0
|
||||
return 10000*Z + 10*A + state
|
||||
|
||||
|
||||
def replace_missing(product, decay_data):
|
||||
"""Replace missing product with suitable decay daughter.
|
||||
|
||||
|
|
@ -197,7 +188,7 @@ class Chain(object):
|
|||
missing_fpy = []
|
||||
missing_fp = []
|
||||
|
||||
for idx, parent in enumerate(sorted(decay_data, key=_get_zai)):
|
||||
for idx, parent in enumerate(sorted(decay_data, key=openmc.data.zam)):
|
||||
data = decay_data[parent]
|
||||
|
||||
nuclide = Nuclide()
|
||||
|
|
@ -290,7 +281,7 @@ class Chain(object):
|
|||
missing_fp.append((parent, E, yield_replace))
|
||||
|
||||
nuclide.yield_data[E] = []
|
||||
for k in sorted(yields, key=_get_zai):
|
||||
for k in sorted(yields, key=openmc.data.zam):
|
||||
nuclide.yield_data[E].append((k, yields[k]))
|
||||
|
||||
# Display warnings
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@ class Material(IDManagerMixin):
|
|||
'atom/b-cm', 'atom/cm3', 'sum', or 'macro'. The 'macro' unit only
|
||||
applies in the case of a multi-group calculation.
|
||||
depletable : bool
|
||||
Indicate whether the material is depletable. This attribute can be used
|
||||
by downstream depletion applications.
|
||||
Indicate whether the material is depletable.
|
||||
nuclides : list of tuple
|
||||
List in which each item is a 3-tuple consisting of a nuclide string, the
|
||||
percent density, and the percent type ('ao' or 'wo').
|
||||
|
|
@ -74,6 +73,9 @@ class Material(IDManagerMixin):
|
|||
:meth:`Geometry.determine_paths` method.
|
||||
num_instances : int
|
||||
The number of instances of this material throughout the geometry.
|
||||
fissionable_mass : float
|
||||
Mass of fissionable nuclides in the material in [g]. Requires that the
|
||||
:attr:`volume` attribute is set.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -245,6 +247,18 @@ class Material(IDManagerMixin):
|
|||
str)
|
||||
self._isotropic = list(isotropic)
|
||||
|
||||
@property
|
||||
def fissionable_mass(self):
|
||||
if self.volume is None:
|
||||
raise ValueError("Volume must be set in order to determine mass.")
|
||||
density = 0.0
|
||||
for nuc, atoms_per_cc in self.get_nuclide_atom_densities().values():
|
||||
Z = openmc.data.zam(nuc)[0]
|
||||
if Z >= 90:
|
||||
density += 1e24 * atoms_per_cc * openmc.data.atomic_mass(nuc) \
|
||||
/ openmc.data.AVOGADRO
|
||||
return density*self.volume
|
||||
|
||||
@classmethod
|
||||
def from_hdf5(cls, group):
|
||||
"""Create material from HDF5 group
|
||||
|
|
@ -687,7 +701,53 @@ class Material(IDManagerMixin):
|
|||
|
||||
return nuclides
|
||||
|
||||
def get_mass_density(self, nuclide=None):
|
||||
"""Return mass density of one or all nuclides
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nuclides : str, optional
|
||||
Nuclide for which density is desired. If not specified, the density
|
||||
for the entire material is given.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Density of the nuclide/material in [g/cm^3]
|
||||
|
||||
"""
|
||||
mass_density = 0.0
|
||||
for nuc, atoms_per_cc in self.get_nuclide_atom_densities().values():
|
||||
density_i = 1e24 * atoms_per_cc * openmc.data.atomic_mass(nuc) \
|
||||
/ openmc.data.AVOGADRO
|
||||
if nuclide is None or nuclide == nuc:
|
||||
mass_density += density_i
|
||||
return mass_density
|
||||
|
||||
def get_mass(self, nuclide=None):
|
||||
"""Return mass of one or all nuclides.
|
||||
|
||||
Note that this method requires that the :attr:`Material.volume` has
|
||||
already been set.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nuclides : str, optional
|
||||
Nuclide for which mass is desired. If not specified, the density
|
||||
for the entire material is given.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Mass of the nuclide/material in [g]
|
||||
|
||||
"""
|
||||
if self.volume is None:
|
||||
raise ValueError("Volume must be set in order to determine mass.")
|
||||
return self.volume*self.get_mass_density(nuclide)
|
||||
|
||||
def clone(self, memo=None):
|
||||
|
||||
"""Create a copy of this material with a new unique ID.
|
||||
|
||||
Parameters
|
||||
|
|
|
|||
|
|
@ -58,3 +58,11 @@ def test_water_density():
|
|||
assert dens(300.0, 3.0) == pytest.approx(1e-3/0.100215168e-2, 1e-6)
|
||||
assert dens(300.0, 80.0) == pytest.approx(1e-3/0.971180894e-3, 1e-6)
|
||||
assert dens(500.0, 3.0) == pytest.approx(1e-3/0.120241800e-2, 1e-6)
|
||||
|
||||
|
||||
def test_zam():
|
||||
assert openmc.data.zam('H1') == (1, 1, 0)
|
||||
assert openmc.data.zam('Zr90') == (40, 90, 0)
|
||||
assert openmc.data.zam('Am242') == (95, 242, 0)
|
||||
assert openmc.data.zam('Am242_m1') == (95, 242, 1)
|
||||
assert openmc.data.zam('Am242_m10') == (95, 242, 10)
|
||||
|
|
|
|||
|
|
@ -121,6 +121,23 @@ def test_get_nuclide_atom_densities(uo2):
|
|||
assert density > 0
|
||||
|
||||
|
||||
def test_mass():
|
||||
m = openmc.Material()
|
||||
m.add_nuclide('Zr90', 1.0, 'wo')
|
||||
m.add_nuclide('U235', 1.0, 'wo')
|
||||
m.set_density('g/cm3', 2.0)
|
||||
m.volume = 10.0
|
||||
|
||||
assert m.get_mass_density('Zr90') == pytest.approx(1.0)
|
||||
assert m.get_mass_density('U235') == pytest.approx(1.0)
|
||||
assert m.get_mass_density() == pytest.approx(2.0)
|
||||
|
||||
assert m.get_mass('Zr90') == pytest.approx(10.0)
|
||||
assert m.get_mass('U235') == pytest.approx(10.0)
|
||||
assert m.get_mass() == pytest.approx(20.0)
|
||||
assert m.fissionable_mass == pytest.approx(10.0)
|
||||
|
||||
|
||||
def test_materials(run_in_tmpdir):
|
||||
m1 = openmc.Material()
|
||||
m1.add_nuclide('U235', 1.0, 'wo')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue