From 3beaf4f36473b65f95ead46f0963979d272069a5 Mon Sep 17 00:00:00 2001 From: liangjg Date: Fri, 19 Oct 2018 16:43:01 -0400 Subject: [PATCH 1/5] update WMP file format to v1.1 --- docs/source/io_formats/data_wmp.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/source/io_formats/data_wmp.rst b/docs/source/io_formats/data_wmp.rst index 25916c5229..8d7cf6ba04 100644 --- a/docs/source/io_formats/data_wmp.rst +++ b/docs/source/io_formats/data_wmp.rst @@ -4,10 +4,15 @@ Windowed Multipole Library Format ================================= -**/version** (*char[]*) - The format version of the file. The current version is "v1.0" +**/** + +:Attributes: - **filetype** (*char[]*) -- String indicating the type of file + - **version** (*int[2]*) -- Major and minor version of the data + +**//** + +:Datasets: -**/nuclide/** - **broaden_poly** (*int[]*) If 1, Doppler broaden curve fit for window with corresponding index. If 0, do not. From 1343ce472d1c93790a2ce9fa0ed30725c1ccff3c Mon Sep 17 00:00:00 2001 From: liangjg Date: Fri, 19 Oct 2018 16:44:17 -0400 Subject: [PATCH 2/5] download WMP library v1.1 --- scripts/openmc-get-multipole-data | 6 +++--- tools/ci/download-xs.sh | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/openmc-get-multipole-data b/scripts/openmc-get-multipole-data index c8a2d1e9b9..554a18428e 100755 --- a/scripts/openmc-get-multipole-data +++ b/scripts/openmc-get-multipole-data @@ -29,9 +29,9 @@ parser.add_argument('-b', '--batch', action='store_true', args = parser.parse_args() -baseUrl = 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.0/' -files = ['WMP_Library_v1.0.tar.gz'] -checksums = ['22cb675734cfccb278dffd40dcfbf26a'] +baseUrl = 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/' +files = ['WMP_Library_v1.1.tar.gz'] +checksums = ['8523895928dd6ba63fba803e3a45d4f3'] block_size = 16384 # ============================================================================== diff --git a/tools/ci/download-xs.sh b/tools/ci/download-xs.sh index ff430ab2c5..eed9e23c41 100755 --- a/tools/ci/download-xs.sh +++ b/tools/ci/download-xs.sh @@ -14,6 +14,6 @@ fi # Download multipole library if [[ ! -e $HOME/WMP_Library/092235.h5 ]]; then - wget -q https://github.com/mit-crpg/WMP_Library/releases/download/v1.0/WMP_Library_v1.0.tar.gz - tar -C $HOME -xzf WMP_Library_v1.0.tar.gz + wget -q https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/WMP_Library_v1.1.tar.gz + tar -C $HOME -xzf WMP_Library_v1.1.tar.gz fi From 5351f723611be28a574d5cb399daa68027538c0c Mon Sep 17 00:00:00 2001 From: liangjg Date: Fri, 19 Oct 2018 16:47:42 -0400 Subject: [PATCH 3/5] openmc reads v1.1 library now --- src/constants.F90 | 3 ++ src/input_xml.F90 | 21 ++++++++--- src/multipole_header.F90 | 77 +++++++++++++++++++++++----------------- src/nuclide_header.F90 | 2 +- 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/src/constants.F90 b/src/constants.F90 index a3118f84da..3e8cbb2dd9 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -17,6 +17,9 @@ module constants ! HDF5 data format integer, parameter :: HDF5_VERSION(2) = [1, 0] + ! WMP data format + integer, parameter :: WMP_VERSION(2) = [1, 1] + ! Version numbers for binary files integer, parameter :: VERSION_STATEPOINT(2) = [17, 0] integer, parameter :: VERSION_PARTICLE_RESTART(2) = [2, 0] diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 81f323351c..f0e8a5fdda 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -22,6 +22,7 @@ module input_xml use mgxs_data, only: create_macro_xs, read_mgxs use mgxs_interface use nuclide_header + use multipole_header use output, only: title, header, print_plot use photon_header use plot_header @@ -3110,7 +3111,9 @@ contains logical :: file_exists ! Does multipole library exist? character(7) :: readable ! Is multipole library readable? - character(MAX_FILE_LEN) :: filename ! Path to multipole xs library + character(MAX_FILE_LEN) :: filename ! Path to multipole xs library + integer(HID_T) :: file_id + integer(HID_T) :: group_id ! For the time being, and I know this is a bit hacky, we just assume ! that the file will be ZZZAAAmM.h5. @@ -3136,14 +3139,22 @@ contains end if ! Display message - call write_message("Loading Multipole XS table: " // filename, 6) + call write_message("Loading Windowed Multipole XS from " // filename, 6) + ! Open file and make sure version is sufficient + file_id = file_open(filename, 'r') + call check_wmp_version(file_id) + + ! Read nuclide data from HDF5 + group_id = open_group(file_id, nuc % name) allocate(nuc % multipole) - - ! Call the read routine - call nuc % multipole % from_hdf5(filename) + call nuc % multipole % from_hdf5(group_id) nuc % mp_present = .true. + ! Close the group and file. + call close_group(group_id) + call file_close(file_id) + end associate end subroutine read_multipole_data diff --git a/src/multipole_header.F90 b/src/multipole_header.F90 index 64610e4716..359bb3ac14 100644 --- a/src/multipole_header.F90 +++ b/src/multipole_header.F90 @@ -1,8 +1,9 @@ module multipole_header use constants - use error, only: fatal_error use hdf5_interface + use error, only: fatal_error + use string, only: to_str implicit none @@ -30,17 +31,15 @@ module multipole_header type MultipoleArray - !========================================================================= + character(20) :: name ! name of nuclide, e.g. U235 + ! Isotope Properties + logical :: fissionable ! Is this isotope fissionable? + complex(8), allocatable :: data(:,:) ! Poles and residues + real(8) :: sqrtAWR ! Square root of the atomic + ! weight ratio - logical :: fissionable ! Is this isotope fissionable? - complex(8), allocatable :: data(:,:) ! Poles and residues - real(8) :: sqrtAWR ! Square root of the atomic - ! weight ratio - - !========================================================================= ! Windows - integer :: fit_order ! Order of the fit. 1 linear, ! 2 quadratic, etc. real(8) :: E_min ! Start energy for the windows @@ -53,11 +52,9 @@ module multipole_header real(8), allocatable :: curvefit(:,:,:) ! Contains the fitting function. ! (reaction type, coeff index, ! window index) - integer, allocatable :: broaden_poly(:) ! if 1, broaden, if 0, don't. contains - procedure :: from_hdf5 => multipole_from_hdf5 end type MultipoleArray @@ -65,29 +62,22 @@ module multipole_header contains !=============================================================================== -! FROM_HDF5 loads multipole data from an HDF5 file. +! FROM_HDF5 loads multipole data from a HDF5 file. !=============================================================================== - subroutine multipole_from_hdf5(this, filename) + subroutine multipole_from_hdf5(this, group_id) class(MultipoleArray), intent(inout) :: this - character(len=*), intent(in) :: filename + integer(HID_T), intent(in) :: group_id - character(len=10) :: version integer :: n_poles, n_residues, n_windows integer(HSIZE_T) :: dims_1d(1), dims_2d(2), dims_3d(3) - integer(HID_T) :: file_id - integer(HID_T) :: group_id integer(HID_T) :: dset - ! Open file for reading and move into the /isotope group - file_id = file_open(filename, 'r', parallel=.true.) - group_id = open_group(file_id, "/nuclide") + ! Get name of nuclide from group + this % name = get_name(group_id) - ! Check the file version number. - call read_dataset(version, file_id, "version") - if (version /= VERSION_MULTIPOLE) call fatal_error("The current multipole& - & format version is " // trim(VERSION_MULTIPOLE) // " but the file "& - // trim(filename) // " uses version " // trim(version) // ".") + ! Get rid of leading '/' + this % name = trim(this % name(2:)) ! Read scalar values. call read_dataset(this % spacing, group_id, "spacing") @@ -121,8 +111,8 @@ contains dset = open_dataset(group_id, "broaden_poly") call get_shape(dset, dims_1d) if (dims_1d(1) /= n_windows) call fatal_error("broaden_poly array shape is& - ¬ consistent with the windows array shape in multipole library"& - // trim(filename) // ".") + ¬ consistent with the windows array shape in WMP library for"& + // trim(this % name) // ".") allocate(this % broaden_poly(n_windows)) call read_dataset(this % broaden_poly, dset) call close_dataset(dset) @@ -131,15 +121,38 @@ contains dset = open_dataset(group_id, "curvefit") call get_shape(dset, dims_3d) if (dims_3d(3) /= n_windows) call fatal_error("curvefit array shape is not& - &consistent with the windows array shape in multipole library"& - // trim(filename) // ".") + &consistent with the windows array shape in WMP library for"& + // trim(this % name) // ".") allocate(this % curvefit(dims_3d(1), dims_3d(2), dims_3d(3))) call read_dataset(this % curvefit, dset) call close_dataset(dset) this % fit_order = int(dims_3d(2), 4) - 1 - ! Close the group and file. - call close_group(group_id) - call file_close(file_id) end subroutine multipole_from_hdf5 + +!=============================================================================== +! CHECK_WMP_VERSION checks for the right version of WMP data within HDF5 +! files +!=============================================================================== + + subroutine check_wmp_version(file_id) + integer(HID_T), intent(in) :: file_id + + integer, allocatable :: version(:) + + if (attribute_exists(file_id, 'version')) then + call read_attribute(version, file_id, 'version') + if (version(1) /= WMP_VERSION(1)) then + call fatal_error("WMP data format uses version " // trim(to_str(& + version(1))) // "." // trim(to_str(version(2))) // " whereas & + &your installation of OpenMC expects version " // trim(to_str(& + WMP_VERSION(1))) // ".x data.") + end if + else + call fatal_error("WMP data does not indicate a version. Your & + &installation of OpenMC expects version " // trim(to_str(& + WMP_VERSION(1))) // ".x data.") + end if + end subroutine check_wmp_version + end module multipole_header diff --git a/src/nuclide_header.F90 b/src/nuclide_header.F90 index 341ff6511c..da66aea4a1 100644 --- a/src/nuclide_header.F90 +++ b/src/nuclide_header.F90 @@ -53,7 +53,7 @@ module nuclide_header type :: Nuclide ! Nuclide meta-data - character(20) :: name ! name of nuclide, e.g. U235.71c + character(20) :: name ! name of nuclide, e.g. U235 integer :: Z ! atomic number integer :: A ! mass number integer :: metastable ! metastable state From e2dc2cee43224c3a5a9fc19641c3b724509e72be Mon Sep 17 00:00:00 2001 From: liangjg Date: Fri, 19 Oct 2018 16:48:12 -0400 Subject: [PATCH 4/5] update python api for wmp v1.1 --- examples/jupyter/nuclear-data.ipynb | 2 +- openmc/data/__init__.py | 4 +- openmc/data/multipole.py | 58 ++++++++++++++++++++--------- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/examples/jupyter/nuclear-data.ipynb b/examples/jupyter/nuclear-data.ipynb index 91923faa1d..f1c4c2b2af 100644 --- a/examples/jupyter/nuclear-data.ipynb +++ b/examples/jupyter/nuclear-data.ipynb @@ -1466,7 +1466,7 @@ }, "outputs": [], "source": [ - "url = 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.0/092238.h5'\n", + "url = 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/092238.h5'\n", "filename, headers = urllib.request.urlretrieve(url, '092238.h5')" ] }, diff --git a/openmc/data/__init__.py b/openmc/data/__init__.py index dec11cd3a9..9aff59444d 100644 --- a/openmc/data/__init__.py +++ b/openmc/data/__init__.py @@ -4,7 +4,9 @@ HDF5_VERSION_MINOR = 0 HDF5_VERSION = (HDF5_VERSION_MAJOR, HDF5_VERSION_MINOR) # Version of WMP nuclear data format -WMP_VERSION = 'v1.0' +WMP_VERSION_MAJOR = 1 +WMP_VERSION_MINOR = 1 +WMP_VERSION = (WMP_VERSION_MAJOR, WMP_VERSION_MINOR) from .data import * diff --git a/openmc/data/multipole.py b/openmc/data/multipole.py index a0d90ac019..5d34c9ff6e 100644 --- a/openmc/data/multipole.py +++ b/openmc/data/multipole.py @@ -4,7 +4,7 @@ from math import exp, erf, pi, sqrt import h5py import numpy as np -from . import WMP_VERSION +from . import WMP_VERSION, WMP_VERSION_MAJOR from .data import K_BOLTZMANN import openmc.checkvalue as cv from openmc.mixin import EqualityMixin @@ -133,6 +133,8 @@ class WindowedMultipole(EqualityMixin): Parameters ---------- + name : str + Name of the nuclide using the GND naming convention Attributes ---------- @@ -171,7 +173,8 @@ class WindowedMultipole(EqualityMixin): a/E + b/sqrt(E) + c + d sqrt(E) + ... """ - def __init__(self): + def __init__(self, name): + self.name = name self.spacing = None self.sqrtAWR = None self.E_min = None @@ -181,6 +184,10 @@ class WindowedMultipole(EqualityMixin): self.broaden_poly = None self.curvefit = None + @property + def name(self): + return self._name + @property def fit_order(self): return self.curvefit.shape[1] - 1 @@ -221,6 +228,11 @@ class WindowedMultipole(EqualityMixin): def curvefit(self): return self._curvefit + @name.setter + def name(self, name): + cv.check_type('name', name, str) + self._name = name + @spacing.setter def spacing(self, spacing): if spacing is not None: @@ -322,17 +334,25 @@ class WindowedMultipole(EqualityMixin): group = group_or_filename else: h5file = h5py.File(group_or_filename, 'r') - try: - version = h5file['version'].value.decode() - except AttributeError: - version = h5file['version'].value[0].decode() - if version != WMP_VERSION: - raise ValueError('The given WMP data uses version ' - + version + ' whereas your installation of the OpenMC ' - 'Python API expects version ' + WMP_VERSION) - group = h5file['nuclide'] - out = cls() + # Make sure version matches + if 'version' in h5file.attrs: + major, minor = h5file.attrs['version'] + if major != WMP_VERSION_MAJOR: + raise IOError( + 'WMP data format uses version {}. {} whereas your ' + 'installation of the OpenMC Python API expects version ' + '{}.x.'.format(major, minor, WMP_VERSION_MAJOR)) + else: + raise IOError( + 'WMP data does not indicate a version. Your installation of ' + 'the OpenMC Python API expects version {}.x data.' + .format(WMP_VERSION_MAJOR)) + + group = list(h5file.values())[0] + + name = group.name[1:] + out = cls(name) # Read scalars. @@ -478,13 +498,16 @@ class WindowedMultipole(EqualityMixin): fun = np.vectorize(lambda x: self._evaluate(x, T)) return fun(E) - def export_to_hdf5(self, path, libver='earliest'): + def export_to_hdf5(self, path, mode='a', libver='earliest'): """Export windowed multipole data to an HDF5 file. Parameters ---------- path : str Path to write HDF5 file to + mode : {'r', r+', 'w', 'x', 'a'} + Mode that is used to open the HDF5 file. This is the second argument + to the :class:`h5py.File` constructor. libver : {'earliest', 'latest'} Compatibility mode for the HDF5 file. 'latest' will produce files that are less backwards compatible but have performance benefits. @@ -492,12 +515,11 @@ class WindowedMultipole(EqualityMixin): """ # Open file and write version. - with h5py.File(path, 'w', libver=libver) as f: - f.create_dataset('version', (1, ), dtype='S10') - f['version'][:] = WMP_VERSION.encode('ASCII') + with h5py.File(path, mode, libver=libver) as f: + f.attrs['filetype'] = np.string_('data_wmp') + f.attrs['version'] = np.array(WMP_VERSION) - # Make a nuclide group. - g = f.create_group('nuclide') + g = f.create_group(self.name) # Write scalars. g.create_dataset('spacing', data=np.array(self.spacing)) From c5146cdedbad4d8d85ac7c013dfc41c438428dde Mon Sep 17 00:00:00 2001 From: liangjg Date: Fri, 19 Oct 2018 19:32:23 -0400 Subject: [PATCH 5/5] remove unused variable --- src/constants.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/constants.F90 b/src/constants.F90 index 3e8cbb2dd9..250b1ef376 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -28,7 +28,6 @@ module constants integer, parameter :: VERSION_VOLUME(2) = [1, 0] integer, parameter :: VERSION_VOXEL(2) = [1, 0] integer, parameter :: VERSION_MGXS_LIBRARY(2) = [1, 0] - character(10), parameter :: VERSION_MULTIPOLE = "v1.0" ! ============================================================================ ! ADJUSTABLE PARAMETERS