Merge pull request #2432 from guyshtot/library_nuclides_specification

Library nuclides specification
This commit is contained in:
Paul Romano 2023-03-26 12:27:48 -05:00 committed by GitHub
commit 99c6514609
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 322 additions and 2 deletions

View file

@ -72,6 +72,11 @@ class Library:
Number of equi-width polar angle bins for angle discretization
num_azimuthal : Integral
Number of equi-width azimuthal angle bins for angle discretization
nuclides : Iterable of str or 'sum'
The optional user-specified nuclides for which to compute cross
sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides
are not specified by the user, all nuclides in the domain
are included.
estimator : str or None
The tally estimator used to compute multi-group cross sections.
If None, the default for each MGXS type is used.
@ -107,6 +112,7 @@ class Library:
self._energy_groups = None
self._num_polar = 1
self._num_azimuthal = 1
self._nuclides = None
self._num_delayed_groups = 0
self._correction = 'P0'
self._scatter_format = 'legendre'
@ -145,6 +151,7 @@ class Library:
clone._energy_groups = copy.deepcopy(self.energy_groups, memo)
clone._num_polar = self.num_polar
clone._num_azimuthal = self.num_azimuthal
clone._nuclides = self._nuclides
clone._num_delayed_groups = self.num_delayed_groups
clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo)
clone._all_mgxs = copy.deepcopy(self.all_mgxs)
@ -205,6 +212,10 @@ class Library:
else:
return self._domains
@property
def nuclides(self):
return self._nuclides
@property
def energy_groups(self):
return self._energy_groups
@ -275,6 +286,11 @@ class Library:
cv.check_type('name', name, str)
self._name = name
@nuclides.setter
def nuclides(self, nuclides):
cv.check_iterable_type('nuclides', nuclides, str)
self._nuclides = nuclides
@mgxs_types.setter
def mgxs_types(self, mgxs_types):
all_mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES + \
@ -524,6 +540,20 @@ class Library:
mgxs.legendre_order = self.legendre_order
mgxs.histogram_bins = self.histogram_bins
if self.by_nuclide:
try:
domain_nuclides = domain.get_nuclides()
except AttributeError:
domain_nuclides = None
if self.nuclides:
if domain_nuclides:
mgxs.nuclides = [
nuclide for nuclide in self.nuclides
if nuclide in domain_nuclides
] + ["total"]
else:
mgxs.nuclides = self.nuclides
self.all_mgxs[domain.id][mgxs_type] = mgxs
def add_to_tallies_file(self, tallies_file, merge=True):
@ -590,7 +620,7 @@ class Library:
self._sp_filename = statepoint._f.filename
self._geometry = statepoint.summary.geometry
self._nuclides = statepoint.summary.nuclides
self._atomic_weight_ratios = statepoint.summary.nuclides
if statepoint.run_mode == 'eigenvalue':
self._keff = statepoint.keff.n
@ -1005,7 +1035,7 @@ class Library:
xsdata.num_azimuthal = self.num_azimuthal
if nuclide != 'total':
xsdata.atomic_weight_ratio = self._nuclides[nuclide]
xsdata.atomic_weight_ratio = self._atomic_weight_ratios[nuclide]
if subdomain is None:
subdomain = 'all'

View file

@ -0,0 +1,218 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell id="1" material="1" name="Fuel" region="-1" universe="0" />
<cell id="2" material="2" name="Cladding" region="1 -2" universe="0" />
<cell id="3" material="3" name="Water" region="2 3 -4 5 -6" universe="0" />
<surface coeffs="0 0 0.39218" id="1" name="Fuel OR" type="z-cylinder" />
<surface coeffs="0 0 0.4572" id="2" name="Clad OR" type="z-cylinder" />
<surface boundary="reflective" coeffs="-0.63" id="3" name="left" type="x-plane" />
<surface boundary="reflective" coeffs="0.63" id="4" name="right" type="x-plane" />
<surface boundary="reflective" coeffs="-0.63" id="5" name="bottom" type="y-plane" />
<surface boundary="reflective" coeffs="0.63" id="6" name="top" type="y-plane" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1" name="UO2 (2.4%)">
<density units="g/cm3" value="10.29769" />
<nuclide ao="4.4843e-06" name="U234" />
<nuclide ao="0.00055815" name="U235" />
<nuclide ao="0.022408" name="U238" />
<nuclide ao="0.045829" name="O16" />
</material>
<material id="2" name="Zircaloy">
<density units="g/cm3" value="6.55" />
<nuclide ao="0.021827" name="Zr90" />
<nuclide ao="0.00476" name="Zr91" />
<nuclide ao="0.0072758" name="Zr92" />
<nuclide ao="0.0073734" name="Zr94" />
<nuclide ao="0.0011879" name="Zr96" />
</material>
<material id="3" name="Hot borated water">
<density units="g/cm3" value="0.740582" />
<nuclide ao="0.049457" name="H1" />
<nuclide ao="0.024672" name="O16" />
<nuclide ao="8.0042e-06" name="B10" />
<nuclide ao="3.2218e-05" name="B11" />
<sab name="c_H_in_H2O" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>100</particles>
<batches>10</batches>
<inactive>5</inactive>
<source strength="1.0">
<space type="fission">
<parameters>-0.63 -0.63 -1 0.63 0.63 1</parameters>
</space>
</source>
</settings>
<?xml version='1.0' encoding='utf-8'?>
<tallies>
<filter id="383" type="material">
<bins>1 2 3</bins>
</filter>
<filter id="2" type="energy">
<bins>0.0 0.625 20000000.0</bins>
</filter>
<filter id="1" type="material">
<bins>1</bins>
</filter>
<filter id="5" type="energyout">
<bins>0.0 0.625 20000000.0</bins>
</filter>
<filter id="6" type="legendre">
<order>1</order>
</filter>
<filter id="30" type="legendre">
<order>3</order>
</filter>
<filter id="54" type="energy">
<bins>0.0 20000000.0</bins>
</filter>
<filter id="106" type="material">
<bins>2</bins>
</filter>
<filter id="251" type="material">
<bins>3</bins>
</filter>
<tally id="528">
<filters>383 2</filters>
<nuclides>total</nuclides>
<scores>flux</scores>
<estimator>tracklength</estimator>
</tally>
<tally id="167">
<filters>1 2</filters>
<nuclides>U235 total</nuclides>
<scores>total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0)</scores>
<estimator>tracklength</estimator>
</tally>
<tally id="540">
<filters>383 2</filters>
<nuclides>total</nuclides>
<scores>flux</scores>
<estimator>analog</estimator>
</tally>
<tally id="119">
<filters>1 5 6</filters>
<nuclides>U235 total</nuclides>
<scores>scatter nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="54">
<filters>1 2</filters>
<nuclides>U235 total</nuclides>
<scores>nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="84">
<filters>1 2 5 30</filters>
<nuclides>U235 total</nuclides>
<scores>scatter nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="179">
<filters>1 2 5</filters>
<nuclides>U235 total</nuclides>
<scores>nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n)</scores>
<estimator>analog</estimator>
</tally>
<tally id="90">
<filters>1 54</filters>
<nuclides>U235 total</nuclides>
<scores>nu-fission prompt-nu-fission</scores>
<estimator>analog</estimator>
</tally>
<tally id="91">
<filters>1 5</filters>
<nuclides>U235 total</nuclides>
<scores>nu-fission prompt-nu-fission</scores>
<estimator>analog</estimator>
</tally>
<tally id="348">
<filters>106 2</filters>
<nuclides>Zr90 total</nuclides>
<scores>total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0)</scores>
<estimator>tracklength</estimator>
</tally>
<tally id="300">
<filters>106 5 6</filters>
<nuclides>Zr90 total</nuclides>
<scores>scatter nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="235">
<filters>106 2</filters>
<nuclides>Zr90 total</nuclides>
<scores>nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="265">
<filters>106 2 5 30</filters>
<nuclides>Zr90 total</nuclides>
<scores>scatter nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="360">
<filters>106 2 5</filters>
<nuclides>Zr90 total</nuclides>
<scores>nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n)</scores>
<estimator>analog</estimator>
</tally>
<tally id="271">
<filters>106 54</filters>
<nuclides>Zr90 total</nuclides>
<scores>nu-fission prompt-nu-fission</scores>
<estimator>analog</estimator>
</tally>
<tally id="272">
<filters>106 5</filters>
<nuclides>Zr90 total</nuclides>
<scores>nu-fission prompt-nu-fission</scores>
<estimator>analog</estimator>
</tally>
<tally id="529">
<filters>251 2</filters>
<nuclides>H1 total</nuclides>
<scores>total absorption (n,2n) (n,3n) (n,4n) fission nu-fission kappa-fission scatter inverse-velocity prompt-nu-fission (n,elastic) (n,level) (n,na) (n,nc) (n,gamma) (n,a) (n,Xa) heating damage-energy (n,n1) (n,a0)</scores>
<estimator>tracklength</estimator>
</tally>
<tally id="481">
<filters>251 5 6</filters>
<nuclides>H1 total</nuclides>
<scores>scatter nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="416">
<filters>251 2</filters>
<nuclides>H1 total</nuclides>
<scores>nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="446">
<filters>251 2 5 30</filters>
<nuclides>H1 total</nuclides>
<scores>scatter nu-scatter</scores>
<estimator>analog</estimator>
</tally>
<tally id="541">
<filters>251 2 5</filters>
<nuclides>H1 total</nuclides>
<scores>nu-scatter scatter nu-fission prompt-nu-fission (n,nc) (n,n1) (n,2n)</scores>
<estimator>analog</estimator>
</tally>
<tally id="452">
<filters>251 54</filters>
<nuclides>H1 total</nuclides>
<scores>nu-fission prompt-nu-fission</scores>
<estimator>analog</estimator>
</tally>
<tally id="453">
<filters>251 5</filters>
<nuclides>H1 total</nuclides>
<scores>nu-fission prompt-nu-fission</scores>
<estimator>analog</estimator>
</tally>
</tallies>

View file

@ -0,0 +1 @@
3e86542d1166b8a0bcc61742b88c9e931d63733477f3274b32b4da64d8f05413fa6330d5615f44f24735c2c2f77d3071f3dce38faba284c321ceab81c1064480

View file

@ -0,0 +1,71 @@
import hashlib
import openmc
import openmc.mgxs
from openmc.examples import pwr_pin_cell
from tests.testing_harness import PyAPITestHarness
class MGXSTestHarness(PyAPITestHarness):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initialize a two-group structure
energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6])
# Initialize MGXS Library for a few cross section types
self.mgxs_lib = openmc.mgxs.Library(self._model.geometry)
self.mgxs_lib.by_nuclide = True
# Test relevant MGXS types
relevant_MGXS_TYPES = [item for item in openmc.mgxs.MGXS_TYPES
if item != 'current']
# Add in a subset of openmc.mgxs.ARBITRARY_VECTOR_TYPES and
# openmc.mgxs.ARBITRARY_MATRIX_TYPES so we can see the code works,
# but not use too much resources
relevant_MGXS_TYPES += [
"(n,elastic)", "(n,level)", "(n,2n)", "(n,na)", "(n,nc)",
"(n,gamma)", "(n,a)", "(n,Xa)", "heating", "damage-energy",
"(n,n1)", "(n,a0)", "(n,nc) matrix", "(n,n1) matrix",
"(n,2n) matrix"]
self.mgxs_lib.mgxs_types = tuple(relevant_MGXS_TYPES)
self.mgxs_lib.energy_groups = energy_groups
self.mgxs_lib.legendre_order = 3
self.mgxs_lib.domain_type = 'material'
self.mgxs_lib.nuclides = ['U235', 'Zr90', 'H1']
self.mgxs_lib.build_library()
# Add tallies
self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=True)
def _get_results(self, hash_output=True):
"""Digest info in the statepoint and return as a string."""
# Read the statepoint file.
sp = openmc.StatePoint(self._sp_name)
# Load the MGXS library from the statepoint
self.mgxs_lib.load_from_statepoint(sp)
# Build a string from Pandas Dataframe for each MGXS
outstr = ''
for domain in self.mgxs_lib.domains:
for mgxs_type in self.mgxs_lib.mgxs_types:
mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type)
df = mgxs.get_pandas_dataframe()
outstr += df.to_string() + '\n'
# Hash the results if necessary
if hash_output:
sha512 = hashlib.sha512()
sha512.update(outstr.encode('utf-8'))
outstr = sha512.hexdigest()
return outstr
def test_mgxs_library_specific_nuclides():
model = pwr_pin_cell()
harness = MGXSTestHarness('statepoint.10.h5', model)
harness.main()