add chain_file, dilute_initial parameters to MicroXS.from_model

This commit is contained in:
yardasol 2022-08-03 12:30:02 -05:00
parent 2a0da7437f
commit 65624df58d
7 changed files with 107 additions and 29 deletions

View file

@ -216,7 +216,7 @@ and a path to a depletion chain file::
materials = openmc.Materials()
...
micro_xs = openmc.deplete.MicroXS()
micro_xs = openmc.deplete.MicroXS
...
op = openmc.deplete.IndependentOperator(materials, micro_xs, chain_file)
@ -267,7 +267,9 @@ Users can generate the one-group microscopic cross sections needed by
model = openmc.Model.from_xml()
micro_xs = openmc.deplete.MicroXS.from_model(model, model.materials[0])
micro_xs = openmc.deplete.MicroXS.from_model(model,
model.materials[0],
chain_file)
The :meth:`~openmc.deplete.MicroXS.from_model()` method will produce a
:class:`~openmc.deplete.MicroXS` object with microscopic cross section data in

View file

@ -8,13 +8,16 @@ import tempfile
from pathlib import Path
from pandas import DataFrame, read_csv, concat
from numpy import ndarray
import numpy as np
from openmc.checkvalue import check_type, check_value, check_iterable_type
from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS
from openmc import Tallies, StatePoint
from openmc.data import DataLibrary
from openmc import Tallies, StatePoint, Materials
from .chain import REACTIONS
from .chain import Chain, REACTIONS
from .coupled_operator import _find_cross_sections
_valid_rxns = list(REACTIONS)
_valid_rxns.append('fission')
@ -29,13 +32,8 @@ class MicroXS(DataFrame):
def from_model(cls,
model,
reaction_domain,
reactions=['(n,gamma)',
'(n,2n)',
'(n,p)',
'(n,a)',
'(n,3n)',
'(n,4n)',
'fission'],
chain_file,
dilute_initial=1.0e3,
energy_bounds=(0, 20e6)):
"""Generate a one-group cross-section dataframe using
OpenMC. Note that the ``openmc`` executable must be compiled.
@ -46,6 +44,14 @@ class MicroXS(DataFrame):
OpenMC model object. Must contain geometry, materials, and settings.
reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh
Domain in which to tally reaction rates.
chain_file : str
Path to the depletion chain XML file that will be used in depletion
simulation. Used to determine cross sections for materials not
present in the inital composition.
dilute_initial : float
Initial atom density [atoms/cm^3] to add for nuclides that
are zero in initial condition to ensure they exist in the cross
section data. Only done for nuclides with reaction rates.
reactions : list of str, optional
Reaction names to tally
energy_bound : 2-tuple of float, optional
@ -63,6 +69,12 @@ class MicroXS(DataFrame):
original_tallies = model.tallies
tallies = Tallies()
xs = {}
reactions, diluted_materials = cls._add_dilute_nuclides(chain_file,
model,
dilute_initial)
diluted_materials.export_to_xml('diluted_materials.xml')
model.materials = diluted_materials
for rxn in reactions:
if rxn == 'fission':
xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True)
@ -94,6 +106,56 @@ class MicroXS(DataFrame):
return micro_xs
@classmethod
def _add_dilute_nuclides(cls, chain_file, model, dilute_initial):
chain = Chain.from_xml(chain_file)
reactions = chain.reactions
cross_sections = _find_cross_sections(model)
nuclides_with_data = cls._get_nuclides_with_data(cross_sections)
burnable_nucs = [nuc.name for nuc in chain.nuclides
if nuc.name in nuclides_with_data]
diluted_materials = Materials()
for material in model.materials:
if material.depletable:
nuc_densities = material.get_nuclide_atom_densities()
dilute_density = 1.E-24 * dilute_initial
material.set_density('sum')
for nuc, density in nuc_densities.items():
material.remove_nuclide(nuc)
material.add_nuclide(nuc, density)
for burn_nuc in burnable_nucs:
if burn_nuc not in nuc_densities:
material.add_nuclide(burn_nuc,
dilute_density)
diluted_materials.append(material)
return reactions, diluted_materials
@staticmethod
def _get_nuclides_with_data(cross_sections):
"""Loads cross_sections.xml file to find nuclides with neutron data
Parameters
----------
cross_sections : str
Path to cross_sections.xml file
Returns
-------
nuclides : set of str
Set of nuclide names that have cross secton data
"""
nuclides = set()
data_lib = DataLibrary.from_xml(cross_sections)
for library in data_lib.libraries:
if library['type'] != 'neutron':
continue
for name in library['materials']:
if name not in nuclides:
nuclides.add(name)
return nuclides
@classmethod
def from_array(cls, nuclides, reactions, data):
"""
@ -162,6 +224,6 @@ class MicroXS(DataFrame):
def _validate_micro_xs_inputs(nuclides, reactions, data):
check_iterable_type('nuclides', nuclides, str)
check_iterable_type('reactions', reactions, str)
check_type('data', data, ndarray, expected_iter_type=float)
check_type('data', data, np.ndarray, expected_iter_type=float)
for reaction in reactions:
check_value('reactions', reaction, _valid_rxns)

View file

@ -1,7 +1,13 @@
nuclide,"(n,gamma)",fission
U234,23.518634203050645,0.49531930067650976
U235,10.621118186344665,49.10955932965905
U238,0.8652742788116043,0.10579281644765708
U236,9.095623870006154,0.32315392339237936
O16,0.0029535689693132015,0.0
O17,0.05980775766572907,0.0
U234,22.231989822002465,0.49620744663749855
U235,10.479008971197121,48.41787337164604
U238,0.8673334105437324,0.10467880588762352
U236,8.65171044607122,0.31948392400019293
O16,7.497851000107524e-05,0.0
O17,0.0004079227797153371,0.0
I135,6.842395323713927,0.0
Xe135,227463.86426990604,0.0
Xe136,0.02317896034753588,0.0
Cs135,2.1721665580713623,0.0
Gd157,12786.09939237018,0.0
Gd156,3.4006085445846983,0.0

1 nuclide (n,gamma) fission
2 U234 23.518634203050645 22.231989822002465 0.49531930067650976 0.49620744663749855
3 U235 10.621118186344665 10.479008971197121 49.10955932965905 48.41787337164604
4 U238 0.8652742788116043 0.8673334105437324 0.10579281644765708 0.10467880588762352
5 U236 9.095623870006154 8.65171044607122 0.32315392339237936 0.31948392400019293
6 O16 0.0029535689693132015 7.497851000107524e-05 0.0
7 O17 0.05980775766572907 0.0004079227797153371 0.0
8 I135 6.842395323713927 0.0
9 Xe135 227463.86426990604 0.0
10 Xe136 0.02317896034753588 0.0
11 Cs135 2.1721665580713623 0.0
12 Gd157 12786.09939237018 0.0
13 Gd156 3.4006085445846983 0.0

View file

@ -1,10 +1,14 @@
"""Test one-group cross section generation"""
from pathlib import Path
import numpy as np
import pytest
import openmc
from openmc.deplete import MicroXS
CHAIN_FILE = Path(__file__).parents[2] / "chain_simple.xml"
@pytest.fixture(scope="module")
def model():
fuel = openmc.Material(name="uo2")
@ -24,8 +28,6 @@ def model():
radii = [0.42, 0.45]
fuel.volume = np.pi * radii[0] ** 2
clad.volume = np.pi * (radii[1]**2 - radii[0]**2)
water.volume = 1.24**2 - (np.pi * radii[1]**2)
materials = openmc.Materials([fuel, clad, water])
@ -45,6 +47,6 @@ def model():
def test_from_model(model):
ref_xs = MicroXS.from_csv('test_reference.csv')
test_xs = MicroXS.from_model(model, model.materials[0])
test_xs = MicroXS.from_model(model, model.materials[0], CHAIN_FILE)
np.testing.assert_allclose(test_xs, ref_xs, rtol=1e-11)

View file

@ -1,7 +1,13 @@
nuclide,"(n,gamma)","(n,2n)","(n,p)","(n,a)","(n,3n)","(n,4n)",fission
U234,23.518634203050674,0.0008255330840536984,0.0,0.0,9.404554397521455e-07,0.0,0.49531930067650964
U235,10.621118186344795,0.004359401013759254,0.0,0.0,7.2974901306692395e-06,0.0,49.10955932965902
U238,0.8652742788116055,0.005661917442209096,0.0,0.0,4.92273921631416e-05,0.0,0.10579281644765708
U236,9.095623870006163,0.0024373322002926834,0.0,0.0,1.966889146690413e-05,0.0,0.3231539233923791
O16,7.511380881289377e-05,0.0,1.3764104470470622e-05,0.002862620940027927,0.0,0.0,0.0
O17,0.00041221042693945085,1.9826700699084533e-05,7.764409141772239e-06,0.05938517754333328,0.0,0.0,0.0
nuclide,"(n,gamma)",fission
U234,22.231989822002465,0.49620744663749855
U235,10.479008971197121,48.41787337164604
U238,0.8673334105437324,0.10467880588762352
U236,8.65171044607122,0.31948392400019293
O16,7.497851000107524e-05,0.0
O17,0.0004079227797153371,0.0
I135,6.842395323713927,0.0
Xe135,227463.86426990604,0.0
Xe136,0.02317896034753588,0.0
Cs135,2.1721665580713623,0.0
Gd157,12786.09939237018,0.0
Gd156,3.4006085445846983,0.0

1 nuclide (n,gamma) (n,2n) fission (n,p) (n,a) (n,3n) (n,4n)
2 U234 23.518634203050674 22.231989822002465 0.0008255330840536984 0.49531930067650964 0.49620744663749855 0.0 0.0 9.404554397521455e-07 0.0
3 U235 10.621118186344795 10.479008971197121 0.004359401013759254 49.10955932965902 48.41787337164604 0.0 0.0 7.2974901306692395e-06 0.0
4 U238 0.8652742788116055 0.8673334105437324 0.005661917442209096 0.10579281644765708 0.10467880588762352 0.0 0.0 4.92273921631416e-05 0.0
5 U236 9.095623870006163 8.65171044607122 0.0024373322002926834 0.3231539233923791 0.31948392400019293 0.0 0.0 1.966889146690413e-05 0.0
6 O16 7.511380881289377e-05 7.497851000107524e-05 0.0 0.0 1.3764104470470622e-05 0.002862620940027927 0.0 0.0
7 O17 0.00041221042693945085 0.0004079227797153371 1.9826700699084533e-05 0.0 7.764409141772239e-06 0.05938517754333328 0.0 0.0
8 I135 6.842395323713927 0.0
9 Xe135 227463.86426990604 0.0
10 Xe136 0.02317896034753588 0.0
11 Cs135 2.1721665580713623 0.0
12 Gd157 12786.09939237018 0.0
13 Gd156 3.4006085445846983 0.0