Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 47 additions & 16 deletions openmc/deplete/chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

import lxml.etree as ET
import scipy.sparse as sp

import xmlschema

from openmc.checkvalue import check_type, check_greater_than, PathLike
from openmc.data import gnds_name, zam
from openmc.exceptions import DataError
Expand All @@ -26,6 +27,8 @@
import openmc.data


# Name of the XML schema file
XML_SCHEMA = "openmc_chain_schemas.xsd"
# tuple of (possible MT values, secondaries)
ReactionInfo = namedtuple('ReactionInfo', ('mts', 'secondaries'))

Expand Down Expand Up @@ -544,7 +547,7 @@ def from_xml(cls, filename, fission_q=None):

"""
chain = cls()

Chain.validate(filename)
if fission_q is not None:
check_type("fission_q", fission_q, Mapping)
else:
Expand Down Expand Up @@ -1043,19 +1046,23 @@ def fission_yields(self, yields):
yields = [yields]
check_type("fission_yields", yields, Iterable, Mapping)
self._fission_yields = yields

def validate(self, strict=True, quiet=False, tolerance=1e-4):

@staticmethod
def validate(filename, strict=True, quiet=False, tolerance = None):
"""Search for possible inconsistencies

The following checks are performed for all nuclides present:

1) For all non-fission reactions, does the sum of branching

1) The XML file structure is validated against an XMLSchema
2) For all non-fission reactions, does the sum of branching
ratios equal about one?
2) For fission reactions, does the sum of fission yield
3) For fission reactions, does the sum of fission yield
fractions equal about two?

Parameters
----------
filename : str
Path of the XML file that needs to be validated
strict : bool, optional
Raise exceptions at the first inconsistency if true.
Otherwise mark a warning
Expand Down Expand Up @@ -1084,16 +1091,40 @@ def validate(self, strict=True, quiet=False, tolerance=1e-4):
--------
openmc.deplete.Nuclide.validate
"""
check_type("tolerance", tolerance, Real)
check_greater_than("tolerance", tolerance, 0.0, True)
msg_func = ("Nuclide {name} caused the following error: {e}").format
xml_tree = ET.parse(filename)
schema_info = Path(__file__).parent / XML_SCHEMA
valid = True
# Sort through nuclides by name
for name in sorted(self.nuclide_dict):
stat = self[name].validate(strict, quiet, tolerance)
if quiet and not stat:
return stat
valid = valid and stat
return valid
if tolerance:
check_type("tolerance", tolerance, Real)
check_greater_than("tolerance", tolerance, 0.0, True)
xsd_text = schema_info.read_text()
schema_info = re.sub(r"0\.0001", str(tolerance), xsd_text)

schema = xmlschema.XMLSchema11(schema_info)
# Get all the validation errors
errors = list(schema.iter_errors(xml_tree))
if errors:
for e in errors:
# Get the element that caused the error
elem = e.elem
parent = elem
# Find parent Nuclide tag
while parent is not None and parent.tag != "nuclide":
parent = parent.getparent()
# Get Nuclide name
name = parent.get("name")
msg = msg_func(name=name, e=e.message)
if strict:
raise ValueError(msg)
elif quiet:
valid = False
continue
else:
warn(msg)
valid = False

return valid

def reduce(self, initial_isotopes, level=None):
"""Reduce the size of the chain by following transmutation paths
Expand Down
142 changes: 142 additions & 0 deletions openmc/deplete/openmc_chain_schemas.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?xml version="1.0"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">
<xs:annotation>
<xs:documentation>
Author: Lorenzo Canzian, newcleo Spa, Italy
Date: 2025-09-25
</xs:documentation>
</xs:annotation>

<xs:element name="depletion_chain" type="chain"/>

<xs:complexType name="chain">
<xs:annotation>
<xs:documentation xml:lang="en">Inside the depletion chain (root tag) one can have unlimited nuclide tags</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="nuclide" type="nuclideinfo" maxOccurs="unbounded"/>

</xs:sequence>
</xs:complexType>

<xs:simpleType name="dataListType">
<xs:list itemType="xs:double"/>
</xs:simpleType>

<xs:complexType name="nuclideinfo">

<xs:choice maxOccurs="unbounded">
<xs:annotation>
<xs:documentation xml:lang="en">Each nuclide can have multiple possibile interactions, so there are unlimited choices between different kind of tags</xs:documentation>
</xs:annotation>
<xs:element name="decay" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">Decay tag contains informations about the decay channel of the nuclide. We have three attributes:
type of decay, target produced, branching ratio. Type of decays include (name, (A_change, Z_change))
0: ('gamma', (0, 0)),
1: ('beta-', (0, 1)),
2: ('ec/beta+', (0, -1)),
3: ('IT', (0, 0)),
4: ('alpha', (-4, -2)),
5: ('n', (-1, 0)),
6: ('sf', None),
7: ('p', (-1, -1)),
8: ('e-', (0, 0)),
9: ('xray', (0, 0)),
10: ('unknown', None)
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="target" type="xs:string" use="optional"/>
<xs:attribute name="branching_ratio" type="xs:decimal" use="required"/>
</xs:complexType>
</xs:element>

<xs:element name="reaction" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">Reaction tag contains informations about the transmutation channel of the nuclide. There are four possible attributes:
type of reaction, target produced, Q value, branching ratio. Reactions are written as (n,2n), (n,fission),(n,gamma),(n,p), etc...
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="target" type="xs:string" use="optional"/>
<xs:attribute name="Q" type="xs:decimal" use="optional"/>
<xs:attribute name="branching_ratio" type="xs:decimal" use="optional"/>
</xs:complexType>
</xs:element>

<xs:element name="source" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">Source tag contains informations about other particles produced during decays of the nuclide. There are three attributes:
type, particle produced, interpolation. We also have another nested tag named parameter which contain the parameters linked to the particle emission
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="parameters">
<xs:annotation>
<xs:documentation xml:lang="en">First half are photon energies (in eV), second half are intensities (probabilities of emission)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:list itemType="xs:string"/>
</xs:simpleType>
</xs:element>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="particle" type="xs:string" use="required"/>
<xs:attribute name="interpolation" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>

<xs:element name="neutron_fission_yields" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">Fission_yields tag contains informations about the products of a fission and the relative fission yields
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence minOccurs="0">
<xs:element name="energies" minOccurs="0">
<xs:simpleType>
<xs:list itemType="xs:double"/>
</xs:simpleType>
</xs:element>
<xs:element name="fission_yields" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="products" minOccurs="0">
<xs:simpleType>
<xs:list itemType="xs:string"/>
</xs:simpleType>
</xs:element>
<xs:element name="data" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="dataListType">
<xs:assert test="abs(sum(for $x in tokenize(., '\s+') return number($x)) - 2) &lt; 0.0001"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="energy" type="xs:double"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="parent" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="half_life" type="xs:string" use="optional"/>
<xs:attribute name="decay_modes" type="xs:integer" use="optional"/>
<xs:attribute name="decay_energy" type="xs:decimal" use="optional"/>
<xs:attribute name="reactions" type="xs:integer" use="optional"/>
<xs:assert test="not(decay) or abs(sum(decay/@branching_ratio) - 1) &lt; 0.001" />
<xs:assert test="not(reaction) or abs(sum(reaction/@branching_ratio) - 1) &lt; 0.001 or sum(reaction/@branching_ratio) &lt; 0.001" />
</xs:complexType>
</xs:schema>
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dependencies = [
"uncertainties",
"setuptools",
"endf",
"xmlschema"
]

[project.optional-dependencies]
Expand Down
8 changes: 4 additions & 4 deletions tests/chain_simple.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<energies>2.53000e-02</energies>
<fission_yields energy="2.53000e-02">
<products>Gd157 Gd156 I135 Xe135 Xe136 Cs135</products>
<data>1.093250e-04 2.087260e-04 2.780820e-02 6.759540e-03 2.392300e-02 4.356330e-05</data>
<data>1.093250e-04 2.087260e-04 2.780820e-02 6.759540e-03 2.392300e-02 1.9411915633</data>
</fission_yields>
</neutron_fission_yields>
</nuclide>
Expand All @@ -41,7 +41,7 @@
<energies>2.53000e-02</energies>
<fission_yields energy="2.53000e-02">
<products>Gd157 Gd156 I135 Xe135 Xe136 Cs135</products>
<data>6.142710e-5 1.483250e-04 0.0292737 0.002566345 0.0219242 4.9097e-6</data>
<data>6.142710e-5 1.483250e-04 0.0292737 0.002566345 0.0219242 1.9460259097</data>
</fission_yields>
</neutron_fission_yields>
</nuclide>
Expand All @@ -53,8 +53,8 @@
<neutron_fission_yields>
<energies>2.53000e-02</energies>
<fission_yields energy="2.53000e-02">
<products>Gd157 Gd156 I135 Xe135 Xe136 Cs135</products>
<data>4.141120e-04 7.605360e-04 0.0135457 0.00026864 0.0024432 3.7100E-07</data>
<products>Gd157 Gd156 I135 Xe135 Xe136 Cs135 Am241</products>
<data>4.141120e-04 7.605360e-04 0.0135457 0.00026864 0.0024432 1.982567371</data>
</fission_yields>
</neutron_fission_yields>
</nuclide>
Expand Down
6 changes: 3 additions & 3 deletions tests/chain_simple_decay.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<energies>2.53000e-02</energies>
<fission_yields energy="2.53000e-02">
<products>Gd157 Gd156 I135 Xe135 Xe136 Cs135</products>
<data>1.093250e-04 2.087260e-04 2.780820e-02 6.759540e-03 2.392300e-02 4.356330e-05</data>
<data>1.093250e-04 2.087260e-04 2.780820e-02 6.759540e-03 2.392300e-02 1.94119120899</data>
</fission_yields>
</neutron_fission_yields>
</nuclide>
Expand All @@ -46,7 +46,7 @@
<energies>2.53000e-02</energies>
<fission_yields energy="2.53000e-02">
<products>Gd157 Gd156 I135 Xe135 Xe136 Cs135</products>
<data>6.142710e-5 1.483250e-04 0.0292737 0.002566345 0.0219242 4.9097e-6</data>
<data>6.142710e-5 1.483250e-04 0.0292737 0.002566345 0.0219242 1.9458259979</data>
</fission_yields>
</neutron_fission_yields>
</nuclide>
Expand All @@ -59,7 +59,7 @@
<energies>2.53000e-02</energies>
<fission_yields energy="2.53000e-02">
<products>Gd157 Gd156 I135 Xe135 Xe136 Cs135</products>
<data>4.141120e-04 7.605360e-04 0.0135457 0.00026864 0.0024432 3.7100E-07</data>
<data>4.141120e-04 7.605360e-04 0.0135457 0.00026864 0.0024432 1.982567812</data>
</fission_yields>
</neutron_fission_yields>
</nuclide>
Expand Down
Loading