From b330d337f1e4e391088199d9141b8a6356a769ec Mon Sep 17 00:00:00 2001 From: Jiankai Yu Date: Mon, 2 Nov 2020 13:05:37 -0500 Subject: [PATCH 01/17] export materials.xml from depletion results --- openmc/deplete/results_list.py | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index bd02d576e5..3b3274bcbc 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -7,7 +7,7 @@ import numpy as np from .results import Results, VERSION_RESULTS from openmc.checkvalue import check_filetype_version, check_value, check_type - +from openmc.material import Material, Materials __all__ = ["ResultsList"] @@ -197,6 +197,7 @@ class ResultsList(list): times[ix] = res.proc_time return times + def get_times(self, time_units="d") -> np.ndarray: """Return the points in time that define the depletion schedule @@ -296,3 +297,40 @@ class ResultsList(list): "relative tolerances {} and {}.".format( time, time_units, atol, rtol) ) + + def export_to_materials_xml(self, mats_list, burnup_index, nuc_with_data=None): + """Export Materials.xml file from the depletion results + + ..note:: + + Will require mats_list from statepoint file match thatin depletion results + + Parameters + ---------- + mats_list : Iterable of openmc.Material + Materials to evaluate + burn_index : int + Index of burnup step to evaluate + nuc_with_data : Iterable of str, optional + nuclides list to evaluate with neutron data + + Returns + ------- + """ + result = self[burnup_index] + mat_file = Materials() + for i, mat in enumerate(mats_list): + mat_id = mat.id + new_mat = Material(mat_id) + if str(mat_id) in result.mat_to_ind.keys(): + new_mat.volume = result.volume[str(mat_id)] + for nuc in result.nuc_to_ind.keys(): + atoms = result[0, str(mat_id), nuc] + if atoms > 0.0: + atoms_per_barn_cm = 1e-24 * atoms / new_mat.volume + if (nuc_with_data is None) or (nuc in nuc_with_data): + new_mat.add_nuclide(nuc, atoms_per_barn_cm) + mat_file.append(new_mat) + else: + mat_file.append(mat) + mat_file.export_to_xml() From 12be239921188a4616e011d6c2abdf40eea1f025 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Wed, 18 Nov 2020 17:28:31 -0500 Subject: [PATCH 02/17] incorporate PR feedback on writing depleted material XML files --- openmc/deplete/results_list.py | 70 +++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 3b3274bcbc..508497906c 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -7,6 +7,7 @@ import numpy as np from .results import Results, VERSION_RESULTS from openmc.checkvalue import check_filetype_version, check_value, check_type +from openmc.data.library import DataLibrary from openmc.material import Material, Materials __all__ = ["ResultsList"] @@ -197,7 +198,6 @@ class ResultsList(list): times[ix] = res.proc_time return times - def get_times(self, time_units="d") -> np.ndarray: """Return the points in time that define the depletion schedule @@ -298,39 +298,63 @@ class ResultsList(list): time, time_units, atol, rtol) ) - def export_to_materials_xml(self, mats_list, burnup_index, nuc_with_data=None): + def export_to_materials_xml(self, burnup_index, nuc_with_data=None, + new_xml_name='depleted_materials.xml'): """Export Materials.xml file from the depletion results - - ..note:: - - Will require mats_list from statepoint file match thatin depletion results Parameters ---------- - mats_list : Iterable of openmc.Material - Materials to evaluate burn_index : int Index of burnup step to evaluate nuc_with_data : Iterable of str, optional nuclides list to evaluate with neutron data + new_xml_name : str, optional + name of xml file to put depleted materials into Returns ------- """ result = self[burnup_index] - mat_file = Materials() - for i, mat in enumerate(mats_list): - mat_id = mat.id - new_mat = Material(mat_id) - if str(mat_id) in result.mat_to_ind.keys(): - new_mat.volume = result.volume[str(mat_id)] - for nuc in result.nuc_to_ind.keys(): - atoms = result[0, str(mat_id), nuc] - if atoms > 0.0: - atoms_per_barn_cm = 1e-24 * atoms / new_mat.volume - if (nuc_with_data is None) or (nuc in nuc_with_data): - new_mat.add_nuclide(nuc, atoms_per_barn_cm) - mat_file.append(new_mat) + + # Only materials found in the original materials.xml file will be + # updated. If for some reason you have modified OpenMC to produce + # new materials as depletion takes place, this method will not + # work as expected and leave out that material. + mat_file = Materials.from_xml("materials.xml") + + # Only nuclides with valid transport data will be written to + # the new materials XML file. The precedence of nuclides to select + # is first ones provided as a kwarg here, then ones specified + # in the materials.xml file if provided, then finally from + # the environment variable OPENMC_CROSS_SECTIONS. + env_xs_name = "OPENMC_CROSS_SECTIONS" + if nuc_with_data: + available_cross_sections = nuc_with_data + else: + # select cross_sections.xml file to use + if mat_file.cross_sections: + this_library = DataLibrary.from_xml(path=mat_file.cross_sections) else: - mat_file.append(mat) - mat_file.export_to_xml() + this_library = DataLibrary.from_xml() + + # Find neutron libraries we have access to + available_cross_sections = [] + for lib in this_library.libraries: + if lib['type'] == 'neutron': + available_cross_sections.extend(lib['materials']) + if not available_cross_sections: + raise Exception('No neutron libraries found in cross_sections.xml') + + # Overwrite material definitions, if they can be found in the depletion + # results, and save them to the new depleted xml file. + for mat in mat_file: + if str(mat.id) in result.mat_to_ind.keys(): + mat.volume = result.volume[str(mat.id)] + for nuc in result.nuc_to_ind.keys(): + atoms = result[0, str(mat.id), nuc] + if atoms > 0.0: + atoms_per_barn_cm = 1e-24 * atoms / mat.volume + if nuc in available_cross_sections: + mat.add_nuclide(nuc, atoms_per_barn_cm) + + mat_file.export_to_xml(path=new_xml_name) From 9ff35d7a3835d52474fce9040734a3d473b27bb2 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Wed, 18 Nov 2020 17:30:47 -0500 Subject: [PATCH 03/17] XML export of depleted material results optional, rather return Materials --- openmc/deplete/results_list.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 508497906c..dffb859614 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -298,8 +298,7 @@ class ResultsList(list): time, time_units, atol, rtol) ) - def export_to_materials_xml(self, burnup_index, nuc_with_data=None, - new_xml_name='depleted_materials.xml'): + def export_to_materials_xml(self, burnup_index, nuc_with_data=None, new_xml_name=None): """Export Materials.xml file from the depletion results Parameters @@ -307,12 +306,19 @@ class ResultsList(list): burn_index : int Index of burnup step to evaluate nuc_with_data : Iterable of str, optional - nuclides list to evaluate with neutron data + nuclides list to evaluate with neutron data. If not provided, + nuclides from the cross_sections element of materials.xml will + be used. If that element is not present, nuclides from + OPENMC_CROSS_SECTIONS will be used. new_xml_name : str, optional - name of xml file to put depleted materials into + name of xml file to put depleted materials into. If not + provided, no new xml file will be written. Returns ------- + mat_file : Materials + A modified Materials instance containing depleted material data, + plus original isotopic compositions of non-depletable materials """ result = self[burnup_index] @@ -327,7 +333,6 @@ class ResultsList(list): # is first ones provided as a kwarg here, then ones specified # in the materials.xml file if provided, then finally from # the environment variable OPENMC_CROSS_SECTIONS. - env_xs_name = "OPENMC_CROSS_SECTIONS" if nuc_with_data: available_cross_sections = nuc_with_data else: @@ -357,4 +362,7 @@ class ResultsList(list): if nuc in available_cross_sections: mat.add_nuclide(nuc, atoms_per_barn_cm) - mat_file.export_to_xml(path=new_xml_name) + if new_xml_name: + mat_file.export_to_xml(path=new_xml_name) + + return mat_file From 3954b260ed0e3965a01f0272319253b04f82c1a7 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Mon, 14 Dec 2020 14:07:15 -0500 Subject: [PATCH 04/17] incorporate review suggestions --- openmc/deplete/results_list.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index dffb859614..bbd840e9ad 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -306,14 +306,14 @@ class ResultsList(list): burn_index : int Index of burnup step to evaluate nuc_with_data : Iterable of str, optional - nuclides list to evaluate with neutron data. If not provided, - nuclides from the cross_sections element of materials.xml will - be used. If that element is not present, nuclides from - OPENMC_CROSS_SECTIONS will be used. - new_xml_name : str, optional - name of xml file to put depleted materials into. If not - provided, no new xml file will be written. + nuclides iterable to evaluate with neutron data + This must be specified because not all nuclides appearing in + depletion results have associated neutron cross sections, and + as such cannot be used in subsequent transport calculations. + If not provided, nuclides from the cross_sections element of + materials.xml will be used. If that element is not present, + nuclides from OPENMC_CROSS_SECTIONS will be used. Returns ------- mat_file : Materials @@ -334,6 +334,8 @@ class ResultsList(list): # in the materials.xml file if provided, then finally from # the environment variable OPENMC_CROSS_SECTIONS. if nuc_with_data: + if not all(isinstance(nuclide_name, str) for nuclide_name in nuc_with_data): + raise Exception("Expected an iterable of strings as acceptable nuclide data.") available_cross_sections = nuc_with_data else: # select cross_sections.xml file to use @@ -343,10 +345,10 @@ class ResultsList(list): this_library = DataLibrary.from_xml() # Find neutron libraries we have access to - available_cross_sections = [] + available_cross_sections = set() for lib in this_library.libraries: if lib['type'] == 'neutron': - available_cross_sections.extend(lib['materials']) + available_cross_sections.update(lib['materials']) if not available_cross_sections: raise Exception('No neutron libraries found in cross_sections.xml') @@ -356,13 +358,11 @@ class ResultsList(list): if str(mat.id) in result.mat_to_ind.keys(): mat.volume = result.volume[str(mat.id)] for nuc in result.nuc_to_ind.keys(): + if nuc not in available_cross_sections: + continue atoms = result[0, str(mat.id), nuc] if atoms > 0.0: atoms_per_barn_cm = 1e-24 * atoms / mat.volume - if nuc in available_cross_sections: - mat.add_nuclide(nuc, atoms_per_barn_cm) - - if new_xml_name: - mat_file.export_to_xml(path=new_xml_name) + mat.add_nuclide(nuc, atoms_per_barn_cm) return mat_file From e99ba6fe765306837f9d099ee8bbebdd3e4f69ed Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Mon, 21 Dec 2020 12:50:34 -0500 Subject: [PATCH 05/17] add more specific exceptions for ResultsList->openmc.Materials and add test for that --- openmc/deplete/results_list.py | 5 +- .../deplete/reference_materials_xml_hash | 1 + tests/regression_tests/deplete/test.py | 50 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 tests/regression_tests/deplete/reference_materials_xml_hash diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index bbd840e9ad..96157f177e 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -9,6 +9,7 @@ from .results import Results, VERSION_RESULTS from openmc.checkvalue import check_filetype_version, check_value, check_type from openmc.data.library import DataLibrary from openmc.material import Material, Materials +from openmc.exceptions import DataError, InvalidArgumentError __all__ = ["ResultsList"] @@ -335,7 +336,7 @@ class ResultsList(list): # the environment variable OPENMC_CROSS_SECTIONS. if nuc_with_data: if not all(isinstance(nuclide_name, str) for nuclide_name in nuc_with_data): - raise Exception("Expected an iterable of strings as acceptable nuclide data.") + raise InvalidArgumentError("Expected an iterable of strings as acceptable nuclide data.") available_cross_sections = nuc_with_data else: # select cross_sections.xml file to use @@ -350,7 +351,7 @@ class ResultsList(list): if lib['type'] == 'neutron': available_cross_sections.update(lib['materials']) if not available_cross_sections: - raise Exception('No neutron libraries found in cross_sections.xml') + raise DataError('No neutron libraries found in cross_sections.xml') # Overwrite material definitions, if they can be found in the depletion # results, and save them to the new depleted xml file. diff --git a/tests/regression_tests/deplete/reference_materials_xml_hash b/tests/regression_tests/deplete/reference_materials_xml_hash new file mode 100644 index 0000000000..72171a4eb0 --- /dev/null +++ b/tests/regression_tests/deplete/reference_materials_xml_hash @@ -0,0 +1 @@ +55e93fbd8f969110b937029432c0e3e08295eb4d23740cd58f0b59bc986522f0ed988e7150916b7d00f75c85003658ff3bab6bb4ccd9aedd255a717fa5b50fc4 \ No newline at end of file diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index 6426c7ddc9..e3ec023200 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -1,5 +1,6 @@ """ Full system test suite. """ +import hashlib # for comparing conversion of depletion results to XML from math import floor import shutil from pathlib import Path @@ -130,3 +131,52 @@ def test_full(run_in_tmpdir, problem, multiproc): # Check that no additional tallies are loaded from the files assert np.all(n_tallies == 0) + +# Checks openmc.Materials objects can be created from depletion results +def test_depletion_results_to_material(run_in_tmpdir, problem): + + # Load the reference/test results + path_reference = Path(__file__).with_name('test_reference.h5') + res_ref = openmc.deplete.ResultsList.from_hdf5(path_reference) + + # Firstly need to export materials.xml file for the initial simulation state + geometry, lower_left, upper_right = problem + materials = openmc.Materials() + for mat in geometry.root_universe.get_all_materials().values(): + materials.append(mat) + materials.export_to_xml() + + # Export last step of depletion to its own openmc.Materials object, + # using only nuclides available in the current nuclear data library + last_step_materials = res_ref.export_to_materials(-1) + + # Because files are written here that need to be cleaned up even + # if something fails, stuff after here goes in a try/except. + + # If updating results, do so and return. We write out the last-step + # depleted materials as an XML, hash the file, and save the hash to + # the reference file. + reference_hash_file = Path(__file__).with_name('reference_materials_xml_hash') + if config['update']: + reference_material_file = 'last_step_materials_reference.xml' + last_step_materials.export_to_xml(path=reference_material_file) + with open(reference_material_file, 'rb') as ref_file: + result_file_hash = hashlib.sha512() + for line in ref_file: + result_file_hash.update(line) + with open(reference_hash_file, 'w') as refhash_file: + refhash_file.write(result_file_hash.hexdigest()) + return + + # Check that the conversion of the final step depleted materials XML + # file hashes to what we expect. + output_xml_file = 'last_step_materials.xml' + last_step_materials.export_to_xml(path=output_xml_file) + with open(output_xml_file, 'rb') as result_file: + result_file_hash = hashlib.sha512() + for line in result_file: + result_file_hash.update(line) + with open(reference_hash_file) as refhash_f: + reference_hash = refhash_f.read() + + assert reference_hash == result_file_hash.hexdigest() From 6cf5253aebdca200216930a06fb044cb6e1a930e Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Mon, 21 Dec 2020 12:58:39 -0500 Subject: [PATCH 06/17] remove redundant code --- tests/regression_tests/deplete/test.py | 30 ++++++++++---------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index e3ec023200..a05cb13b67 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -150,24 +150,6 @@ def test_depletion_results_to_material(run_in_tmpdir, problem): # using only nuclides available in the current nuclear data library last_step_materials = res_ref.export_to_materials(-1) - # Because files are written here that need to be cleaned up even - # if something fails, stuff after here goes in a try/except. - - # If updating results, do so and return. We write out the last-step - # depleted materials as an XML, hash the file, and save the hash to - # the reference file. - reference_hash_file = Path(__file__).with_name('reference_materials_xml_hash') - if config['update']: - reference_material_file = 'last_step_materials_reference.xml' - last_step_materials.export_to_xml(path=reference_material_file) - with open(reference_material_file, 'rb') as ref_file: - result_file_hash = hashlib.sha512() - for line in ref_file: - result_file_hash.update(line) - with open(reference_hash_file, 'w') as refhash_file: - refhash_file.write(result_file_hash.hexdigest()) - return - # Check that the conversion of the final step depleted materials XML # file hashes to what we expect. output_xml_file = 'last_step_materials.xml' @@ -176,7 +158,17 @@ def test_depletion_results_to_material(run_in_tmpdir, problem): result_file_hash = hashlib.sha512() for line in result_file: result_file_hash.update(line) + + # If updating results, do so and return. We write out the last-step + # depleted materials as an XML, hash the file, and save the hash to + # the reference file. + reference_hash_file = Path(__file__).with_name('reference_materials_xml_hash') + if config['update']: + with open(reference_hash_file, 'w') as refhash_file: + refhash_file.write(result_file_hash.hexdigest()) + return + + # Check hash of final depletion point material XML matches expected with open(reference_hash_file) as refhash_f: reference_hash = refhash_f.read() - assert reference_hash == result_file_hash.hexdigest() From 63a56701fd8860aef859c30af724aa8e8d6a2cfc Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 24 Dec 2020 15:50:39 -0500 Subject: [PATCH 07/17] Update openmc/deplete/results_list.py Co-authored-by: Andrew Johnson --- openmc/deplete/results_list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 96157f177e..d2d964a1fb 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -315,6 +315,7 @@ class ResultsList(list): If not provided, nuclides from the cross_sections element of materials.xml will be used. If that element is not present, nuclides from OPENMC_CROSS_SECTIONS will be used. + Returns ------- mat_file : Materials From a2f1a2fd59a78d264ff12e4a25598f4b6e4d212d Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 24 Dec 2020 15:51:00 -0500 Subject: [PATCH 08/17] Update tests/regression_tests/deplete/test.py Co-authored-by: Andrew Johnson --- tests/regression_tests/deplete/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index a05cb13b67..a91b6e53da 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -132,9 +132,9 @@ def test_full(run_in_tmpdir, problem, multiproc): # Check that no additional tallies are loaded from the files assert np.all(n_tallies == 0) -# Checks openmc.Materials objects can be created from depletion results -def test_depletion_results_to_material(run_in_tmpdir, problem): +def test_depletion_results_to_material(run_in_tmpdir, problem): + """Checks openmc.Materials objects can be created from depletion results""" # Load the reference/test results path_reference = Path(__file__).with_name('test_reference.h5') res_ref = openmc.deplete.ResultsList.from_hdf5(path_reference) From eec5bfc4094b98efd53ab9ca5fa2f4fc652cbc2e Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 24 Dec 2020 16:12:08 -0500 Subject: [PATCH 09/17] fix rebase screwup --- openmc/deplete/results_list.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index d2d964a1fb..899540d60a 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -299,8 +299,8 @@ class ResultsList(list): time, time_units, atol, rtol) ) - def export_to_materials_xml(self, burnup_index, nuc_with_data=None, new_xml_name=None): - """Export Materials.xml file from the depletion results + def export_to_materials(self, burnup_index, nuc_with_data=None): + """Export openmc.Materials file from the depletion results Parameters ---------- @@ -309,7 +309,7 @@ class ResultsList(list): nuc_with_data : Iterable of str, optional nuclides iterable to evaluate with neutron data - This must be specified because not all nuclides appearing in + This must be specified if not all nuclides appearing in depletion results have associated neutron cross sections, and as such cannot be used in subsequent transport calculations. If not provided, nuclides from the cross_sections element of From 4d777a76e21ae8707a5896962ea10e840dbe0a27 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 24 Dec 2020 16:15:14 -0500 Subject: [PATCH 10/17] paragrpah formatting --- openmc/deplete/results_list.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 899540d60a..01fd244ee6 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -300,15 +300,14 @@ class ResultsList(list): ) def export_to_materials(self, burnup_index, nuc_with_data=None): - """Export openmc.Materials file from the depletion results + """Return openmc.Materials created from these depletion results. Parameters ---------- burn_index : int Index of burnup step to evaluate nuc_with_data : Iterable of str, optional - nuclides iterable to evaluate with neutron data - + Nuclides iterable to evaluate with neutron data. This must be specified if not all nuclides appearing in depletion results have associated neutron cross sections, and as such cannot be used in subsequent transport calculations. From de0eef06165f08b2b4c5e1f0aba1c72841d4122b Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 7 Jan 2021 10:18:46 -0500 Subject: [PATCH 11/17] improve export_to_materials docstring Co-authored-by: Paul Romano --- openmc/deplete/results_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 01fd244ee6..e31cbecdce 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -300,7 +300,7 @@ class ResultsList(list): ) def export_to_materials(self, burnup_index, nuc_with_data=None): - """Return openmc.Materials created from these depletion results. + """Return openmc.Materials object based on results at a given step Parameters ---------- From d9f94fcc7151db385a4a4141d87cf9a841e0e40a Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 7 Jan 2021 10:21:09 -0500 Subject: [PATCH 12/17] Update openmc/deplete/results_list.py Co-authored-by: Paul Romano --- openmc/deplete/results_list.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index e31cbecdce..4e79071ade 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -356,12 +356,13 @@ class ResultsList(list): # Overwrite material definitions, if they can be found in the depletion # results, and save them to the new depleted xml file. for mat in mat_file: - if str(mat.id) in result.mat_to_ind.keys(): - mat.volume = result.volume[str(mat.id)] - for nuc in result.nuc_to_ind.keys(): + mat_id = str(mat.id) + if mat_id in result.mat_to_ind: + mat.volume = result.volume[mat_id] + for nuc in result.nuc_to_ind: if nuc not in available_cross_sections: continue - atoms = result[0, str(mat.id), nuc] + atoms = result[0, mat_id, nuc] if atoms > 0.0: atoms_per_barn_cm = 1e-24 * atoms / mat.volume mat.add_nuclide(nuc, atoms_per_barn_cm) From 79da586881a0809438e3310c36cea423eb163e25 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 7 Jan 2021 10:21:31 -0500 Subject: [PATCH 13/17] Update openmc/deplete/results_list.py Co-authored-by: Paul Romano --- openmc/deplete/results_list.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 4e79071ade..767d32243c 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -318,8 +318,8 @@ class ResultsList(list): Returns ------- mat_file : Materials - A modified Materials instance containing depleted material data, - plus original isotopic compositions of non-depletable materials + A modified Materials instance containing depleted material data + and original isotopic compositions of non-depletable materials """ result = self[burnup_index] From 863f0f432e69618391f962509f9af61a98bd018c Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 7 Jan 2021 11:28:07 -0500 Subject: [PATCH 14/17] use direct file diff rather than hash comparison for export_to_materials test --- openmc/deplete/results_list.py | 28 +- .../deplete/last_step_reference_materials.xml | 1537 +++++++++++++++++ .../deplete/reference_materials_xml_hash | 1 - tests/regression_tests/deplete/test.py | 30 +- 4 files changed, 1569 insertions(+), 27 deletions(-) create mode 100644 tests/regression_tests/deplete/last_step_reference_materials.xml delete mode 100644 tests/regression_tests/deplete/reference_materials_xml_hash diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index 767d32243c..c632e5d073 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -6,7 +6,7 @@ import h5py import numpy as np from .results import Results, VERSION_RESULTS -from openmc.checkvalue import check_filetype_version, check_value, check_type +import openmc.checkvalue as cv from openmc.data.library import DataLibrary from openmc.material import Material, Materials from openmc.exceptions import DataError, InvalidArgumentError @@ -36,7 +36,7 @@ class ResultsList(list): New instance of depletion results """ with h5py.File(str(filename), "r") as fh: - check_filetype_version(fh, 'depletion results', VERSION_RESULTS[0]) + cv.check_filetype_version(fh, 'depletion results', VERSION_RESULTS[0]) new = cls() # Get number of results stored @@ -80,8 +80,8 @@ class ResultsList(list): Concentration of specified nuclide in units of ``nuc_units`` """ - check_value("time_units", time_units, {"s", "d", "min", "h"}) - check_value("nuc_units", nuc_units, + cv.check_value("time_units", time_units, {"s", "d", "min", "h"}) + cv.check_value("nuc_units", nuc_units, {"atoms", "atom/b-cm", "atom/cm3"}) times = np.empty_like(self, dtype=float) @@ -217,7 +217,7 @@ class ResultsList(list): 1-D vector of time points """ - check_type("time_units", time_units, str) + cv.check_type("time_units", time_units, str) times = np.fromiter( (r.time[0] for r in self), @@ -271,9 +271,9 @@ class ResultsList(list): int """ - check_type("time", time, numbers.Real) - check_type("atol", atol, numbers.Real) - check_type("rtol", rtol, numbers.Real) + cv.check_type("time", time, numbers.Real) + cv.check_type("atol", atol, numbers.Real) + cv.check_type("rtol", rtol, numbers.Real) times = self.get_times(time_units) @@ -299,16 +299,17 @@ class ResultsList(list): time, time_units, atol, rtol) ) - def export_to_materials(self, burnup_index, nuc_with_data=None): + def export_to_materials(self, burnup_index, nuc_with_data=None) -> Materials: """Return openmc.Materials object based on results at a given step Parameters ---------- burn_index : int - Index of burnup step to evaluate + Index of burnup step to evaluate. See also: get_step_where for + obtaining burnup step indices from other data such as the time. nuc_with_data : Iterable of str, optional - Nuclides iterable to evaluate with neutron data. - This must be specified if not all nuclides appearing in + Nuclides to include in resulting materials. + This can be specified if not all nuclides appearing in depletion results have associated neutron cross sections, and as such cannot be used in subsequent transport calculations. If not provided, nuclides from the cross_sections element of @@ -335,8 +336,7 @@ class ResultsList(list): # in the materials.xml file if provided, then finally from # the environment variable OPENMC_CROSS_SECTIONS. if nuc_with_data: - if not all(isinstance(nuclide_name, str) for nuclide_name in nuc_with_data): - raise InvalidArgumentError("Expected an iterable of strings as acceptable nuclide data.") + cv.check_iterable_type('nuclide names', nuc_with_data, str) available_cross_sections = nuc_with_data else: # select cross_sections.xml file to use diff --git a/tests/regression_tests/deplete/last_step_reference_materials.xml b/tests/regression_tests/deplete/last_step_reference_materials.xml new file mode 100644 index 0000000000..91a6e50f0c --- /dev/null +++ b/tests/regression_tests/deplete/last_step_reference_materials.xml @@ -0,0 +1,1537 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/regression_tests/deplete/reference_materials_xml_hash b/tests/regression_tests/deplete/reference_materials_xml_hash deleted file mode 100644 index 72171a4eb0..0000000000 --- a/tests/regression_tests/deplete/reference_materials_xml_hash +++ /dev/null @@ -1 +0,0 @@ -55e93fbd8f969110b937029432c0e3e08295eb4d23740cd58f0b59bc986522f0ed988e7150916b7d00f75c85003658ff3bab6bb4ccd9aedd255a717fa5b50fc4 \ No newline at end of file diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index a91b6e53da..cea4615dfc 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -1,10 +1,10 @@ """ Full system test suite. """ -import hashlib # for comparing conversion of depletion results to XML from math import floor import shutil from pathlib import Path +from difflib import unified_diff import numpy as np import pytest import openmc @@ -154,21 +154,27 @@ def test_depletion_results_to_material(run_in_tmpdir, problem): # file hashes to what we expect. output_xml_file = 'last_step_materials.xml' last_step_materials.export_to_xml(path=output_xml_file) - with open(output_xml_file, 'rb') as result_file: - result_file_hash = hashlib.sha512() - for line in result_file: - result_file_hash.update(line) + with open(output_xml_file, 'r') as result_file: + result_file_lines = result_file.readlines() # If updating results, do so and return. We write out the last-step # depleted materials as an XML, hash the file, and save the hash to # the reference file. - reference_hash_file = Path(__file__).with_name('reference_materials_xml_hash') + reference_file = Path(__file__).with_name('last_step_reference_materials.xml') if config['update']: - with open(reference_hash_file, 'w') as refhash_file: - refhash_file.write(result_file_hash.hexdigest()) + with open(reference_file, 'w') as ref_file: + ref_file.writelines(result_file_lines) return - # Check hash of final depletion point material XML matches expected - with open(reference_hash_file) as refhash_f: - reference_hash = refhash_f.read() - assert reference_hash == result_file_hash.hexdigest() + # Check text of final depletion point material XML matches reference + with open(reference_file) as ref_file: + reference_lines = ref_file.readlines() + diff_vs_expected = unified_diff(reference_lines, result_file_lines) + + # Check all lines match, printing along the way + success = True + for line in diff_vs_expected: + if line: + success = False + print(line) + assert success From f018ba72ba422c26b74b407589a290431fbd3dbf Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 7 Jan 2021 11:34:27 -0500 Subject: [PATCH 15/17] remove unnecessary newline --- tests/regression_tests/deplete/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index cea4615dfc..99eb70cbf8 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -176,5 +176,5 @@ def test_depletion_results_to_material(run_in_tmpdir, problem): for line in diff_vs_expected: if line: success = False - print(line) + print(line.rstrip()) assert success From 91bc2e53860ac41d81a22724eb8d4b7d3712749d Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 7 Jan 2021 11:38:52 -0500 Subject: [PATCH 16/17] final cleanup --- tests/regression_tests/deplete/test.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py index 99eb70cbf8..fcc2099cf9 100644 --- a/tests/regression_tests/deplete/test.py +++ b/tests/regression_tests/deplete/test.py @@ -150,16 +150,14 @@ def test_depletion_results_to_material(run_in_tmpdir, problem): # using only nuclides available in the current nuclear data library last_step_materials = res_ref.export_to_materials(-1) - # Check that the conversion of the final step depleted materials XML - # file hashes to what we expect. + # Export final depletion step materials to XML output_xml_file = 'last_step_materials.xml' last_step_materials.export_to_xml(path=output_xml_file) with open(output_xml_file, 'r') as result_file: result_file_lines = result_file.readlines() # If updating results, do so and return. We write out the last-step - # depleted materials as an XML, hash the file, and save the hash to - # the reference file. + # depleted materials as an XML, and save the list of lines to diff. reference_file = Path(__file__).with_name('last_step_reference_materials.xml') if config['update']: with open(reference_file, 'w') as ref_file: @@ -171,10 +169,9 @@ def test_depletion_results_to_material(run_in_tmpdir, problem): reference_lines = ref_file.readlines() diff_vs_expected = unified_diff(reference_lines, result_file_lines) - # Check all lines match, printing along the way + # Check all lines match, printing errors along the way success = True for line in diff_vs_expected: - if line: - success = False - print(line.rstrip()) + success = False + print(line.rstrip()) assert success From 67542a3239f82fc9b43aaba5bea79500389d2fd2 Mon Sep 17 00:00:00 2001 From: Gavin Ridley Date: Thu, 7 Jan 2021 11:52:16 -0500 Subject: [PATCH 17/17] ensure no duplicate nuclides in materials --- openmc/deplete/results_list.py | 1 + .../deplete/last_step_reference_materials.xml | 480 ------------------ 2 files changed, 1 insertion(+), 480 deletions(-) diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py index c632e5d073..c0639d53f6 100644 --- a/openmc/deplete/results_list.py +++ b/openmc/deplete/results_list.py @@ -365,6 +365,7 @@ class ResultsList(list): atoms = result[0, mat_id, nuc] if atoms > 0.0: atoms_per_barn_cm = 1e-24 * atoms / mat.volume + mat.remove_nuclide(nuc) # Replace if it's there mat.add_nuclide(nuc, atoms_per_barn_cm) return mat_file diff --git a/tests/regression_tests/deplete/last_step_reference_materials.xml b/tests/regression_tests/deplete/last_step_reference_materials.xml index 91a6e50f0c..2021b7c1b7 100644 --- a/tests/regression_tests/deplete/last_step_reference_materials.xml +++ b/tests/regression_tests/deplete/last_step_reference_materials.xml @@ -2,13 +2,6 @@ - - - - - - - @@ -23,13 +16,6 @@ - - - - - - - @@ -44,13 +30,6 @@ - - - - - - - @@ -65,13 +44,6 @@ - - - - - - - @@ -86,10 +58,6 @@ - - - - @@ -103,13 +71,6 @@ - - - - - - - @@ -124,13 +85,6 @@ - - - - - - - @@ -145,13 +99,6 @@ - - - - - - - @@ -166,13 +113,6 @@ - - - - - - - @@ -187,13 +127,6 @@ - - - - - - - @@ -208,13 +141,6 @@ - - - - - - - @@ -229,13 +155,6 @@ - - - - - - - @@ -250,13 +169,6 @@ - - - - - - - @@ -271,10 +183,6 @@ - - - - @@ -288,13 +196,6 @@ - - - - - - - @@ -309,13 +210,6 @@ - - - - - - - @@ -330,13 +224,6 @@ - - - - - - - @@ -351,13 +238,6 @@ - - - - - - - @@ -372,13 +252,6 @@ - - - - - - - @@ -393,13 +266,6 @@ - - - - - - - @@ -414,13 +280,6 @@ - - - - - - - @@ -435,13 +294,6 @@ - - - - - - - @@ -456,10 +308,6 @@ - - - - @@ -473,13 +321,6 @@ - - - - - - - @@ -494,13 +335,6 @@ - - - - - - - @@ -515,13 +349,6 @@ - - - - - - - @@ -536,13 +363,6 @@ - - - - - - - @@ -557,13 +377,6 @@ - - - - - - - @@ -578,13 +391,6 @@ - - - - - - - @@ -599,13 +405,6 @@ - - - - - - - @@ -620,13 +419,6 @@ - - - - - - - @@ -641,10 +433,6 @@ - - - - @@ -658,13 +446,6 @@ - - - - - - - @@ -679,13 +460,6 @@ - - - - - - - @@ -700,13 +474,6 @@ - - - - - - - @@ -721,13 +488,6 @@ - - - - - - - @@ -742,13 +502,6 @@ - - - - - - - @@ -763,13 +516,6 @@ - - - - - - - @@ -784,13 +530,6 @@ - - - - - - - @@ -805,13 +544,6 @@ - - - - - - - @@ -826,10 +558,6 @@ - - - - @@ -843,13 +571,6 @@ - - - - - - - @@ -864,13 +585,6 @@ - - - - - - - @@ -885,13 +599,6 @@ - - - - - - - @@ -906,13 +613,6 @@ - - - - - - - @@ -927,13 +627,6 @@ - - - - - - - @@ -948,13 +641,6 @@ - - - - - - - @@ -969,13 +655,6 @@ - - - - - - - @@ -990,13 +669,6 @@ - - - - - - - @@ -1011,10 +683,6 @@ - - - - @@ -1028,13 +696,6 @@ - - - - - - - @@ -1049,13 +710,6 @@ - - - - - - - @@ -1070,13 +724,6 @@ - - - - - - - @@ -1091,13 +738,6 @@ - - - - - - - @@ -1112,13 +752,6 @@ - - - - - - - @@ -1133,13 +766,6 @@ - - - - - - - @@ -1154,13 +780,6 @@ - - - - - - - @@ -1175,13 +794,6 @@ - - - - - - - @@ -1196,10 +808,6 @@ - - - - @@ -1213,13 +821,6 @@ - - - - - - - @@ -1234,13 +835,6 @@ - - - - - - - @@ -1255,13 +849,6 @@ - - - - - - - @@ -1276,13 +863,6 @@ - - - - - - - @@ -1297,13 +877,6 @@ - - - - - - - @@ -1318,13 +891,6 @@ - - - - - - - @@ -1339,13 +905,6 @@ - - - - - - - @@ -1360,13 +919,6 @@ - - - - - - - @@ -1381,10 +933,6 @@ - - - - @@ -1398,13 +946,6 @@ - - - - - - - @@ -1419,13 +960,6 @@ - - - - - - - @@ -1440,13 +974,6 @@ - - - - - - - @@ -1461,13 +988,6 @@ - - - - - - -