diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 63ca703003..f2fa223c89 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -74,16 +74,12 @@ The current revision of the statepoint file format is 16.0. **/tallies/** :Attributes: - **n_tallies** (*int*) -- Number of user-defined tallies. - -:Datasets: - **ids** (*int[]*) -- Internal unique ID of each tally. - - **keys** (*int[]*) -- User-defined unique ID of each tally. + - **ids** (*int[]*) -- User-defined unique ID of each tally. **/tallies/meshes/** :Attributes: - **n_meshes** (*int*) -- Number of meshes in the problem. - -:Datasets: - **ids** (*int[]*) -- Internal unique ID of each mesh. - - **keys** (*int[]*) -- User-identified unique ID of each mesh. + - **ids** (*int[]*) -- User-identified unique ID of each mesh. **/tallies/meshes/mesh /** diff --git a/docs/source/io_formats/summary.rst b/docs/source/io_formats/summary.rst index 28aca93498..671fa33348 100644 --- a/docs/source/io_formats/summary.rst +++ b/docs/source/io_formats/summary.rst @@ -120,7 +120,7 @@ The current version of the summary file format is 5.0. material, e.g., 'U235'. - **nuclide_densities** (*double[]*) -- Atom density of each nuclide. - **sab_names** (*char[][]*) -- Names of - S(:math:`\alpha`,:math:`\beta`) tables assigned to the material. + S(:math:`\alpha,\beta`) tables assigned to the material. **/nuclides/** diff --git a/openmc/statepoint.py b/openmc/statepoint.py index c3436ceb57..3354181fd5 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -111,6 +111,8 @@ class StatePoint(object): def __init__(self, filename, autolink=True): self._f = h5py.File(filename, 'r') + self._meshes = {} + self._tallies = {} # Check filetype and version cv.check_filetype_version(self._f, 'statepoint', _VERSION_STATEPOINT) @@ -256,27 +258,14 @@ class StatePoint(object): @property def meshes(self): if not self._meshes_read: - # Initialize dictionaries for the Meshes - # Keys - Mesh IDs - # Values - Mesh objects - self._meshes = {} - - # Read the number of Meshes - n_meshes = self._f['tallies/meshes'].attrs['n_meshes'] - - # Read a list of the IDs for each Mesh - if n_meshes > 0: - # User-defined Mesh IDs - mesh_keys = self._f['tallies/meshes/keys'].value - else: - mesh_keys = [] + mesh_group = self._f['tallies/meshes'] # Iterate over all Meshes - for mesh_key in mesh_keys: - group = self._f['tallies/meshes/mesh {}'.format(mesh_key)] + for key, group in mesh_group.items(): + mesh_id = int(key.lstrip('mesh ')) # Read and assign mesh properties - mesh = openmc.Mesh(mesh_key) + mesh = openmc.Mesh(mesh_id) mesh.type = group['type'].value.decode() mesh.dimension = group['dimension'].value mesh.lower_left = group['lower_left'].value @@ -284,7 +273,7 @@ class StatePoint(object): mesh.width = group['width'].value # Add mesh to the global dictionary of all Meshes - self._meshes[mesh_key] = mesh + self._meshes[mesh_id] = mesh self._meshes_read = True @@ -340,30 +329,27 @@ class StatePoint(object): @property def tallies(self): - if not self._tallies_read: - # Initialize dictionary for tallies - self._tallies = {} - + if self.tallies_present and not self._tallies_read: # Read the number of tallies - n_tallies = self._f['tallies'].attrs['n_tallies'] + tallies_group = self._f['tallies'] + n_tallies = tallies_group.attrs['n_tallies'] # Read a list of the IDs for each Tally if n_tallies > 0: - # OpenMC Tally IDs (redefined internally from user definitions) - tally_keys = self._f['tallies/keys'].value + # Tally used-defined IDs + tally_ids = tallies_group.attrs['ids'] else: - tally_keys = [] + tally_ids = [] - # Iterate over all Tallies - for tally_key in tally_keys: - group = self._f['tallies/tally {}'.format(tally_key)] + # Iterate over all tallies + for tally_id in tally_ids: + group = tallies_group['tally {}'.format(tally_id)] - - # Read the Tally size specifications + # Read the number of realizations n_realizations = group['n_realizations'].value # Create Tally object and assign basic properties - tally = openmc.Tally(tally_id=tally_key) + tally = openmc.Tally(tally_id) tally._sp_filename = self._f.filename tally.name = group['name'].value.decode() tally.estimator = group['estimator'].value.decode() @@ -416,7 +402,7 @@ class StatePoint(object): # Add Tally to the global dictionary of all Tallies tally.sparse = self.sparse - self._tallies[tally_key] = tally + self._tallies[tally_id] = tally self._tallies_read = True diff --git a/src/state_point.F90 b/src/state_point.F90 index ee7c7bf528..fcbe9f6daf 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -16,7 +16,6 @@ module state_point use hdf5 use constants - use dict_header, only: ElemKeyValueII, ElemKeyValueCI use endf, only: reaction_name use error, only: fatal_error, warning use global @@ -50,10 +49,7 @@ contains runtime_group character(MAX_WORD_LEN), allocatable :: str_array(:) character(MAX_FILE_LEN) :: filename - type(RegularMesh), pointer :: meshp type(TallyObject), pointer :: tally - type(ElemKeyValueII), pointer :: current - type(ElemKeyValueII), pointer :: next ! Set filename for state point filename = trim(path_output) // 'statepoint.' // & @@ -149,49 +145,32 @@ contains call write_attribute(meshes_group, "n_meshes", n_meshes) if (n_meshes > 0) then - - ! Print list of mesh IDs - current => mesh_dict % keys() - + ! Write IDs of meshes allocate(id_array(n_meshes)) - allocate(key_array(n_meshes)) - i = 1 - - do while (associated(current)) - key_array(i) = current % key - id_array(i) = current % value - - ! Move to next mesh - next => current % next - deallocate(current) - current => next - i = i + 1 + do i = 1, n_meshes + id_array(i) = meshes(i) % id end do - - call write_dataset(meshes_group, "ids", id_array) - call write_dataset(meshes_group, "keys", key_array) - - deallocate(key_array) + call write_attribute(meshes_group, "ids", id_array) + deallocate(id_array) ! Write information for meshes MESH_LOOP: do i = 1, n_meshes - meshp => meshes(id_array(i)) - mesh_group = create_group(meshes_group, "mesh " & - // trim(to_str(meshp % id))) + associate (m => meshes(i)) + mesh_group = create_group(meshes_group, "mesh " & + // trim(to_str(m % id))) - select case (meshp % type) - case (MESH_REGULAR) - call write_dataset(mesh_group, "type", "regular") - end select - call write_dataset(mesh_group, "dimension", meshp % dimension) - call write_dataset(mesh_group, "lower_left", meshp % lower_left) - call write_dataset(mesh_group, "upper_right", meshp % upper_right) - call write_dataset(mesh_group, "width", meshp % width) + select case (m % type) + case (MESH_REGULAR) + call write_dataset(mesh_group, "type", "regular") + end select + call write_dataset(mesh_group, "dimension", m % dimension) + call write_dataset(mesh_group, "lower_left", m % lower_left) + call write_dataset(mesh_group, "upper_right", m % upper_right) + call write_dataset(mesh_group, "width", m % width) - call close_group(mesh_group) + call close_group(mesh_group) + end associate end do MESH_LOOP - - deallocate(id_array) end if call close_group(meshes_group) @@ -232,22 +211,13 @@ contains call write_attribute(tallies_group, "n_tallies", n_tallies) if (n_tallies > 0) then - - ! Print list of tally IDs + ! Write array of tally IDs allocate(id_array(n_tallies)) - allocate(key_array(n_tallies)) - - ! Write all tally information except results do i = 1, n_tallies - tally => tallies(i) - key_array(i) = tally % id - id_array(i) = i + id_array(i) = tallies(i) % id end do - - call write_dataset(tallies_group, "ids", id_array) - call write_dataset(tallies_group, "keys", key_array) - - deallocate(key_array) + call write_attribute(tallies_group, "ids", id_array) + deallocate(id_array) ! Write all tally information except results TALLY_METADATA: do i = 1, n_tallies @@ -525,10 +495,6 @@ contains #ifdef MPI real(8) :: dummy ! temporary receive buffer for non-root reduces #endif - integer, allocatable :: id_array(:) - type(ElemKeyValueII), pointer :: current - type(ElemKeyValueII), pointer :: next - type(TallyObject), pointer :: tally type(TallyObject) :: dummy_tally ! ========================================================================== @@ -575,83 +541,65 @@ contains ! Indicate that tallies are on if (master) then call write_attribute(file_id, "tallies_present", 1) - - ! Build list of tally IDs - current => tally_dict%keys() - allocate(id_array(n_tallies)) - i = 1 - - do while (associated(current)) - id_array(i) = current%value - ! Move to next tally - next => current%next - deallocate(current) - current => next - i = i + 1 - end do - end if ! Write all tally results TALLY_RESULTS: do i = 1, n_tallies + associate (t => tallies(i)) + ! Determine size of tally results array + m = size(t % results, 2) + n = size(t % results, 3) + n_bins = m*n*2 - tally => tallies(i) + ! Allocate array for storing sums and sums of squares, but + ! contiguously in memory for each + allocate(tally_temp(2,m,n)) + tally_temp(1,:,:) = t % results(RESULT_SUM,:,:) + tally_temp(2,:,:) = t % results(RESULT_SUM_SQ,:,:) - ! Determine size of tally results array - m = size(tally%results, 2) - n = size(tally%results, 3) - n_bins = m*n*2 + if (master) then + tally_group = open_group(tallies_group, "tally " // & + trim(to_str(t % id))) - ! Allocate array for storing sums and sums of squares, but - ! contiguously in memory for each - allocate(tally_temp(2,m,n)) - tally_temp(1,:,:) = tally%results(RESULT_SUM,:,:) - tally_temp(2,:,:) = tally%results(RESULT_SUM_SQ,:,:) - - if (master) then - tally_group = open_group(tallies_group, "tally " // & - trim(to_str(tally%id))) - - ! The MPI_IN_PLACE specifier allows the master to copy values into - ! a receive buffer without having a temporary variable + ! The MPI_IN_PLACE specifier allows the master to copy values into + ! a receive buffer without having a temporary variable #ifdef MPI - call MPI_REDUCE(MPI_IN_PLACE, tally_temp, n_bins, MPI_REAL8, & - MPI_SUM, 0, mpi_intracomm, mpi_err) + call MPI_REDUCE(MPI_IN_PLACE, tally_temp, n_bins, MPI_REAL8, & + MPI_SUM, 0, mpi_intracomm, mpi_err) #endif - ! At the end of the simulation, store the results back in the - ! regular TallyResults array - if (current_batch == n_max_batches .or. satisfy_triggers) then - tally%results(RESULT_SUM,:,:) = tally_temp(1,:,:) - tally%results(RESULT_SUM_SQ,:,:) = tally_temp(2,:,:) + ! At the end of the simulation, store the results back in the + ! regular TallyResults array + if (current_batch == n_max_batches .or. satisfy_triggers) then + t % results(RESULT_SUM,:,:) = tally_temp(1,:,:) + t % results(RESULT_SUM_SQ,:,:) = tally_temp(2,:,:) + end if + + ! Put in temporary tally result + allocate(dummy_tally % results(3,m,n)) + dummy_tally % results(RESULT_SUM,:,:) = tally_temp(1,:,:) + dummy_tally % results(RESULT_SUM_SQ,:,:) = tally_temp(2,:,:) + + ! Write reduced tally results to file + call dummy_tally % write_results_hdf5(tally_group) + + ! Deallocate temporary tally result + deallocate(dummy_tally % results) + else + ! Receive buffer not significant at other processors +#ifdef MPI + call MPI_REDUCE(tally_temp, dummy, n_bins, MPI_REAL8, MPI_SUM, & + 0, mpi_intracomm, mpi_err) +#endif end if - ! Put in temporary tally result - allocate(dummy_tally % results(3,m,n)) - dummy_tally % results(RESULT_SUM,:,:) = tally_temp(1,:,:) - dummy_tally % results(RESULT_SUM_SQ,:,:) = tally_temp(2,:,:) + ! Deallocate temporary copy of tally results + deallocate(tally_temp) - ! Write reduced tally results to file - call dummy_tally % write_results_hdf5(tally_group) - - ! Deallocate temporary tally result - deallocate(dummy_tally % results) - else - ! Receive buffer not significant at other processors -#ifdef MPI - call MPI_REDUCE(tally_temp, dummy, n_bins, MPI_REAL8, MPI_SUM, & - 0, mpi_intracomm, mpi_err) -#endif - end if - - ! Deallocate temporary copy of tally results - deallocate(tally_temp) - - if (master) call close_group(tally_group) + if (master) call close_group(tally_group) + end associate end do TALLY_RESULTS - deallocate(id_array) - if (master) call close_group(tallies_group) else ! Indicate that tallies are off @@ -677,7 +625,6 @@ contains real(8) :: real_array(3) logical :: source_present character(MAX_WORD_LEN) :: word - type(TallyObject), pointer :: tally ! Write message call write_message("Loading state point " // trim(path_state_point) & @@ -809,16 +756,15 @@ contains tallies_group = open_group(file_id, "tallies") TALLY_RESULTS: do i = 1, n_tallies - ! Set pointer to tally - tally => tallies(i) - - ! Read sum, sum_sq, and N for each bin - tally_group = open_group(tallies_group, "tally " // & - trim(to_str(tally % id))) - call tally % read_results_hdf5(tally_group) - call read_dataset(tally % n_realizations, tally_group, & - "n_realizations") - call close_group(tally_group) + associate (t => tallies(i)) + ! Read sum, sum_sq, and N for each bin + tally_group = open_group(tallies_group, "tally " // & + trim(to_str(t % id))) + call t % read_results_hdf5(tally_group) + call read_dataset(t % n_realizations, tally_group, & + "n_realizations") + call close_group(tally_group) + end associate end do TALLY_RESULTS call close_group(tallies_group)