From c00834dbb6cbaa2e287f6f5645d69f317ef3ba30 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 29 Aug 2015 16:31:29 +0700 Subject: [PATCH 01/95] Make sure Fortran module directory is included. Get rid of verbose option. --- CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd122a14c..c4a8e8ece 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,9 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/include) +# Make sure Fortran module directory is included when building +include_directories(${CMAKE_BINARY_DIR}/include) + #=============================================================================== # Architecture specific definitions #=============================================================================== @@ -23,13 +26,9 @@ option(openmp "Enable shared-memory parallelism with OpenMP" OFF) option(profile "Compile with profiling flags" OFF) option(debug "Compile with debug flags" OFF) option(optimize "Turn on all compiler optimization flags" OFF) -option(verbose "Create verbose Makefiles" OFF) option(coverage "Compile with coverage analysis flags" OFF) option(mpif08 "Use Fortran 2008 MPI interface" OFF) -if (verbose) - set(CMAKE_VERBOSE_MAKEFILE on) -endif() # Maximum number of nested coordinates levels set(maxcoord 10 CACHE STRING "Maximum number of nested coordinate levels") From ab59b90cfee9a62c61ac06696fa43485b2edc2d9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 29 Aug 2015 16:32:02 +0700 Subject: [PATCH 02/95] Use lists for f90flags and ldflags instead of space-separated strings --- CMakeLists.txt | 115 ++++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4a8e8ece..e4452d323 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,21 @@ endif() # Set compile/link flags based on which compiler is being used #=============================================================================== -if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") +# Support for Fortran in FindOpenMP was added in CMake 3.1. To support lower +# versions, we manually add the flags. However, at some point in time, the +# manual logic can be removed in favor of the block below + +#if(NOT (CMAKE_VERSION VERSION_LESS 3.1)) +# if(openmp) +# find_package(OpenMP) +# if(OPENMP_FOUND) +# list(APPEND f90flags ${OpenMP_Fortran_FLAGS}) +# list(APPEND ldflags ${OpenMP_Fortran_FLAGS}) +# endif() +# endif() +#endif() + +if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU) # Make sure version is sufficient execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) @@ -74,88 +88,90 @@ if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") endif() # GNU Fortran compiler options - set(f90flags "-cpp -std=f2008 -fbacktrace") + list(APPEND f90flags -cpp -std=f2008 -fbacktrace) if(debug) - set(f90flags "-g -Wall -pedantic -fbounds-check -ffpe-trap=invalid,overflow,underflow ${f90flags}") - set(ldflags "-g") + list(APPEND f90flags -g -Wall -pedantic -fbounds-check + -ffpe-trap=invalid,overflow,underflow) + list(APPEND ldflags -g) endif() if(profile) - set(f90flags "-pg ${f90flags}") - set(ldflags "-pg ${ldflags}") + list(APPEND f90flags -pg) + list(APPEND ldflags -pg) endif() if(optimize) - set(f90flags "-O3 ${f90flags}") + list(APPEND f90flags -O3) endif() if(openmp) - set(f90flags "-fopenmp ${f90flags}") - set(ldflags "-fopenmp ${ldflags}") + list(APPEND f90flags -fopenmp) + list(APPEND ldflags -fopenmp) endif() if(coverage) - set(f90flags "-coverage ${f90flags}") - set(ldflags "-coverage ${ldflags}") + list(APPEND f90flags -coverage) + list(APPEND ldflags -coverage) endif() -elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel") +elseif(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) # Intel Fortran compiler options - set(f90flags "-fpp -std08 -assume byterecl -traceback") + list(APPEND f90flags -fpp -std08 -assume byterecl -traceback) if(debug) - set(f90flags "-g -warn -ftrapuv -fp-stack-check -check all -fpe0 ${f90flags}") - set(ldflags "-g") + list(APPEND f90flags -g -warn -ftrapuv -fp-stack-check + "-check all" -fpe0) + list(APPEND ldflags -g) endif() if(profile) - set(f90flags "-pg ${f90flags}") - set(ldflags "-pg ${ldflags}") + list(APPEND f90flags -pg) + list(APPEND ldflags -pg) endif() if(optimize) - set(f90flags "-O3 ${f90flags}") + list(APPEND f90flags -O3) endif() if(openmp) - set(f90flags "-openmp ${f90flags}") - set(ldflags "-openmp ${ldflags}") + list(APPEND f90flags -openmp) + list(APPEND ldflags -openmp) endif() -elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "PGI") +elseif(CMAKE_Fortran_COMPILER_ID STREQUAL PGI) # PGI Fortran compiler options - set(f90flags "-Mpreprocess -Minform=inform -traceback") + list(APPEND f90flags -Mpreprocess -Minform=inform -traceback) add_definitions(-DNO_F2008) if(debug) - set(f90flags "-g -Mbounds -Mchkptr -Mchkstk ${f90flags}") - set(ldflags "-g") + list(APPEND f90flags -g -Mbounds -Mchkptr -Mchkstk) + list(APPEND ldflags -g) endif() if(profile) - set(f90flags "-pg ${f90flags}") - set(ldflags "-pg ${ldflags}") + list(APPEND f90flags -pg) + list(APPEND ldflags -pg) endif() if(optimize) - set(f90flags "-fast -Mipa ${f90flags}") + list(APPEND f90flags -fast -Mipa) endif() -elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "XL") +elseif(CMAKE_Fortran_COMPILER_ID STREQUAL XL) # IBM XL compiler options - set(f90flags "-O2") + list(APPEND f90flags -O2) add_definitions(-DNO_F2008) if(debug) - set(f90flags "-g -C -qflag=i:i -u") - set(ldflags "-g") + list(APPEND f90flags -g -C -qflag=i:i -u) + list(APPEND ldflags -g) endif() if(profile) - set(f90flags "-p ${f90flags}") - set(ldflags "-p ${ldflags}") + list(APPEND f90flags -p) + list(APPEND ldflags -p) endif() if(optimize) - set(f90flags "-O3 ${f90flags}") + list(APPEND f90flags -O3) endif() if(openmp) - set(f90flags "-qsmp=omp ${f90flags}") - set(ldflags "-qsmp=omp ${ldflags}") + list(APPEND f90flags -qsmp=omp) + list(APPEND ldflags -qsmp=omp) endif() -elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Cray") +elseif(CMAKE_Fortran_COMPILER_ID STREQUAL Cray) # Cray Fortran compiler options - set(f90flags "-e Z -m 0") + list(APPEND f90flags -e Z -m 0) if(debug) - set(f90flags "-g -R abcnsp -O0 ${f90flags}") - set(ldflags "-g") + list(APPEND f90flags -g -R abcnsp -O0) + list(APPEND ldflags -g) endif() endif() @@ -203,10 +219,21 @@ add_subdirectory(src/xml/fox) set(program "openmc") file(GLOB source src/*.F90 src/xml/openmc_fox.F90) add_executable(${program} ${source}) -target_link_libraries(${program} ${libraries} fox_dom) -set_target_properties(${program} PROPERTIES - COMPILE_FLAGS "${f90flags}" - LINK_FLAGS "${ldflags}") + +# target_compile_options was added in CMake 2.8.12 and is the recommended way to +# set compile flags. Note that this sets the COMPILE_OPTIONS property (also +# available only in 2.8.12+) rather than the COMPILE_FLAGS property, which is +# deprecated. The former can handle lists whereas the latter cannot. +if(CMAKE_VERSION VERSION_LESS 4.8.12) + string(REPLACE ";" " " f90flags "${f90flags}") + set_property(TARGET ${program} PROPERTY COMPILE_FLAGS "${f90flags}") +else() + target_compile_options(${program} PUBLIC ${f90flags}) +endif() + +# target_link_libraries treats any arguments starting with - but not -l as +# linker flags. Thus, we can pass both linker flags and libraries together. +target_link_libraries(${program} ${ldflags} ${libraries} fox_dom) #=============================================================================== # Install executable, scripts, manpage, license From e93afed7a08be46e4b95f58f0384d6590750a2a7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 16 Jul 2015 18:56:35 +0400 Subject: [PATCH 03/95] Make HDF5 only binary output option in source and Python API. Still need to update test suite and get rid of output_interface. --- openmc/particle_restart.py | 38 +-- openmc/statepoint.py | 80 +---- src/finalize.F90 | 4 - src/global.F90 | 4 - src/hdf5_interface.F90 | 4 - src/hdf5_summary.F90 | 4 - src/initialize.F90 | 17 +- src/output.F90 | 92 ----- src/output_interface.F90 | 599 +++++---------------------------- src/particle_restart_write.F90 | 4 - src/source.F90 | 4 - src/state_point.F90 | 23 +- src/track_output.F90 | 6 - 13 files changed, 109 insertions(+), 770 deletions(-) diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py index d664de1ae..5ae534dbd 100644 --- a/openmc/particle_restart.py +++ b/openmc/particle_restart.py @@ -40,13 +40,8 @@ class Particle(object): """ def __init__(self, filename): - if filename.endswith('.h5'): - import h5py - self._f = h5py.File(filename, 'r') - self._hdf5 = True - else: - self._f = open(filename, 'rb') - self._hdf5 = False + import h5py + self._f = h5py.File(filename, 'r') # Read all metadata self._read_data() @@ -74,36 +69,17 @@ class Particle(object): self.xyz = self._get_double(3, path='xyz') self.uvw = self._get_double(3, path='uvw') - def _get_data(self, n, typeCode, size): - return list(struct.unpack('={0}{1}'.format(n, typeCode), - self._f.read(n*size))) - def _get_int(self, n=1, path=None): - if self._hdf5: - return [int(v) for v in self._f[path].value] - else: - return [int(v) for v in self._get_data(n, 'i', 4)] + return [int(v) for v in self._f[path].value] def _get_long(self, n=1, path=None): - if self._hdf5: - return [int(v) for v in self._f[path].value] - else: - return [int(v) for v in self._get_data(n, 'q', 8)] + return [int(v) for v in self._f[path].value] def _get_float(self, n=1, path=None): - if self._hdf5: - return [float(v) for v in self._f[path].value] - else: - return [float(v) for v in self._get_data(n, 'f', 4)] + return [float(v) for v in self._f[path].value] def _get_double(self, n=1, path=None): - if self._hdf5: - return [float(v) for v in self._f[path].value] - else: - return [float(v) for v in self._get_data(n, 'd', 8)] + return [float(v) for v in self._f[path].value] def _get_string(self, n=1, path=None): - if self._hdf5: - return str(self._f[path].value) - else: - return str(self._get_data(n, 's', 1)[0]) + return str(self._f[path].value) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 6a4713e91..673b41e17 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -92,13 +92,8 @@ class StatePoint(object): """ def __init__(self, filename): - if filename.endswith('.h5'): - import h5py - self._f = h5py.File(filename, 'r') - self._hdf5 = True - else: - self._f = open(filename, 'rb') - self._hdf5 = False + import h5py + self._f = h5py.File(filename, 'r') # Set flags for what data has been read self._results = False @@ -171,12 +166,9 @@ class StatePoint(object): raise Exception('Statepoint Revision is not consistent.') # Read OpenMC version - if self._hdf5: - self._version = [self._get_int(path='version_major')[0], - self._get_int(path='version_minor')[0], - self._get_int(path='version_release')[0]] - else: - self._version = self._get_int(3) + self._version = [self._get_int(path='version_major')[0], + self._get_int(path='version_minor')[0], + self._get_int(path='version_release')[0]] # Read date and time self._date_and_time = self._get_string(19, path='date_and_time') @@ -473,13 +465,8 @@ class StatePoint(object): # Read global Tallies n_global_tallies = self._get_int(path='n_global_tallies')[0] - if self._hdf5: - data = self._f['global_tallies'].value - self._global_tallies = np.column_stack((data['sum'], data['sum_sq'])) - - else: - self._global_tallies = np.array(self._get_double(2*n_global_tallies)) - self._global_tallies.shape = (n_global_tallies, 2) + data = self._f['global_tallies'].value + self._global_tallies = np.column_stack((data['sum'], data['sum_sq'])) # Flag indicating if Tallies are present self._tallies_present = self._get_int(path='tallies/tallies_present')[0] @@ -499,15 +486,9 @@ class StatePoint(object): num_tot_bins = tally.num_bins # Extract Tally data from the file - if self._hdf5: - data = self._f['{0}{1}/results'.format(base, tally_key)].value - sum = data['sum'] - sum_sq = data['sum_sq'] - - else: - results = np.array(self._get_double(2*num_tot_bins)) - sum = results[0::2] - sum_sq = results[1::2] + data = self._f['{0}{1}/results'.format(base, tally_key)].value + sum = data['sum'] + sum_sq = data['sum_sq'] # Define a routine to convert 0 to 1 def nonzero(val): @@ -547,8 +528,7 @@ class StatePoint(object): self._source = np.empty(self._n_particles, dtype=SourceSite) # For HDF5 state points, copy entire bank - if self._hdf5: - source_sites = self._f['source_bank'].value + source_sites = self._f['source_bank'].value # Initialize SourceSite object for each particle for i in range(self._n_particles): @@ -556,13 +536,7 @@ class StatePoint(object): site = SourceSite() # Read position, angle, and energy - if self._hdf5: - site._weight, site._xyz, site._uvw, site._E = source_sites[i] - else: - site._weight = self._get_double()[0] - site._xyz = self._get_double(3) - site._uvw = self._get_double(3) - site._E = self._get_double()[0] + site._weight, site._xyz, site._uvw, site._E = source_sites[i] # Store the source site in the NumPy array self._source[i] = site @@ -798,37 +772,19 @@ class StatePoint(object): self._f.read(n*size))) def _get_int(self, n=1, path=None): - if self._hdf5: - return [int(v) for v in self._f[path].value] - else: - return [int(v) for v in self._get_data(n, 'i', 4)] + return [int(v) for v in self._f[path].value] def _get_long(self, n=1, path=None): - if self._hdf5: - return [long(v) for v in self._f[path].value] - else: - return [long(v) for v in self._get_data(n, 'q', 8)] + return [long(v) for v in self._f[path].value] def _get_float(self, n=1, path=None): - if self._hdf5: - return [float(v) for v in self._f[path].value] - else: - return [float(v) for v in self._get_data(n, 'f', 4)] + return [float(v) for v in self._f[path].value] def _get_double(self, n=1, path=None): - if self._hdf5: - return [float(v) for v in self._f[path].value] - else: - return [float(v) for v in self._get_data(n, 'd', 8)] + return [float(v) for v in self._f[path].value] def _get_double_array(self, n=1, path=None): - if self._hdf5: - return self._f[path].value - else: - return self._get_data(n, 'd', 8) + return self._f[path].value def _get_string(self, n=1, path=None): - if self._hdf5: - return str(self._f[path].value) - else: - return str(self._get_data(n, 's', 1)[0]) + return str(self._f[path].value) diff --git a/src/finalize.F90 b/src/finalize.F90 index aa11f4769..b795cdb4f 100644 --- a/src/finalize.F90 +++ b/src/finalize.F90 @@ -9,9 +9,7 @@ module finalize use message_passing #endif -#ifdef HDF5 use hdf5_interface, only: h5tclose_f, h5close_f, hdf5_err -#endif implicit none @@ -51,14 +49,12 @@ contains ! Deallocate arrays call free_memory() -#ifdef HDF5 ! Release compound datatypes call h5tclose_f(hdf5_tallyresult_t, hdf5_err) call h5tclose_f(hdf5_bank_t, hdf5_err) ! Close FORTRAN interface. call h5close_f(hdf5_err) -#endif #ifdef MPI ! Free all MPI types diff --git a/src/global.F90 b/src/global.F90 index 564fcda84..ae2f5bb27 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -16,9 +16,7 @@ module global use trigger_header, only: KTrigger use timer_header, only: Timer -#ifdef HDF5 use hdf5_interface, only: HID_T -#endif #ifdef MPIF08 use mpi_f08 #endif @@ -270,12 +268,10 @@ module global ! ============================================================================ ! HDF5 VARIABLES -#ifdef HDF5 integer(HID_T) :: hdf5_output_file ! identifier for output file integer(HID_T) :: hdf5_tallyresult_t ! Compound type for TallyResult integer(HID_T) :: hdf5_bank_t ! Compound type for Bank integer(HID_T) :: hdf5_integer8_t ! type for integer(8) -#endif ! ============================================================================ ! MISCELLANEOUS VARIABLES diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 34b72196e..e7ba39b64 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1,7 +1,5 @@ module hdf5_interface -#ifdef HDF5 - use hdf5 use h5lt use, intrinsic :: ISO_C_BINDING @@ -1811,6 +1809,4 @@ contains # endif -#endif - end module hdf5_interface diff --git a/src/hdf5_summary.F90 b/src/hdf5_summary.F90 index 375ab7460..a9dab46f5 100644 --- a/src/hdf5_summary.F90 +++ b/src/hdf5_summary.F90 @@ -1,7 +1,5 @@ module hdf5_summary -#ifdef HDF5 - use ace_header, only: Reaction, UrrData, Nuclide use constants use endf, only: reaction_name @@ -875,6 +873,4 @@ contains end subroutine hdf5_write_timing -#endif - end module hdf5_summary diff --git a/src/initialize.F90 b/src/initialize.F90 index b944b6677..22521b24d 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -15,9 +15,8 @@ module initialize use input_xml, only: read_input_xml, read_cross_sections_xml, & cells_in_univ_dict, read_plots_xml use material_header, only: Material - use output, only: title, header, write_summary, print_version, & - print_usage, write_xs_summary, print_plot, & - write_message + use output, only: title, header, print_version, write_message, & + print_usage, write_xs_summary, print_plot use output_interface use random_lcg, only: initialize_prng use state_point, only: load_state_point @@ -33,10 +32,8 @@ module initialize use omp_lib #endif -#ifdef HDF5 use hdf5_interface use hdf5_summary, only: hdf5_write_summary -#endif implicit none @@ -60,10 +57,8 @@ contains call initialize_mpi() #endif -#ifdef HDF5 ! Initialize HDF5 interface call hdf5_initialize() -#endif ! Read command line arguments call read_command_line() @@ -155,11 +150,7 @@ contains call print_plot() else ! Write summary information -#ifdef HDF5 if (output_summary) call hdf5_write_summary() -#else - if (output_summary) call write_summary() -#endif ! Write cross section information if (output_xs) call write_xs_summary() @@ -275,8 +266,6 @@ contains end subroutine initialize_mpi #endif -#ifdef HDF5 - !=============================================================================== ! HDF5_INITIALIZE !=============================================================================== @@ -319,8 +308,6 @@ contains end subroutine hdf5_initialize -#endif - !=============================================================================== ! READ_COMMAND_LINE reads all parameters from the command line !=============================================================================== diff --git a/src/output.F90 b/src/output.F90 index d1d4ec72a..2ddbf6499 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -1203,98 +1203,6 @@ contains end subroutine print_sab_table -!=============================================================================== -! WRITE_SUMMARY displays summary information about the problem about to be run -! after reading all input files -!=============================================================================== - - subroutine write_summary() - - integer :: i ! loop index - character(MAX_FILE_LEN) :: path ! path of summary file - type(Material), pointer :: m => null() - type(TallyObject), pointer :: t => null() - - ! Create filename for log file - path = trim(path_output) // "summary.out" - - ! Open log file for writing - open(UNIT=UNIT_SUMMARY, FILE=path, STATUS='replace', ACTION='write') - - call header("OpenMC Monte Carlo Code", unit=UNIT_SUMMARY, level=1) - write(UNIT=UNIT_SUMMARY, FMT=*) & - "Copyright: 2011-2015 Massachusetts Institute of Technology" - write(UNIT=UNIT_SUMMARY, FMT='(1X,A,7X,2(I1,"."),I1)') & - "Version:", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE -#ifdef GIT_SHA1 - write(UNIT=UNIT_SUMMARY, FMT='(1X,"Git SHA1:",6X,A)') GIT_SHA1 -#endif - write(UNIT=UNIT_SUMMARY, FMT='(1X,"Date/Time:",5X,A)') & - time_stamp() - - ! Write information on number of processors -#ifdef MPI - write(UNIT=UNIT_SUMMARY, FMT='(1X,"MPI Processes:",1X,A)') & - trim(to_str(n_procs)) -#endif - - ! Display problem summary - call header("PROBLEM SUMMARY", unit=UNIT_SUMMARY) - select case(run_mode) - case (MODE_EIGENVALUE) - write(UNIT_SUMMARY,100) 'Problem type:', 'k eigenvalue' - write(UNIT_SUMMARY,101) 'Number of Batches:', n_batches - write(UNIT_SUMMARY,101) 'Number of Inactive Batches:', n_inactive - write(UNIT_SUMMARY,101) 'Generations per Batch:', gen_per_batch - case (MODE_FIXEDSOURCE) - write(UNIT_SUMMARY,100) 'Problem type:', 'fixed source' - end select - write(UNIT_SUMMARY,101) 'Number of Particles:', n_particles - - ! Display geometry summary - call header("GEOMETRY SUMMARY", unit=UNIT_SUMMARY) - write(UNIT_SUMMARY,101) 'Number of Cells:', n_cells - write(UNIT_SUMMARY,101) 'Number of Surfaces:', n_surfaces - write(UNIT_SUMMARY,101) 'Number of Materials:', n_materials - - ! print summary of all geometry - call print_geometry() - - ! print summary of materials - call header("MATERIAL SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_materials - m => materials(i) - call print_material(m, unit=UNIT_SUMMARY) - end do - - ! print summary of tallies - if (n_tallies > 0) then - call header("TALLY SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_tallies - t=> tallies(i) - call print_tally(t, unit=UNIT_SUMMARY) - end do - end if - - ! print summary of variance reduction - call header("VARIANCE REDUCTION", unit=UNIT_SUMMARY) - if (survival_biasing) then - write(UNIT_SUMMARY,100) "Survival Biasing:", "on" - else - write(UNIT_SUMMARY,100) "Survival Biasing:", "off" - end if - write(UNIT_SUMMARY,100) "Weight Cutoff:", trim(to_str(weight_cutoff)) - write(UNIT_SUMMARY,100) "Survival weight:", trim(to_str(weight_survive)) - - ! Close summary file - close(UNIT_SUMMARY) - - ! Format descriptor for columns -100 format (1X,A,T35,A) -101 format (1X,A,T35,I11) - - end subroutine write_summary - !=============================================================================== ! WRITE_XS_SUMMARY writes information about each nuclide and S(a,b) table to a ! file called cross_sections.out. This file shows the list of reactions as well diff --git a/src/output_interface.F90 b/src/output_interface.F90 index 05fcd0010..f56a4b339 100644 --- a/src/output_interface.F90 +++ b/src/output_interface.F90 @@ -5,12 +5,9 @@ module output_interface use global use tally_header, only: TallyResult -#ifdef HDF5 use hdf5_interface -#else #ifdef MPI use mpiio_interface -#endif #endif implicit none @@ -19,17 +16,8 @@ module output_interface type, public :: BinaryOutput private ! Compilation specific data -#ifdef HDF5 integer(HID_T) :: hdf5_fh integer(HID_T) :: hdf5_grp -#else - integer :: unit_fh -#ifdef MPIF08 - type(MPI_File) :: mpi_fh -#else - integer :: mpi_fh -#endif -#endif logical :: serial ! Serial I/O when using MPI/PHDF5 contains generic, public :: write_data => write_double, & @@ -87,11 +75,9 @@ module output_interface procedure, public :: read_tally_result => read_tally_result procedure, public :: write_source_bank => write_source_bank procedure, public :: read_source_bank => read_source_bank -#ifdef HDF5 procedure, public :: write_attribute_string => write_attribute_string procedure, public :: open_group => open_group procedure, public :: close_group => close_group -#endif end type BinaryOutput contains @@ -113,26 +99,14 @@ contains self % serial = .true. end if -#ifdef HDF5 -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_file_create(filename, self % hdf5_fh) else call hdf5_file_create_parallel(filename, self % hdf5_fh) endif -# else - call hdf5_file_create(filename, self % hdf5_fh) -# endif -#elif MPI - if (self % serial) then - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION="write", & - STATUS='replace', ACCESS='stream') - else - call mpi_create_file(filename, self % mpi_fh) - end if #else - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION="write", & - STATUS='replace', ACCESS='stream') + call hdf5_file_create(filename, self % hdf5_fh) #endif end subroutine file_create @@ -155,38 +129,14 @@ contains self % serial = .true. end if -#ifdef HDF5 -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_file_open(filename, self % hdf5_fh, mode) else call hdf5_file_open_parallel(filename, self % hdf5_fh, mode) endif -# else - call hdf5_file_open(filename, self % hdf5_fh, mode) -# endif -#elif MPI - if (self % serial) then - ! Check for read/write mode to open, default is read only - if (mode == 'w') then - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION='write', & - STATUS='old', ACCESS='stream', POSITION='append') - else - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION='read', & - STATUS='old', ACCESS='stream') - end if - else - call mpi_open_file(filename, self % mpi_fh, mode) - end if #else - ! Check for read/write mode to open, default is read only - if (mode == 'w') then - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION='write', & - STATUS='old', ACCESS='stream', POSITION='append') - else - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION='read', & - STATUS='old', ACCESS='stream') - end if + call hdf5_file_open(filename, self % hdf5_fh, mode) #endif end subroutine file_open @@ -199,21 +149,7 @@ contains class(BinaryOutput) :: self -#ifdef HDF5 -# ifdef MPI call hdf5_file_close(self % hdf5_fh) -# else - call hdf5_file_close(self % hdf5_fh) -# endif -#elif MPI - if (self % serial) then - close(UNIT=self % unit_fh) - else - call mpi_close_file(self % mpi_fh) - end if -#else - close(UNIT=self % unit_fh) -#endif end subroutine file_close @@ -221,7 +157,6 @@ contains ! OPEN_GROUP call hdf5 routine to open a group within binary output context !=============================================================================== -#ifdef HDF5 subroutine open_group(self, group) character(*), intent(in) :: group ! HDF5 group name @@ -230,13 +165,11 @@ contains call hdf5_open_group(self % hdf5_fh, group, self % hdf5_grp) end subroutine open_group -#endif !=============================================================================== ! CLOSE_GROUP call hdf5 routine to close a group within binary output context !=============================================================================== -#ifdef HDF5 subroutine close_group(self) class(BinaryOutput) :: self @@ -244,7 +177,6 @@ contains call hdf5_close_group(self % hdf5_grp) end subroutine close_group -#endif !=============================================================================== ! WRITE_DOUBLE writes double precision scalar data @@ -277,33 +209,23 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_double(self % hdf5_grp, name_, buffer) else call hdf5_write_double_parallel(self % hdf5_grp, name_, buffer, collect_) end if -# else +#else call hdf5_write_double(self % hdf5_grp, name_, buffer) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer - else - call mpi_write_double(self % mpi_fh, buffer, collect_) - end if -#else - write(self % unit_fh) buffer -#endif end subroutine write_double @@ -338,33 +260,23 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_double(self % hdf5_grp, name_, buffer) else call hdf5_read_double_parallel(self % hdf5_grp, name_, buffer, collect_) end if -# else +#else call hdf5_read_double(self % hdf5_grp, name_, buffer) -# endif +#endif ! Check if HDf5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer - else - call mpi_read_double(self % mpi_fh, buffer, collect_) - end if -#else - read(self % unit_fh) buffer -#endif end subroutine read_double @@ -400,34 +312,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_double_1Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_write_double_1Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_write_double_1Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length) - else - call mpi_write_double_1Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length) -#endif end subroutine write_double_1Darray @@ -463,34 +365,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_double_1Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_read_double_1Darray_parallel(self % hdf5_grp, name_, buffer, & length, collect_) end if -# else +#else call hdf5_read_double_1Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length) - else - call mpi_read_double_1Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length) -#endif end subroutine read_double_1Darray @@ -526,34 +418,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_double_2Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_write_double_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_write_double_2Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2)) - else - call mpi_write_double_2Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2)) -#endif end subroutine write_double_2Darray @@ -589,34 +471,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_double_2Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_read_double_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_read_double_2Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2)) - else - call mpi_read_double_2Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2)) -#endif end subroutine read_double_2Darray @@ -652,34 +524,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_double_3Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_write_double_3Darray_parallel(self % hdf5_grp, name_, buffer, & length, collect_) end if -# else +#else call hdf5_write_double_3Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) - else - call mpi_write_double_3Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) -#endif end subroutine write_double_3Darray @@ -715,34 +577,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_double_3Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_read_double_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_read_double_3Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) - else - call mpi_read_double_3Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) -#endif end subroutine read_double_3Darray @@ -779,37 +631,25 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_double_4Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_write_double_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else ! Write the data in serial call hdf5_write_double_4Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) - else - call mpi_write_double_4Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) -#endif end subroutine write_double_4Darray @@ -846,36 +686,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_double_4Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_read_double_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_read_double_4Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) - else - call mpi_read_double_4Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) -#endif end subroutine read_double_4Darray @@ -910,33 +738,23 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_integer(self % hdf5_grp, name_, buffer) else call hdf5_write_integer_parallel(self % hdf5_grp, name_, buffer, collect_) end if -# else +#else call hdf5_write_integer(self % hdf5_grp, name_, buffer) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer - else - call mpi_write_integer(self % mpi_fh, buffer, collect_) - end if -#else - write(self % unit_fh) buffer -#endif end subroutine write_integer @@ -971,33 +789,23 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_integer(self % hdf5_grp, name_, buffer) else call hdf5_read_integer_parallel(self % hdf5_grp, name_, buffer, collect_) end if -# else +#else call hdf5_read_integer(self % hdf5_grp, name_, buffer) -# endif +#endif ! Check if HDf5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer - else - call mpi_read_integer(self % mpi_fh, buffer, collect_) - end if -#else - read(self % unit_fh) buffer -#endif end subroutine read_integer @@ -1033,34 +841,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_integer_1Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_write_integer_1Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_write_integer_1Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length) - else - call mpi_write_integer_1Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length) -#endif end subroutine write_integer_1Darray @@ -1096,35 +894,25 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_integer_1Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_read_integer_1Darray_parallel(self % hdf5_grp, name_, buffer, & length, collect_) end if -# else +#else ! Read the data in serial call hdf5_read_integer_1Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length) - else - call mpi_read_integer_1Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length) -#endif end subroutine read_integer_1Darray @@ -1160,34 +948,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_integer_2Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_write_integer_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_write_integer_2Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2)) - else - call mpi_write_integer_2Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2)) -#endif end subroutine write_integer_2Darray @@ -1223,34 +1001,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_integer_2Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_read_integer_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_read_integer_2Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2)) - else - call mpi_read_integer_2Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2)) -#endif end subroutine read_integer_2Darray @@ -1286,34 +1054,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_integer_3Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_write_integer_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_write_integer_3Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) - else - call mpi_write_integer_3Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) -#endif end subroutine write_integer_3Darray @@ -1349,34 +1107,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_integer_3Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_read_integer_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_read_integer_3Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) - else - call mpi_read_integer_3Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) -#endif end subroutine read_integer_3Darray @@ -1413,36 +1161,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_integer_4Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_write_integer_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_write_integer_4Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) - else - call mpi_write_integer_4Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) -#endif end subroutine write_integer_4Darray @@ -1479,36 +1215,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_integer_4Darray(self % hdf5_grp, name_, buffer, length) else call hdf5_read_integer_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & collect_) end if -# else +#else call hdf5_read_integer_4Darray(self % hdf5_grp, name_, buffer, length) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) - else - call mpi_read_integer_4Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) -#endif end subroutine read_integer_4Darray @@ -1543,34 +1267,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) else call hdf5_write_long_parallel(self % hdf5_grp, name_, buffer, & hdf5_integer8_t, collect_) end if -# else +#else call hdf5_write_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer - else - call mpi_write_long(self % mpi_fh, buffer, collect_) - end if -#else - write(self % unit_fh) buffer -#endif end subroutine write_long @@ -1605,34 +1319,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) else call hdf5_read_long_parallel(self % hdf5_grp, name_, buffer, & hdf5_integer8_t, collect_) end if -# else +#else call hdf5_read_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer - else - call mpi_read_long(self % mpi_fh, buffer, collect_) - end if -#else - read(self % unit_fh) buffer -#endif end subroutine read_long @@ -1671,34 +1375,24 @@ contains collect_ = .true. end if -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_write_string(self % hdf5_grp, name_, buffer, n) else call hdf5_write_string_parallel(self % hdf5_grp, name_, buffer, n, collect_) end if -# else +#else ! Write the data call hdf5_write_string(self % hdf5_grp, name_, buffer, n) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer - else - call mpi_write_string(self % mpi_fh, buffer, n, collect_) - end if -#else - write(self % unit_fh) buffer -#endif end subroutine write_string @@ -1737,34 +1431,23 @@ contains collect_ = .true. end if - -#ifdef HDF5 ! Check if HDF5 group should be created/opened if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) else self % hdf5_grp = self % hdf5_fh endif -# ifdef MPI +#ifdef MPI if (self % serial) then call hdf5_read_string(self % hdf5_grp, name_, buffer, n) else call hdf5_read_string_parallel(self % hdf5_grp, name_, buffer, n, collect_) end if -# else +#else call hdf5_read_string(self % hdf5_grp, name_, buffer, n) -# endif +#endif ! Check if HDF5 group should be closed if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer - else - call mpi_read_string(self % mpi_fh, buffer, n, collect_) - end if -#else - read(self % unit_fh) buffer -#endif end subroutine read_string @@ -1772,7 +1455,6 @@ contains ! WRITE_ATTRIBUTE_STRING !=============================================================================== -#ifdef HDF5 subroutine write_attribute_string(self, var, attr_type, attr_str, group) character(*), intent(in) :: var ! variable name for attr @@ -1795,7 +1477,6 @@ contains if (present(group)) call hdf5_close_group(self % hdf5_grp) end subroutine write_attribute_string -#endif !=============================================================================== ! WRITE_TALLY_RESULT writes an OpenMC TallyResult type @@ -1812,10 +1493,6 @@ contains character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name -#ifndef HDF5 - integer :: j,k ! iteration counters -#endif - ! Set name name_ = trim(name) @@ -1824,8 +1501,6 @@ contains group_ = trim(group) end if -#ifdef HDF5 - ! Open up sub-group if present if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) @@ -1854,18 +1529,6 @@ contains call hdf5_close_group(self % hdf5_grp) end if -#else - - ! Write out tally buffer - do k = 1, n2 - do j = 1, n1 - write(self % unit_fh) buffer(j,k) % sum - write(self % unit_fh) buffer(j,k) % sum_sq - end do - end do - -#endif - end subroutine write_tally_result !=============================================================================== @@ -1883,12 +1546,6 @@ contains character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name -#ifndef HDF5 -# ifndef MPI - integer :: j,k ! iteration counters -# endif -#endif - ! Set name name_ = trim(name) @@ -1897,8 +1554,6 @@ contains group_ = trim(group) end if -#ifdef HDF5 - ! Open up sub-group if present if (present(group)) then call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) @@ -1917,24 +1572,6 @@ contains call h5dclose_f(dset, hdf5_err) if (present(group)) call hdf5_close_group(self % hdf5_grp) -# elif MPI - - ! Write out tally buffer - call MPI_FILE_READ(self % mpi_fh, buffer, n1*n2, MPI_TALLYRESULT, & - MPI_STATUS_IGNORE, mpiio_err) - -#else - - ! Read tally result - do k = 1, n2 - do j = 1, n1 - read(self % unit_fh) buffer(j,k) % sum - read(self % unit_fh) buffer(j,k) % sum_sq - end do - end do - -#endif - end subroutine read_tally_result !=============================================================================== @@ -1946,21 +1583,9 @@ contains class(BinaryOutput) :: self #ifdef MPI -# ifndef HDF5 - integer(MPI_OFFSET_KIND) :: offset ! offset of data - integer :: size_bank ! size of bank to write -#ifdef MPIF08 - type(MPI_Datatype) :: datatype -#else - integer :: datatype -#endif -# endif -# ifdef HDF5 - integer(8) :: offset(1) ! source data offset -# endif + integer(8) :: offset(1) ! source data offset #endif -#ifdef HDF5 #ifdef MPI ! Set size of total dataspace for all procs and rank @@ -2005,7 +1630,7 @@ contains call h5dclose_f(dset, hdf5_err) call h5pclose_f(plist, hdf5_err) -# else +#else ! Set size dims1(1) = work @@ -2028,31 +1653,6 @@ contains call h5dclose_f(dset, hdf5_err) call h5sclose_f(dspace, hdf5_err) -# endif - -#elif MPI - - ! Get current offset for master - if (master) call MPI_FILE_GET_POSITION(self % mpi_fh, offset, mpiio_err) - - ! Determine offset on master process and broadcast to all processors - call MPI_TYPE_MATCH_SIZE(MPI_TYPECLASS_INTEGER, MPI_OFFSET_KIND, & - datatype, mpi_err) - call MPI_BCAST(offset, 1, datatype, 0, MPI_COMM_WORLD, mpi_err) - - ! Set the proper offset for source data on this processor - call MPI_TYPE_SIZE(MPI_BANK, size_bank, mpi_err) - offset = offset + size_bank*work_index(rank) - - ! Write all source sites - call MPI_FILE_WRITE_AT(self % mpi_fh, offset, source_bank(1), int(work), & - MPI_BANK, MPI_STATUS_IGNORE, mpiio_err) - -#else - - ! Write out source sites - write(self % unit_fh) source_bank - #endif end subroutine write_source_bank @@ -2066,17 +1666,10 @@ contains class(BinaryOutput) :: self #ifdef MPI -# ifndef HDF5 - integer(MPI_OFFSET_KIND) :: offset ! offset of data - integer :: size_bank ! size of bank to read -# endif -# ifdef HDF5 - integer(8) :: offset(1) ! offset of data -# endif + integer(8) :: offset(1) ! offset of data #endif -#ifdef HDF5 -# ifdef MPI +#ifdef MPI ! Set size of total dataspace for all procs and rank dims1(1) = n_particles @@ -2114,7 +1707,7 @@ contains call h5dclose_f(dset, hdf5_err) call h5pclose_f(plist, hdf5_err) -# else +#else ! Open dataset call h5dopen_f(self % hdf5_fh, "source_bank", dset, hdf5_err) @@ -2128,36 +1721,6 @@ contains ! Close all ids call h5dclose_f(dset, hdf5_err) -# endif - -#elif MPI - - ! Go to the end of the file to set file pointer - offset = 0 - call MPI_FILE_SEEK(self % mpi_fh, offset, MPI_SEEK_END, & - mpiio_err) - - ! Get current offset (will be at EOF) - call MPI_FILE_GET_POSITION(self % mpi_fh, offset, mpiio_err) - - ! Get the size of the source bank on all procs - call MPI_TYPE_SIZE(MPI_BANK, size_bank, mpi_err) - - ! Calculate offset where the source bank will begin - offset = offset - n_particles*size_bank - - ! Set the proper offset for source data on this processor - offset = offset + size_bank*work_index(rank) - - ! Write all source sites - call MPI_FILE_READ_AT(self % mpi_fh, offset, source_bank(1), int(work), & - MPI_BANK, MPI_STATUS_IGNORE, mpiio_err) - -#else - - ! Write out source sites - read(self % unit_fh) source_bank - #endif end subroutine read_source_bank diff --git a/src/particle_restart_write.F90 b/src/particle_restart_write.F90 index f138a6740..48b4af661 100644 --- a/src/particle_restart_write.F90 +++ b/src/particle_restart_write.F90 @@ -32,11 +32,7 @@ contains ! Set up file name filename = trim(path_output) // 'particle_' // trim(to_str(current_batch)) & // '_' // trim(to_str(p % id)) -#ifdef HDF5 filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif !$omp critical (WriteParticleRestart) ! Create file diff --git a/src/source.F90 b/src/source.F90 index e82482915..4b0de58b5 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -79,11 +79,7 @@ contains ! Write out initial source if (write_initial_source) then call write_message('Writing out initial source...', 1) -#ifdef HDF5 filename = trim(path_output) // 'initial_source.h5' -#else - filename = trim(path_output) // 'initial_source.binary' -#endif call sp % file_create(filename, serial = .false.) call sp % write_source_bank() call sp % file_close() diff --git a/src/state_point.F90 b/src/state_point.F90 index 6b983231f..790fd58c5 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -55,11 +55,7 @@ contains & zero_padded(current_batch, count_digits(n_max_batches)) ! Append appropriate extension -#ifdef HDF5 filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif ! Write message call write_message("Creating state point " // trim(filename) // "...", 1) @@ -118,10 +114,8 @@ contains ! Write out CMFD info if (cmfd_on) then -#ifdef HDF5 call sp % open_group("cmfd") call sp % close_group() -#endif call sp % write_data(1, "cmfd_on") call sp % write_data(cmfd % indices, "indices", length=4, group="cmfd") call sp % write_data(cmfd % k_cmfd, "k_cmfd", length=current_batch, & @@ -143,10 +137,8 @@ contains end if end if -#ifdef HDF5 call sp % open_group("tallies") call sp % close_group() -#endif ! Write number of meshes call sp % write_data(n_meshes, "n_meshes", group="tallies/meshes") @@ -414,11 +406,7 @@ contains filename = trim(path_output) // 'source.' // & & zero_padded(current_batch, count_digits(n_max_batches)) -#ifdef HDF5 filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif ! Write message for new file creation call write_message("Creating source file " // trim(filename) // "...", & @@ -434,12 +422,8 @@ contains ! Set filename for state point filename = trim(path_output) // 'statepoint.' // & - & zero_padded(current_batch, count_digits(n_max_batches)) -#ifdef HDF5 + zero_padded(current_batch, count_digits(n_max_batches)) filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif ! Reopen statepoint file in parallel call sp % file_open(filename, 'w', serial = .false.) @@ -456,14 +440,9 @@ contains ! Also check to write source separately in overwritten file if (source_latest) then - ! Set filename filename = trim(path_output) // 'source' -#ifdef HDF5 filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif ! Write message for new file creation call write_message("Creating source file " // trim(filename) // "...", 1) diff --git a/src/track_output.F90 b/src/track_output.F90 index 6ab514cdb..d3716e9b0 100644 --- a/src/track_output.F90 +++ b/src/track_output.F90 @@ -95,15 +95,9 @@ contains integer, allocatable :: n_coords(:) integer :: n_particle_tracks -#ifdef HDF5 fname = trim(path_output) // 'track_' // trim(to_str(current_batch)) & // '_' // trim(to_str(current_gen)) // '_' // trim(to_str(p % id)) & // '.h5' -#else - fname = trim(path_output) // 'track_' // trim(to_str(current_batch)) & - // '_' // trim(to_str(current_gen)) // '_' // trim(to_str(p % id)) & - // '.binary' -#endif ! Determine total number of particles and number of coordinates for each n_particle_tracks = size(tracks) From d1139cbedcd8624cefae3140d70f606581e21a6a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 16 Jul 2015 21:58:17 +0400 Subject: [PATCH 04/95] Remove non-HDF5 configurations from tests --- CMakeLists.txt | 56 +++++++++-------------------------- tests/run_tests.py | 63 ++++++++++++++-------------------------- tests/testing_harness.py | 16 +++++----- tests/travis.sh | 4 +-- 4 files changed, 44 insertions(+), 95 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e4452d323..7d4dfde7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,20 +39,12 @@ add_definitions(-DMAX_COORD=${maxcoord}) #=============================================================================== set(MPI_ENABLED FALSE) -set(HDF5_ENABLED FALSE) -if($ENV{FC} MATCHES "mpi[^/]*$") - message("-- Detected MPI wrapper: $ENV{FC}") - add_definitions(-DMPI) - set(MPI_ENABLED TRUE) -elseif($ENV{FC} MATCHES "h5fc$") +if($ENV{FC} MATCHES "h5fc$") message("-- Detected HDF5 wrapper: $ENV{FC}") - add_definitions(-DHDF5) - set(HDF5_ENABLED TRUE) elseif($ENV{FC} MATCHES "h5pfc$") message("-- Detected parallel HDF5 wrapper: $ENV{FC}") - add_definitions(-DMPI -DHDF5) + add_definitions(-DMPI) set(MPI_ENABLED TRUE) - set(HDF5_ENABLED TRUE) endif() # Check for Fortran 2008 MPI interface @@ -332,38 +324,18 @@ foreach(test ${TESTS}) # If a restart test is encounted, need to run with -r and restart file(s) elseif(${test} MATCHES "restart") - # Set restart file names - if (${HDF5_ENABLED}) - - # Handle restart tests separately - if(${test} MATCHES "test_statepoint_restart") - set(RESTART_FILE statepoint.07.h5) - elseif(${test} MATCHES "test_sourcepoint_restart") - set(RESTART_FILE statepoint.07.h5 source.07.h5) - elseif(${test} MATCHES "test_particle_restart_eigval") - set(RESTART_FILE particle_9_555.h5) - elseif(${test} MATCHES "test_particle_restart_fixed") - set(RESTART_FILE particle_7_928.h5) - else(${test} MATCHES "test_statepoint_restart") - message(FATAL_ERROR "Restart test ${test} not recognized") - endif(${test} MATCHES "test_statepoint_restart") - - else(${HDF5_ENABLED}) - - # Handle restart tests separately - if(${test} MATCHES "test_statepoint_restart") - set(RESTART_FILE statepoint.07.binary) - elseif(${test} MATCHES "test_sourcepoint_restart") - set(RESTART_FILE statepoint.07.binary source.07.binary) - elseif(${test} MATCHES "test_particle_restart_eigval") - set(RESTART_FILE particle_9_555.binary) - elseif(${test} MATCHES "test_particle_restart_fixed") - set(RESTART_FILE particle_7_6144.binary) - else(${test} MATCHES "test_statepoint_restart") - message(FATAL_ERROR "Restart test ${test} not recognized") - endif(${test} MATCHES "test_statepoint_restart") - - endif(${HDF5_ENABLED}) + # Handle restart tests separately + if(${test} MATCHES "test_statepoint_restart") + set(RESTART_FILE statepoint.07.h5) + elseif(${test} MATCHES "test_sourcepoint_restart") + set(RESTART_FILE statepoint.07.h5 source.07.h5) + elseif(${test} MATCHES "test_particle_restart_eigval") + set(RESTART_FILE particle_9_555.h5) + elseif(${test} MATCHES "test_particle_restart_fixed") + set(RESTART_FILE particle_7_928.h5) + else(${test} MATCHES "test_statepoint_restart") + message(FATAL_ERROR "Restart test ${test} not recognized") + endif(${test} MATCHES "test_statepoint_restart") # Perform serial valgrind and coverage test add_test(NAME ${TEST_NAME} diff --git a/tests/run_tests.py b/tests/run_tests.py index 3550ad7cb..aa2eb14cf 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -107,13 +107,12 @@ tests = OrderedDict() class Test(object): def __init__(self, name, debug=False, optimize=False, mpi=False, openmp=False, - hdf5=False, valgrind=False, coverage=False): + valgrind=False, coverage=False): self.name = name self.debug = debug self.optimize = optimize self.mpi = mpi self.openmp = openmp - self.hdf5 = hdf5 self.valgrind = valgrind self.coverage = coverage self.success = True @@ -124,15 +123,11 @@ class Test(object): self.cmake = ['cmake', '-H..', '-Bbuild', '-DPYTHON_EXECUTABLE=' + sys.executable] - # Check for MPI/HDF5 - if self.mpi and not self.hdf5: - self.fc = MPI_DIR+'/bin/mpif90' - elif not self.mpi and self.hdf5: - self.fc = HDF5_DIR+'/bin/h5fc' - elif self.mpi and self.hdf5: - self.fc = PHDF5_DIR+'/bin/h5pfc' + # Check for MPI + if self.mpi: + self.fc = PHDF5_DIR + '/bin/h5pfc' else: - self.fc = FC + self.fc = HDF5_DIR + '/bin/h5fc' # Sets the build name that will show up on the CDash def get_build_name(self): @@ -263,41 +258,26 @@ class Test(object): # Simple function to add a test to the global tests dictionary def add_test(name, debug=False, optimize=False, mpi=False, openmp=False,\ - hdf5=False, valgrind=False, coverage=False): - tests.update({name: Test(name, debug, optimize, mpi, openmp, hdf5, + valgrind=False, coverage=False): + tests.update({name: Test(name, debug, optimize, mpi, openmp, valgrind, coverage)}) # List of all tests that may be run. User can add -C to command line to specify # a subset of these configurations -add_test('basic-normal') -add_test('basic-debug', debug=True) -add_test('basic-optimize', optimize=True) -add_test('omp-normal', openmp=True) -add_test('omp-debug', openmp=True, debug=True) -add_test('omp-optimize', openmp=True, optimize=True) -add_test('hdf5-normal', hdf5=True) -add_test('hdf5-debug', hdf5=True, debug=True) -add_test('hdf5-optimize', hdf5=True, optimize=True) -add_test('omp-hdf5-normal', openmp=True, hdf5=True) -add_test('omp-hdf5-debug', openmp=True, hdf5=True, debug=True) -add_test('omp-hdf5-optimize', openmp=True, hdf5=True, optimize=True) -add_test('mpi-normal', mpi=True) -add_test('mpi-debug', mpi=True, debug=True) -add_test('mpi-optimize', mpi=True, optimize=True) -add_test('mpi-omp-normal', mpi=True, openmp=True) -add_test('mpi-omp-debug', mpi=True, openmp=True, debug=True) -add_test('mpi-omp-optimize', mpi=True, openmp=True, optimize=True) -add_test('phdf5-normal', mpi=True, hdf5=True) -add_test('phdf5-debug', mpi=True, hdf5=True, debug=True) -add_test('phdf5-optimize', mpi=True, hdf5=True, optimize=True) -add_test('phdf5-omp-normal', mpi=True, hdf5=True, openmp=True) -add_test('phdf5-omp-debug', mpi=True, hdf5=True, openmp=True, debug=True) -add_test('phdf5-omp-optimize', mpi=True, hdf5=True, openmp=True, optimize=True) -add_test('basic-debug_valgrind', debug=True, valgrind=True) -add_test('hdf5-debug_valgrind', hdf5=True, debug=True, valgrind=True) -add_test('basic-debug_coverage', debug=True, coverage=True) -add_test('hdf5-debug_coverage', debug=True, hdf5=True, coverage=True) -add_test('mpi-debug_coverage', debug=True, mpi=True, coverage=True) +add_test('hdf5-normal') +add_test('hdf5-debug', debug=True) +add_test('hdf5-optimize', optimize=True) +add_test('omp-hdf5-normal', openmp=True) +add_test('omp-hdf5-debug', openmp=True, debug=True) +add_test('omp-hdf5-optimize', openmp=True, optimize=True) +add_test('phdf5-normal', mpi=True) +add_test('phdf5-debug', mpi=True, debug=True) +add_test('phdf5-optimize', mpi=True, optimize=True) +add_test('phdf5-omp-normal', mpi=True, openmp=True) +add_test('phdf5-omp-debug', mpi=True, openmp=True, debug=True) +add_test('phdf5-omp-optimize', mpi=True, openmp=True, optimize=True) +add_test('hdf5-debug_valgrind', debug=True, valgrind=True) +add_test('hdf5-debug_coverage', debug=True, coverage=True) # Check to see if we should just print build configuration information to user if options.list_build_configs: @@ -305,7 +285,6 @@ if options.list_build_configs: print('Configuration Name: {0}'.format(key)) print(' Debug Flags:..........{0}'.format(tests[key].debug)) print(' Optimization Flags:...{0}'.format(tests[key].optimize)) - print(' HDF5 Active:..........{0}'.format(tests[key].hdf5)) print(' MPI Active:...........{0}'.format(tests[key].mpi)) print(' OpenMP Active:........{0}'.format(tests[key].openmp)) print(' Valgrind Test:........{0}'.format(tests[key].valgrind)) diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 9405db845..2059c46da 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -82,9 +82,8 @@ class TestHarness(object): statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ 'exist.' - assert statepoint[0].endswith('binary') \ - or statepoint[0].endswith('h5'), \ - 'Statepoint file is not a binary or hdf5 file.' + assert statepoint[0].endswith('h5'), \ + 'Statepoint file is not a HDF5 file.' if self._tallies: assert os.path.exists(os.path.join(os.getcwd(), 'tallies.out')), \ 'Tally output file does not exist.' @@ -155,7 +154,7 @@ class HashedTestHarness(TestHarness): class PlotTestHarness(TestHarness): - """Specialized TestHarness for running OpenMC plotting tests.""" + """Specialized TestHarness for running OpenMC plotting tests.""" def __init__(self, plot_names): self._plot_names = plot_names self._opts = None @@ -199,7 +198,7 @@ class PlotTestHarness(TestHarness): class CMFDTestHarness(TestHarness): - """Specialized TestHarness for running OpenMC CMFD tests.""" + """Specialized TestHarness for running OpenMC CMFD tests.""" def _get_results(self): """Digest info in the statepoint and return as a string.""" # Read the statepoint file. @@ -233,15 +232,14 @@ class CMFDTestHarness(TestHarness): class ParticleRestartTestHarness(TestHarness): - """Specialized TestHarness for running OpenMC particle restart tests.""" + """Specialized TestHarness for running OpenMC particle restart tests.""" def _test_output_created(self): """Make sure the restart file has been created.""" particle = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(particle) == 1, 'Either multiple or no particle restart ' \ 'files exist.' - assert particle[0].endswith('binary') \ - or particle[0].endswith('h5'), \ - 'Particle restart file is not a binary or hdf5 file.' + assert particle[0].endswith('h5'), \ + 'Particle restart file is not a HDF5 file.' def _get_results(self): """Digest info in the statepoint and return as a string.""" diff --git a/tests/travis.sh b/tests/travis.sh index fac8d793a..af54b4ff6 100755 --- a/tests/travis.sh +++ b/tests/travis.sh @@ -5,7 +5,7 @@ set -ev # Run all debug tests ./check_source.py if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - ./run_tests.py -C "^basic-debug$|^hdf5-debug$|^mpi-omp-debug$|^phdf5-omp-debug$" -j 2 -s + ./run_tests.py -C "^hdf5-debug$|^phdf5-debug$|^phdf5-omp-debug$" -j 2 -s else - ./run_tests.py -C "^basic-debug$" -j 2 + ./run_tests.py -C "^hdf5-debug$" -j 2 fi From 4db5ff01bdccf4219943b656c7092e022f5cf7ca Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 16 Jul 2015 22:43:57 +0400 Subject: [PATCH 05/95] Remove mpiio_interface module --- src/mpiio_interface.F90 | 610 --------------------------------------- src/output_interface.F90 | 3 - 2 files changed, 613 deletions(-) delete mode 100644 src/mpiio_interface.F90 diff --git a/src/mpiio_interface.F90 b/src/mpiio_interface.F90 deleted file mode 100644 index b9652c8ae..000000000 --- a/src/mpiio_interface.F90 +++ /dev/null @@ -1,610 +0,0 @@ -module mpiio_interface - -#ifdef MPI -#ifndef HDF5 - use message_passing - - implicit none - -#ifdef MPIF08 -#define FH_TYPE type(MPI_File) -#else -#define FH_TYPE integer -#endif - - integer :: mpiio_err ! MPI error code - - ! Generic HDF5 write procedure interface - interface mpi_write_data - module procedure mpi_write_double - module procedure mpi_write_double_1Darray - module procedure mpi_write_double_2Darray - module procedure mpi_write_double_3Darray - module procedure mpi_write_double_4Darray - module procedure mpi_write_integer - module procedure mpi_write_integer_1Darray - module procedure mpi_write_integer_2Darray - module procedure mpi_write_integer_3Darray - module procedure mpi_write_integer_4Darray - module procedure mpi_write_long - module procedure mpi_write_string - end interface mpi_write_data - - ! Generic HDF5 read procedure interface - interface mpi_read_data - module procedure mpi_read_double - module procedure mpi_read_double_1Darray - module procedure mpi_read_double_2Darray - module procedure mpi_read_double_3Darray - module procedure mpi_read_double_4Darray - module procedure mpi_read_integer - module procedure mpi_read_integer_1Darray - module procedure mpi_read_integer_2Darray - module procedure mpi_read_integer_3Darray - module procedure mpi_read_integer_4Darray - module procedure mpi_read_long - module procedure mpi_read_string - end interface mpi_read_data - -contains - -!=============================================================================== -! MPI_CREATE_FILE creates a file using MPI file I/O -!=============================================================================== - - subroutine mpi_create_file(filename, fh) - - character(*), intent(in) :: filename ! name of file to create - FH_TYPE, intent(inout) :: fh ! file handle - - ! Create the file - call MPI_FILE_OPEN(MPI_COMM_WORLD, filename, MPI_MODE_CREATE + & - MPI_MODE_WRONLY, MPI_INFO_NULL, fh, mpiio_err) - - end subroutine mpi_create_file - -!=============================================================================== -! MPI_OPEN_FILE opens a file using MPI file I/O -!=============================================================================== - - subroutine mpi_open_file(filename, fh, mode) - - character(*), intent(in) :: filename ! name of file to open - character(*), intent(in) :: mode ! open 'r' read, 'w' write - FH_TYPE, intent(inout) :: fh ! file handle - - integer :: open_mode - - ! Determine access mode - open_mode = MPI_MODE_RDONLY - if (mode == 'w') then - open_mode = ior(MPI_MODE_APPEND, MPI_MODE_WRONLY) - end if - - ! Create the file - call MPI_FILE_OPEN(MPI_COMM_WORLD, filename, & - open_mode, MPI_INFO_NULL, fh, mpiio_err) - - end subroutine mpi_open_file - -!=============================================================================== -! MPI_CLOSE_FILE closes a file using MPI file I/O -!=============================================================================== - - subroutine mpi_close_file(fh) - - FH_TYPE, intent(inout) :: fh ! file handle - - call MPI_FILE_CLOSE(fh, mpiio_err) - - end subroutine mpi_close_file - -!=============================================================================== -! MPI_WRITE_INTEGER writes integer scalar data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, 1, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, 1, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer - -!=============================================================================== -! MPI_READ_INTEGER reads integer scalar data using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, 1, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, 1, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer - -!=============================================================================== -! MPI_WRITE_INTEGER_1DARRAY writes integer 1-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer_1Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of array - integer, intent(in) :: buffer(:) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, length, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, length, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer_1Darray - -!=============================================================================== -! MPI_READ_INTEGER_1DARRAY reads integer 1-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer_1Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of array - integer, intent(inout) :: buffer(:) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, length, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, length, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer_1Darray - -!=============================================================================== -! MPI_WRITE_INTEGER_2DARRAY writes integer 2-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer_2Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(2) ! length of array - integer, intent(in) :: buffer(length(1),length(2)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer_2Darray - -!=============================================================================== -! MPI_READ_INTEGER_2DARRAY reads integer 2-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer_2Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(2) ! length of array - integer, intent(inout) :: buffer(length(1),length(2)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer_2Darray - -!=============================================================================== -! MPI_WRITE_INTEGER_3DARRAY writes integer 3-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer_3Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(3) ! length of array - integer, intent(in) :: buffer(length(1),length(2),& - length(3)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer_3Darray - -!=============================================================================== -! MPI_READ_INTEGER_3DARRAY reads integer 3-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer_3Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(3) ! length of array - integer, intent(inout) :: buffer(length(1),length(2), & - length(3)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer_3Darray - -!=============================================================================== -! MPI_WRITE_INTEGER_4DARRAY writes integer 4-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer_4Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(4) ! length of array - integer, intent(in) :: buffer(length(1),length(2),& - length(3),length(4)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer_4Darray - -!=============================================================================== -! MPI_READ_INTEGER_4DARRAY reads integer 4-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer_4Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(4) ! length of array - integer, intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer_4Darray - -!=============================================================================== -! MPI_WRITE_DOUBLE writes integer scalar data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - real(8), intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, 1, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, 1, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double - -!=============================================================================== -! MPI_READ_DOUBLE reads integer scalar data using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - real(8), intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, 1, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, 1, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double - -!=============================================================================== -! MPI_WRITE_DOUBLE_1DARRAY writes integer 1-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double_1Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of array - real(8), intent(in) :: buffer(:) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, length, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, length, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double_1Darray - -!=============================================================================== -! MPI_READ_DOUBLE_1DARRAY reads integer 1-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double_1Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of array - real(8), intent(inout) :: buffer(:) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, length, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, length, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double_1Darray - -!=============================================================================== -! MPI_WRITE_DOUBLE_2DARRAY writes integer 2-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double_2Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(2) ! length of array - real(8), intent(in) :: buffer(length(1),length(2)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double_2Darray - -!=============================================================================== -! MPI_READ_DOUBLE_2DARRAY reads integer 2-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double_2Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(2) ! length of array - real(8), intent(inout) :: buffer(length(1),length(2)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double_2Darray - -!=============================================================================== -! MPI_WRITE_DOUBLE_3DARRAY writes integer 3-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double_3Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(3) ! length of array - real(8), intent(in) :: buffer(length(1),length(2),& - length(3)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double_3Darray - -!=============================================================================== -! MPI_READ_DOUBLE_3DARRAY reads integer 3-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double_3Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(3) ! length of array - real(8), intent(inout) :: buffer(length(1),length(2), & - length(3)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double_3Darray - -!=============================================================================== -! MPI_WRITE_DOUBLE_4DARRAY writes integer 4-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double_4Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(4) ! length of array - real(8), intent(in) :: buffer(length(1),length(2),& - length(3),length(4)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double_4Darray - -!=============================================================================== -! MPI_READ_DOUBLE_4DARRAY reads integer 4-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double_4Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(4) ! length of array - real(8), intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double_4Darray - -!=============================================================================== -! MPI_WRITE_LONG writes long integer scalar data using MPI file I/O -!=============================================================================== - - subroutine mpi_write_long(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer(8), intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, 1, MPI_INTEGER8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, 1, MPI_INTEGER8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_long - -!=============================================================================== -! MPI_READ_LONG reads long integer scalar data using MPI file I/O -!=============================================================================== - - subroutine mpi_read_long(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer(8), intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, 1, MPI_INTEGER8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, 1, MPI_INTEGER8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_long - -!=============================================================================== -! MPI_WRITE_STRING writes string data using MPI file I/O -!=============================================================================== - - subroutine mpi_write_string(fh, buffer, length, collect) - - character(*), intent(in) :: buffer ! data to write - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of data - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, length, MPI_CHARACTER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, length, MPI_CHARACTER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_string - -!=============================================================================== -! MPI_READ_STRING reads string data using MPI file I/O -!=============================================================================== - - subroutine mpi_read_string(fh, buffer, length, collect) - - character(*), intent(inout) :: buffer ! read data to here - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of string - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, length, MPI_CHARACTER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, length, MPI_CHARACTER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_string - -#endif -#endif -end module mpiio_interface diff --git a/src/output_interface.F90 b/src/output_interface.F90 index f56a4b339..7ced3c052 100644 --- a/src/output_interface.F90 +++ b/src/output_interface.F90 @@ -6,9 +6,6 @@ module output_interface use tally_header, only: TallyResult use hdf5_interface -#ifdef MPI - use mpiio_interface -#endif implicit none private From 3c1ba76f95617b7d2d7ad5ad56ccee246187d7a3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 31 Aug 2015 11:13:21 +0700 Subject: [PATCH 06/95] Rely on FindHDF5 rather than h5fc and h5pfc scripts The FindHDF5.cmake packaged with CMake is broken in a number of respects. The HL components don't work (debian has a patch in cmake-data). It's also impossible to prefer a parallel installation if both h5fc and h5pfc appear on your PATH. Finally, hdf5_hl is not included in the list of libraries needed for the Fortran_HL component. A local version of FindHDF5 is used here which fixes all these issues. This enables one to compile OpenMC with MPI + serial HDF5 if needed by introducing the PHDF5 preprocessor flag. --- CMakeLists.txt | 48 ++++- cmake/Modules/FindHDF5.cmake | 407 +++++++++++++++++++++++++++++++++++ src/hdf5_interface.F90 | 12 +- src/output_interface.F90 | 60 +++--- tests/run_tests.py | 34 ++- 5 files changed, 508 insertions(+), 53 deletions(-) create mode 100644 cmake/Modules/FindHDF5.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d4dfde7f..623eb0dcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,9 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/include) +# Set module path +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) + # Make sure Fortran module directory is included when building include_directories(${CMAKE_BINARY_DIR}/include) @@ -35,14 +38,12 @@ set(maxcoord 10 CACHE STRING "Maximum number of nested coordinate levels") add_definitions(-DMAX_COORD=${maxcoord}) #=============================================================================== -# MPI for distributed-memory parallelism / HDF5 for binary output +# MPI for distributed-memory parallelism #=============================================================================== set(MPI_ENABLED FALSE) -if($ENV{FC} MATCHES "h5fc$") - message("-- Detected HDF5 wrapper: $ENV{FC}") -elseif($ENV{FC} MATCHES "h5pfc$") - message("-- Detected parallel HDF5 wrapper: $ENV{FC}") +if($ENV{FC} MATCHES "mpi[^/]*$") + message("-- Detected MPI wrapper: $ENV{FC}") add_definitions(-DMPI) set(MPI_ENABLED TRUE) endif() @@ -53,6 +54,33 @@ if(MPI_ENABLED AND mpif08) add_definitions(-DMPIF08) endif() +#=============================================================================== +# HDF5 for binary output +#=============================================================================== + +# Unfortunately FindHDF5.cmake will always prefer a serial HDF5 installation +# over a parallel installation if both appear on the user's PATH. To get around +# this, we check for the environment variable HDF5_ROOT and if it exists, use it +# to check whether its a parallel version. + +if(DEFINED ENV{HDF5_ROOT} AND EXISTS $ENV{HDF5_ROOT}/bin/h5pcc) + set(HDF5_PREFER_PARALLEL TRUE) +else() + set(HDF5_PREFER_PARALLEL FALSE) +endif() + +find_package(HDF5 COMPONENTS Fortran_HL) +if(NOT HDF5_FOUND) + message(FATAL_ERROR "Could not find HDF5") +endif() +if(HDF5_IS_PARALLEL) + if(NOT MPI_ENABLED) + message(FATAL_ERROR "Parallel HDF5 must be used with MPI.") + endif() + add_definitions(-DPHDF5) + message("-- Using parallel HDF5") +endif() + #=============================================================================== # Set compile/link flags based on which compiler is being used #=============================================================================== @@ -212,6 +240,14 @@ set(program "openmc") file(GLOB source src/*.F90 src/xml/openmc_fox.F90) add_executable(${program} ${source}) +# target_include_directories was added in CMake 2.8.11 and is the recommended +# way to set include directories. For lesser versions, we revert to set_property +if(CMAKE_VERSION VERSION_LESS 2.8.11) + include_directories(${HDF5_INCLUDE_DIRS}) +else() + target_include_directories(${program} PUBLIC ${HDF5_INCLUDE_DIRS}) +endif() + # target_compile_options was added in CMake 2.8.12 and is the recommended way to # set compile flags. Note that this sets the COMPILE_OPTIONS property (also # available only in 2.8.12+) rather than the COMPILE_FLAGS property, which is @@ -225,7 +261,7 @@ endif() # target_link_libraries treats any arguments starting with - but not -l as # linker flags. Thus, we can pass both linker flags and libraries together. -target_link_libraries(${program} ${ldflags} ${libraries} fox_dom) +target_link_libraries(${program} ${ldflags} ${HDF5_LIBRARIES} fox_dom) #=============================================================================== # Install executable, scripts, manpage, license diff --git a/cmake/Modules/FindHDF5.cmake b/cmake/Modules/FindHDF5.cmake new file mode 100644 index 000000000..1631f0193 --- /dev/null +++ b/cmake/Modules/FindHDF5.cmake @@ -0,0 +1,407 @@ +#.rst: +# FindHDF5 +# -------- +# +# Find HDF5, a library for reading and writing self describing array data. +# +# +# +# This module invokes the HDF5 wrapper compiler that should be installed +# alongside HDF5. Depending upon the HDF5 Configuration, the wrapper +# compiler is called either h5cc or h5pcc. If this succeeds, the module +# will then call the compiler with the -show argument to see what flags +# are used when compiling an HDF5 client application. +# +# The module will optionally accept the COMPONENTS argument. If no +# COMPONENTS are specified, then the find module will default to finding +# only the HDF5 C library. If one or more COMPONENTS are specified, the +# module will attempt to find the language bindings for the specified +# components. The only valid components are C, CXX, Fortran, HL, and +# Fortran_HL. If the COMPONENTS argument is not given, the module will +# attempt to find only the C bindings. +# +# On UNIX systems, this module will read the variable +# HDF5_USE_STATIC_LIBRARIES to determine whether or not to prefer a +# static link to a dynamic link for HDF5 and all of it's dependencies. +# To use this feature, make sure that the HDF5_USE_STATIC_LIBRARIES +# variable is set before the call to find_package. +# +# To provide the module with a hint about where to find your HDF5 +# installation, you can set the environment variable HDF5_ROOT. The +# Find module will then look in this path when searching for HDF5 +# executables, paths, and libraries. +# +# In addition to finding the includes and libraries required to compile +# an HDF5 client application, this module also makes an effort to find +# tools that come with the HDF5 distribution that may be useful for +# regression testing. +# +# This module will define the following variables: +# +# :: +# +# HDF5_INCLUDE_DIRS - Location of the hdf5 includes +# HDF5_INCLUDE_DIR - Location of the hdf5 includes (deprecated) +# HDF5_DEFINITIONS - Required compiler definitions for HDF5 +# HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings. +# HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings +# HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings +# HDF5_HL_LIBRARIES - Required libraries for the HDF5 high level API +# HDF5_Fortran_HL_LIBRARIES - Required libraries for the high level Fortran +# bindings. +# HDF5_LIBRARIES - Required libraries for all requested bindings +# HDF5_FOUND - true if HDF5 was found on the system +# HDF5_VERSION - HDF5 version in format Major.Minor.Release +# HDF5_LIBRARY_DIRS - the full set of library directories +# HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support +# HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler +# HDF5_CXX_COMPILER_EXECUTABLE - the path to the HDF5 C++ wrapper compiler +# HDF5_Fortran_COMPILER_EXECUTABLE - the path to the HDF5 Fortran wrapper compiler +# HDF5_DIFF_EXECUTABLE - the path to the HDF5 dataset comparison tool + +#============================================================================= +# Copyright 2015 Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf +# Copyright 2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# This module is maintained by Will Dicharry . + +include(SelectLibraryConfigurations) +include(FindPackageHandleStandardArgs) + +# List of the valid HDF5 components +set( HDF5_VALID_COMPONENTS + C + CXX + Fortran + HL + Fortran_HL +) + +# Validate the list of find components. +if( NOT HDF5_FIND_COMPONENTS ) + set( HDF5_LANGUAGE_BINDINGS "C" ) +else() + # add the extra specified components, ensuring that they are valid. + foreach( component ${HDF5_FIND_COMPONENTS} ) + list( FIND HDF5_VALID_COMPONENTS ${component} component_location ) + if( ${component_location} EQUAL -1 ) + message( FATAL_ERROR + "\"${component}\" is not a valid HDF5 component." ) + else() + list( APPEND HDF5_LANGUAGE_BINDINGS ${component} ) + endif() + endforeach() +endif() + +if(HDF5_PREFER_PARALLEL) + # try to find the HDF5 wrapper compilers + find_program( HDF5_C_COMPILER_EXECUTABLE + NAMES h5pcc h5cc + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 Wrapper compiler. Used only to detect HDF5 compile flags." ) + mark_as_advanced( HDF5_C_COMPILER_EXECUTABLE ) + + find_program( HDF5_CXX_COMPILER_EXECUTABLE + NAMES h5pc++ h5c++ + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 C++ Wrapper compiler. Used only to detect HDF5 compile flags." ) + mark_as_advanced( HDF5_CXX_COMPILER_EXECUTABLE ) + + find_program( HDF5_Fortran_COMPILER_EXECUTABLE + NAMES h5pfc h5fc + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 Fortran Wrapper compiler. Used only to detect HDF5 compile flags." ) + mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE ) +else() + # try to find the HDF5 wrapper compilers + find_program( HDF5_C_COMPILER_EXECUTABLE + NAMES h5cc h5pcc + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 Wrapper compiler. Used only to detect HDF5 compile flags." ) + mark_as_advanced( HDF5_C_COMPILER_EXECUTABLE ) + + find_program( HDF5_CXX_COMPILER_EXECUTABLE + NAMES h5c++ h5pc++ + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 C++ Wrapper compiler. Used only to detect HDF5 compile flags." ) + mark_as_advanced( HDF5_CXX_COMPILER_EXECUTABLE ) + + find_program( HDF5_Fortran_COMPILER_EXECUTABLE + NAMES h5fc h5pfc + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 Fortran Wrapper compiler. Used only to detect HDF5 compile flags." ) + mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE ) +endif() + +find_program( HDF5_DIFF_EXECUTABLE + NAMES h5diff + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 file differencing tool." ) +mark_as_advanced( HDF5_DIFF_EXECUTABLE ) + +# Invoke the HDF5 wrapper compiler. The compiler return value is stored to the +# return_value argument, the text output is stored to the output variable. +macro( _HDF5_invoke_compiler language output return_value ) + if( HDF5_${language}_COMPILER_EXECUTABLE ) + exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE} + ARGS -show + OUTPUT_VARIABLE ${output} + RETURN_VALUE ${return_value} + ) + if( ${${return_value}} EQUAL 0 ) + # do nothing + else() + message( STATUS + "Unable to determine HDF5 ${language} flags from HDF5 wrapper." ) + endif() + endif() +endmacro() + +# Parse a compile line for definitions, includes, library paths, and libraries. +macro( _HDF5_parse_compile_line + compile_line_var + include_paths + definitions + library_paths + libraries ) + + # Match the include paths + string( REGEX MATCHALL "-I([^\" ]+)" include_path_flags + "${${compile_line_var}}" + ) + foreach( IPATH ${include_path_flags} ) + string( REGEX REPLACE "^-I" "" IPATH ${IPATH} ) + string( REPLACE "//" "/" IPATH ${IPATH} ) + list( APPEND ${include_paths} ${IPATH} ) + endforeach() + + # Match the definitions + string( REGEX MATCHALL "-D[^ ]*" definition_flags "${${compile_line_var}}" ) + foreach( DEF ${definition_flags} ) + list( APPEND ${definitions} ${DEF} ) + endforeach() + + # Match the library paths + string( REGEX MATCHALL "-L([^\" ]+|\"[^\"]+\")" library_path_flags + "${${compile_line_var}}" + ) + + foreach( LPATH ${library_path_flags} ) + string( REGEX REPLACE "^-L" "" LPATH ${LPATH} ) + string( REPLACE "//" "/" LPATH ${LPATH} ) + list( APPEND ${library_paths} ${LPATH} ) + endforeach() + + # now search for the library names specified in the compile line (match -l...) + # match only -l's preceded by a space or comma + # this is to exclude directory names like xxx-linux/ + string( REGEX MATCHALL "[, ]-l([^\", ]+)" library_name_flags + "${${compile_line_var}}" ) + # strip the -l from all of the library flags and add to the search list + foreach( LIB ${library_name_flags} ) + string( REGEX REPLACE "^[, ]-l" "" LIB ${LIB} ) + list( APPEND ${libraries} ${LIB} ) + endforeach() +endmacro() + +# Try to find HDF5 using an installed hdf5-config.cmake +if( NOT HDF5_FOUND ) + find_package( HDF5 QUIET NO_MODULE ) + if( HDF5_FOUND ) + set( HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR} ) + set( HDF5_LIBRARIES ) + set( HDF5_C_TARGET hdf5 ) + set( HDF5_CXX_TARGET hdf5_cpp ) + set( HDF5_HL_TARGET hdf5_hl ) + set( HDF5_Fortran_TARGET hdf5_fortran ) + set( HDF5_Fortran_HL_TARGET hdf5_hl_fortran ) + foreach( _component ${HDF5_LANGUAGE_BINDINGS} ) + list( FIND HDF5_VALID_COMPONENTS ${_component} _component_location ) + get_target_property( _comp_location ${HDF5_${_component}_TARGET} LOCATION ) + if( _comp_location ) + set( HDF5_${_component}_LIBRARY ${_comp_location} CACHE PATH + "HDF5 ${_component} library" ) + mark_as_advanced( HDF5_${_component}_LIBRARY ) + list( APPEND HDF5_LIBRARIES ${HDF5_${_component}_LIBRARY} ) + endif() + endforeach() + endif() +endif() + +if( NOT HDF5_FOUND ) + _HDF5_invoke_compiler( C HDF5_C_COMPILE_LINE HDF5_C_RETURN_VALUE ) + _HDF5_invoke_compiler( CXX HDF5_CXX_COMPILE_LINE HDF5_CXX_RETURN_VALUE ) + _HDF5_invoke_compiler( Fortran HDF5_Fortran_COMPILE_LINE HDF5_Fortran_RETURN_VALUE ) + set(HDF5_HL_COMPILE_LINE ${HDF5_C_COMPILE_LINE}) + set(HDF5_Fortran_HL_COMPILE_LINE ${HDF5_Fortran_COMPILE_LINE}) + + # seed the initial lists of libraries to find with items we know we need + set( HDF5_C_LIBRARY_NAMES_INIT hdf5 ) + set( HDF5_HL_LIBRARY_NAMES_INIT hdf5_hl ${HDF5_C_LIBRARY_NAMES_INIT} ) + set( HDF5_CXX_LIBRARY_NAMES_INIT hdf5_cpp ${HDF5_C_LIBRARY_NAMES_INIT} ) + set( HDF5_Fortran_LIBRARY_NAMES_INIT hdf5_fortran + ${HDF5_C_LIBRARY_NAMES_INIT} ) + set( HDF5_Fortran_HL_LIBRARY_NAMES_INIT hdf5hl_fortran hdf5_hl + ${HDF5_Fortran_LIBRARY_NAMES_INIT} ) + + foreach( LANGUAGE ${HDF5_LANGUAGE_BINDINGS} ) + if( HDF5_${LANGUAGE}_COMPILE_LINE ) + _HDF5_parse_compile_line( HDF5_${LANGUAGE}_COMPILE_LINE + HDF5_${LANGUAGE}_INCLUDE_FLAGS + HDF5_${LANGUAGE}_DEFINITIONS + HDF5_${LANGUAGE}_LIBRARY_DIRS + HDF5_${LANGUAGE}_LIBRARY_NAMES + ) + + # take a guess that the includes may be in the 'include' sibling + # directory of a library directory. + foreach( dir ${HDF5_${LANGUAGE}_LIBRARY_DIRS} ) + list( APPEND HDF5_${LANGUAGE}_INCLUDE_FLAGS ${dir}/../include ) + endforeach() + endif() + + # set the definitions for the language bindings. + list( APPEND HDF5_DEFINITIONS ${HDF5_${LANGUAGE}_DEFINITIONS} ) + + # find the HDF5 include directories + if(${LANGUAGE} MATCHES "Fortran") + set(HDF5_INCLUDE_FILENAME hdf5.mod) + else() + set(HDF5_INCLUDE_FILENAME hdf5.h) + endif() + + find_path( HDF5_${LANGUAGE}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME} + HINTS + ${HDF5_${LANGUAGE}_INCLUDE_FLAGS} + ENV + HDF5_ROOT + PATHS + $ENV{HOME}/.local/include + PATH_SUFFIXES + include + Include + ) + mark_as_advanced( HDF5_${LANGUAGE}_INCLUDE_DIR ) + list( APPEND HDF5_INCLUDE_DIRS ${HDF5_${LANGUAGE}_INCLUDE_DIR} ) + + set( HDF5_${LANGUAGE}_LIBRARY_NAMES + ${HDF5_${LANGUAGE}_LIBRARY_NAMES_INIT} + ${HDF5_${LANGUAGE}_LIBRARY_NAMES} ) + + # find the HDF5 libraries + foreach( LIB ${HDF5_${LANGUAGE}_LIBRARY_NAMES} ) + if( UNIX AND HDF5_USE_STATIC_LIBRARIES ) + # According to bug 1643 on the CMake bug tracker, this is the + # preferred method for searching for a static library. + # See http://www.cmake.org/Bug/view.php?id=1643. We search + # first for the full static library name, but fall back to a + # generic search on the name if the static search fails. + set( THIS_LIBRARY_SEARCH_DEBUG lib${LIB}d.a ${LIB}d ) + set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a ${LIB} ) + else() + set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ) + set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ) + endif() + find_library( HDF5_${LIB}_LIBRARY_DEBUG + NAMES ${THIS_LIBRARY_SEARCH_DEBUG} + HINTS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} + ENV HDF5_ROOT + PATH_SUFFIXES lib Lib ) + find_library( HDF5_${LIB}_LIBRARY_RELEASE + NAMES ${THIS_LIBRARY_SEARCH_RELEASE} + HINTS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} + ENV HDF5_ROOT + PATH_SUFFIXES lib Lib ) + select_library_configurations( HDF5_${LIB} ) + list(APPEND HDF5_${LANGUAGE}_LIBRARIES ${HDF5_${LIB}_LIBRARY}) + endforeach() + list( APPEND HDF5_LIBRARY_DIRS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} ) + + # Append the libraries for this language binding to the list of all + # required libraries. + list(APPEND HDF5_LIBRARIES ${HDF5_${LANGUAGE}_LIBRARIES}) + endforeach() + + # We may have picked up some duplicates in various lists during the above + # process for the language bindings (both the C and C++ bindings depend on + # libz for example). Remove the duplicates. It appears that the default + # CMake behavior is to remove duplicates from the end of a list. However, + # for link lines, this is incorrect since unresolved symbols are searched + # for down the link line. Therefore, we reverse the list, remove the + # duplicates, and then reverse it again to get the duplicates removed from + # the beginning. + macro( _remove_duplicates_from_beginning _list_name ) + list( REVERSE ${_list_name} ) + list( REMOVE_DUPLICATES ${_list_name} ) + list( REVERSE ${_list_name} ) + endmacro() + + if( HDF5_INCLUDE_DIRS ) + _remove_duplicates_from_beginning( HDF5_INCLUDE_DIRS ) + endif() + if( HDF5_LIBRARY_DIRS ) + _remove_duplicates_from_beginning( HDF5_LIBRARY_DIRS ) + endif() + if( HDF5_LIBRARIES ) + _remove_duplicates_from_beginning( HDF5_LIBRARIES ) + endif() + + # If the HDF5 include directory was found, open H5pubconf.h to determine if + # HDF5 was compiled with parallel IO support + set( HDF5_IS_PARALLEL FALSE ) + set( HDF5_VERSION "" ) + foreach( _dir IN LISTS HDF5_INCLUDE_DIRS ) + foreach(_hdr "${_dir}/H5pubconf.h" "${_dir}/H5pubconf-64.h" "${_dir}/H5pubconf-32.h") + if( EXISTS "${_hdr}" ) + file( STRINGS "${_hdr}" + HDF5_HAVE_PARALLEL_DEFINE + REGEX "HAVE_PARALLEL 1" ) + if( HDF5_HAVE_PARALLEL_DEFINE ) + set( HDF5_IS_PARALLEL TRUE ) + endif() + unset(HDF5_HAVE_PARALLEL_DEFINE) + + file( STRINGS "${_hdr}" + HDF5_VERSION_DEFINE + REGEX "^[ \t]*#[ \t]*define[ \t]+H5_VERSION[ \t]+" ) + if( "${HDF5_VERSION_DEFINE}" MATCHES + "H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+).*\"" ) + set( HDF5_VERSION "${CMAKE_MATCH_1}" ) + endif() + unset(HDF5_VERSION_DEFINE) + endif() + endforeach() + endforeach() + set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL + "HDF5 library compiled with parallel IO support" ) + mark_as_advanced( HDF5_IS_PARALLEL ) + + # For backwards compatibility we set HDF5_INCLUDE_DIR to the value of + # HDF5_INCLUDE_DIRS + if( HDF5_INCLUDE_DIRS ) + set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" ) + endif() + +endif() + +find_package_handle_standard_args( HDF5 + REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS + VERSION_VAR HDF5_VERSION +) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index e7ba39b64..28ac445ab 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -4,7 +4,7 @@ module hdf5_interface use h5lt use, intrinsic :: ISO_C_BINDING -#ifdef MPI +#ifdef PHDF5 use message_passing, only: MPI_COMM_WORLD, MPI_INFO_NULL #endif @@ -36,7 +36,7 @@ module hdf5_interface module procedure hdf5_write_integer_4Darray module procedure hdf5_write_long module procedure hdf5_write_string -#ifdef MPI +#ifdef PHDF5 module procedure hdf5_write_double_parallel module procedure hdf5_write_double_1Darray_parallel module procedure hdf5_write_double_2Darray_parallel @@ -66,7 +66,7 @@ module hdf5_interface module procedure hdf5_read_integer_4Darray module procedure hdf5_read_long module procedure hdf5_read_string -#ifdef MPI +#ifdef PHDF5 module procedure hdf5_read_double_parallel module procedure hdf5_read_double_1Darray_parallel module procedure hdf5_read_double_2Darray_parallel @@ -134,7 +134,7 @@ contains end subroutine hdf5_file_close -#ifdef MPI +#ifdef PHDF5 !=============================================================================== ! HDF5_FILE_CREATE_PARALLEL creates HDF5 file with parallel I/O @@ -809,7 +809,7 @@ contains end subroutine hdf5_write_attribute_string -# ifdef MPI +#ifdef PHDF5 !=============================================================================== ! HDF5_WRITE_INTEGER_PARALLEL writes integer scalar data in parallel @@ -1807,6 +1807,6 @@ contains end subroutine hdf5_read_string_parallel -# endif +#endif end module hdf5_interface diff --git a/src/output_interface.F90 b/src/output_interface.F90 index 7ced3c052..1e08ce491 100644 --- a/src/output_interface.F90 +++ b/src/output_interface.F90 @@ -96,7 +96,7 @@ contains self % serial = .true. end if -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_file_create(filename, self % hdf5_fh) else @@ -126,7 +126,7 @@ contains self % serial = .true. end if -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_file_open(filename, self % hdf5_fh, mode) else @@ -212,7 +212,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_double(self % hdf5_grp, name_, buffer) else @@ -263,7 +263,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_double(self % hdf5_grp, name_, buffer) else @@ -315,7 +315,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_double_1Darray(self % hdf5_grp, name_, buffer, length) else @@ -368,7 +368,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_double_1Darray(self % hdf5_grp, name_, buffer, length) else @@ -421,7 +421,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_double_2Darray(self % hdf5_grp, name_, buffer, length) else @@ -474,7 +474,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_double_2Darray(self % hdf5_grp, name_, buffer, length) else @@ -527,7 +527,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_double_3Darray(self % hdf5_grp, name_, buffer, length) else @@ -580,7 +580,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_double_3Darray(self % hdf5_grp, name_, buffer, length) else @@ -634,7 +634,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_double_4Darray(self % hdf5_grp, name_, buffer, length) else @@ -689,7 +689,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_double_4Darray(self % hdf5_grp, name_, buffer, length) else @@ -741,7 +741,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_integer(self % hdf5_grp, name_, buffer) else @@ -792,7 +792,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_integer(self % hdf5_grp, name_, buffer) else @@ -844,7 +844,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_integer_1Darray(self % hdf5_grp, name_, buffer, length) else @@ -897,7 +897,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_integer_1Darray(self % hdf5_grp, name_, buffer, length) else @@ -951,7 +951,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_integer_2Darray(self % hdf5_grp, name_, buffer, length) else @@ -1004,7 +1004,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_integer_2Darray(self % hdf5_grp, name_, buffer, length) else @@ -1057,7 +1057,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_integer_3Darray(self % hdf5_grp, name_, buffer, length) else @@ -1110,7 +1110,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_integer_3Darray(self % hdf5_grp, name_, buffer, length) else @@ -1164,7 +1164,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_integer_4Darray(self % hdf5_grp, name_, buffer, length) else @@ -1218,7 +1218,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_integer_4Darray(self % hdf5_grp, name_, buffer, length) else @@ -1270,7 +1270,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) else @@ -1322,7 +1322,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) else @@ -1378,7 +1378,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_write_string(self % hdf5_grp, name_, buffer, n) else @@ -1434,7 +1434,7 @@ contains else self % hdf5_grp = self % hdf5_fh endif -#ifdef MPI +#ifdef PHDF5 if (self % serial) then call hdf5_read_string(self % hdf5_grp, name_, buffer, n) else @@ -1579,11 +1579,11 @@ contains class(BinaryOutput) :: self -#ifdef MPI +#ifdef PHDF5 integer(8) :: offset(1) ! source data offset #endif -#ifdef MPI +#ifdef PHDF5 ! Set size of total dataspace for all procs and rank dims1(1) = n_particles @@ -1662,11 +1662,11 @@ contains class(BinaryOutput) :: self -#ifdef MPI +#ifdef PHDF5 integer(8) :: offset(1) ! offset of data #endif -#ifdef MPI +#ifdef PHDF5 ! Set size of total dataspace for all procs and rank dims1(1) = n_particles diff --git a/tests/run_tests.py b/tests/run_tests.py index aa2eb14cf..d3b79aa3b 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -107,12 +107,13 @@ tests = OrderedDict() class Test(object): def __init__(self, name, debug=False, optimize=False, mpi=False, openmp=False, - valgrind=False, coverage=False): + phdf5=False, valgrind=False, coverage=False): self.name = name self.debug = debug self.optimize = optimize self.mpi = mpi self.openmp = openmp + self.phdf5 = phdf5 self.valgrind = valgrind self.coverage = coverage self.success = True @@ -125,9 +126,9 @@ class Test(object): # Check for MPI if self.mpi: - self.fc = PHDF5_DIR + '/bin/h5pfc' + self.fc = os.path.join(MPI_DIR, 'bin', 'mpifort') else: - self.fc = HDF5_DIR + '/bin/h5fc' + self.fc = FC # Sets the build name that will show up on the CDash def get_build_name(self): @@ -159,6 +160,10 @@ class Test(object): os.environ['FC'] = self.fc if self.mpi: os.environ['MPI_DIR'] = MPI_DIR + if self.phdf5: + os.environ['HDF5_ROOT'] = PHDF5_DIR + else: + os.environ['HDF5_ROOT'] = HDF5_DIR rc = call(['ctest', '-S', 'ctestscript.run','-V']) if rc != 0: self.success = False @@ -169,6 +174,10 @@ class Test(object): os.environ['FC'] = self.fc if self.mpi: os.environ['MPI_DIR'] = MPI_DIR + if self.phdf5: + os.environ['HDF5_ROOT'] = PHDF5_DIR + else: + os.environ['HDF5_ROOT'] = HDF5_DIR build_opts = self.build_opts.split() self.cmake += build_opts rc = call(self.cmake) @@ -258,8 +267,8 @@ class Test(object): # Simple function to add a test to the global tests dictionary def add_test(name, debug=False, optimize=False, mpi=False, openmp=False,\ - valgrind=False, coverage=False): - tests.update({name: Test(name, debug, optimize, mpi, openmp, + phdf5=False, valgrind=False, coverage=False): + tests.update({name: Test(name, debug, optimize, mpi, openmp, phdf5, valgrind, coverage)}) # List of all tests that may be run. User can add -C to command line to specify @@ -270,12 +279,15 @@ add_test('hdf5-optimize', optimize=True) add_test('omp-hdf5-normal', openmp=True) add_test('omp-hdf5-debug', openmp=True, debug=True) add_test('omp-hdf5-optimize', openmp=True, optimize=True) -add_test('phdf5-normal', mpi=True) -add_test('phdf5-debug', mpi=True, debug=True) -add_test('phdf5-optimize', mpi=True, optimize=True) -add_test('phdf5-omp-normal', mpi=True, openmp=True) -add_test('phdf5-omp-debug', mpi=True, openmp=True, debug=True) -add_test('phdf5-omp-optimize', mpi=True, openmp=True, optimize=True) +add_test('mpi-hdf5-normal', mpi=True) +add_test('mpi-hdf5-debug', mpi=True, debug=True) +add_test('mpi-hdf5-optimize', mpi=True, optimize=True) +add_test('phdf5-normal', mpi=True, phdf5=True) +add_test('phdf5-debug', mpi=True, phdf5=True, debug=True) +add_test('phdf5-optimize', mpi=True, phdf5=True, optimize=True) +add_test('phdf5-omp-normal', mpi=True, phdf5=True, openmp=True) +add_test('phdf5-omp-debug', mpi=True, phdf5=True, openmp=True, debug=True) +add_test('phdf5-omp-optimize', mpi=True, phdf5=True, openmp=True, optimize=True) add_test('hdf5-debug_valgrind', debug=True, valgrind=True) add_test('hdf5-debug_coverage', debug=True, coverage=True) From 3fb6f99ecdca38fb4050179f3f10b03ed26fac35 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 1 Sep 2015 09:54:49 +0700 Subject: [PATCH 07/95] Update FindHDF5 based on Brad King comments --- cmake/Modules/FindHDF5.cmake | 74 ++++++++++++++---------------------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/cmake/Modules/FindHDF5.cmake b/cmake/Modules/FindHDF5.cmake index 1631f0193..08ba0abaf 100644 --- a/cmake/Modules/FindHDF5.cmake +++ b/cmake/Modules/FindHDF5.cmake @@ -103,52 +103,39 @@ else() endforeach() endif() +# Determine whether to search for serial or parallel executable first if(HDF5_PREFER_PARALLEL) - # try to find the HDF5 wrapper compilers - find_program( HDF5_C_COMPILER_EXECUTABLE - NAMES h5pcc h5cc - HINTS ENV HDF5_ROOT - PATH_SUFFIXES bin Bin - DOC "HDF5 Wrapper compiler. Used only to detect HDF5 compile flags." ) - mark_as_advanced( HDF5_C_COMPILER_EXECUTABLE ) - - find_program( HDF5_CXX_COMPILER_EXECUTABLE - NAMES h5pc++ h5c++ - HINTS ENV HDF5_ROOT - PATH_SUFFIXES bin Bin - DOC "HDF5 C++ Wrapper compiler. Used only to detect HDF5 compile flags." ) - mark_as_advanced( HDF5_CXX_COMPILER_EXECUTABLE ) - - find_program( HDF5_Fortran_COMPILER_EXECUTABLE - NAMES h5pfc h5fc - HINTS ENV HDF5_ROOT - PATH_SUFFIXES bin Bin - DOC "HDF5 Fortran Wrapper compiler. Used only to detect HDF5 compile flags." ) - mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE ) + set(HDF5_C_COMPILER_NAMES h5pcc h5cc) + set(HDF5_CXX_COMPILER_NAMES h5pc++ h5c++) + set(HDF5_Fortran_COMPILER_NAMES h5pfc h5fc) else() - # try to find the HDF5 wrapper compilers - find_program( HDF5_C_COMPILER_EXECUTABLE - NAMES h5cc h5pcc - HINTS ENV HDF5_ROOT - PATH_SUFFIXES bin Bin - DOC "HDF5 Wrapper compiler. Used only to detect HDF5 compile flags." ) - mark_as_advanced( HDF5_C_COMPILER_EXECUTABLE ) - - find_program( HDF5_CXX_COMPILER_EXECUTABLE - NAMES h5c++ h5pc++ - HINTS ENV HDF5_ROOT - PATH_SUFFIXES bin Bin - DOC "HDF5 C++ Wrapper compiler. Used only to detect HDF5 compile flags." ) - mark_as_advanced( HDF5_CXX_COMPILER_EXECUTABLE ) - - find_program( HDF5_Fortran_COMPILER_EXECUTABLE - NAMES h5fc h5pfc - HINTS ENV HDF5_ROOT - PATH_SUFFIXES bin Bin - DOC "HDF5 Fortran Wrapper compiler. Used only to detect HDF5 compile flags." ) - mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE ) + set(HDF5_C_COMPILER_NAMES h5cc h5pcc) + set(HDF5_CXX_COMPILER_NAMES h5c++ h5pc++) + set(HDF5_Fortran_COMPILER_NAMES h5fc h5pfc) endif() +# try to find the HDF5 wrapper compilers +find_program( HDF5_C_COMPILER_EXECUTABLE + NAMES ${HDF5_C_COMPILER_NAMES} + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 Wrapper compiler. Used only to detect HDF5 compile flags." ) +mark_as_advanced( HDF5_C_COMPILER_EXECUTABLE ) + +find_program( HDF5_CXX_COMPILER_EXECUTABLE + NAMES ${HDF5_CXX_COMPILER_NAMES} + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 C++ Wrapper compiler. Used only to detect HDF5 compile flags." ) +mark_as_advanced( HDF5_CXX_COMPILER_EXECUTABLE ) + +find_program( HDF5_Fortran_COMPILER_EXECUTABLE + NAMES ${HDF5_Fortran_COMPILER_NAMES} + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 Fortran Wrapper compiler. Used only to detect HDF5 compile flags." ) +mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE ) + find_program( HDF5_DIFF_EXECUTABLE NAMES h5diff HINTS ENV HDF5_ROOT @@ -359,9 +346,6 @@ if( NOT HDF5_FOUND ) if( HDF5_LIBRARY_DIRS ) _remove_duplicates_from_beginning( HDF5_LIBRARY_DIRS ) endif() - if( HDF5_LIBRARIES ) - _remove_duplicates_from_beginning( HDF5_LIBRARIES ) - endif() # If the HDF5 include directory was found, open H5pubconf.h to determine if # HDF5 was compiled with parallel IO support From 779a401448b5d014535f6924861b04f5162ed62a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 1 Sep 2015 16:47:08 +0700 Subject: [PATCH 08/95] Have write_integer, write_double, and write_long use scalar values --- openmc/particle_restart.py | 39 +++----- openmc/statepoint.py | 182 +++++++++++++----------------------- scripts/openmc-track-to-vtk | 2 +- src/hdf5_interface.F90 | 85 ++++++----------- 4 files changed, 108 insertions(+), 200 deletions(-) diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py index 5ae534dbd..846c7d566 100644 --- a/openmc/particle_restart.py +++ b/openmc/particle_restart.py @@ -48,38 +48,23 @@ class Particle(object): def _read_data(self): # Read filetype - self.filetype = self._get_int(path='filetype')[0] + self.filetype = self._f['filetype'].value # Read statepoint revision - self.revision = self._get_int(path='revision')[0] + self.revision = self._f['revision'].value # Read current batch - self.current_batch = self._get_int(path='current_batch')[0] + self.current_batch = self._f['current_batch'].value # Read run information - self.gen_per_batch = self._get_int(path='gen_per_batch')[0] - self.current_gen = self._get_int(path='current_gen')[0] - self.n_particles = self._get_long(path='n_particles')[0] - self.run_mode = self._get_int(path='run_mode')[0] + self.gen_per_batch = self._f['gen_per_batch'].value + self.current_gen = self._f['current_gen'].value + self.n_particles = self._f['n_particles'].value + self.run_mode = self._f['run_mode'].value # Read particle properties - self.id = self._get_long(path='id')[0] - self.weight = self._get_double(path='weight')[0] - self.energy = self._get_double(path='energy')[0] - self.xyz = self._get_double(3, path='xyz') - self.uvw = self._get_double(3, path='uvw') - - def _get_int(self, n=1, path=None): - return [int(v) for v in self._f[path].value] - - def _get_long(self, n=1, path=None): - return [int(v) for v in self._f[path].value] - - def _get_float(self, n=1, path=None): - return [float(v) for v in self._f[path].value] - - def _get_double(self, n=1, path=None): - return [float(v) for v in self._f[path].value] - - def _get_string(self, n=1, path=None): - return str(self._f[path].value) + self.id = self._f['id'].value + self.weight = self._f['weight'].value + self.energy = self._f['energy'].value + self.xyz = self._f['xyz'].value + self.uvw = self._f['uvw'].value diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 673b41e17..af423b027 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -1,5 +1,4 @@ import copy -import struct import sys import numpy as np @@ -158,37 +157,37 @@ class StatePoint(object): def _read_metadata(self): # Read filetype - self._filetype = self._get_int(path='filetype')[0] + self._filetype = self._f['filetype'].value # Read statepoint revision - self._revision = self._get_int(path='revision')[0] + self._revision = self._f['revision'].value if self._revision != 13: raise Exception('Statepoint Revision is not consistent.') # Read OpenMC version - self._version = [self._get_int(path='version_major')[0], - self._get_int(path='version_minor')[0], - self._get_int(path='version_release')[0]] + self._version = [self._f['version_major'].value, + self._f['version_minor'].value, + self._f['version_release'].value] # Read date and time - self._date_and_time = self._get_string(19, path='date_and_time') + self._date_and_time = self._f['date_and_time'].value[0] # Read path - self._path = self._get_string(255, path='path').strip() + self._path = self._f['path'].value[0].strip() # Read random number seed - self._seed = self._get_long(path='seed')[0] + self._seed = self._f['seed'].value # Read run information - self._run_mode = self._get_int(path='run_mode')[0] - self._n_particles = self._get_long(path='n_particles')[0] - self._n_batches = self._get_int(path='n_batches')[0] + self._run_mode = self._f['run_mode'].value + self._n_particles = self._f['n_particles'].value + self._n_batches = self._f['n_batches'].value # Read current batch - self._current_batch = self._get_int(path='current_batch')[0] + self._current_batch = self._f['current_batch'].value # Read whether or not the source site distribution is present - self._source_present = self._get_int(path='source_present')[0] + self._source_present = self._f['source_present'].value # Read criticality information if self._run_mode == 2: @@ -198,18 +197,15 @@ class StatePoint(object): # Read criticality information if self._run_mode == 2: - self._n_inactive = self._get_int(path='n_inactive')[0] - self._gen_per_batch = self._get_int(path='gen_per_batch')[0] - self._k_batch = self._get_double( - self._current_batch*self._gen_per_batch, - path='k_generation') - self._entropy = self._get_double( - self._current_batch*self._gen_per_batch, path='entropy') + self._n_inactive = self._f['n_inactive'].value + self._gen_per_batch = self._f['gen_per_batch'].value + self._k_batch = self._f['k_generation'].value + self._entropy = self._f['entropy'].value - self._k_col_abs = self._get_double(path='k_col_abs')[0] - self._k_col_tra = self._get_double(path='k_col_tra')[0] - self._k_abs_tra = self._get_double(path='k_abs_tra')[0] - self._k_combined = self._get_double(2, path='k_combined') + self._k_col_abs = self._f['k_col_abs'].value + self._k_col_tra = self._f['k_col_tra'].value + self._k_abs_tra = self._f['k_abs_tra'].value + self._k_combined = self._f['k_combined'].value # Read CMFD information (if used) self._read_cmfd() @@ -218,25 +214,18 @@ class StatePoint(object): base = 'cmfd' # Read CMFD information - self._cmfd_on = self._get_int(path='cmfd_on')[0] + self._cmfd_on = self._f['cmfd_on'].value if self._cmfd_on == 1: - - self._cmfd_indices = self._get_int(4, path='{0}/indices'.format(base)) - self._k_cmfd = self._get_double(self._current_batch, - path='{0}/k_cmfd'.format(base)) - self._cmfd_src = self._get_double_array(np.product(self._cmfd_indices), - path='{0}/cmfd_src'.format(base)) + self._cmfd_indices = self._f['{0}/indices'.format(base)].value + self._k_cmfd = self._f['{0}/k_cmfd'.format(base)].value + self._cmfd_src = self._f['{0}/cmfd_src'.format(base)].value self._cmfd_src = np.reshape(self._cmfd_src, tuple(self._cmfd_indices), order='F') - self._cmfd_entropy = self._get_double(self._current_batch, - path='{0}/cmfd_entropy'.format(base)) - self._cmfd_balance = self._get_double(self._current_batch, - path='{0}/cmfd_balance'.format(base)) - self._cmfd_dominance = self._get_double(self._current_batch, - path='{0}/cmfd_dominance'.format(base)) - self._cmfd_srccmp = self._get_double(self._current_batch, - path='{0}/cmfd_srccmp'.format(base)) + self._cmfd_entropy = self._f['{0}/cmfd_entropy'.format(base)].value + self._cmfd_balance = self._f['{0}/cmfd_balance'.format(base)].value + self._cmfd_dominance = self._f['{0}/cmfd_dominance'.format(base)].value + self._cmfd_srccmp = self._f['{0}/cmfd_srccmp'.format(base)].value def _read_meshes(self): # Initialize dictionaries for the Meshes @@ -245,18 +234,16 @@ class StatePoint(object): self._meshes = {} # Read the number of Meshes - self._n_meshes = self._get_int(path='tallies/meshes/n_meshes')[0] + self._n_meshes = self._f['tallies/meshes/n_meshes'].value # Read a list of the IDs for each Mesh if self._n_meshes > 0: # OpenMC Mesh IDs (redefined internally from user definitions) - self._mesh_ids = self._get_int(self._n_meshes, - path='tallies/meshes/ids') + self._mesh_ids = self._f['tallies/meshes/ids'].value # User-defined Mesh IDs - self._mesh_keys = self._get_int(self._n_meshes, - path='tallies/meshes/keys') + self._mesh_keys = self._f['tallies/meshes/keys'].value else: self._mesh_keys = [] @@ -269,23 +256,18 @@ class StatePoint(object): for mesh_key in self._mesh_keys: # Read the user-specified Mesh ID and type - mesh_id = self._get_int(path='{0}{1}/id'.format(base, mesh_key))[0] - mesh_type = self._get_int(path='{0}{1}/type'.format(base, mesh_key))[0] + mesh_id = self._f['{0}{1}/id'.format(base, mesh_key)].value + mesh_type = self._f['{0}{1}/type'.format(base, mesh_key)].value # Get the Mesh dimension - n_dimension = self._get_int( - path='{0}{1}/n_dimension'.format(base, mesh_key))[0] + n_dimension = self._f['{0}{1}/n_dimension'.format(base, mesh_key)].value # Read the mesh dimensions, lower-left coordinates, # upper-right coordinates, and width of each mesh cell - dimension = self._get_int( - n_dimension, path='{0}{1}/dimension'.format(base, mesh_key)) - lower_left = self._get_double( - n_dimension, path='{0}{1}/lower_left'.format(base, mesh_key)) - upper_right = self._get_double( - n_dimension, path='{0}{1}/upper_right'.format(base, mesh_key)) - width = self._get_double( - n_dimension, path='{0}{1}/width'.format(base, mesh_key)) + dimension = self._f['{0}{1}/dimension'.format(base, mesh_key)].value + lower_left = self._f['{0}{1}/lower_left'.format(base, mesh_key)].value + upper_right = self._f['{0}{1}/upper_right'.format(base, mesh_key)].value + width = self._f['{0}{1}/width'.format(base, mesh_key)].value # Create the Mesh and assign properties to it mesh = openmc.Mesh(mesh_id) @@ -308,18 +290,16 @@ class StatePoint(object): self._tallies = {} # Read the number of tallies - self._n_tallies = self._get_int(path='/tallies/n_tallies')[0] + self._n_tallies = self._f['/tallies/n_tallies'].value # Read a list of the IDs for each Tally if self._n_tallies > 0: # OpenMC Tally IDs (redefined internally from user definitions) - self._tally_ids = self._get_int( - self._n_tallies, path='tallies/ids') + self._tally_ids = self._f['tallies/ids'].value # User-defined Tally IDs - self._tally_keys = self._get_int( - self._n_tallies, path='tallies/keys') + self._tally_keys = self._f['tallies/keys'].value else: self._tally_keys = [] @@ -331,12 +311,10 @@ class StatePoint(object): for tally_key in self._tally_keys: # Read integer Tally estimator type code (analog or tracklength) - estimator_type = self._get_int( - path='{0}{1}/estimator'.format(base, tally_key))[0] + estimator_type = self._f['{0}{1}/estimator'.format(base, tally_key)].value # Read the Tally size specifications - n_realizations = self._get_int( - path='{0}{1}/n_realizations'.format(base, tally_key))[0] + n_realizations = self._f['{0}{1}/n_realizations'.format(base, tally_key)].value # Create Tally object and assign basic properties tally = openmc.Tally(tally_key) @@ -344,8 +322,7 @@ class StatePoint(object): tally.num_realizations = n_realizations # Read the number of Filters - n_filters = self._get_int( - path='{0}{1}/n_filters'.format(base, tally_key))[0] + n_filters = self._f['{0}{1}/n_filters'.format(base, tally_key)].value subbase = '{0}{1}/filter '.format(base, tally_key) @@ -353,15 +330,12 @@ class StatePoint(object): for j in range(1, n_filters+1): # Read the integer Filter type code - filter_type = self._get_int( - path='{0}{1}/type'.format(subbase, j))[0] + filter_type = self._f['{0}{1}/type'.format(subbase, j)].value # Read the Filter offset - offset = self._get_int( - path='{0}{1}/offset'.format(subbase, j))[0] + offset = self._f['{0}{1}/offset'.format(subbase, j)].value - n_bins = self._get_int( - path='{0}{1}/n_bins'.format(subbase, j))[0] + n_bins = self._f['{0}{1}/n_bins'.format(subbase, j)].value if n_bins <= 0: msg = 'Unable to create Filter "{0}" for Tally ID="{1}" ' \ @@ -370,16 +344,13 @@ class StatePoint(object): # Read the bin values if FILTER_TYPES[filter_type] in ['energy', 'energyout']: - bins = self._get_double( - n_bins+1, path='{0}{1}/bins'.format(subbase, j)) + bins = self._f['{0}{1}/bins'.format(subbase, j)].value elif FILTER_TYPES[filter_type] in ['mesh', 'distribcell']: - bins = self._get_int( - path='{0}{1}/bins'.format(subbase, j))[0] + bins = self._f['{0}{1}/bins'.format(subbase, j)].value else: - bins = self._get_int( - n_bins, path='{0}{1}/bins'.format(subbase, j)) + bins = self._f['{0}{1}/bins'.format(subbase, j)].value # Create Filter object filter = openmc.Filter(FILTER_TYPES[filter_type], bins) @@ -387,33 +358,30 @@ class StatePoint(object): filter.num_bins = n_bins if FILTER_TYPES[filter_type] == 'mesh': - key = self._mesh_keys[self._mesh_ids.index(bins)] + key = self._mesh_keys[list(self._mesh_ids).index(bins)] filter.mesh = self._meshes[key] # Add Filter to the Tally tally.add_filter(filter) # Read Nuclide bins - n_nuclides = self._get_int( - path='{0}{1}/n_nuclides'.format(base, tally_key))[0] + n_nuclides = self._f['{0}{1}/n_nuclides'.format(base, tally_key)].value - nuclide_zaids = self._get_int( - n_nuclides, path='{0}{1}/nuclides'.format(base, tally_key)) + nuclide_zaids = self._f['{0}{1}/nuclides'.format(base, tally_key)].value # Add all Nuclides to the Tally for nuclide_zaid in nuclide_zaids: tally.add_nuclide(nuclide_zaid) # Read score bins - n_score_bins = self._get_int( - path='{0}{1}/n_score_bins'.format(base, tally_key))[0] + n_score_bins = self._f['{0}{1}/n_score_bins'.format(base, tally_key)].value tally.num_score_bins = n_score_bins - scores = [SCORE_TYPES[j] for j in self._get_int( - n_score_bins, path='{0}{1}/score_bins'.format(base, tally_key))] - n_user_scores = self._get_int( - path='{0}{1}/n_user_score_bins'.format(base, tally_key))[0] + scores = [SCORE_TYPES[j] for j in self._f[ + '{0}{1}/score_bins'.format(base, tally_key)].value] + n_user_scores = self._f['{0}{1}/n_user_score_bins' + .format(base, tally_key)].value # Compute and set the filter strides for i in range(n_filters): @@ -429,8 +397,8 @@ class StatePoint(object): # Extract the moment order string for each score for k in range(len(scores)): - moment = self._get_string(8, - path='{0}order{1}'.format(subbase, k+1)) + moment = str(self._f['{0}order{1}'.format( + subbase, k+1)].value[0]) moment = moment.lstrip('[\'') moment = moment.rstrip('\']') @@ -460,16 +428,16 @@ class StatePoint(object): """ # Number of realizations for global Tallies - self._n_realizations = self._get_int(path='n_realizations')[0] + self._n_realizations = self._f['n_realizations'].value # Read global Tallies - n_global_tallies = self._get_int(path='n_global_tallies')[0] + n_global_tallies = self._f['n_global_tallies'].value data = self._f['global_tallies'].value self._global_tallies = np.column_stack((data['sum'], data['sum_sq'])) # Flag indicating if Tallies are present - self._tallies_present = self._get_int(path='tallies/tallies_present')[0] + self._tallies_present = self._f['tallies/tallies_present'].value base = 'tallies/tally ' @@ -766,25 +734,3 @@ class StatePoint(object): filter.bins = material_ids self._with_summary = True - - def _get_data(self, n, typeCode, size): - return list(struct.unpack('={0}{1}'.format(n, typeCode), - self._f.read(n*size))) - - def _get_int(self, n=1, path=None): - return [int(v) for v in self._f[path].value] - - def _get_long(self, n=1, path=None): - return [long(v) for v in self._f[path].value] - - def _get_float(self, n=1, path=None): - return [float(v) for v in self._f[path].value] - - def _get_double(self, n=1, path=None): - return [float(v) for v in self._f[path].value] - - def _get_double_array(self, n=1, path=None): - return self._f[path].value - - def _get_string(self, n=1, path=None): - return str(self._f[path].value) diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index f44b3871a..434cd3bb0 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -82,7 +82,7 @@ def main(): else: track = h5py.File(fname) - n_particles = track['n_particles'].value[0] + n_particles = track['n_particles'].value n_coords = track['n_coords'] coords = [] for i in range(n_particles): diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 28ac445ab..b22d0414f 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -246,14 +246,17 @@ contains integer(HID_T), intent(in) :: group ! name of group character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer ! data to write + integer, target, intent(in) :: buffer ! data to write - ! Set rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 + ! Create space, dataset, and write + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims1, & - (/ buffer /), hdf5_err) + ! Close all + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) end subroutine hdf5_write_integer @@ -265,16 +268,12 @@ contains integer(HID_T), intent(in) :: group ! name of group character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer ! read data to here + integer, target, intent(inout) :: buffer ! read data to here - integer :: buffer_copy(1) ! need an array for read - - ! Set up dimensions - dims1(1) = 1 - - ! Read data - call h5ltread_dataset_int_f(group, name, buffer_copy, dims1, hdf5_err) - buffer = buffer_copy(1) + call h5dopen_f(group, name, dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) end subroutine hdf5_read_integer @@ -450,14 +449,17 @@ contains integer(HID_T), intent(in) :: group ! name of group character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer ! data to write + real(8), target, intent(in) :: buffer ! data to write - ! Set rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 + ! Create space, dataset, and write + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims1, & - (/ buffer /), hdf5_err) + ! Close all + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) end subroutine hdf5_write_double @@ -469,16 +471,12 @@ contains integer(HID_T), intent(in) :: group ! name of group character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer ! read data to here + real(8), target, intent(inout) :: buffer ! read data to here - real(8) :: buffer_copy(1) ! need an array for read - - ! Set up dimensions - dims1(1) = 1 - - ! Read data - call h5ltread_dataset_double_f(group, name, buffer_copy, dims1, hdf5_err) - buffer = buffer_copy(1) + call h5dopen_f(group, name, dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) end subroutine hdf5_read_double @@ -657,15 +655,9 @@ contains integer(8), target, intent(in) :: buffer ! data to write integer(HID_T), intent(in) :: long_type ! HDF5 long type - ! Set up rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - ! Create dataspace and dataset - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) call h5dcreate_f(group, name, long_type, dspace, dset, hdf5_err) - - ! Write eight-byte integer f_ptr = c_loc(buffer) call h5dwrite_f(dset, long_type, f_ptr, hdf5_err) @@ -686,16 +678,9 @@ contains integer(8), target, intent(out) :: buffer ! read data to here integer(HID_T), intent(in) :: long_type ! long integer type - ! Open dataset call h5dopen_f(group, name, dset, hdf5_err) - - ! Get pointer to buffer f_ptr = c_loc(buffer) - - ! Read data from dataset call h5dread_f(dset, long_type, f_ptr, hdf5_err) - - ! Close dataset call h5dclose_f(dset, hdf5_err) end subroutine hdf5_read_long @@ -822,10 +807,6 @@ contains integer,target, intent(in) :: buffer ! data to write logical, intent(in) :: collect ! collect I/O - ! Set rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - ! Create property list for independent or collective read call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) @@ -837,7 +818,7 @@ contains end if ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) ! Create dataset call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) @@ -1222,10 +1203,6 @@ contains real(8),target, intent(in) :: buffer ! data to write logical, intent(in) :: collect ! collect I/O - ! Set rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - ! Create property list for independent or collective read call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) @@ -1237,7 +1214,7 @@ contains end if ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) ! Create dataset call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) From dce020b59e59da41b34ebc901631455a66f4207e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 1 Sep 2015 16:51:11 +0700 Subject: [PATCH 09/95] Remove logic for binary file in openmc-track-to-vtk --- scripts/openmc-track-to-vtk | 46 +++++++++---------------------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index 434cd3bb0..c900c4aa5 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -18,6 +18,7 @@ Usage information can be obtained by running 'track.py --help': import os import argparse +import h5py import struct import vtk @@ -41,9 +42,8 @@ def main(): # Check input file extensions. for fname in args.input: - if not (fname.endswith('.h5') or fname.endswith('.binary')): - raise ValueError("Input file names must either end with '.h5' or" - "'.binary'.") + if not fname.endswith('.h5'): + raise ValueError("Input file names must an HDF5 file.") # Make sure that the output filename ends with '.pvtp'. if not args.out: @@ -51,44 +51,20 @@ def main(): elif not args.out.endswith('.pvtp'): args.out += '.pvtp' - # Import HDF library if HDF files are present - for fname in args.input: - if fname.endswith('.h5'): - import h5py - break - # Initialize data arrays and offset. points = vtk.vtkPoints() cells = vtk.vtkCellArray() point_offset = 0 for fname in args.input: # Write coordinate values to points array. - if fname.endswith('.binary'): - track = open(fname, 'rb') - - # Determine number of particles and tracks/particle - n_particles = struct.unpack('i', track.read(4))[0] - n_coords = struct.unpack('i'*n_particles, track.read(4*n_particles)) - - coords = [] - for i in range(n_particles): - # Read coordinates for each particle - coords.append([struct.unpack('ddd', track.read(24)) - for j in range(n_coords[i])]) - - # Add coordinates to points data - for triplet in coords[i]: - points.InsertNextPoint(triplet) - - else: - track = h5py.File(fname) - n_particles = track['n_particles'].value - n_coords = track['n_coords'] - coords = [] - for i in range(n_particles): - coords.append(track['coordinates_' + str(i + 1)].value) - for j in range(n_coords[i]): - points.InsertNextPoint(coords[i][j,:]) + track = h5py.File(fname) + n_particles = track['n_particles'].value + n_coords = track['n_coords'] + coords = [] + for i in range(n_particles): + coords.append(track['coordinates_' + str(i + 1)].value) + for j in range(n_coords[i]): + points.InsertNextPoint(coords[i][j,:]) for i in range(n_particles): # Create VTK line and assign points to line. From 205be92897f435a88679c3b6c703cf078a8c0f74 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 2 Sep 2015 09:43:13 +0700 Subject: [PATCH 10/95] Complete rewrite of hdf5_interface with a flat API --- src/bank_header.F90 | 17 +- src/global.F90 | 9 - src/hdf5_interface.F90 | 3389 ++++++++++++++++++++-------------------- src/tally_header.F90 | 9 +- 4 files changed, 1743 insertions(+), 1681 deletions(-) diff --git a/src/bank_header.F90 b/src/bank_header.F90 index 1a91f86f7..499358120 100644 --- a/src/bank_header.F90 +++ b/src/bank_header.F90 @@ -1,5 +1,7 @@ module bank_header + use, intrinsic :: ISO_C_BINDING + implicit none !=============================================================================== @@ -8,16 +10,11 @@ module bank_header ! stored with less memory !=============================================================================== - type Bank - ! The 'sequence' attribute is used here to ensure that the data listed - ! appears in the given order. This is important for MPI purposes when bank - ! sites are sent from one processor to another. - sequence - - real(8) :: wgt ! weight of bank site - real(8) :: xyz(3) ! location of bank particle - real(8) :: uvw(3) ! diretional cosines - real(8) :: E ! energy + type, bind(C) :: Bank + real(C_DOUBLE) :: wgt ! weight of bank site + real(C_DOUBLE) :: xyz(3) ! location of bank particle + real(C_DOUBLE) :: uvw(3) ! diretional cosines + real(C_DOUBLE) :: E ! energy end type Bank end module bank_header diff --git a/src/global.F90 b/src/global.F90 index ae2f5bb27..0c5e38212 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -16,7 +16,6 @@ module global use trigger_header, only: KTrigger use timer_header, only: Timer - use hdf5_interface, only: HID_T #ifdef MPIF08 use mpi_f08 #endif @@ -265,14 +264,6 @@ module global real(8) :: weight_cutoff = 0.25_8 real(8) :: weight_survive = ONE - ! ============================================================================ - ! HDF5 VARIABLES - - integer(HID_T) :: hdf5_output_file ! identifier for output file - integer(HID_T) :: hdf5_tallyresult_t ! Compound type for TallyResult - integer(HID_T) :: hdf5_bank_t ! Compound type for Bank - integer(HID_T) :: hdf5_integer8_t ! type for integer(8) - ! ============================================================================ ! MISCELLANEOUS VARIABLES diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index b22d0414f..041e948ff 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1,5 +1,15 @@ module hdf5_interface + ! This module provides the high-level procedures which greatly simplify + ! writing/reading different types of data to HDF5 files. In order to get it to + ! work with gfotran 4.6, all the write__ND subroutines had to be split + ! into two procedures, one accepting an assumed-shape array and another one + ! with an explicit-shape array since in gfortran 4.6 C_LOC does not work with + ! an assumed-shape array. When we move to gfortran 4.9+, these procedures can + ! be combined into one simply accepting an assumed-shape array. + + use tally_header, only: TallyResult + use hdf5 use h5lt use, intrinsic :: ISO_C_BINDING @@ -9,1781 +19,1844 @@ module hdf5_interface #endif implicit none + private - integer :: hdf5_err ! HDF5 error code - integer :: hdf5_rank ! rank of data - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - integer(HID_T) :: memspace ! data space handle for individual procs - integer(HID_T) :: plist ! property list handle - integer(HSIZE_T) :: dims1(1) ! dims type for 1-D array - integer(HSIZE_T) :: dims2(2) ! dims type for 2-D array - integer(HSIZE_T) :: dims3(3) ! dims type for 3-D array - integer(HSIZE_T) :: dims4(4) ! dims type for 4-D array - type(c_ptr) :: f_ptr ! pointer to data + integer(HID_T), public :: hdf5_tallyresult_t ! Compound type for TallyResult + integer(HID_T), public :: hdf5_bank_t ! Compound type for Bank + integer(HID_T), public :: hdf5_integer8_t ! type for integer(8) - ! Generic HDF5 write procedure interface - interface hdf5_write_data - module procedure hdf5_write_double - module procedure hdf5_write_double_1Darray - module procedure hdf5_write_double_2Darray - module procedure hdf5_write_double_3Darray - module procedure hdf5_write_double_4Darray - module procedure hdf5_write_integer - module procedure hdf5_write_integer_1Darray - module procedure hdf5_write_integer_2Darray - module procedure hdf5_write_integer_3Darray - module procedure hdf5_write_integer_4Darray - module procedure hdf5_write_long - module procedure hdf5_write_string -#ifdef PHDF5 - module procedure hdf5_write_double_parallel - module procedure hdf5_write_double_1Darray_parallel - module procedure hdf5_write_double_2Darray_parallel - module procedure hdf5_write_double_3Darray_parallel - module procedure hdf5_write_double_4Darray_parallel - module procedure hdf5_write_integer_parallel - module procedure hdf5_write_integer_1Darray_parallel - module procedure hdf5_write_integer_2Darray_parallel - module procedure hdf5_write_integer_3Darray_parallel - module procedure hdf5_write_integer_4Darray_parallel - module procedure hdf5_write_long_parallel - module procedure hdf5_write_string_parallel -#endif - end interface hdf5_write_data + interface write_dataset + module procedure write_double + module procedure write_double_1D + module procedure write_double_2D + module procedure write_double_3D + module procedure write_double_4D + module procedure write_integer + module procedure write_integer_1D + module procedure write_integer_2D + module procedure write_integer_3D + module procedure write_integer_4D + module procedure write_long + module procedure write_string + module procedure write_tally_result_1D + module procedure write_tally_result_2D + end interface write_dataset - ! Generic HDF5 read procedure interface - interface hdf5_read_data - module procedure hdf5_read_double - module procedure hdf5_read_double_1Darray - module procedure hdf5_read_double_2Darray - module procedure hdf5_read_double_3Darray - module procedure hdf5_read_double_4Darray - module procedure hdf5_read_integer - module procedure hdf5_read_integer_1Darray - module procedure hdf5_read_integer_2Darray - module procedure hdf5_read_integer_3Darray - module procedure hdf5_read_integer_4Darray - module procedure hdf5_read_long - module procedure hdf5_read_string -#ifdef PHDF5 - module procedure hdf5_read_double_parallel - module procedure hdf5_read_double_1Darray_parallel - module procedure hdf5_read_double_2Darray_parallel - module procedure hdf5_read_double_3Darray_parallel - module procedure hdf5_read_double_4Darray_parallel - module procedure hdf5_read_integer_parallel - module procedure hdf5_read_integer_1Darray_parallel - module procedure hdf5_read_integer_2Darray_parallel - module procedure hdf5_read_integer_3Darray_parallel - module procedure hdf5_read_integer_4Darray_parallel - module procedure hdf5_read_long_parallel - module procedure hdf5_read_string_parallel -#endif - end interface hdf5_read_data + interface read_dataset + module procedure read_double + module procedure read_double_1D + module procedure read_double_2D + module procedure read_double_3D + module procedure read_double_4D + module procedure read_integer + module procedure read_integer_1D + module procedure read_integer_2D + module procedure read_integer_3D + module procedure read_integer_4D + module procedure read_long + module procedure read_string + module procedure read_tally_result_1D + module procedure read_tally_result_2D + end interface read_dataset + + public :: write_dataset + public :: read_dataset + public :: file_create + public :: file_open + public :: file_close + public :: open_group + public :: close_group + public :: write_source_bank + public :: read_source_bank + public :: write_attribute_string contains !=============================================================================== -! HDF5_FILE_CREATE creates HDF5 file +! FILE_CREATE creates HDF5 file !=============================================================================== - subroutine hdf5_file_create(filename, file_id) + function file_create(filename, parallel) result(file_id) + character(*), intent(in) :: filename ! name of file + logical, optional, intent(in) :: parallel ! whether to write in serial + integer(HID_T) :: file_id - character(*), intent(in) :: filename ! name of file - integer(HID_T), intent(inout) :: file_id ! file handle + integer(HID_T) :: plist ! property list handle + integer :: hdf5_err ! HDF5 error code + logical :: parallel_ - ! Create the file - call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err) + ! Check for serial option + if (present(parallel)) then + parallel_ = parallel + else + parallel_ = .false. + end if - end subroutine hdf5_file_create + if (parallel_) then + ! Setup file access property list with parallel I/O access + call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) +#ifdef PHDF5 +#ifdef MPIF08 + call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD%MPI_VAL, & + MPI_INFO_NULL%MPI_VAL, hdf5_err) +#else + call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD, MPI_INFO_NULL, hdf5_err) +#endif +#endif + + ! Create the file collectively + call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err, & + access_prp = plist) + + ! Close the property list + call h5pclose_f(plist, hdf5_err) + else + ! Create the file + call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err) + end if + + end function file_create !=============================================================================== -! HDF5_FILE_OPEN opens HDF5 file +! FILE_OPEN opens HDF5 file !=============================================================================== - subroutine hdf5_file_open(filename, file_id, mode) + function file_open(filename, mode, parallel) result(file_id) + character(*), intent(in) :: filename ! name of file + character(*), intent(in) :: mode ! access mode to file + logical, optional, intent(in) :: parallel ! whether to write in serial + integer(HID_T) :: file_id - character(*), intent(in) :: filename ! name of file - character(*), intent(in) :: mode ! access mode to file - integer(HID_T), intent(inout) :: file_id ! file handle + logical :: parallel_ + integer(HID_T) :: plist ! property list handle + integer :: hdf5_err ! HDF5 error code + integer :: open_mode ! HDF5 open mode - integer :: open_mode ! HDF5 open mode + ! Check for serial option + if (present(parallel)) then + parallel_ = parallel + else + parallel_ = .false. + end if ! Determine access type open_mode = H5F_ACC_RDONLY_F - if (trim(mode) == 'w') then - open_mode = H5F_ACC_RDWR_F - end if - - ! Open file - call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err) - - end subroutine hdf5_file_open - -!=============================================================================== -! HDF5_FILE_CLOSE closes HDF5 file -!=============================================================================== - - subroutine hdf5_file_close(file_id) - - integer(HID_T), intent(inout) :: file_id ! file handle - - ! Close the file - call h5fclose_f(file_id, hdf5_err) - - end subroutine hdf5_file_close + if (trim(mode) == 'w') open_mode = H5F_ACC_RDWR_F + if (parallel_) then + ! Setup file access property list with parallel I/O access + call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) #ifdef PHDF5 - -!=============================================================================== -! HDF5_FILE_CREATE_PARALLEL creates HDF5 file with parallel I/O -!=============================================================================== - - subroutine hdf5_file_create_parallel(filename, file_id) - - character(*), intent(in) :: filename ! name of file - integer(HID_T), intent(inout) :: file_id ! file handle - - ! Setup file access property list with parallel I/O access - call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) #ifdef MPIF08 - call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD%MPI_VAL, & - MPI_INFO_NULL%MPI_VAL, hdf5_err) + call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD%MPI_VAL, & + MPI_INFO_NULL%MPI_VAL, hdf5_err) #else - call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD, MPI_INFO_NULL, hdf5_err) + call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD, MPI_INFO_NULL, hdf5_err) +#endif #endif - ! Create the file collectively - call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err, & + ! Open the file collectively + call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err, & access_prp = plist) - ! Close the property list - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_file_create_parallel - -!=============================================================================== -! HDF5_FILE_OPEN_PARALLEL opens HDF5 file with parallel I/O -!=============================================================================== - - subroutine hdf5_file_open_parallel(filename, file_id, mode) - - character(*), intent(in) :: filename ! name of file - character(*), intent(in) :: mode ! access mode - integer(HID_T), intent(inout) :: file_id ! file handle - - integer :: open_mode ! HDF5 access mode - - ! Setup file access property list with parallel I/O access - call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) -#ifdef MPIF08 - call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD%MPI_VAL, & - MPI_INFO_NULL%MPI_VAL, hdf5_err) -#else - call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD, MPI_INFO_NULL, hdf5_err) -#endif - - ! Determine access type - open_mode = H5F_ACC_RDONLY_F - if (trim(mode) == 'w') then - open_mode = H5F_ACC_RDWR_F + ! Close the property list + call h5pclose_f(plist, hdf5_err) + else + ! Open file + call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err) end if - ! Create the file collectively - call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err, & - access_prp = plist) - - ! Close the property list - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_file_open_parallel - -#endif + end function file_open !=============================================================================== -! HDF5_OPEN_GROUP creates/opens HDF5 group to temp_group +! FILE_CLOSE closes HDF5 file !=============================================================================== - subroutine hdf5_open_group(hdf5_fh, group, hdf5_grp) + subroutine file_close(file_id) + integer(HID_T), intent(in) :: file_id - character(*), intent(in) :: group ! name of group - integer(HID_T), intent(in) :: hdf5_fh ! file handle of main output file - integer(HID_T), intent(inout) :: hdf5_grp ! handle for group + integer :: hdf5_err - logical :: status ! does the group exist + call h5fclose_f(file_id, hdf5_err) + end subroutine file_close + +!=============================================================================== +! OPEN_GROUP opens an existing HDF5 group +!=============================================================================== + + function open_group(group_id, name) result(newgroup_id) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of group + integer(HID_T) :: newgroup_id + + logical :: exists ! does the group exist + integer :: hdf5_err ! HDF5 error code ! Check if group exists - call h5ltpath_valid_f(hdf5_fh, trim(group), .true., status, hdf5_err) + call h5ltpath_valid_f(group_id, trim(name), .true., exists, hdf5_err) ! Either create or open group - if (status) then - call h5gopen_f(hdf5_fh, trim(group), hdf5_grp, hdf5_err) - else - call h5gcreate_f(hdf5_fh, trim(group), hdf5_grp, hdf5_err) + if (exists) call h5gopen_f(group_id, trim(name), newgroup_id, hdf5_err) + end function open_group + +!=============================================================================== +! CREATE_GROUP creates a new HDF5 group +!=============================================================================== + + function create_group(group_id, name) result(newgroup_id) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of group + integer(HID_T) :: newgroup_id + + integer :: hdf5_err ! HDF5 error code + logical :: exists ! does the group exist + + ! Check if group exists + call h5ltpath_valid_f(group_id, trim(name), .true., exists, hdf5_err) + + ! create group + if (.not. exists) & + call h5gcreate_f(group_id, trim(name), newgroup_id, hdf5_err) + end function create_group + +!=============================================================================== +! CLOSE_GROUP closes HDF5 temp_group +!=============================================================================== + + subroutine close_group(group_id) + integer(HID_T), intent(inout) :: group_id + + integer :: hdf5_err ! HDF5 error code + + call h5gclose_f(group_id, hdf5_err) + end subroutine close_group + +!=============================================================================== +! WRITE_DOUBLE writes double precision scalar data +!=============================================================================== + + subroutine write_double(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + real(8), intent(in), target :: buffer ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up independentive vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F end if - end subroutine hdf5_open_group - -!=============================================================================== -! HDF5_CLOSE_GROUP closes HDF5 temp_group -!=============================================================================== - - subroutine hdf5_close_group(hdf5_grp) - - integer(HID_T), intent(inout) :: hdf5_grp - - ! Close the group - call h5gclose_f(hdf5_grp, hdf5_err) - - end subroutine hdf5_close_group - -!=============================================================================== -! HDF5_WRITE_INTEGER writes integer scalar data -!=============================================================================== - - subroutine hdf5_write_integer(group, name, buffer) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, target, intent(in) :: buffer ! data to write - - ! Create space, dataset, and write - call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - - end subroutine hdf5_write_integer - -!=============================================================================== -! HDF5_READ_INTEGER reads integer scalar data -!=============================================================================== - - subroutine hdf5_read_integer(group, name, buffer) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, target, intent(inout) :: buffer ! read data to here - - call h5dopen_f(group, name, dset, hdf5_err) - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - call h5dclose_f(dset, hdf5_err) - - end subroutine hdf5_read_integer - -!=============================================================================== -! HDF5_WRITE_INTEGER_1DARRAY writes integer 1-D array -!=============================================================================== - - subroutine hdf5_write_integer_1Darray(group, name, buffer, len) - - integer, intent(in) :: len ! length of array to write - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer(:) ! data to write - - ! Set rank and dimensions of data - hdf5_rank = 1 - dims1(1) = len - - ! Write data - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims1, & - buffer, hdf5_err) - - end subroutine hdf5_write_integer_1Darray - -!=============================================================================== -! HDF5_READ_INTEGER_1DARRAY reads integer 1-D array -!=============================================================================== - - subroutine hdf5_read_integer_1Darray(group, name, buffer, length) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer(:) ! read data to here - integer, intent(in) :: length ! length of array - - ! Set dimensions - dims1(1) = length - - ! Read data - call h5ltread_dataset_int_f(group, name, buffer, dims1, hdf5_err) - - end subroutine hdf5_read_integer_1Darray - -!=============================================================================== -! HDF5_WRITE_INTEGER_2DARRAY writes integer 2-D array -!=============================================================================== - - subroutine hdf5_write_integer_2Darray(group, name, buffer, length) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer(length(1),length(2)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 2 - dims2 = length - - ! Write data - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims2, & - buffer, hdf5_err) - - end subroutine hdf5_write_integer_2Darray - -!=============================================================================== -! HDF5_READ_INTEGER_2DARRAY reads integer 2-D array -!=============================================================================== - - subroutine hdf5_read_integer_2Darray(group, name, buffer, length) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer(length(1),length(2)) ! data to read - - ! Set rank and dimensions - dims2 = length - - ! Write data - call h5ltread_dataset_int_f(group, name, buffer, dims2, hdf5_err) - - end subroutine hdf5_read_integer_2Darray - -!=============================================================================== -! HDF5_WRITE_INTEGER_3DARRAY writes integer 3-D array -!=============================================================================== - - subroutine hdf5_write_integer_3Darray(group, name, buffer, length) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer(length(1),length(2), & - length(3)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 3 - dims3 = length - - ! Write data - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims3, & - buffer, hdf5_err) - - end subroutine hdf5_write_integer_3Darray - -!=============================================================================== -! HDF5_READ_INTEGER_3DARRAY reads integer 3-D array -!=============================================================================== - - subroutine hdf5_read_integer_3Darray(group, name, buffer, length) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer(length(1),length(2), & - length(3)) ! data to read - - ! Set rank and dimensions - dims3 = length - - ! Write data - call h5ltread_dataset_int_f(group, name, buffer, dims3, hdf5_err) - - end subroutine hdf5_read_integer_3Darray - -!=============================================================================== -! HDF5_WRITE_INTEGER_4DARRAY writes integer 4-D array -!=============================================================================== - - subroutine hdf5_write_integer_4Darray(group, name, buffer, length) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 4 - dims4 = length - - ! Write data - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims4, & - buffer, hdf5_err) - - end subroutine hdf5_write_integer_4Darray - -!=============================================================================== -! HDF5_READ_INTEGER_4DARRAY reads integer 4-D array -!=============================================================================== - - subroutine hdf5_read_integer_4Darray(group, name, buffer, length) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to read - - ! Set rank and dimensions - dims4 = length - - ! Write data - call h5ltread_dataset_int_f(group, name, buffer, dims4, hdf5_err) - - end subroutine hdf5_read_integer_4Darray - -!=============================================================================== -! HDF5_WRITE_DOUBLE writes integer scalar data -!=============================================================================== - - subroutine hdf5_write_double(group, name, buffer) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), target, intent(in) :: buffer ! data to write - - ! Create space, dataset, and write - call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - - end subroutine hdf5_write_double - -!=============================================================================== -! HDF5_READ_DOUBLE reads double scalar data -!=============================================================================== - - subroutine hdf5_read_double(group, name, buffer) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), target, intent(inout) :: buffer ! read data to here - - call h5dopen_f(group, name, dset, hdf5_err) - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - call h5dclose_f(dset, hdf5_err) - - end subroutine hdf5_read_double - -!=============================================================================== -! HDF5_WRITE_DOUBLE_1DARRAY writes double 1-D array -!=============================================================================== - - subroutine hdf5_write_double_1Darray(group, name, buffer, length) - - integer, intent(in) :: length ! length of array to write - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer(:) ! data to write - - ! Set rank and dimensions of data - hdf5_rank = 1 - dims1(1) = length - - ! Write data - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims1, & - buffer, hdf5_err) - - end subroutine hdf5_write_double_1Darray - -!=============================================================================== -! HDF5_READ_DOUBLE_1DARRAY reads double 1-D array -!=============================================================================== - - subroutine hdf5_read_double_1Darray(group, name, buffer, length) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer(:) ! read data to here - integer, intent(in) :: length ! length of array - - ! Set dimensions - dims1(1) = length - - ! Read data - call h5ltread_dataset_double_f(group, name, buffer, dims1, hdf5_err) - - end subroutine hdf5_read_double_1Darray - -!=============================================================================== -! HDF5_WRITE_DOUBLE_2DARRAY writes double 2-D array -!=============================================================================== - - subroutine hdf5_write_double_2Darray(group, name, buffer, length) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer(length(1),length(2)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 2 - dims2 = length - - ! Write data - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims2, & - buffer, hdf5_err) - - end subroutine hdf5_write_double_2Darray - -!=============================================================================== -! HDF5_READ_DOUBLE_2DARRAY reads double 2-D array -!=============================================================================== - - subroutine hdf5_read_double_2Darray(group, name, buffer, length) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer(length(1),length(2)) ! data to read - - ! Set rank and dimensions - dims2 = length - - ! Write data - call h5ltread_dataset_double_f(group, name, buffer, dims2, hdf5_err) - - end subroutine hdf5_read_double_2Darray - -!=============================================================================== -! HDF5_WRITE_DOUBLE_3DARRAY writes double 3-D array -!=============================================================================== - - subroutine hdf5_write_double_3Darray(group, name, buffer, length) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer(length(1),length(2), & - length(3)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 3 - dims3 = length - - ! Write data - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims3, & - buffer, hdf5_err) - - end subroutine hdf5_write_double_3Darray - -!=============================================================================== -! HDF5_READ_DOUBLE_3DARRAY reads double 3-D array -!=============================================================================== - - subroutine hdf5_read_double_3Darray(group, name, buffer, length) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer(length(1),length(2), & - length(3)) ! data to read - - ! Set rank and dimensions - dims3 = length - - ! Write data - call h5ltread_dataset_double_f(group, name, buffer, dims3, hdf5_err) - - end subroutine hdf5_read_double_3Darray - -!=============================================================================== -! HDF5_WRITE_DOUBLE_4DARRAY writes double 4-D array -!=============================================================================== - - subroutine hdf5_write_double_4Darray(group, name, buffer, length) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 4 - dims4 = length - - ! Write data - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims4, & - buffer, hdf5_err) - - end subroutine hdf5_write_double_4Darray - -!=============================================================================== -! HDF5_READ_DOUBLE_4DARRAY reads double 4-D array -!=============================================================================== - - subroutine hdf5_read_double_4Darray(group, name, buffer, length) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to read - - ! Set rank and dimensions - dims4 = length - - ! Write data - call h5ltread_dataset_double_f(group, name, buffer, dims4, hdf5_err) - - end subroutine hdf5_read_double_4Darray - -!=============================================================================== -! HDF5_WRITE_LONG writes long integer scalar data -!=============================================================================== - - subroutine hdf5_write_long(group, name, buffer, long_type) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer(8), target, intent(in) :: buffer ! data to write - integer(HID_T), intent(in) :: long_type ! HDF5 long type - ! Create dataspace and dataset call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - call h5dcreate_f(group, name, long_type, dspace, dset, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) f_ptr = c_loc(buffer) - call h5dwrite_f(dset, long_type, f_ptr, hdf5_err) - ! Close dataspace and dataset for long integer + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + call h5dclose_f(dset, hdf5_err) call h5sclose_f(dspace, hdf5_err) - - end subroutine hdf5_write_long + end subroutine write_double !=============================================================================== -! HDF5_READ_LONG read long integer scalar data +! READ_DOUBLE reads double precision scalar data !=============================================================================== - subroutine hdf5_read_long(group, name, buffer, long_type) + subroutine read_double(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + real(8), intent(inout), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer(8), target, intent(out) :: buffer ! read data to here - integer(HID_T), intent(in) :: long_type ! long integer type + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr - call h5dopen_f(group, name, dset, hdf5_err) + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) f_ptr = c_loc(buffer) - call h5dread_f(dset, long_type, f_ptr, hdf5_err) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + call h5dclose_f(dset, hdf5_err) - - end subroutine hdf5_read_long + end subroutine read_double !=============================================================================== -! HDF5_WRITE_STRING writes string data +! WRITE_DOUBLE_1DARRAY writes double precision 1-D array data !=============================================================================== - subroutine hdf5_write_string(group, name, buffer, length) + subroutine write_double_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:) ! data to write + logical, intent(in), optional :: indep ! independent I/O - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - character(*), intent(in) :: buffer ! data to write - integer, intent(in) :: length + integer(HSIZE_T) :: dims(1) - character(len=length), dimension(1) :: str_tmp + dims(:) = shape(buffer) + if (present(indep)) then + call write_double_1D_explicit(group_id, dims, name, buffer, indep) + else + call write_double_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_double_1D -! Fortran 2003 implementation not compatible with IBM compiler Feb 2013 -! type(c_ptr), dimension(1), target :: wdata -! character(len=length, kind=c_char), dimension(1), target :: c_str -! dims1(1) = 1 -! call h5screate_simple_f(1, dims1, dspace, hdf5_err) -! call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err) -! c_str(1) = buffer -! wdata(1) = c_loc(c_str(1)) -! f_ptr = c_loc(wdata(1)) + subroutine write_double_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(dims(1)) ! data to write + logical, intent(in), optional :: indep ! independent I/O - ! Number of strings to write - dims1(1) = 1 + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double_1D_explicit + +!=============================================================================== +! READ_DOUBLE_1DARRAY reads double precision 1-D array data +!=============================================================================== + + subroutine read_double_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_double_1D_explicit(group_id, dims, name, buffer, indep) + else + call read_double_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_double_1D + + subroutine read_double_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(dims(1)) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double_1D_explicit + +!=============================================================================== +! WRITE_DOUBLE_2DARRAY writes double precision 2-D array data +!=============================================================================== + + subroutine write_double_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_double_2D_explicit(group_id, dims, name, buffer, indep) + else + call write_double_2D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_double_2D + + subroutine write_double_2D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(dims(1),dims(2)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(2, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double_2D_explicit + +!=============================================================================== +! READ_DOUBLE_2DARRAY reads double precision 2-D array data +!=============================================================================== + + subroutine read_double_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_double_2D_explicit(group_id, dims, name, buffer, indep) + else + call read_double_2D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_double_2D + + subroutine read_double_2D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(dims(1),dims(2)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double_2D_explicit + +!=============================================================================== +! WRITE_DOUBLE_3DARRAY writes double precision 3-D array data +!=============================================================================== + + subroutine write_double_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_double_3D_explicit(group_id, dims, name, buffer, indep) + else + call write_double_3D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_double_3D + + subroutine write_double_3D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(3) + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(dims(1),dims(2),dims(3)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(3, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double_3D_explicit + +!=============================================================================== +! READ_DOUBLE_3DARRAY reads double precision 3-D array data +!=============================================================================== + + subroutine read_double_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_double_3D_explicit(group_id, dims, name, buffer, indep) + else + call read_double_3D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_double_3D + + subroutine read_double_3D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(3) + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(dims(1),dims(2),dims(3)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double_3D_explicit + +!=============================================================================== +! WRITE_DOUBLE_4DARRAY writes double precision 4-D array data +!=============================================================================== + + subroutine write_double_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_double_4D_explicit(group_id, dims, name, buffer, indep) + else + call write_double_4D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_double_4D + + subroutine write_double_4D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(4) + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(dims(1),dims(2),dims(3),dims(4)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(4, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double_4D_explicit + +!=============================================================================== +! READ_DOUBLE_4DARRAY reads double precision 4-D array data +!=============================================================================== + + subroutine read_double_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_double_4D_explicit(group_id, dims, name, buffer, indep) + else + call read_double_4D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_double_4D + + subroutine read_double_4D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(4) + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(dims(1),dims(2),dims(3),dims(4)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double_4D_explicit + +!=============================================================================== +! WRITE_INTEGER writes integer precision scalar data +!=============================================================================== + + subroutine write_integer(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer, intent(in), target :: buffer ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Create dataspace and dataset + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer + +!=============================================================================== +! READ_INTEGER reads integer precision scalar data +!=============================================================================== + + subroutine read_integer(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer, intent(inout), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer + +!=============================================================================== +! WRITE_INTEGER_1DARRAY writes integer precision 1-D array data +!=============================================================================== + + subroutine write_integer_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_integer_1D_explicit(group_id, dims, name, buffer, indep) + else + call write_integer_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_integer_1D + + subroutine write_integer_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(dims(1)) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer_1D_explicit + +!=============================================================================== +! READ_INTEGER_1DARRAY reads integer precision 1-D array data +!=============================================================================== + + subroutine read_integer_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_integer_1D_explicit(group_id, dims, name, buffer, indep) + else + call read_integer_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_integer_1D + + subroutine read_integer_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(dims(1)) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer_1D_explicit + +!=============================================================================== +! WRITE_INTEGER_2DARRAY writes integer precision 2-D array data +!=============================================================================== + + subroutine write_integer_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_integer_2D_explicit(group_id, dims, name, buffer, indep) + else + call write_integer_2D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_integer_2D + + subroutine write_integer_2D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(dims(1),dims(2)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(2, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer_2D_explicit + +!=============================================================================== +! READ_INTEGER_2DARRAY reads integer precision 2-D array data +!=============================================================================== + + subroutine read_integer_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_integer_2D_explicit(group_id, dims, name, buffer, indep) + else + call read_integer_2D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_integer_2D + + subroutine read_integer_2D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(dims(1),dims(2)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer_2D_explicit + +!=============================================================================== +! WRITE_INTEGER_3DARRAY writes integer precision 3-D array data +!=============================================================================== + + subroutine write_integer_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_integer_3D_explicit(group_id, dims, name, buffer, indep) + else + call write_integer_3D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_integer_3D + + subroutine write_integer_3D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(3) + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(dims(1),dims(2),dims(3)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(3, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer_3D_explicit + +!=============================================================================== +! READ_INTEGER_3DARRAY reads integer precision 3-D array data +!=============================================================================== + + subroutine read_integer_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_integer_3D_explicit(group_id, dims, name, buffer, indep) + else + call read_integer_3D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_integer_3D + + subroutine read_integer_3D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(3) + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(dims(1),dims(2),dims(3)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer_3D_explicit + +!=============================================================================== +! WRITE_INTEGER_4DARRAY writes integer precision 4-D array data +!=============================================================================== + + subroutine write_integer_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_integer_4D_explicit(group_id, dims, name, buffer, indep) + else + call write_integer_4D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_integer_4D + + subroutine write_integer_4D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(4) + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(dims(1),dims(2),dims(3),dims(4)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(4, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer_4D_explicit + +!=============================================================================== +! READ_INTEGER_4DARRAY reads integer precision 4-D array data +!=============================================================================== + + subroutine read_integer_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_integer_4D_explicit(group_id, dims, name, buffer, indep) + else + call read_integer_4D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_integer_4D + + subroutine read_integer_4D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(4) + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(dims(1),dims(2),dims(3),dims(4)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer_4D_explicit + +!=============================================================================== +! WRITE_LONG writes long integer scalar data +!=============================================================================== + + subroutine write_long(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer(8), intent(in), target :: buffer ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Create dataspace and dataset + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), hdf5_integer8_t, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, hdf5_integer8_t, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, hdf5_integer8_t, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_long + +!=============================================================================== +! READ_LONG reads long integer scalar data +!=============================================================================== + + subroutine read_long(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer(8), intent(inout), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, hdf5_integer8_t, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, hdf5_integer8_t, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_long + +!=============================================================================== +! WRITE_STRING writes string data +!=============================================================================== + + subroutine write_string(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + character(*), intent(in) :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer :: n + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HSIZE_T) :: dims1(1) + integer(HSIZE_T) :: dims2(2) + type(c_ptr) :: f_ptr + character(len=len_trim(buffer)), dimension(1) :: str_tmp + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if ! Insert null character at end of string when writing call h5tset_strpad_f(H5T_STRING, H5T_STR_NULLPAD_F, hdf5_err) ! Create the dataspace and dataset + dims1(1) = 1 call h5screate_simple_f(1, dims1, dspace, hdf5_err) - call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_STRING, dspace, dset, hdf5_err) ! Set up dimesnions of string to write - dims2 = (/length, 1/) ! full array of strings to write - dims1(1) = length ! length of string + n = len_trim(buffer) + dims2(:) = [n, 1] ! full array of strings to write + dims1(1) = n ! length of string ! Copy over string buffer to a rank 1 array str_tmp(1) = buffer - ! Write the variable dataset - call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace) + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & + mem_space_id=dspace, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & + mem_space_id=dspace) + end if - ! Close all call h5dclose_f(dset, hdf5_err) call h5sclose_f(dspace, hdf5_err) - - end subroutine hdf5_write_string + end subroutine write_string !=============================================================================== -! HDF5_READ_STRING reads string data +! READ_STRING reads string data !=============================================================================== - subroutine hdf5_read_string(group, name, buffer, length) + subroutine read_string(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + character(*), intent(inout) :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - character(*), intent(inout) :: buffer ! read data to here - integer, intent(in) :: length ! length of string to read + integer :: n + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HSIZE_T) :: dims1(1) + integer(HSIZE_T) :: dims2(2) + type(c_ptr) :: f_ptr + character(len=len_trim(buffer)), dimension(1) :: str_tmp - character(len=length), dimension(1) :: str_tmp + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if - ! Fortran 2003 implementation not compatible with IBM Feb 2013 compiler -! type(c_ptr), dimension(1), target :: buf_ptr -! character(len=length, kind=c_char), pointer :: chr_ptr -! f_ptr = c_loc(buf_ptr(1)) -! call h5dread_f(dset, H5T_STRING, f_ptr, hdf5_err, xfer_prp=plist) -! call c_f_pointer(buf_ptr(1), chr_ptr) -! buffer = chr_ptr -! nullify(chr_ptr) + ! Set up dimesnions of string to write + n = len_trim(buffer) + dims2(:) = [n, 1] ! full array of strings to write + dims1(1) = n ! length of string - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Get dataspace to read + call h5dopen_f(group_id, trim(name), dset, hdf5_err) call h5dget_space_f(dset, dspace, hdf5_err) - ! Set dimensions - dims2 = (/length, 1/) - dims1(1) = length - - ! Read in the data - call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace, xfer_prp = plist) + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & + mem_space_id=dspace, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & + mem_space_id=dspace) + end if ! Copy over buffer buffer = str_tmp(1) ! Close dataset call h5dclose_f(dset, hdf5_err) - - end subroutine hdf5_read_string + end subroutine read_string !=============================================================================== -! HDF5_WRITE_ATTRIBUTE_STRING writes a string attribute to a variables +! WRITE_ATTRIBUTE_STRING !=============================================================================== - subroutine hdf5_write_attribute_string(group, var, attr_type, attr_str) + subroutine write_attribute_string(group_id, var, attr_type, attr_str) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: var ! variable name for attr + character(*), intent(in) :: attr_type ! attr identifier type + character(*), intent(in) :: attr_str ! string for attr id type - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: var ! name of varaible to set attr - character(*), intent(in) :: attr_type ! the attr type id - character(*), intent(in) :: attr_str ! attribute sting + integer :: hdf5_err - call h5ltset_attribute_string_f(group, var, attr_type, attr_str, hdf5_err) + call h5ltset_attribute_string_f(group_id, var, attr_type, attr_str, hdf5_err) + end subroutine write_attribute_string - end subroutine hdf5_write_attribute_string +!=============================================================================== +! WRITE_TALLY_RESULT writes an OpenMC TallyResult type +!=============================================================================== + + subroutine write_tally_result_1D(group_id, name, buffer) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(in), target :: buffer(:) ! data to write + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + call write_tally_result_1D_explicit(group_id, dims, name, buffer) + end subroutine write_tally_result_1D + + subroutine write_tally_result_1D_explicit(group_id, dims, name, buffer) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(in), target :: buffer(dims(1)) + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), hdf5_tallyresult_t, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dwrite_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_tally_result_1D_explicit + + subroutine write_tally_result_2D(group_id, name, buffer) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(in), target :: buffer(:,:) ! data to write + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + call write_tally_result_2D_explicit(group_id, dims, name, buffer) + end subroutine write_tally_result_2D + + subroutine write_tally_result_2D_explicit(group_id, dims, name, buffer) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(in), target :: buffer(dims(1),dims(2)) + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + call h5screate_simple_f(2, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), hdf5_tallyresult_t, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dwrite_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_tally_result_2D_explicit + +!=============================================================================== +! READ_TALLY_RESULT reads OpenMC TallyResult data +!=============================================================================== + + subroutine read_tally_result_1D(group_id, name, buffer) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(inout), target :: buffer(:) ! read data here + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + call read_tally_result_1D_explicit(group_id, dims, name, buffer) + end subroutine read_tally_result_1D + + subroutine read_tally_result_1D_explicit(group_id, dims, name, buffer) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(inout), target :: buffer(dims(1)) + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dread_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) + end subroutine read_tally_result_1D_explicit + + subroutine read_tally_result_2D(group_id, name, buffer) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(inout), target :: buffer(:,:) + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + call read_tally_result_2D_explicit(group_id, dims, name, buffer) + end subroutine read_tally_result_2D + + subroutine read_tally_result_2D_explicit(group_id, dims, name, buffer) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(inout), target :: buffer(dims(1),dims(2)) + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dread_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) + end subroutine read_tally_result_2D_explicit + +!=============================================================================== +! WRITE_SOURCE_BANK writes OpenMC source_bank data +!=============================================================================== + + subroutine write_source_bank(group_id) + use bank_header, only: Bank + use global, only: n_particles, work, source_bank + + integer(HID_T), intent(in) :: group_id + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: memspace ! memory space handle + integer(HSIZE_T) :: dims(1) + type(c_ptr) :: f_ptr +#ifdef PHDF5 + integer(HSIZE_T) :: offset(1) ! source data offset +#endif #ifdef PHDF5 - -!=============================================================================== -! HDF5_WRITE_INTEGER_PARALLEL writes integer scalar data in parallel -!=============================================================================== - - subroutine hdf5_write_integer_parallel(group, name, buffer, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collect I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) + ! Set size of total dataspace for all procs and rank + dims(1) = n_particles + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, dspace, dset, hdf5_err) call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - end subroutine hdf5_write_integer_parallel + ! Create another data space but for each proc individually + dims(1) = work + call h5screate_simple_f(rank, dims, memspace, hdf5_err) -!=============================================================================== -! HDF5_READ_INTEGER_PARALLEL reads integer scalar data -!=============================================================================== - - subroutine hdf5_read_integer_parallel(group, name, buffer, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, target, intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_1DARRAY_PARALLEL writes integer 1-D array in parallel -!=============================================================================== - - subroutine hdf5_write_integer_1Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length ! length of array to write - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer(length) ! data to write - logical, intent(in) :: collect ! collect I/O - - ! Set rank and dimensions of data - hdf5_rank = 1 - dims1(1) = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_1Darray_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_1DARRAY_PARALLEL reads integer 1-D array in parallel -!=============================================================================== - - subroutine hdf5_read_integer_1Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length ! length of array - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, target, intent(inout) :: buffer(length) ! read data to here - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_1Darray_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_2DARRAY_PARALLEL writes integer 2-D array in parallel -!=============================================================================== - - subroutine hdf5_write_integer_2Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer(length(1),length(2)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 2 - dims2 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims2, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_2Darray_parallel - -!=============================================================================== -! HDF5_READ_INTEGER_2DARRAY_PARALLEL reads integer 2-D array in parallel -!=============================================================================== - - subroutine hdf5_read_integer_2Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(inout) :: buffer(length(1),length(2)) ! data to read - logical, intent(in) :: collect ! collect I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_2Darray_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_3DARRAY_PARALLEL writes integer 3-D array in parallel -!=============================================================================== - - subroutine hdf5_write_integer_3Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer(length(1),length(2), & - length(3)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 3 - dims3 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims3, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_3Darray_parallel - -!=============================================================================== -! HDF5_READ_INTEGER_3DARRAY_PARALLEL reads integer 3-D array in parallel -!=============================================================================== - - subroutine hdf5_read_integer_3Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(inout) :: buffer(length(1),length(2), & - length(3)) ! data to read - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_3Darray_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_4DARRAY_PARALLEL writes integer 4-D array in parallel -!=============================================================================== - - subroutine hdf5_write_integer_4Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 4 - dims4 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims4, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_4Darray_parallel - -!=============================================================================== -! HDF5_READ_INTEGER_4DARRAY_PARALLEL reads integer 4-D array in parallel -!=============================================================================== - - subroutine hdf5_read_integer_4Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to read - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_4Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_PARALLEL writes double scalar data in parallel -!=============================================================================== - - subroutine hdf5_write_double_parallel(group, name, buffer, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collect I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_parallel - -!=============================================================================== -! HDF5_READ_DOUBLE_PARALLEL reads double scalar data -!=============================================================================== - - subroutine hdf5_read_double_parallel(group, name, buffer, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), target, intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_1DARRAY_PARALLEL writes double 1-D array in parallel -!=============================================================================== - - subroutine hdf5_write_double_1Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length ! length of array to write - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer(length) ! data to write - logical, intent(in) :: collect ! collect I/O - - ! Set rank and dimensions of data - hdf5_rank = 1 - dims1(1) = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_1Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_1DARRAY_PARALLEL reads double 1-D array in parallel -!=============================================================================== - - subroutine hdf5_read_double_1Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length ! length of array - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(inout) :: buffer(length) ! read data to here - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_1Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_2DARRAY_PARALLEL writes double 2-D array in parallel -!=============================================================================== - - subroutine hdf5_write_double_2Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer(length(1),length(2)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 2 - dims2 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims2, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer(1,1)) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_2Darray_parallel - -!=============================================================================== -! HDF5_READ_DOUBLE_2DARRAY_PARALLEL reads double 2-D array in parallel -!=============================================================================== - - subroutine hdf5_read_double_2Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(inout) :: buffer(length(1),length(2)) ! data to read - logical, intent(in) :: collect ! collect I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_2Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_3DARRAY_PARALLEL writes double 3-D array in parallel -!=============================================================================== - - subroutine hdf5_write_double_3Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer(length(1),length(2), & - length(3)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 3 - dims3 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims3, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_3Darray_parallel - -!=============================================================================== -! HDF5_READ_DOUBLE_3DARRAY_PARALLEL reads double 3-D array in parallel -!=============================================================================== - - subroutine hdf5_read_double_3Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(inout) :: buffer(length(1),length(2), & - length(3)) ! data to read - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_3Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_4DARRAY_PARALLEL writes double 4-D array in parallel -!=============================================================================== - - subroutine hdf5_write_double_4Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 4 - dims4 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims4, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_4Darray_parallel - -!=============================================================================== -! HDF5_READ_DOUBLE_4DARRAY_PARALLEL reads double 4-D array in parallel -!=============================================================================== - - subroutine hdf5_read_double_4Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to read - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_4Darray_parallel - -!=============================================================================== -! HDF5_WRITE_LONG_PARALLEL writes long integer scalar data in parallel -!=============================================================================== - - subroutine hdf5_write_long_parallel(group, name, buffer, long_type, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer(8), target, intent(in) :: buffer ! data to write - integer(HID_T), intent(in) :: long_type ! HDF5 long type - logical, intent(in) :: collect ! collective I/O - - ! Set up rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, long_type, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, long_type, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_long_parallel - -!=============================================================================== -! HDF5_READ_LONG_PARALLEL read long integer scalar data in parallel -!=============================================================================== - - subroutine hdf5_read_long_parallel(group, name, buffer, long_type, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer(8), target, intent(out) :: buffer ! read data to here - integer(HID_T), intent(in) :: long_type ! long integer type - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, long_type, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_long_parallel - -!=============================================================================== -! HDF5_WRITE_STRING_PARALLEL writes string data in parallel -!=============================================================================== - - subroutine hdf5_write_string_parallel(group, name, buffer, length, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - character(*), intent(in) :: buffer ! data to write - integer, intent(in) :: length ! length of string - logical, intent(in) :: collect ! collective I/O - - character(len=length), dimension(1) :: str_tmp - -! Fortran 2003 implementation not compatible with IBM compiler Feb 2013 -! type(c_ptr), dimension(1), target :: wdata -! character(len=length, kind=c_char), dimension(1), target :: c_str -! dims1(1) = 1 -! call h5screate_simple_f(1, dims1, dspace, hdf5_err) -! call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err) -! c_str(1) = buffer -! wdata(1) = c_loc(c_str(1)) -! f_ptr = c_loc(wdata(1)) - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Number of strings to write - dims1(1) = 1 - - ! Insert null character at end of string when writing - call h5tset_strpad_f(H5T_STRING, H5T_STR_NULLPAD_F, hdf5_err) - - ! Create the dataspace and dataset - call h5screate_simple_f(1, dims1, dspace, hdf5_err) - call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err) - - ! Set up dimesnions of string to write - dims2 = (/length, 1/) ! full array of strings to write - dims1(1) = length ! length of string - - ! Copy over string buffer to a rank 1 array - str_tmp(1) = buffer - - ! Write the variable dataset - call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_string_parallel - -!=============================================================================== -! HDF5_READ_STRING_PARALLEL reads string data in parallel -!=============================================================================== - - subroutine hdf5_read_string_parallel(group, name, buffer, length, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - character(*), intent(inout) :: buffer ! read data to here - integer, intent(in) :: length ! length of string - logical, intent(in) :: collect ! collective I/O - - character(len=length), dimension(1) :: str_tmp - - ! Fortran 2003 implementation not compatible with IBM Feb 2013 compiler -! type(c_ptr), dimension(1), target :: buf_ptr -! character(len=length, kind=c_char), pointer :: chr_ptr -! f_ptr = c_loc(buf_ptr(1)) -! call h5dread_f(dset, H5T_STRING, f_ptr, hdf5_err, xfer_prp=plist) -! call c_f_pointer(buf_ptr(1), chr_ptr) -! buffer = chr_ptr -! nullify(chr_ptr) - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Get dataspace to read + ! Get the individual local proc dataspace call h5dget_space_f(dset, dspace, hdf5_err) - ! Set dimensions - dims2 = (/length, 1/) - dims1(1) = length + ! Select hyperslab for this dataspace + offset(1) = work_index(rank) + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) - ! Read in the data - call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace, xfer_prp = plist) + ! Set up the property list for parallel writing + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - ! Copy over buffer - buffer = str_tmp(1) + ! Set up pointer to data + f_ptr = c_loc(source_bank) - ! Close dataset and property list + ! Write data to file in parallel + call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace, & + xfer_prp=plist) + + ! Close all ids + call h5sclose_f(dspace, hdf5_err) + call h5sclose_f(memspace, hdf5_err) call h5dclose_f(dset, hdf5_err) call h5pclose_f(plist, hdf5_err) - end subroutine hdf5_read_string_parallel +#else + + ! Set size + dims(1) = work + + ! Create dataspace + call h5screate_simple_f(1, dims, dspace, hdf5_err) + + ! Create dataset + call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, & + dspace, dset, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + + ! Write dataset to file + call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err) + + ! Close all ids + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) #endif + end subroutine write_source_bank + +!=============================================================================== +! READ_SOURCE_BANK reads OpenMC source_bank data +!=============================================================================== + + subroutine read_source_bank(group_id) + use bank_header, only: Bank + use global, only: work, source_bank + + integer(HID_T), intent(in) :: group_id + + integer :: hdf5_err + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data space handle + integer(HID_T) :: memspace ! memory space handle + integer(HSIZE_T) :: dims(1) + type(c_ptr) :: f_ptr +#ifdef PHDF5 + integer(HSIZE_T) :: offset(1) ! offset of data +#endif + +#ifdef PHDF5 + + ! Open the dataset + call h5dopen_f(group_id, "source_bank", dset, hdf5_err) + + ! Create another data space but for each proc individually + dims(1) = work + call h5screate_simple_f(1, dims, memspace, hdf5_err) + + ! Get the individual local proc dataspace + call h5dget_space_f(dset, dspace, hdf5_err) + + ! Select hyperslab for this dataspace + offset(1) = work_index(rank) + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) + + ! Set up the property list for parallel writing + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + + ! Read data from file in parallel + call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace, & + xfer_prp=plist) + + ! Close all ids + call h5sclose_f(dspace, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call h5dclose_f(dset, hdf5_err) + call h5pclose_f(plist, hdf5_err) + +#else + + ! Open dataset + call h5dopen_f(group_id, "source_bank", dset, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + + ! Read dataset from file + call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err) + + ! Close all ids + call h5dclose_f(dset, hdf5_err) + +#endif + + end subroutine read_source_bank + + function using_mpio_device(obj_id) result(mpio) + integer(HID_T), intent(in) :: obj_id + logical :: mpio + + integer :: hdf5_err + integer :: driver + integer(HID_T) :: file_id + integer(HID_T) :: fapl_id + + ! Determine file that this object is part of + call h5iget_file_id_f(obj_id, file_id, hdf5_err) + + ! Get file access property list + call h5fget_access_plist_f(file_id, fapl_id, hdf5_err) + + ! Get low-level driver identifier + call h5pget_driver_f(fapl_id, driver, hdf5_err) + + ! Close file access property list access + call h5pclose_f(fapl_id, hdf5_err) + + ! Close file access -- note that this only decreases the reference count so + ! that the file is not actually closed + call h5fclose_f(file_id, hdf5_err) + + mpio = (driver == H5FD_MPIO_F) + end function using_mpio_device + end module hdf5_interface diff --git a/src/tally_header.F90 b/src/tally_header.F90 index d20c3fea2..ca4e25fd8 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -2,6 +2,7 @@ module tally_header use constants, only: NONE, N_FILTER_TYPES use trigger_header, only: TriggerObject + use, intrinsic :: ISO_C_BINDING implicit none @@ -39,10 +40,10 @@ module tally_header ! TALLYRESULT provides accumulation of results in a particular tally bin !=============================================================================== - type TallyResult - real(8) :: value = 0. - real(8) :: sum = 0. - real(8) :: sum_sq = 0. + type, bind(C) :: TallyResult + real(C_DOUBLE) :: value = 0. + real(C_DOUBLE) :: sum = 0. + real(C_DOUBLE) :: sum_sq = 0. end type TallyResult !=============================================================================== From 2f18e4b57ec3e2216f85e463e0d795647ffa675e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 3 Sep 2015 09:20:47 +0700 Subject: [PATCH 11/95] Refactored rest of code to use new HDF5_interface API --- src/finalize.F90 | 11 +- src/hdf5_interface.F90 | 222 +--- src/hdf5_summary.F90 | 814 +++++++-------- src/initialize.F90 | 313 +++--- src/output_interface.F90 | 1725 -------------------------------- src/particle_restart.F90 | 53 +- src/particle_restart_write.F90 | 42 +- src/source.F90 | 93 +- src/state_point.F90 | 828 ++++++++------- src/track_output.F90 | 53 +- 10 files changed, 1146 insertions(+), 3008 deletions(-) delete mode 100644 src/output_interface.F90 diff --git a/src/finalize.F90 b/src/finalize.F90 index b795cdb4f..86100d195 100644 --- a/src/finalize.F90 +++ b/src/finalize.F90 @@ -9,7 +9,8 @@ module finalize use message_passing #endif - use hdf5_interface, only: h5tclose_f, h5close_f, hdf5_err + use hdf5_interface, only: hdf5_bank_t, hdf5_tallyresult_t + use hdf5, only: h5tclose_f, h5close_f implicit none @@ -22,8 +23,10 @@ contains subroutine finalize_run() + integer :: hdf5_err + ! Start finalization timer - call time_finalize % start() + call time_finalize%start() if (run_mode /= MODE_PLOTTING .and. run_mode /= MODE_PARTICLE) then ! Calculate statistics for tallies and write to tallies.out @@ -37,8 +40,8 @@ contains end if ! Stop timers and show timing statistics - call time_finalize % stop() - call time_total % stop() + call time_finalize%stop() + call time_total%stop() if (master .and. (run_mode /= MODE_PLOTTING .and. & run_mode /= MODE_PARTICLE)) then call print_runtime() diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 041e948ff..1684c352b 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -64,10 +64,9 @@ module hdf5_interface public :: file_create public :: file_open public :: file_close + public :: create_group public :: open_group public :: close_group - public :: write_source_bank - public :: read_source_bank public :: write_attribute_string contains @@ -243,7 +242,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -287,9 +288,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -344,7 +346,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -404,9 +408,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -461,7 +466,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -521,9 +528,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -578,7 +586,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -638,9 +648,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -695,7 +706,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -755,9 +768,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -795,7 +809,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -839,9 +855,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -896,7 +913,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -956,9 +975,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -1013,7 +1033,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -1073,9 +1095,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -1130,7 +1153,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -1190,9 +1215,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -1247,7 +1273,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -1307,9 +1335,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -1347,7 +1376,9 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr @@ -1391,9 +1422,10 @@ contains integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O @@ -1432,12 +1464,13 @@ contains integer :: n integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle integer(HSIZE_T) :: dims1(1) integer(HSIZE_T) :: dims2(2) - type(c_ptr) :: f_ptr character(len=len_trim(buffer)), dimension(1) :: str_tmp ! Set up collective vs. independent I/O @@ -1492,12 +1525,13 @@ contains integer :: n integer :: hdf5_err integer :: data_xfer_mode +#ifdef PHDF5 integer(HID_T) :: plist ! property list +#endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle integer(HSIZE_T) :: dims1(1) integer(HSIZE_T) :: dims2(2) - type(c_ptr) :: f_ptr character(len=len_trim(buffer)), dimension(1) :: str_tmp ! Set up collective vs. independent I/O @@ -1673,164 +1707,6 @@ contains call h5dclose_f(dset, hdf5_err) end subroutine read_tally_result_2D_explicit -!=============================================================================== -! WRITE_SOURCE_BANK writes OpenMC source_bank data -!=============================================================================== - - subroutine write_source_bank(group_id) - use bank_header, only: Bank - use global, only: n_particles, work, source_bank - - integer(HID_T), intent(in) :: group_id - - integer :: hdf5_err - integer :: data_xfer_mode - integer(HID_T) :: plist ! property list - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - integer(HID_T) :: memspace ! memory space handle - integer(HSIZE_T) :: dims(1) - type(c_ptr) :: f_ptr -#ifdef PHDF5 - integer(HSIZE_T) :: offset(1) ! source data offset -#endif - -#ifdef PHDF5 - ! Set size of total dataspace for all procs and rank - dims(1) = n_particles - call h5screate_simple_f(1, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, dspace, dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - - ! Create another data space but for each proc individually - dims(1) = work - call h5screate_simple_f(rank, dims, memspace, hdf5_err) - - ! Get the individual local proc dataspace - call h5dget_space_f(dset, dspace, hdf5_err) - - ! Select hyperslab for this dataspace - offset(1) = work_index(rank) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) - - ! Set up the property list for parallel writing - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank) - - ! Write data to file in parallel - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id=dspace, mem_space_id=memspace, & - xfer_prp=plist) - - ! Close all ids - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - -#else - - ! Set size - dims(1) = work - - ! Create dataspace - call h5screate_simple_f(1, dims, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, & - dspace, dset, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank) - - ! Write dataset to file - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err) - - ! Close all ids - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - -#endif - - end subroutine write_source_bank - -!=============================================================================== -! READ_SOURCE_BANK reads OpenMC source_bank data -!=============================================================================== - - subroutine read_source_bank(group_id) - use bank_header, only: Bank - use global, only: work, source_bank - - integer(HID_T), intent(in) :: group_id - - integer :: hdf5_err - integer :: data_xfer_mode - integer(HID_T) :: plist ! property list - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data space handle - integer(HID_T) :: memspace ! memory space handle - integer(HSIZE_T) :: dims(1) - type(c_ptr) :: f_ptr -#ifdef PHDF5 - integer(HSIZE_T) :: offset(1) ! offset of data -#endif - -#ifdef PHDF5 - - ! Open the dataset - call h5dopen_f(group_id, "source_bank", dset, hdf5_err) - - ! Create another data space but for each proc individually - dims(1) = work - call h5screate_simple_f(1, dims, memspace, hdf5_err) - - ! Get the individual local proc dataspace - call h5dget_space_f(dset, dspace, hdf5_err) - - ! Select hyperslab for this dataspace - offset(1) = work_index(rank) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) - - ! Set up the property list for parallel writing - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank) - - ! Read data from file in parallel - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id=dspace, mem_space_id=memspace, & - xfer_prp=plist) - - ! Close all ids - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - -#else - - ! Open dataset - call h5dopen_f(group_id, "source_bank", dset, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank) - - ! Read dataset from file - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err) - - ! Close all ids - call h5dclose_f(dset, hdf5_err) - -#endif - - end subroutine read_source_bank - function using_mpio_device(obj_id) result(mpio) integer(HID_T), intent(in) :: obj_id logical :: mpio diff --git a/src/hdf5_summary.F90 b/src/hdf5_summary.F90 index a9dab46f5..e8f566c43 100644 --- a/src/hdf5_summary.F90 +++ b/src/hdf5_summary.F90 @@ -6,16 +6,16 @@ module hdf5_summary use geometry_header, only: Cell, Surface, Universe, Lattice, RectLattice, & &HexLattice use global + use hdf5_interface use material_header, only: Material use mesh_header, only: StructuredMesh - use output_interface use output, only: time_stamp use string, only: to_str use tally_header, only: TallyObject - implicit none + use hdf5 - type(BinaryOutput) :: su + implicit none contains @@ -25,48 +25,48 @@ contains subroutine hdf5_write_summary() - character(MAX_FILE_LEN) :: filename = "summary.h5" + integer(HID_T) :: file_id ! Create a new file using default properties. - call su % file_create(filename) + file_id = file_create("summary.h5") ! Write header information - call hdf5_write_header() + call hdf5_write_header(file_id) ! Write eigenvalue information if (run_mode == MODE_EIGENVALUE) then ! Write number of particles - call su % write_data(n_particles, "n_particles") + call write_dataset(file_id, "n_particles", n_particles) ! Use H5LT interface to write n_batches, n_inactive, and n_active - call su % write_data(n_batches, "n_batches") - call su % write_data(n_inactive, "n_inactive") - call su % write_data(n_active, "n_active") - call su % write_data(gen_per_batch, "gen_per_batch") + call write_dataset(file_id, "n_batches", n_batches) + call write_dataset(file_id, "n_inactive", n_inactive) + call write_dataset(file_id, "n_active", n_active) + call write_dataset(file_id, "gen_per_batch", gen_per_batch) ! Add description of each variable - call su % write_attribute_string("n_particles", & + call write_attribute_string(file_id, "n_particles", & "description", "Number of particles per generation") - call su % write_attribute_string("n_batches", & + call write_attribute_string(file_id, "n_batches", & "description", "Total number of batches") - call su % write_attribute_string("n_inactive", & + call write_attribute_string(file_id, "n_inactive", & "description", "Number of inactive batches") - call su % write_attribute_string("n_active", & + call write_attribute_string(file_id, "n_active", & "description", "Number of active batches") - call su % write_attribute_string("gen_per_batch", & + call write_attribute_string(file_id, "gen_per_batch", & "description", "Number of generations per batch") end if - call hdf5_write_geometry() - call hdf5_write_materials() - call hdf5_write_nuclides() + call hdf5_write_geometry(file_id) + call hdf5_write_materials(file_id) + call hdf5_write_nuclides(file_id) if (n_tallies > 0) then - call hdf5_write_tallies() + call hdf5_write_tallies(file_id) end if ! Terminate access to the file. - call su % file_close() + call file_close(file_id) end subroutine hdf5_write_summary @@ -74,19 +74,20 @@ contains ! HDF5_WRITE_HEADER !=============================================================================== - subroutine hdf5_write_header() + subroutine hdf5_write_header(file_id) + integer(HID_T), intent(in) :: file_id ! Write version information - call su % write_data(VERSION_MAJOR, "version_major") - call su % write_data(VERSION_MINOR, "version_minor") - call su % write_data(VERSION_RELEASE, "version_release") + call write_dataset(file_id, "version_major", VERSION_MAJOR) + call write_dataset(file_id, "version_minor", VERSION_MINOR) + call write_dataset(file_id, "version_release", VERSION_RELEASE) ! Write current date and time - call su % write_data(time_stamp(), "date_and_time") + call write_dataset(file_id, "date_and_time", time_stamp()) ! Write MPI information - call su % write_data(n_procs, "n_procs") - call su % write_attribute_string("n_procs", "description", & + call write_dataset(file_id, "n_procs", n_procs) + call write_attribute_string(file_id, "n_procs", "description", & "Number of MPI processes") end subroutine hdf5_write_header @@ -95,782 +96,659 @@ contains ! HDF5_WRITE_GEOMETRY !=============================================================================== - subroutine hdf5_write_geometry() + subroutine hdf5_write_geometry(file_id) + integer(HID_T), intent(in) :: file_id integer :: i, j, k, m integer, allocatable :: lattice_universes(:,:,:) - type(Cell), pointer :: c => null() - type(Surface), pointer :: s => null() - type(Universe), pointer :: u => null() - class(Lattice), pointer :: lat => null() + integer(HID_T) :: geom_group + integer(HID_T) :: cells_group, cell_group + integer(HID_T) :: surfaces_group, surface_group + integer(HID_T) :: universes_group, univ_group + integer(HID_T) :: lattices_group, lattice_group + type(Cell), pointer :: c + type(Surface), pointer :: s + type(Universe), pointer :: u + class(Lattice), pointer :: lat ! Use H5LT interface to write number of geometry objects - call su % write_data(n_cells, "n_cells", group="geometry") - call su % write_data(n_surfaces, "n_surfaces", group="geometry") - call su % write_data(n_universes, "n_universes", group="geometry") - call su % write_data(n_lattices, "n_lattices", group="geometry") + geom_group = create_group(file_id, "geometry") + call write_dataset(geom_group, "n_cells", n_cells) + call write_dataset(geom_group, "n_surfaces", n_surfaces) + call write_dataset(geom_group, "n_universes", n_universes) + call write_dataset(geom_group, "n_lattices", n_lattices) ! ========================================================================== ! WRITE INFORMATION ON CELLS ! Create a cell group (nothing directly written in this group) then close - call su % open_group("geometry/cells") - call su % close_group() + cells_group = create_group(geom_group, "cells") ! Write information on each cell CELL_LOOP: do i = 1, n_cells c => cells(i) + cell_group = create_group(cells_group, "cell " // trim(to_str(c%id))) ! Write internal OpenMC index for this cell - call su % write_data(i, "index", & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "index", i) ! Write name for this cell - call su % write_data(c % name, "name", & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "name", c%name) ! Write universe for this cell - call su % write_data(universes(c % universe) % id, "universe", & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "universe", universes(c%universe)%id) ! Write information on what fills this cell - select case (c % type) + select case (c%type) case (CELL_NORMAL) - call su % write_data("normal", "fill_type", & - group="geometry/cells/cell " // trim(to_str(c % id))) - if (c % material == MATERIAL_VOID) then - call su % write_data(-1, "material", & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "fill_type", "normal") + if (c%material == MATERIAL_VOID) then + call write_dataset(cell_group, "material", -1) else - call su % write_data(materials(c % material) % id, "material", & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "material", materials(c%material)%id) end if case (CELL_FILL) - call su % write_data("universe", "fill_type", & - group="geometry/cells/cell " // trim(to_str(c % id))) - call su % write_data(universes(c % fill) % id, "fill", & - group="geometry/cells/cell " // trim(to_str(c % id))) - - call su % write_data(size(c % offset), "maps", & - group="geometry/cells/cell " // trim(to_str(c % id))) - if (size(c % offset) > 0) then - call su % write_data(c % offset, "offset", & - length=size(c % offset), & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "fill_type", "universe") + call write_dataset(cell_group, "fill", universes(c%fill)%id) + call write_dataset(cell_group, "maps", size(c%offset)) + if (size(c%offset) > 0) then + call write_dataset(cell_group, "offset", c%offset) end if - if (allocated(c % translation)) then - call su % write_data(1, "translated", & - group="geometry/cells/cell " // trim(to_str(c % id))) - call su % write_data(c % translation, "translation", length=3, & - group="geometry/cells/cell " // trim(to_str(c % id))) + if (allocated(c%translation)) then + call write_dataset(cell_group, "translated", 1) + call write_dataset(cell_group, "translation", c%translation) else - call su % write_data(0, "translated", & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "translated", 0) end if - if (allocated(c % rotation)) then - call su % write_data(1, "rotated", & - group="geometry/cells/cell " // trim(to_str(c % id))) - call su % write_data(c % rotation, "rotation", length=3, & - group="geometry/cells/cell " // trim(to_str(c % id))) + if (allocated(c%rotation)) then + call write_dataset(cell_group, "rotated", 1) + call write_dataset(cell_group, "rotation", c%rotation) else - call su % write_data(0, "rotated", & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "rotated", 0) end if case (CELL_LATTICE) - call su % write_data("lattice", "fill_type", & - group="geometry/cells/cell " // trim(to_str(c % id))) - call su % write_data(lattices(c % fill) % obj % id, "lattice", & - group="geometry/cells/cell " // trim(to_str(c % id))) + call write_dataset(cell_group, "fill_type", "lattice") + call write_dataset(cell_group, "lattice", lattices(c%fill)%obj%id) end select ! Write list of bounding surfaces - if (c % n_surfaces > 0) then - call su % write_data(c % surfaces, "surfaces", length= c % n_surfaces, & - group="geometry/cells/cell " // trim(to_str(c % id))) + if (c%n_surfaces > 0) then + call write_dataset(cell_group, "surfaces", c%surfaces) end if + call close_group(cell_group) end do CELL_LOOP + call close_group(cells_group) + ! ========================================================================== ! WRITE INFORMATION ON SURFACES - ! Create surfaces group (nothing directly written here) then close - call su % open_group("geometry/surfaces") - call su % close_group() + ! Create surfaces group + surfaces_group = create_group(file_id, "surfaces") ! Write information on each surface SURFACE_LOOP: do i = 1, n_surfaces s => surfaces(i) + surface_group = create_group(surfaces_group, "surface " // & + trim(to_str(s%id))) ! Write internal OpenMC index for this surface - call su % write_data(i, "index", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "index", i) ! Write name for this surface - call su % write_data(s % name, "name", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "name", s%name) ! Write surface type - select case (s % type) + select case (s%type) case (SURF_PX) - call su % write_data("X Plane", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "X Plane") case (SURF_PY) - call su % write_data("Y Plane", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "Y Plane") case (SURF_PZ) - call su % write_data("Z Plane", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "Z Plane") case (SURF_PLANE) - call su % write_data("Plane", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "Plane") case (SURF_CYL_X) - call su % write_data("X Cylinder", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "X Cylinder") case (SURF_CYL_Y) - call su % write_data("Y Cylinder", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "Y Cylinder") case (SURF_CYL_Z) - call su % write_data("Z Cylinder", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "Z Cylinder") case (SURF_SPHERE) - call su % write_data("Sphere", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "Sphere") case (SURF_CONE_X) - call su % write_data("X Cone", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "X Cone") case (SURF_CONE_Y) - call su % write_data("Y Cone", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "Y Cone") case (SURF_CONE_Z) - call su % write_data("Z Cone", "type", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "type", "Z Cone") end select ! Write coefficients for surface - call su % write_data(s % coeffs, "coefficients", length=size(s % coeffs), & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "coefficients", s%coeffs) ! Write positive neighbors - if (allocated(s % neighbor_pos)) then - call su % write_data(s % neighbor_pos, "neighbors_positive", & - length=size(s % neighbor_pos), & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + if (allocated(s%neighbor_pos)) then + call write_dataset(surface_group, "neighbors_positive", s%neighbor_pos) end if ! Write negative neighbors - if (allocated(s % neighbor_neg)) then - call su % write_data(s % neighbor_neg, "neighbors_negative", & - length=size(s % neighbor_neg), & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + if (allocated(s%neighbor_neg)) then + call write_dataset(surface_group, "neighbors_negative", s%neighbor_neg) end if ! Write boundary condition - select case (s % bc) + select case (s%bc) case (BC_TRANSMIT) - call su % write_data("transmission", "boundary_condition", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "boundary_condition", "transmission") case (BC_VACUUM) - call su % write_data("vacuum", "boundary_condition", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "boundary_condition", "vacuum") case (BC_REFLECT) - call su % write_data("reflective", "boundary_condition", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "boundary_condition", "reflective") case (BC_PERIODIC) - call su % write_data("periodic", "boundary_condition", & - group="geometry/surfaces/surface " // trim(to_str(s % id))) + call write_dataset(surface_group, "boundary_condition", "periodic") end select + call close_group(surface_group) end do SURFACE_LOOP + call close_group(surfaces_group) + ! ========================================================================== ! WRITE INFORMATION ON UNIVERSES ! Create universes group (nothing directly written here) then close - call su % open_group("geometry/universes") - call su % close_group() + universes_group = create_group(geom_group, "universes") ! Write information on each universe UNIVERSE_LOOP: do i = 1, n_universes u => universes(i) + univ_group = create_group(universes_group, "universe " // & + trim(to_str(u%id))) ! Write internal OpenMC index for this universe - call su % write_data(i, "index", & - group="geometry/universes/universe " // trim(to_str(u % id))) + call write_dataset(univ_group, "index", i) ! Write list of cells in this universe - if (u % n_cells > 0) then - call su % write_data(u % cells, "cells", length=u % n_cells, & - group="geometry/universes/universe " // trim(to_str(u % id))) - end if + if (u%n_cells > 0) call write_dataset(univ_group, "cells", u%cells) + call close_group(univ_group) end do UNIVERSE_LOOP + call close_group(universes_group) + ! ========================================================================== ! WRITE INFORMATION ON LATTICES ! Create lattices group (nothing directly written here) then close - call su % open_group("geometry/lattices") - call su % close_group() + lattices_group = create_group(geom_group, "lattices") ! Write information on each lattice LATTICE_LOOP: do i = 1, n_lattices - lat => lattices(i) % obj + lat => lattices(i)%obj + lattice_group = create_group(lattices_group, "lattice " // trim(to_str(lat%id))) ! Write internal OpenMC index for this lattice - call su % write_data(i, "index", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + call write_dataset(lattice_group, "index", i) ! Write name for this lattice - call su % write_data(lat % name, "name", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + call write_dataset(lattice_group, "name", lat%name) ! Write lattice type select type (lat) type is (RectLattice) ! Write lattice type. - call su % write_data("rectangular", "type", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + call write_dataset(lattice_group, "type", "rectangular") ! Write lattice dimensions, lower left corner, and pitch - call su % write_data(lat % n_cells, "dimension", length=3, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + call write_dataset(lattice_group, "dimension", lat%n_cells) + call write_dataset(lattice_group, "lower_left", lat%lower_left) + call write_dataset(lattice_group, "pitch", lat%pitch) - if (lat % is_3d) then - call su % write_data(lat % lower_left, "lower_left", length=3, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - else - call su % write_data(lat % lower_left, "lower_left", length=2, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - end if + call write_dataset(lattice_group, "outer", lat%outer) + call write_dataset(lattice_group, "offset_size", size(lat%offset)) + call write_dataset(lattice_group, "maps", size(lat%offset,1)) - if (lat % is_3d) then - call su % write_data(lat % pitch, "pitch", length=3, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - else - call su % write_data(lat % pitch, "pitch", length=2, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - end if - - call su % write_data(lat % outer, "outer", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - call su % write_data(size(lat % offset), "offset_size", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - call su % write_data(size(lat % offset,1), "maps", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - - if (size(lat % offset) > 0) then - call su % write_data(lat % offset, "offsets", & - length=shape(lat % offset), & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + if (size(lat%offset) > 0) then + call write_dataset(lattice_group, "offsets", lat%offset) end if ! Write lattice universes. - allocate(lattice_universes(lat % n_cells(1), lat % n_cells(2), & - &lat % n_cells(3))) - do j = 1, lat % n_cells(1) - do k = 1, lat % n_cells(2) - do m = 1, lat % n_cells(3) - lattice_universes(j,k,m) = universes(lat % universes(j,k,m)) % id + allocate(lattice_universes(lat%n_cells(1), lat%n_cells(2), & + &lat%n_cells(3))) + do j = 1, lat%n_cells(1) + do k = 1, lat%n_cells(2) + do m = 1, lat%n_cells(3) + lattice_universes(j,k,m) = universes(lat%universes(j,k,m))%id end do end do end do - call su % write_data(lattice_universes, "universes", & - length=lat % n_cells, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + call write_dataset(lattice_group, "universes", lattice_universes) deallocate(lattice_universes) type is (HexLattice) ! Write lattice type. - call su % write_data("hexagonal", "type", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + call write_dataset(lattice_group, "type", "hexagonal") ! Write number of lattice cells. - call su % write_data(lat % n_rings, "n_rings", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - call su % write_data(lat % n_axial, "n_axial", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + call write_dataset(lattice_group, "n_rings", lat%n_rings) + call write_dataset(lattice_group, "n_axial", lat%n_axial) ! Write lattice center, pitch and outer universe. - if (lat % is_3d) then - call su % write_data(lat % center, "center", length=3, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - else - call su % write_data(lat % center, "center", length=2, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - end if + call write_dataset(lattice_group, "center", lat%center) + call write_dataset(lattice_group, "pitch", lat%pitch) - if (lat % is_3d) then - call su % write_data(lat % pitch, "pitch", length=2, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - else - call su % write_data(lat % pitch, "pitch", length=1, & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - end if + call write_dataset(lattice_group, "outer", lat%outer) + call write_dataset(lattice_group, "offset_size", size(lat%offset)) + call write_dataset(lattice_group, "maps", size(lat%offset,1)) - call su % write_data(lat % outer, "outer", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - call su % write_data(size(lat % offset), "offset_size", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - call su % write_data(size(lat % offset,1), "maps", & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) - - if (size(lat % offset) > 0) then - call su % write_data(lat % offset, "offsets", & - length=shape(lat % offset), & - group="geometry/lattices/lattice " // trim(to_str(lat % id))) + if (size(lat%offset) > 0) then + call write_dataset(lattice_group, "offsets", lat%offset) end if ! Write lattice universes. - allocate(lattice_universes(2*lat % n_rings - 1, 2*lat % n_rings - 1, & - &lat % n_axial)) - do m = 1, lat % n_axial - do k = 1, 2*lat % n_rings - 1 - do j = 1, 2*lat % n_rings - 1 - if (j + k < lat % n_rings + 1) then + allocate(lattice_universes(2*lat%n_rings - 1, 2*lat%n_rings - 1, & + &lat%n_axial)) + do m = 1, lat%n_axial + do k = 1, 2*lat%n_rings - 1 + do j = 1, 2*lat%n_rings - 1 + if (j + k < lat%n_rings + 1) then ! This array position is never used; put a -1 to indicate this lattice_universes(j,k,m) = -1 cycle - else if (j + k > 3*lat % n_rings - 1) then + else if (j + k > 3*lat%n_rings - 1) then ! This array position is never used; put a -1 to indicate this lattice_universes(j,k,m) = -1 cycle end if - lattice_universes(j,k,m) = universes(lat % universes(j,k,m)) % id + lattice_universes(j,k,m) = universes(lat%universes(j,k,m))%id end do end do end do - call su % write_data(lattice_universes, "universes", & - &length=(/2*lat % n_rings-1, 2*lat % n_rings-1, lat % n_axial/), & - &group="geometry/lattices/lattice " // trim(to_str(lat % id))) + call write_dataset(lattice_group, "universes", lattice_universes) deallocate(lattice_universes) end select + + call close_group(lattice_group) end do LATTICE_LOOP + call close_group(lattices_group) + call close_group(geom_group) + end subroutine hdf5_write_geometry !=============================================================================== ! HDF5_WRITE_MATERIALS !=============================================================================== - subroutine hdf5_write_materials() + subroutine hdf5_write_materials(file_id) + integer(HID_T), intent(in) :: file_id integer :: i integer :: j integer, allocatable :: zaids(:) - type(Material), pointer :: m => null() + integer(HID_T) :: materials_group + integer(HID_T) :: material_group + integer(HID_T) :: sab_group + type(Material), pointer :: m - ! Use H5LT interface to write number of materials - call su % write_data(n_materials, "n_materials", group="materials") + materials_group = create_group(file_id, "materials") + + ! write number of materials + call write_dataset(file_id, "n_materials", n_materials) ! Write information on each material do i = 1, n_materials m => materials(i) + material_group = create_group(materials_group, "material " // & + trim(to_str(m%id))) ! Write internal OpenMC index for this material - call su % write_data(i, "index", & - group="materials/material " // trim(to_str(m % id))) + call write_dataset(material_group, "index", i) ! Write name for this material - call su % write_data(m % name, "name", & - group="materials/material " // trim(to_str(m % id))) + call write_dataset(material_group, "name", m%name) ! Write atom density with units - call su % write_data(m % density, "atom_density", & - group="materials/material " // trim(to_str(m % id))) - call su % write_attribute_string("atom_density", "units", "atom/b-cm", & - group="materials/material " // trim(to_str(m % id))) + call write_dataset(material_group, "atom_density", m%density) + call write_attribute_string(material_group, "atom_density", "units", & + "atom/b-cm") ! Copy ZAID for each nuclide to temporary array - allocate(zaids(m % n_nuclides)) - do j = 1, m % n_nuclides - zaids(j) = nuclides(m % nuclide(j)) % zaid + allocate(zaids(m%n_nuclides)) + do j = 1, m%n_nuclides + zaids(j) = nuclides(m%nuclide(j))%zaid end do ! Write temporary array to 'nuclides' - call su % write_data(zaids, "nuclides", length=m % n_nuclides, & - group="materials/material " // trim(to_str(m % id))) + call write_dataset(material_group, "nuclides", zaids) ! Deallocate temporary array deallocate(zaids) ! Write atom densities - call su % write_data(m % atom_density, "nuclide_densities", & - length=m % n_nuclides, & - group="materials/material " // trim(to_str(m % id))) + call write_dataset(material_group, "nuclide_densities", m%atom_density) ! Write S(a,b) information if present - call su % write_data(m % n_sab, "n_sab", & - group="materials/material " // trim(to_str(m % id))) + call write_dataset(material_group, "n_sab", m%n_sab) - if (m % n_sab > 0) then - call su % write_data(m % i_sab_nuclides, "i_sab_nuclides", & - length=m % n_sab, & - group="materials/material " // trim(to_str(m % id))) - call su % write_data(m % i_sab_tables, "i_sab_tables", & - length=m % n_sab, & - group="materials/material " // trim(to_str(m % id))) + if (m%n_sab > 0) then + call write_dataset(material_group, "i_sab_nuclides", m%i_sab_nuclides) + call write_dataset(material_group, "i_sab_tables", m%i_sab_tables) - do j = 1, m % n_sab - call su % write_data(m % sab_names(j), to_str(j), & - group="materials/material " // & - trim(to_str(m % id)) // "/sab_tables") + sab_group = create_group(material_group, "sab_tables") + do j = 1, m%n_sab + call write_dataset(sab_group, to_str(j), m%sab_names(j)) end do + call close_group(sab_group) end if + call close_group(material_group) end do + call close_group(materials_group) + end subroutine hdf5_write_materials !=============================================================================== ! HDF5_WRITE_TALLIES !=============================================================================== - subroutine hdf5_write_tallies() + subroutine hdf5_write_tallies(file_id) + integer(HID_T), intent(in) :: file_id integer :: i, j integer, allocatable :: temp_array(:) ! nuclide bin array - type(StructuredMesh), pointer :: m => null() - type(TallyObject), pointer :: t => null() + integer(HID_T) :: tallies_group + integer(HID_T) :: mesh_group + integer(HID_T) :: tally_group + integer(HID_T) :: filter_group + type(StructuredMesh), pointer :: m + type(TallyObject), pointer :: t + + tallies_group = create_group(file_id, "tallies") ! Write total number of meshes - call su % write_data(n_meshes, "n_meshes", group="tallies") + call write_dataset(tallies_group, "n_meshes", n_meshes) ! Write information for meshes MESH_LOOP: do i = 1, n_meshes m => meshes(i) + mesh_group = create_group(tallies_group, "mesh " // trim(to_str(m%id))) ! Write type and number of dimensions - call su % write_data(m % type, "type", & - group="tallies/mesh " // trim(to_str(m % id))) - - call su % write_data(m % n_dimension, "n_dimension", & - group="tallies/mesh " // trim(to_str(m % id))) + call write_dataset(mesh_group, "type", m%type) + call write_dataset(mesh_group, "n_dimension", m%n_dimension) ! Write mesh information - call su % write_data(m % dimension, "dimension", & - length=m % n_dimension, & - group="tallies/mesh " // trim(to_str(m % id))) - call su % write_data(m % lower_left, "lower_left", & - length=m % n_dimension, & - group="tallies/mesh " // trim(to_str(m % id))) - call su % write_data(m % upper_right, "upper_right", & - length=m % n_dimension, & - group="tallies/mesh " // trim(to_str(m % id))) - call su % write_data(m % width, "width", & - length=m % n_dimension, & - group="tallies/mesh " // trim(to_str(m % id))) + 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) end do MESH_LOOP ! Write number of tallies - call su % write_data(n_tallies, "n_tallies", group="tallies") + call write_dataset(tallies_group, "n_tallies", n_tallies) TALLY_METADATA: do i = 1, n_tallies ! Get pointer to tally t => tallies(i) + tally_group = create_group(tallies_group, "tally " // trim(to_str(t%id))) ! Write the name for this tally - call su % write_data(len(t % name), "name_size", & - group="tallies/tally " // trim(to_str(t % id))) - if (len(t % name) > 0) then - call su % write_data(t % name, "name", & - group="tallies/tally " // trim(to_str(t % id))) + call write_dataset(tally_group, "name_size", len(t%name)) + if (len(t%name) > 0) then + call write_dataset(tally_group, "name", t%name) endif ! Write size of each tally - call su % write_data(t % total_score_bins, "total_score_bins", & - group="tallies/tally " // trim(to_str(t % id))) - call su % write_data(t % total_filter_bins, "total_filter_bins", & - group="tallies/tally " // trim(to_str(t % id))) + call write_dataset(tally_group, "total_score_bins", t%total_score_bins) + call write_dataset(tally_group, "total_filter_bins", t%total_filter_bins) ! Write number of filters - call su % write_data(t % n_filters, "n_filters", & - group="tallies/tally " // trim(to_str(t % id))) + call write_dataset(tally_group, "n_filters", t%n_filters) + + FILTER_LOOP: do j = 1, t%n_filters + filter_group = create_group(tally_group, "filter " // trim(to_str(j))) - FILTER_LOOP: do j = 1, t % n_filters ! Write type of filter - call su % write_data(t % filters(j) % type, "type", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type", t%filters(j)%type) ! Write number of bins for this filter - call su % write_data(t % filters(j) % n_bins, "n_bins", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "n_bins", t%filters(j)%n_bins) ! Write filter bins - if (t % filters(j) % type == FILTER_ENERGYIN .or. & - t % filters(j) % type == FILTER_ENERGYOUT) then - call su % write_data(t % filters(j) % real_bins, "bins", & - length=size(t % filters(j) % real_bins), & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + if (t%filters(j)%type == FILTER_ENERGYIN .or. & + t%filters(j)%type == FILTER_ENERGYOUT) then + call write_dataset(filter_group, "bins", t%filters(j)%real_bins) else - call su % write_data(t % filters(j) % int_bins, "bins", & - length=size(t % filters(j) % int_bins), & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "bins", t%filters(j)%int_bins) end if ! Write name of type - select case (t % filters(j) % type) + select case (t%filters(j)%type) case(FILTER_UNIVERSE) - call su % write_data("universe", "type_name", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type_name", "universe") case(FILTER_MATERIAL) - call su % write_data("material", "type_name", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type_name", "material") case(FILTER_CELL) - call su % write_data("cell", "type_name", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type_name", "cell") case(FILTER_CELLBORN) - call su % write_data("cellborn", "type_name", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type_name", "cellborn") case(FILTER_SURFACE) - call su % write_data("surface", "type_name", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type_name", "surface") case(FILTER_MESH) - call su % write_data("mesh", "type_name", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type_name", "mesh") case(FILTER_ENERGYIN) - call su % write_data("energy", "type_name", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type_name", "energy") case(FILTER_ENERGYOUT) - call su % write_data("energyout", "type_name", & - group="tallies/tally " // trim(to_str(t % id)) & - // "/filter " // trim(to_str(j))) + call write_dataset(filter_group, "type_name", "energyout") end select + call close_group(filter_group) end do FILTER_LOOP ! Write number of nuclide bins - call su % write_data(t % n_nuclide_bins, "n_nuclide_bins", & - group="tallies/tally " // trim(to_str(t % id))) + call write_dataset(tally_group, "n_nuclide_bins", t%n_nuclide_bins) ! Create temporary array for nuclide bins - allocate(temp_array(t % n_nuclide_bins)) - NUCLIDE_LOOP: do j = 1, t % n_nuclide_bins - if (t % nuclide_bins(j) > 0) then - temp_array(j) = nuclides(t % nuclide_bins(j)) % zaid + allocate(temp_array(t%n_nuclide_bins)) + NUCLIDE_LOOP: do j = 1, t%n_nuclide_bins + if (t%nuclide_bins(j) > 0) then + temp_array(j) = nuclides(t%nuclide_bins(j))%zaid else - temp_array(j) = t % nuclide_bins(j) + temp_array(j) = t%nuclide_bins(j) end if end do NUCLIDE_LOOP ! Write and deallocate nuclide bins - call su % write_data(temp_array, "nuclide_bins", length=t % n_nuclide_bins, & - group="tallies/tally " // trim(to_str(t % id))) + call write_dataset(tally_group, "nuclide_bins", temp_array) deallocate(temp_array) ! Write number of score bins - call su % write_data(t % n_score_bins, "n_score_bins", & - group="tallies/tally " // trim(to_str(t % id))) - call su % write_data(t % score_bins, "score_bins", length=t % n_score_bins, & - group="tallies/tally " // trim(to_str(t % id))) + call write_dataset(tally_group, "n_score_bins", t%n_score_bins) + call write_dataset(tally_group, "score_bins", t%score_bins) + call close_group(tally_group) end do TALLY_METADATA + call close_group(tallies_group) + end subroutine hdf5_write_tallies !=============================================================================== ! HDF5_WRITE_NUCLIDES !=============================================================================== - subroutine hdf5_write_nuclides() + subroutine hdf5_write_nuclides(file_id) + integer(HID_T), intent(in) :: file_id integer :: i, j integer :: size_total integer :: size_xs integer :: size_angle integer :: size_energy - type(Nuclide), pointer :: nuc => null() - type(Reaction), pointer :: rxn => null() - type(UrrData), pointer :: urr => null() + integer(HID_T) :: nuclides_group, nuclide_group + integer(HID_T) :: reactions_group, rxn_group + type(Nuclide), pointer :: nuc + type(Reaction), pointer :: rxn + type(UrrData), pointer :: urr - ! Use H5LT interface to write number of nuclides - call su % write_data(n_nuclides_total, "n_nuclides", group="nuclides") + nuclides_group = create_group(file_id, "nuclides") + + ! write number of nuclides + call write_dataset(nuclides_group, "n_nuclides", n_nuclides_total) ! Write information on each nuclide NUCLIDE_LOOP: do i = 1, n_nuclides_total nuc => nuclides(i) + nuclide_group = create_group(nuclides_group, nuc%name) ! Write internal OpenMC index for this nuclide - call su % write_data(i, "index", & - group="nuclides/" // trim(nuc % name)) + call write_dataset(nuclide_group, "index", i) ! Determine size of cross-sections - size_xs = (5 + nuc % n_reaction) * nuc % n_grid * 8 + size_xs = (5 + nuc%n_reaction) * nuc%n_grid * 8 size_total = size_xs ! Write some basic attributes - call su % write_data(nuc % zaid, "zaid", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(xs_listings(nuc % listing) % alias, "alias", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(nuc % awr, "awr", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(nuc % kT, "kT", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(nuc % n_grid, "n_grid", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(nuc % n_reaction, "n_reactions", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(nuc % n_fission, "n_fission", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(size_xs, "size_xs", & - group="nuclides/" // trim(nuc % name)) + call write_dataset(nuclide_group, "zaid", nuc%zaid) + call write_dataset(nuclide_group, "alias", xs_listings(nuc%listing)%alias) + call write_dataset(nuclide_group, "awr", nuc%awr) + call write_dataset(nuclide_group, "kT", nuc%kT) + call write_dataset(nuclide_group, "n_grid", nuc%n_grid) + call write_dataset(nuclide_group, "n_reactions", nuc%n_reaction) + call write_dataset(nuclide_group, "n_fission", nuc%n_fission) + call write_dataset(nuclide_group, "size_xs", size_xs) ! ======================================================================= ! WRITE INFORMATION ON EACH REACTION ! Create overall group for reactions and close it - call su % open_group("nuclides/" // trim(nuc % name) // "/reactions") - call su % close_group() + reactions_group = create_group(nuclide_group, "reactions") - RXN_LOOP: do j = 1, nuc % n_reaction + RXN_LOOP: do j = 1, nuc%n_reaction ! Information on each reaction - rxn => nuc % reactions(j) + rxn => nuc%reactions(j) + rxn_group = create_group(reactions_group, trim(reaction_name(rxn%MT))) ! Determine size of angle distribution - if (rxn % has_angle_dist) then - size_angle = rxn % adist % n_energy * 16 + size(rxn % adist % data) * 8 + if (rxn%has_angle_dist) then + size_angle = rxn%adist%n_energy * 16 + size(rxn%adist%data) * 8 else size_angle = 0 end if ! Determine size of energy distribution - if (rxn % has_energy_dist) then - size_energy = size(rxn % edist % data) * 8 + if (rxn%has_energy_dist) then + size_energy = size(rxn%edist%data) * 8 else size_energy = 0 end if ! Write information on reaction - call su % write_data(rxn % Q_value, "Q_value", & - group="nuclides/" // trim(nuc % name) // "/reactions/" // & - trim(reaction_name(rxn % MT))) - call su % write_data(rxn % multiplicity, "multiplicity", & - group="nuclides/" // trim(nuc % name) // "/reactions/" // & - trim(reaction_name(rxn % MT))) - call su % write_data(rxn % threshold, "threshold", & - group="nuclides/" // trim(nuc % name) // "/reactions/" // & - trim(reaction_name(rxn % MT))) - call su % write_data(size_angle, "size_angle", & - group="nuclides/" // trim(nuc % name) // "/reactions/" // & - trim(reaction_name(rxn % MT))) - call su % write_data(size_energy, "size_energy", & - group="nuclides/" // trim(nuc % name) // "/reactions/" // & - trim(reaction_name(rxn % MT))) + call write_dataset(rxn_group, "Q_value", rxn%Q_value) + call write_dataset(rxn_group, "multiplicity", rxn%multiplicity) + call write_dataset(rxn_group, "threshold", rxn%threshold) + call write_dataset(rxn_group, "size_angle", size_angle) + call write_dataset(rxn_group, "size_energy", size_energy) ! Accumulate data size size_total = size_total + size_angle + size_energy + + call close_group(rxn_group) end do RXN_LOOP + call close_group(reactions_group) + ! ======================================================================= ! WRITE INFORMATION ON URR PROBABILITY TABLES - if (nuc % urr_present) then - urr => nuc % urr_data - call su % write_data(urr % n_energy, "urr_n_energy", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(urr % n_prob, "urr_n_prob", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(urr % interp, "urr_interp", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(urr % inelastic_flag, "urr_inelastic", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(urr % absorption_flag, "urr_absorption", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(urr % energy(1), "urr_min_E", & - group="nuclides/" // trim(nuc % name)) - call su % write_data(urr % energy(urr % n_energy), "urr_max_E", & - group="nuclides/" // trim(nuc % name)) + if (nuc%urr_present) then + urr => nuc%urr_data + call write_dataset(nuclide_group, "urr_n_energy", urr%n_energy) + call write_dataset(nuclide_group, "urr_n_prob", urr%n_prob) + call write_dataset(nuclide_group, "urr_interp", urr%interp) + call write_dataset(nuclide_group, "urr_inelastic", urr%inelastic_flag) + call write_dataset(nuclide_group, "urr_absorption", urr%absorption_flag) + call write_dataset(nuclide_group, "urr_min_E", urr%energy(1)) + call write_dataset(nuclide_group, "urr_max_E", urr%energy(urr%n_energy)) end if ! Write total memory used - call su % write_data(size_total, "size_total", & - group="nuclides/" // trim(nuc % name)) + call write_dataset(nuclide_group, "size_total", size_total) + call close_group(nuclide_group) end do NUCLIDE_LOOP + call close_group(nuclides_group) + end subroutine hdf5_write_nuclides !=============================================================================== ! HDF5_WRITE_TIMING !=============================================================================== - subroutine hdf5_write_timing() + subroutine hdf5_write_timing(file_id) + integer(HID_T), intent(in) :: file_id - integer(8) :: total_particles - real(8) :: speed + integer(8) :: total_particles + integer(HID_T) :: time_group + real(8) :: speed + + time_group = create_group(file_id, "timing") ! Write timing data - call su % write_data(time_initialize % elapsed, "time_initialize", & - group="timing") - call su % write_data(time_read_xs % elapsed, "time_read_xs", & - group="timing") - call su % write_data(time_transport % elapsed, "time_transport", & - group="timing") - call su % write_data(time_bank % elapsed, "time_bank", & - group="timing") - call su % write_data(time_bank_sample % elapsed, "time_bank_sample", & - group="timing") - call su % write_data(time_bank_sendrecv % elapsed, "time_bank_sendrecv", & - group="timing") - call su % write_data(time_tallies % elapsed, "time_tallies", & - group="timing") - call su % write_data(time_inactive % elapsed, "time_inactive", & - group="timing") - call su % write_data(time_active % elapsed, "time_active", & - group="timing") - call su % write_data(time_finalize % elapsed, "time_finalize", & - group="timing") - call su % write_data(time_total % elapsed, "time_total", & - group="timing") + call write_dataset(time_group, "time_initialize", time_initialize%elapsed) + call write_dataset(time_group, "time_read_xs", time_read_xs%elapsed) + call write_dataset(time_group, "time_transport", time_transport%elapsed) + call write_dataset(time_group, "time_bank", time_bank%elapsed) + call write_dataset(time_group, "time_bank_sample", time_bank_sample%elapsed) + call write_dataset(time_group, "time_bank_sendrecv", time_bank_sendrecv%elapsed) + call write_dataset(time_group, "time_tallies", time_tallies%elapsed) + call write_dataset(time_group, "time_inactive", time_inactive%elapsed) + call write_dataset(time_group, "time_active", time_active%elapsed) + call write_dataset(time_group, "time_finalize", time_finalize%elapsed) + call write_dataset(time_group, "time_total", time_total%elapsed) ! Add descriptions to timing data - call su % write_attribute_string("time_initialize", "description", & - "Total time elapsed for initialization (s)", group="timing") - call su % write_attribute_string("time_read_xs", "description", & - "Time reading cross-section libraries (s)", group="timing") - call su % write_attribute_string("time_transport", "description", & - "Time in transport only (s)", group="timing") - call su % write_attribute_string("time_bank", "description", & - "Total time synchronizing fission bank (s)", group="timing") - call su % write_attribute_string("time_bank_sample", "description", & - "Time between generations sampling source sites (s)", group="timing") - call su % write_attribute_string("time_bank_sendrecv", "description", & - "Time between generations SEND/RECVing source sites (s)", & - group="timing") - call su % write_attribute_string("time_tallies", "description", & - "Time between batches accumulating tallies (s)", group="timing") - call su % write_attribute_string("time_inactive", "description", & - "Total time in inactive batches (s)", group="timing") - call su % write_attribute_string("time_active", "description", & - "Total time in active batches (s)", group="timing") - call su % write_attribute_string("time_finalize", "description", & - "Total time for finalization (s)", group="timing") - call su % write_attribute_string("time_total", "description", & - "Total time elapsed (s)", group="timing") + call write_attribute_string(time_group, "time_initialize", "description", & + "Total time elapsed for initialization (s)") + call write_attribute_string(time_group, "time_read_xs", "description", & + "Time reading cross-section libraries (s)") + call write_attribute_string(time_group, "time_transport", "description", & + "Time in transport only (s)") + call write_attribute_string(time_group, "time_bank", "description", & + "Total time synchronizing fission bank (s)") + call write_attribute_string(time_group, "time_bank_sample", "description", & + "Time between generations sampling source sites (s)") + call write_attribute_string(time_group, "time_bank_sendrecv", "description", & + "Time between generations SEND/RECVing source sites (s)") + call write_attribute_string(time_group, "time_tallies", "description", & + "Time between batches accumulating tallies (s)") + call write_attribute_string(time_group, "time_inactive", "description", & + "Total time in inactive batches (s)") + call write_attribute_string(time_group, "time_active", "description", & + "Total time in active batches (s)") + call write_attribute_string(time_group, "time_finalize", "description", & + "Total time for finalization (s)") + call write_attribute_string(time_group, "time_total", "description", & + "Total time elapsed (s)") ! Write calculation rate total_particles = n_particles * n_batches * gen_per_batch - speed = real(total_particles) / (time_inactive % elapsed + & - time_active % elapsed) - call su % write_data(speed, "neutrons_per_second", group="timing") + speed = real(total_particles) / (time_inactive%elapsed + & + time_active%elapsed) + call write_dataset(time_group, "neutrons_per_second", speed) + call close_group(time_group) end subroutine hdf5_write_timing end module hdf5_summary diff --git a/src/initialize.F90 b/src/initialize.F90 index 22521b24d..29e5f8921 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -12,12 +12,14 @@ module initialize use geometry_header, only: Cell, Universe, Lattice, RectLattice, HexLattice,& &BASE_UNIVERSE use global + use hdf5_interface, only: file_open, read_dataset, file_close, hdf5_bank_t,& + hdf5_tallyresult_t, hdf5_integer8_t + use hdf5_summary, only: hdf5_write_summary use input_xml, only: read_input_xml, read_cross_sections_xml, & cells_in_univ_dict, read_plots_xml use material_header, only: Material use output, only: title, header, print_version, write_message, & print_usage, write_xs_summary, print_plot - use output_interface use random_lcg, only: initialize_prng use state_point, only: load_state_point use string, only: to_str, str_to_int, starts_with, ends_with @@ -32,8 +34,7 @@ module initialize use omp_lib #endif - use hdf5_interface - use hdf5_summary, only: hdf5_write_summary + use hdf5 implicit none @@ -49,8 +50,8 @@ contains subroutine initialize_run() ! Start total and initialization timer - call time_total % start() - call time_initialize % start() + call time_total%start() + call time_initialize%start() #ifdef MPI ! Setup MPI @@ -110,9 +111,9 @@ contains call normalize_ao() ! Read ACE-format cross sections - call time_read_xs % start() + call time_read_xs%start() call read_xs() - call time_read_xs % stop() + call time_read_xs%stop() ! Create linked lists for multiple instances of the same nuclide call same_nuclide_list() @@ -122,9 +123,9 @@ contains case (GRID_NUCLIDE) continue case (GRID_MAT_UNION) - call time_unionize % start() + call time_unionize%start() call unionized_grid() - call time_unionize % stop() + call time_unionize%stop() case (GRID_LOGARITHM) call logarithmic_grid() end select @@ -167,7 +168,7 @@ contains end if ! Stop initialization timer - call time_initialize % stop() + call time_initialize%stop() end subroutine initialize_run @@ -220,10 +221,10 @@ contains ! CREATE MPI_BANK TYPE ! Determine displacements for MPI_BANK type - call MPI_GET_ADDRESS(b % wgt, bank_disp(1), mpi_err) - call MPI_GET_ADDRESS(b % xyz, bank_disp(2), mpi_err) - call MPI_GET_ADDRESS(b % uvw, bank_disp(3), mpi_err) - call MPI_GET_ADDRESS(b % E, bank_disp(4), mpi_err) + call MPI_GET_ADDRESS(b%wgt, bank_disp(1), mpi_err) + call MPI_GET_ADDRESS(b%xyz, bank_disp(2), mpi_err) + call MPI_GET_ADDRESS(b%uvw, bank_disp(3), mpi_err) + call MPI_GET_ADDRESS(b%E, bank_disp(4), mpi_err) ! Adjust displacements bank_disp = bank_disp - bank_disp(1) @@ -239,8 +240,8 @@ contains ! CREATE MPI_TALLYRESULT TYPE ! Determine displacements for MPI_BANK type - call MPI_GET_ADDRESS(tr % value, result_base_disp, mpi_err) - call MPI_GET_ADDRESS(tr % sum, result_disp(1), mpi_err) + call MPI_GET_ADDRESS(tr%value, result_base_disp, mpi_err) + call MPI_GET_ADDRESS(tr%sum, result_disp(1), mpi_err) ! Adjust displacements result_disp = result_disp - result_base_disp @@ -274,6 +275,7 @@ contains type(TallyResult), target :: tmp(2) ! temporary TallyResult type(Bank), target :: tmpb(2) ! temporary Bank + integer :: hdf5_err integer(HID_T) :: coordinates_t ! HDF5 type for 3 reals integer(HSIZE_T) :: dims(1) = (/3/) ! size of coordinates @@ -318,8 +320,8 @@ contains integer :: argc ! number of command line arguments integer :: last_flag ! index of last flag integer :: filetype + integer(HID_T) :: file_id character(MAX_WORD_LEN), allocatable :: argv(:) ! command line arguments - type(BinaryOutput) :: sp ! Check number of command line arguments and allocate argv argc = COMMAND_ARGUMENT_COUNT() @@ -356,9 +358,9 @@ contains i = i + 1 ! Check what type of file this is - call sp % file_open(argv(i), 'r', serial = .false.) - call sp % read_data(filetype, 'filetype') - call sp % file_close() + file_id = file_open(argv(i), 'r', parallel=.true.) + call read_dataset(file_id, 'filetype', filetype) + call file_close(file_id) ! Set path and flag for type of run select case (filetype) @@ -379,13 +381,12 @@ contains i = i + 1 ! Check if it has extension we can read - if ((ends_with(argv(i), '.binary') .or. & - ends_with(argv(i), '.h5'))) then + if (ends_with(argv(i), '.h5')) then ! Check file type is a source file - call sp % file_open(argv(i), 'r', serial = .false.) - call sp % read_data(filetype, 'filetype') - call sp % file_close() + file_id = file_open(argv(i), 'r', parallel=.true.) + call read_dataset(file_id, 'filetype', filetype) + call file_close(file_id) if (filetype /= FILETYPE_SOURCE) then call fatal_error("Second file after restart flag must be a & &source file") @@ -494,26 +495,26 @@ contains ! pairs are the id of the universe and the index in the array. In ! cells_in_univ_dict, it's the id of the universe and the number of cells. - pair_list => universe_dict % keys() + pair_list => universe_dict%keys() current => pair_list do while (associated(current)) ! Find index of universe in universes array - i_univ = current % value + i_univ = current%value univ => universes(i_univ) - univ % id = current % key + univ%id = current%key ! Check for lowest level universe - if (univ % id == 0) BASE_UNIVERSE = i_univ + if (univ%id == 0) BASE_UNIVERSE = i_univ ! Find cell count for this universe - n_cells_in_univ = cells_in_univ_dict % get_key(univ % id) + n_cells_in_univ = cells_in_univ_dict%get_key(univ%id) ! Allocate cell list for universe - allocate(univ % cells(n_cells_in_univ)) - univ % n_cells = n_cells_in_univ + allocate(univ%cells(n_cells_in_univ)) + univ%n_cells = n_cells_in_univ ! Move to next universe - next => current % next + next => current%next deallocate(current) current => next end do @@ -528,17 +529,17 @@ contains c => cells(i) ! Get pointer to corresponding universe - i_univ = universe_dict % get_key(c % universe) + i_univ = universe_dict%get_key(c%universe) univ => universes(i_univ) ! Increment the index for the cells array within the Universe object and ! then store the index of the Cell object in that array index_cell_in_univ(i_univ) = index_cell_in_univ(i_univ) + 1 - univ % cells(index_cell_in_univ(i_univ)) = i + univ%cells(index_cell_in_univ(i_univ)) = i end do ! Clear dictionary - call cells_in_univ_dict % clear() + call cells_in_univ_dict%clear() end subroutine prepare_universes @@ -568,15 +569,15 @@ contains ! ADJUST SURFACE LIST FOR EACH CELL c => cells(i) - do j = 1, c % n_surfaces - id = c % surfaces(j) + do j = 1, c%n_surfaces + id = c%surfaces(j) if (id < OP_DIFFERENCE) then - if (surface_dict % has_key(abs(id))) then - i_array = surface_dict % get_key(abs(id)) - c % surfaces(j) = sign(i_array, id) + if (surface_dict%has_key(abs(id))) then + i_array = surface_dict%get_key(abs(id)) + c%surfaces(j) = sign(i_array, id) else call fatal_error("Could not find surface " // trim(to_str(abs(id)))& - &// " specified on cell " // trim(to_str(c % id))) + &// " specified on cell " // trim(to_str(c%id))) end if end if end do @@ -584,40 +585,40 @@ contains ! ======================================================================= ! ADJUST UNIVERSE INDEX FOR EACH CELL - id = c % universe - if (universe_dict % has_key(id)) then - c % universe = universe_dict % get_key(id) + id = c%universe + if (universe_dict%has_key(id)) then + c%universe = universe_dict%get_key(id) else call fatal_error("Could not find universe " // trim(to_str(id)) & - &// " specified on cell " // trim(to_str(c % id))) + &// " specified on cell " // trim(to_str(c%id))) end if ! ======================================================================= ! ADJUST MATERIAL/FILL POINTERS FOR EACH CELL - id = c % material + id = c%material if (id == MATERIAL_VOID) then - c % type = CELL_NORMAL + c%type = CELL_NORMAL elseif (id /= 0) then - if (material_dict % has_key(id)) then - c % type = CELL_NORMAL - c % material = material_dict % get_key(id) + if (material_dict%has_key(id)) then + c%type = CELL_NORMAL + c%material = material_dict%get_key(id) else call fatal_error("Could not find material " // trim(to_str(id)) & - &// " specified on cell " // trim(to_str(c % id))) + &// " specified on cell " // trim(to_str(c%id))) end if else - id = c % fill - if (universe_dict % has_key(id)) then - c % type = CELL_FILL - c % fill = universe_dict % get_key(id) - elseif (lattice_dict % has_key(id)) then - lid = lattice_dict % get_key(id) - c % type = CELL_LATTICE - c % fill = lid + id = c%fill + if (universe_dict%has_key(id)) then + c%type = CELL_FILL + c%fill = universe_dict%get_key(id) + elseif (lattice_dict%has_key(id)) then + lid = lattice_dict%get_key(id) + c%type = CELL_LATTICE + c%fill = lid else call fatal_error("Specified fill " // trim(to_str(id)) // " on cell "& - &// trim(to_str(c % id)) // " is neither a universe nor a & + &// trim(to_str(c%id)) // " is neither a universe nor a & &lattice.") end if end if @@ -627,41 +628,41 @@ contains ! ADJUST UNIVERSE INDICES FOR EACH LATTICE do i = 1, n_lattices - lat => lattices(i) % obj + lat => lattices(i)%obj select type (lat) type is (RectLattice) - do m = 1, lat % n_cells(3) - do k = 1, lat % n_cells(2) - do j = 1, lat % n_cells(1) - id = lat % universes(j,k,m) - if (universe_dict % has_key(id)) then - lat % universes(j,k,m) = universe_dict % get_key(id) + do m = 1, lat%n_cells(3) + do k = 1, lat%n_cells(2) + do j = 1, lat%n_cells(1) + id = lat%universes(j,k,m) + if (universe_dict%has_key(id)) then + lat%universes(j,k,m) = universe_dict%get_key(id) else call fatal_error("Invalid universe number " & &// trim(to_str(id)) // " specified on lattice " & - &// trim(to_str(lat % id))) + &// trim(to_str(lat%id))) end if end do end do end do type is (HexLattice) - do m = 1, lat % n_axial - do k = 1, 2*lat % n_rings - 1 - do j = 1, 2*lat % n_rings - 1 - if (j + k < lat % n_rings + 1) then + do m = 1, lat%n_axial + do k = 1, 2*lat%n_rings - 1 + do j = 1, 2*lat%n_rings - 1 + if (j + k < lat%n_rings + 1) then cycle - else if (j + k > 3*lat % n_rings - 1) then + else if (j + k > 3*lat%n_rings - 1) then cycle end if - id = lat % universes(j, k, m) - if (universe_dict % has_key(id)) then - lat % universes(j, k, m) = universe_dict % get_key(id) + id = lat%universes(j, k, m) + if (universe_dict%has_key(id)) then + lat%universes(j, k, m) = universe_dict%get_key(id) else call fatal_error("Invalid universe number " & &// trim(to_str(id)) // " specified on lattice " & - &// trim(to_str(lat % id))) + &// trim(to_str(lat%id))) end if end do end do @@ -669,13 +670,13 @@ contains end select - if (lat % outer /= NO_OUTER_UNIVERSE) then - if (universe_dict % has_key(lat % outer)) then - lat % outer = universe_dict % get_key(lat % outer) + if (lat%outer /= NO_OUTER_UNIVERSE) then + if (universe_dict%has_key(lat%outer)) then + lat%outer = universe_dict%get_key(lat%outer) else call fatal_error("Invalid universe number " & - &// trim(to_str(lat % outer)) & - &// " specified on lattice " // trim(to_str(lat % id))) + &// trim(to_str(lat%outer)) & + &// " specified on lattice " // trim(to_str(lat%id))) end if end if @@ -687,68 +688,68 @@ contains ! ======================================================================= ! ADJUST INDICES FOR EACH TALLY FILTER - FILTER_LOOP: do j = 1, t % n_filters + FILTER_LOOP: do j = 1, t%n_filters - select case (t % filters(j) % type) + select case (t%filters(j)%type) case (FILTER_DISTRIBCELL) - do k = 1, size(t % filters(j) % int_bins) - id = t % filters(j) % int_bins(k) - if (cell_dict % has_key(id)) then - t % filters(j) % int_bins(k) = cell_dict % get_key(id) + do k = 1, size(t%filters(j)%int_bins) + id = t%filters(j)%int_bins(k) + if (cell_dict%has_key(id)) then + t%filters(j)%int_bins(k) = cell_dict%get_key(id) else call fatal_error("Could not find cell " // trim(to_str(id)) // & - " specified on tally " // trim(to_str(t % id))) + " specified on tally " // trim(to_str(t%id))) end if end do case (FILTER_CELL, FILTER_CELLBORN) - do k = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(k) - if (cell_dict % has_key(id)) then - t % filters(j) % int_bins(k) = cell_dict % get_key(id) + do k = 1, t%filters(j)%n_bins + id = t%filters(j)%int_bins(k) + if (cell_dict%has_key(id)) then + t%filters(j)%int_bins(k) = cell_dict%get_key(id) else call fatal_error("Could not find cell " // trim(to_str(id)) & - &// " specified on tally " // trim(to_str(t % id))) + &// " specified on tally " // trim(to_str(t%id))) end if end do case (FILTER_SURFACE) ! Check if this is a surface filter only for surface currents - if (any(t % score_bins == SCORE_CURRENT)) cycle FILTER_LOOP + if (any(t%score_bins == SCORE_CURRENT)) cycle FILTER_LOOP - do k = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(k) - if (surface_dict % has_key(id)) then - t % filters(j) % int_bins(k) = surface_dict % get_key(id) + do k = 1, t%filters(j)%n_bins + id = t%filters(j)%int_bins(k) + if (surface_dict%has_key(id)) then + t%filters(j)%int_bins(k) = surface_dict%get_key(id) else call fatal_error("Could not find surface " // trim(to_str(id)) & - &// " specified on tally " // trim(to_str(t % id))) + &// " specified on tally " // trim(to_str(t%id))) end if end do case (FILTER_UNIVERSE) - do k = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(k) - if (universe_dict % has_key(id)) then - t % filters(j) % int_bins(k) = universe_dict % get_key(id) + do k = 1, t%filters(j)%n_bins + id = t%filters(j)%int_bins(k) + if (universe_dict%has_key(id)) then + t%filters(j)%int_bins(k) = universe_dict%get_key(id) else call fatal_error("Could not find universe " // trim(to_str(id)) & - &// " specified on tally " // trim(to_str(t % id))) + &// " specified on tally " // trim(to_str(t%id))) end if end do case (FILTER_MATERIAL) - do k = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(k) - if (material_dict % has_key(id)) then - t % filters(j) % int_bins(k) = material_dict % get_key(id) + do k = 1, t%filters(j)%n_bins + id = t%filters(j)%int_bins(k) + if (material_dict%has_key(id)) then + t%filters(j)%int_bins(k) = material_dict%get_key(id) else call fatal_error("Could not find material " // trim(to_str(id)) & - &// " specified on tally " // trim(to_str(t % id))) + &// " specified on tally " // trim(to_str(t%id))) end if end do @@ -786,46 +787,46 @@ contains do i = 1, n_materials mat => materials(i) - percent_in_atom = (mat % atom_density(1) > ZERO) - density_in_atom = (mat % density > ZERO) + percent_in_atom = (mat%atom_density(1) > ZERO) + density_in_atom = (mat%density > ZERO) sum_percent = ZERO - do j = 1, mat % n_nuclides + do j = 1, mat%n_nuclides ! determine atomic weight ratio - index_list = xs_listing_dict % get_key(mat % names(j)) - awr = xs_listings(index_list) % awr + index_list = xs_listing_dict%get_key(mat%names(j)) + awr = xs_listings(index_list)%awr ! if given weight percent, convert all values so that they are divided ! by awr. thus, when a sum is done over the values, it's actually ! sum(w/awr) if (.not. percent_in_atom) then - mat % atom_density(j) = -mat % atom_density(j) / awr + mat%atom_density(j) = -mat%atom_density(j) / awr end if end do ! determine normalized atom percents. if given atom percents, this is ! straightforward. if given weight percents, the value is w/awr and is ! divided by sum(w/awr) - sum_percent = sum(mat % atom_density) - mat % atom_density = mat % atom_density / sum_percent + sum_percent = sum(mat%atom_density) + mat%atom_density = mat%atom_density / sum_percent ! Change density in g/cm^3 to atom/b-cm. Since all values are now in atom ! percent, the sum needs to be re-evaluated as 1/sum(x*awr) if (.not. density_in_atom) then sum_percent = ZERO - do j = 1, mat % n_nuclides - index_list = xs_listing_dict % get_key(mat % names(j)) - awr = xs_listings(index_list) % awr - x = mat % atom_density(j) + do j = 1, mat%n_nuclides + index_list = xs_listing_dict%get_key(mat%names(j)) + awr = xs_listings(index_list)%awr + x = mat%atom_density(j) sum_percent = sum_percent + x*awr end do sum_percent = ONE / sum_percent - mat % density = -mat % density * N_AVOGADRO & + mat%density = -mat%density * N_AVOGADRO & / MASS_NEUTRON * sum_percent end if ! Calculate nuclide atom densities - mat % atom_density = mat % density * mat % atom_density + mat%atom_density = mat%density * mat%atom_density end do end subroutine normalize_ao @@ -942,16 +943,16 @@ contains ! Get pointer to tally tally => tallies(i) - n_filt = tally % n_filters + n_filt = tally%n_filters ! Loop over the filters to determine how many additional filters ! need to be added to this tally - do j = 1, tally % n_filters + do j = 1, tally%n_filters ! Determine type of filter - if (tally % filters(j) % type == FILTER_DISTRIBCELL) then + if (tally%filters(j)%type == FILTER_DISTRIBCELL) then count_all = .true. - if (size(tally % filters(j) % int_bins) > 1) then + if (size(tally%filters(j)%int_bins) > 1) then call fatal_error("A distribcell filter was specified with & &multiple bins. This feature is not supported.") end if @@ -975,12 +976,12 @@ contains tally => tallies(i) ! Initialize the filters - do j = 1, tally % n_filters + do j = 1, tally%n_filters ! Set the number of bins to the number of instances of the cell - if (tally % filters(j) % type == FILTER_DISTRIBCELL) then - c => cells(tally % filters(j) % int_bins(1)) - tally % filters(j) % n_bins = c % instances + if (tally%filters(j)%type == FILTER_DISTRIBCELL) then + c => cells(tally%filters(j)%int_bins(1)) + tally%filters(j)%n_bins = c%instances end if end do @@ -1031,12 +1032,12 @@ contains do i = 1, n_tallies tally => tallies(i) - do j = 1, tally % n_filters - filter => tally % filters(j) + do j = 1, tally%n_filters + filter => tally%filters(j) - if (filter % type == FILTER_DISTRIBCELL) then - if (.not. cell_list % contains(filter % int_bins(1))) then - call cell_list % add(filter % int_bins(1)) + if (filter%type == FILTER_DISTRIBCELL) then + if (.not. cell_list%contains(filter%int_bins(1))) then + call cell_list%add(filter%int_bins(1)) end if end if @@ -1047,8 +1048,8 @@ contains ! to determine the number of offset tables to allocate do i = 1, n_universes univ => universes(i) - do j = 1, univ % n_cells - if (cell_list % contains(univ % cells(j))) then + do j = 1, univ%n_cells + if (cell_list%contains(univ%cells(j))) then n_maps = n_maps + 1 end if end do @@ -1070,29 +1071,29 @@ contains do i = 1, n_universes univ => universes(i) - do j = 1, univ % n_cells + do j = 1, univ%n_cells - if (cell_list % contains(univ % cells(j))) then + if (cell_list%contains(univ%cells(j))) then ! Loop over all tallies do l = 1, n_tallies tally => tallies(l) - do m = 1, tally % n_filters - filter => tally % filters(m) + do m = 1, tally%n_filters + filter => tally%filters(m) ! Loop over only distribcell filters ! If filter points to cell we just found, set offset index - if (filter % type == FILTER_DISTRIBCELL) then - if (filter % int_bins(1) == univ % cells(j)) then - filter % offset = k + if (filter%type == FILTER_DISTRIBCELL) then + if (filter%int_bins(1) == univ%cells(j)) then + filter%offset = k end if end if end do end do - univ_list(k) = univ % id + univ_list(k) = univ%id k = k + 1 end if end do @@ -1100,26 +1101,26 @@ contains ! Allocate the offset tables for lattices do i = 1, n_lattices - lat => lattices(i) % obj + lat => lattices(i)%obj select type(lat) type is (RectLattice) - allocate(lat % offset(n_maps, lat % n_cells(1), lat % n_cells(2), & - lat % n_cells(3))) + allocate(lat%offset(n_maps, lat%n_cells(1), lat%n_cells(2), & + lat%n_cells(3))) type is (HexLattice) - allocate(lat % offset(n_maps, 2 * lat % n_rings - 1, & - 2 * lat % n_rings - 1, lat % n_axial)) + allocate(lat%offset(n_maps, 2 * lat%n_rings - 1, & + 2 * lat%n_rings - 1, lat%n_axial)) end select - lat % offset(:, :, :, :) = 0 + lat%offset(:, :, :, :) = 0 end do ! Allocate offset table for fill cells do i = 1, n_cells - if (cells(i) % material == NONE) then - allocate(cells(i) % offset(n_maps)) + if (cells(i)%material == NONE) then + allocate(cells(i)%offset(n_maps)) end if end do diff --git a/src/output_interface.F90 b/src/output_interface.F90 deleted file mode 100644 index 1e08ce491..000000000 --- a/src/output_interface.F90 +++ /dev/null @@ -1,1725 +0,0 @@ -module output_interface - - use constants - use error, only: warning, fatal_error - use global - use tally_header, only: TallyResult - - use hdf5_interface - - implicit none - private - - type, public :: BinaryOutput - private - ! Compilation specific data - integer(HID_T) :: hdf5_fh - integer(HID_T) :: hdf5_grp - logical :: serial ! Serial I/O when using MPI/PHDF5 - contains - generic, public :: write_data => write_double, & - write_double_1Darray, & - write_double_2Darray, & - write_double_3Darray, & - write_double_4Darray, & - write_integer, & - write_integer_1Darray, & - write_integer_2Darray, & - write_integer_3Darray, & - write_integer_4Darray, & - write_long, & - write_string - generic, public :: read_data => read_double, & - read_double_1Darray, & - read_double_2Darray, & - read_double_3Darray, & - read_double_4Darray, & - read_integer, & - read_integer_1Darray, & - read_integer_2Darray, & - read_integer_3Darray, & - read_integer_4Darray, & - read_long, & - read_string - procedure :: write_double => write_double - procedure :: write_double_1Darray => write_double_1Darray - procedure :: write_double_2Darray => write_double_2Darray - procedure :: write_double_3Darray => write_double_3Darray - procedure :: write_double_4Darray => write_double_4Darray - procedure :: write_integer => write_integer - procedure :: write_integer_1Darray => write_integer_1Darray - procedure :: write_integer_2Darray => write_integer_2Darray - procedure :: write_integer_3Darray => write_integer_3Darray - procedure :: write_integer_4Darray => write_integer_4Darray - procedure :: write_long => write_long - procedure :: write_string => write_string - procedure :: read_double => read_double - procedure :: read_double_1Darray => read_double_1Darray - procedure :: read_double_2Darray => read_double_2Darray - procedure :: read_double_3Darray => read_double_3Darray - procedure :: read_double_4Darray => read_double_4Darray - procedure :: read_integer => read_integer - procedure :: read_integer_1Darray => read_integer_1Darray - procedure :: read_integer_2Darray => read_integer_2Darray - procedure :: read_integer_3Darray => read_integer_3Darray - procedure :: read_integer_4Darray => read_integer_4Darray - procedure :: read_long => read_long - procedure :: read_string => read_string - procedure, public :: file_create => file_create - procedure, public :: file_open => file_open - procedure, public :: file_close => file_close - procedure, public :: write_tally_result => write_tally_result - procedure, public :: read_tally_result => read_tally_result - procedure, public :: write_source_bank => write_source_bank - procedure, public :: read_source_bank => read_source_bank - procedure, public :: write_attribute_string => write_attribute_string - procedure, public :: open_group => open_group - procedure, public :: close_group => close_group - end type BinaryOutput - -contains - -!=============================================================================== -! FILE_CREATE creates a new file to write data to -!=============================================================================== - - subroutine file_create(self, filename, serial) - - character(*), intent(in) :: filename ! name of file to be created - logical, optional, intent(in) :: serial ! processor rank to write from - class(BinaryOutput) :: self - - ! Check for serial option - if (present(serial)) then - self % serial = serial - else - self % serial = .true. - end if - -#ifdef PHDF5 - if (self % serial) then - call hdf5_file_create(filename, self % hdf5_fh) - else - call hdf5_file_create_parallel(filename, self % hdf5_fh) - endif -#else - call hdf5_file_create(filename, self % hdf5_fh) -#endif - - end subroutine file_create - -!=============================================================================== -! FILE_OPEN opens an existing file for reading or read/writing -!=============================================================================== - - subroutine file_open(self, filename, mode, serial) - - character(*), intent(in) :: filename ! name of file to be opened - character(*), intent(in) :: mode ! file access mode - logical, optional, intent(in) :: serial ! processor rank to write from - class(BinaryOutput) :: self - - ! Check for serial option - if (present(serial)) then - self % serial = serial - else - self % serial = .true. - end if - -#ifdef PHDF5 - if (self % serial) then - call hdf5_file_open(filename, self % hdf5_fh, mode) - else - call hdf5_file_open_parallel(filename, self % hdf5_fh, mode) - endif -#else - call hdf5_file_open(filename, self % hdf5_fh, mode) -#endif - - end subroutine file_open - -!=============================================================================== -! FILE_CLOSE closes a file -!=============================================================================== - - subroutine file_close(self) - - class(BinaryOutput) :: self - - call hdf5_file_close(self % hdf5_fh) - - end subroutine file_close - -!=============================================================================== -! OPEN_GROUP call hdf5 routine to open a group within binary output context -!=============================================================================== - - subroutine open_group(self, group) - - character(*), intent(in) :: group ! HDF5 group name - class(BinaryOutput) :: self - - call hdf5_open_group(self % hdf5_fh, group, self % hdf5_grp) - - end subroutine open_group - -!=============================================================================== -! CLOSE_GROUP call hdf5 routine to close a group within binary output context -!=============================================================================== - - subroutine close_group(self) - - class(BinaryOutput) :: self - - call hdf5_close_group(self % hdf5_grp) - - end subroutine close_group - -!=============================================================================== -! WRITE_DOUBLE writes double precision scalar data -!=============================================================================== - - subroutine write_double(self, buffer, name, group, collect) - - real(8), intent(in) :: buffer ! data to write - character(*), intent(in) :: name ! name for data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_double(self % hdf5_grp, name_, buffer) - else - call hdf5_write_double_parallel(self % hdf5_grp, name_, buffer, collect_) - end if -#else - call hdf5_write_double(self % hdf5_grp, name_, buffer) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_double - -!=============================================================================== -! READ_DOUBLE reads double precision scalar data -!=============================================================================== - - subroutine read_double(self, buffer, name, group, collect) - - real(8), intent(inout) :: buffer ! read data to here - character(*), intent(in) :: name ! name for data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_double(self % hdf5_grp, name_, buffer) - else - call hdf5_read_double_parallel(self % hdf5_grp, name_, buffer, collect_) - end if -#else - call hdf5_read_double(self % hdf5_grp, name_, buffer) -#endif - ! Check if HDf5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_double - -!=============================================================================== -! WRITE_DOUBLE_1DARRAY writes double precision 1-D array data -!=============================================================================== - - subroutine write_double_1Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length ! length of array to write - real(8), intent(in) :: buffer(:) ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_double_1Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_double_1Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_write_double_1Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_double_1Darray - -!=============================================================================== -! READ_DOUBLE_1DARRAY reads double precision 1-D array data -!=============================================================================== - - subroutine read_double_1Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length ! length of array to read - real(8), intent(inout) :: buffer(:) ! read data to here - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_double_1Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_double_1Darray_parallel(self % hdf5_grp, name_, buffer, & - length, collect_) - end if -#else - call hdf5_read_double_1Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_double_1Darray - -!=============================================================================== -! WRITE_DOUBLE_2DARRAY writes double precision 2-D array data -!=============================================================================== - - subroutine write_double_2Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(2) ! dimension of array - real(8), intent(in) :: buffer(length(1),length(2)) ! the data - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_double_2Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_double_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_write_double_2Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_double_2Darray - -!=============================================================================== -! READ_DOUBLE_2DARRAY reads double precision 2-D array data -!=============================================================================== - - subroutine read_double_2Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(2) ! dimension of array - real(8), intent(inout) :: buffer(length(1),length(2)) ! the data - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_double_2Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_double_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_read_double_2Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_double_2Darray - -!=============================================================================== -! WRITE_DOUBLE_3DARRAY writes double precision 3-D array data -!=============================================================================== - - subroutine write_double_3Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(3) ! length of each dimension - real(8), intent(in) :: buffer(length(1),length(2),length(3)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_double_3Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_double_3Darray_parallel(self % hdf5_grp, name_, buffer, & - length, collect_) - end if -#else - call hdf5_write_double_3Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_double_3Darray - -!=============================================================================== -! READ_DOUBLE_3DARRAY reads double precision 3-D array data -!=============================================================================== - - subroutine read_double_3Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(3) ! length of each dimension - real(8), intent(inout) :: buffer(length(1),length(2),length(3)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_double_3Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_double_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_read_double_3Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_double_3Darray - -!=============================================================================== -! WRITE_DOUBLE_4DARRAY writes double precision 4-D array data -!=============================================================================== - - subroutine write_double_4Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(4) ! length of each dimension - real(8), intent(in) :: buffer(length(1),length(2),& - length(3),length(4)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_double_4Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_double_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - ! Write the data in serial - call hdf5_write_double_4Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_double_4Darray - -!=============================================================================== -! READ_DOUBLE_4DARRAY reads double precision 4-D array data -!=============================================================================== - - subroutine read_double_4Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(4) ! length of each dimension - real(8), intent(inout) :: buffer(length(1),length(2),& - length(3),length(4)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_double_4Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_double_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_read_double_4Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_double_4Darray - -!=============================================================================== -! WRITE_INTEGER writes integer precision scalar data -!=============================================================================== - - subroutine write_integer(self, buffer, name, group, collect) - - integer, intent(in) :: buffer ! data to write - character(*), intent(in) :: name ! name for data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_integer(self % hdf5_grp, name_, buffer) - else - call hdf5_write_integer_parallel(self % hdf5_grp, name_, buffer, collect_) - end if -#else - call hdf5_write_integer(self % hdf5_grp, name_, buffer) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_integer - -!=============================================================================== -! READ_INTEGER reads integer precision scalar data -!=============================================================================== - - subroutine read_integer(self, buffer, name, group, collect) - - integer, intent(inout) :: buffer ! read data to here - character(*), intent(in) :: name ! name for data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_integer(self % hdf5_grp, name_, buffer) - else - call hdf5_read_integer_parallel(self % hdf5_grp, name_, buffer, collect_) - end if -#else - call hdf5_read_integer(self % hdf5_grp, name_, buffer) -#endif - ! Check if HDf5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_integer - -!=============================================================================== -! WRITE_INTEGER_1DARRAY writes integer precision 1-D array data -!=============================================================================== - - subroutine write_integer_1Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length ! length of array to write - integer, intent(in) :: buffer(:) ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_integer_1Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_integer_1Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_write_integer_1Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_integer_1Darray - -!=============================================================================== -! READ_INTEGER_1DARRAY reads integer precision 1-D array data -!=============================================================================== - - subroutine read_integer_1Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length ! length of array to read - integer, intent(inout) :: buffer(:) ! read data to here - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_integer_1Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_integer_1Darray_parallel(self % hdf5_grp, name_, buffer, & - length, collect_) - end if -#else - ! Read the data in serial - call hdf5_read_integer_1Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_integer_1Darray - -!=============================================================================== -! WRITE_INTEGER_2DARRAY writes integer precision 2-D array data -!=============================================================================== - - subroutine write_integer_2Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(2) ! dimension of array - integer, intent(in) :: buffer(length(1),length(2)) ! the data - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_integer_2Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_integer_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_write_integer_2Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_integer_2Darray - -!=============================================================================== -! READ_INTEGER_2DARRAY reads integer precision 2-D array data -!=============================================================================== - - subroutine read_integer_2Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(2) ! dimension of array - integer, intent(inout) :: buffer(length(1),length(2)) ! the data - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_integer_2Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_integer_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_read_integer_2Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_integer_2Darray - -!=============================================================================== -! WRITE_INTEGER_3DARRAY writes integer precision 3-D array data -!=============================================================================== - - subroutine write_integer_3Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(3) ! length of each dimension - integer, intent(in) :: buffer(length(1),length(2),length(3)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_integer_3Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_integer_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_write_integer_3Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_integer_3Darray - -!=============================================================================== -! READ_INTEGER_3DARRAY reads integer precision 3-D array data -!=============================================================================== - - subroutine read_integer_3Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(3) ! length of each dimension - integer, intent(inout) :: buffer(length(1),length(2),length(3)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_integer_3Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_integer_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_read_integer_3Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_integer_3Darray - -!=============================================================================== -! WRITE_INTEGER_4DARRAY writes integer precision 4-D array data -!=============================================================================== - - subroutine write_integer_4Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(4) ! length of each dimension - integer, intent(in) :: buffer(length(1),length(2),& - length(3),length(4)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_integer_4Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_integer_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_write_integer_4Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_integer_4Darray - -!=============================================================================== -! READ_INTEGER_4DARRAY reads integer precision 4-D array data -!=============================================================================== - - subroutine read_integer_4Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(4) ! length of each dimension - integer, intent(inout) :: buffer(length(1),length(2),& - length(3),length(4)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_integer_4Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_integer_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -#else - call hdf5_read_integer_4Darray(self % hdf5_grp, name_, buffer, length) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_integer_4Darray - -!=============================================================================== -! WRITE_LONG writes long integer scalar data -!=============================================================================== - - subroutine write_long(self, buffer, name, group, collect) - - integer(8), intent(in) :: buffer ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) - else - call hdf5_write_long_parallel(self % hdf5_grp, name_, buffer, & - hdf5_integer8_t, collect_) - end if -#else - call hdf5_write_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_long - -!=============================================================================== -! READ_LONG reads long integer scalar data -!=============================================================================== - - subroutine read_long(self, buffer, name, group, collect) - - integer(8), intent(inout) :: buffer ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) - else - call hdf5_read_long_parallel(self % hdf5_grp, name_, buffer, & - hdf5_integer8_t, collect_) - end if -#else - call hdf5_read_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_long - -!=============================================================================== -! WRITE_STRING writes string data -!=============================================================================== - - subroutine write_string(self, buffer, name, group, collect) - - character(*), intent(in) :: buffer ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - integer :: n - logical :: collect_ - - ! Get string length - n = len_trim(buffer) - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_write_string(self % hdf5_grp, name_, buffer, n) - else - call hdf5_write_string_parallel(self % hdf5_grp, name_, buffer, n, collect_) - end if -#else - ! Write the data - call hdf5_write_string(self % hdf5_grp, name_, buffer, n) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_string - -!=============================================================================== -! READ_STRING reads string data -!=============================================================================== - - subroutine read_string(self, buffer, name, group, collect) - - character(*), intent(inout) :: buffer ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - integer :: n - logical :: collect_ - - ! Get string length - n = len(buffer) - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -#ifdef PHDF5 - if (self % serial) then - call hdf5_read_string(self % hdf5_grp, name_, buffer, n) - else - call hdf5_read_string_parallel(self % hdf5_grp, name_, buffer, n, collect_) - end if -#else - call hdf5_read_string(self % hdf5_grp, name_, buffer, n) -#endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_string - -!=============================================================================== -! WRITE_ATTRIBUTE_STRING -!=============================================================================== - - subroutine write_attribute_string(self, var, attr_type, attr_str, group) - - character(*), intent(in) :: var ! variable name for attr - character(*), intent(in) :: attr_type ! attr identifier type - character(*), intent(in) :: attr_str ! string for attr id type - character(*), intent(in), optional :: group ! HDF5 group name - class(BinaryOutput) :: self - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif - - ! Write the attribute string - call hdf5_write_attribute_string(self % hdf5_grp, var, attr_type, attr_str) - - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_attribute_string - -!=============================================================================== -! WRITE_TALLY_RESULT writes an OpenMC TallyResult type -!=============================================================================== - - subroutine write_tally_result(self, buffer, name, group, n1, n2) - - character(*), intent(in), optional :: group ! HDF5 group name - character(*), intent(in) :: name ! name of data - integer, intent(in) :: n1, n2 ! TallyResult dims - type(TallyResult), intent(in), target :: buffer(n1, n2) ! data to write - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Open up sub-group if present - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - end if - - ! Set overall size of vector to write - dims1(1) = n1*n2 - - ! Create up a dataspace for size - call h5screate_simple_f(1, dims1, dspace, hdf5_err) - - ! Create the dataset - call h5dcreate_f(self % hdf5_grp, name_, hdf5_tallyresult_t, dspace, dset, & - hdf5_err) - - ! Set pointer to first value and write - f_ptr = c_loc(buffer(1,1)) - call h5dwrite_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) - - ! Close ids - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - if (present(group)) then - call hdf5_close_group(self % hdf5_grp) - end if - - end subroutine write_tally_result - -!=============================================================================== -! READ_TALLY_RESULT reads OpenMC TallyResult data -!=============================================================================== - - subroutine read_tally_result(self, buffer, name, group, n1, n2) - - character(*), intent(in), optional :: group ! HDF5 group name - character(*), intent(in) :: name ! name of data - integer, intent(in) :: n1, n2 ! TallyResult dims - type(TallyResult), intent(inout), target :: buffer(n1, n2) ! read data here - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Open up sub-group if present - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - end if - - ! Open the dataset - call h5dopen_f(self % hdf5_grp, name, dset, hdf5_err) - - ! Set pointer to first value and write - f_ptr = c_loc(buffer(1,1)) - call h5dread_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) - - ! Close ids - call h5dclose_f(dset, hdf5_err) - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine read_tally_result - -!=============================================================================== -! WRITE_SOURCE_BANK writes OpenMC source_bank data -!=============================================================================== - - subroutine write_source_bank(self) - - class(BinaryOutput) :: self - -#ifdef PHDF5 - integer(8) :: offset(1) ! source data offset -#endif - -#ifdef PHDF5 - - ! Set size of total dataspace for all procs and rank - dims1(1) = n_particles - hdf5_rank = 1 - - ! Create that dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create the dataset for that dataspace - call h5dcreate_f(self % hdf5_fh, "source_bank", hdf5_bank_t, dspace, dset, hdf5_err) - - ! Close the dataspace - call h5sclose_f(dspace, hdf5_err) - - ! Create another data space but for each proc individually - dims1(1) = work - call h5screate_simple_f(hdf5_rank, dims1, memspace, hdf5_err) - - ! Get the individual local proc dataspace - call h5dget_space_f(dset, dspace, hdf5_err) - - ! Select hyperslab for this dataspace - offset(1) = work_index(rank) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims1, hdf5_err) - - ! Set up the property list for parallel writing - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank(1)) - - ! Write data to file in parallel - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id = dspace, mem_space_id = memspace, & - xfer_prp = plist) - - ! Close all ids - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - -#else - - ! Set size - dims1(1) = work - hdf5_rank = 1 - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(self % hdf5_fh, "source_bank", hdf5_bank_t, & - dspace, dset, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank(1)) - - ! Write dataset to file - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err) - - ! Close all ids - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - -#endif - - end subroutine write_source_bank - -!=============================================================================== -! READ_SOURCE_BANK reads OpenMC source_bank data -!=============================================================================== - - subroutine read_source_bank(self) - - class(BinaryOutput) :: self - -#ifdef PHDF5 - integer(8) :: offset(1) ! offset of data -#endif - -#ifdef PHDF5 - - ! Set size of total dataspace for all procs and rank - dims1(1) = n_particles - hdf5_rank = 1 - - ! Open the dataset - call h5dopen_f(self % hdf5_fh, "source_bank", dset, hdf5_err) - - ! Create another data space but for each proc individually - dims1(1) = work - call h5screate_simple_f(hdf5_rank, dims1, memspace, hdf5_err) - - ! Get the individual local proc dataspace - call h5dget_space_f(dset, dspace, hdf5_err) - - ! Select hyperslab for this dataspace - offset(1) = work_index(rank) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims1, hdf5_err) - - ! Set up the property list for parallel writing - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank(1)) - - ! Read data from file in parallel - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id = dspace, mem_space_id = memspace, & - xfer_prp = plist) - - ! Close all ids - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - -#else - - ! Open dataset - call h5dopen_f(self % hdf5_fh, "source_bank", dset, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank(1)) - - ! Read dataset from file - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err) - - ! Close all ids - call h5dclose_f(dset, hdf5_err) - -#endif - - end subroutine read_source_bank - -end module output_interface diff --git a/src/particle_restart.F90 b/src/particle_restart.F90 index 0ed25fdc8..c8874b071 100644 --- a/src/particle_restart.F90 +++ b/src/particle_restart.F90 @@ -6,18 +6,18 @@ module particle_restart use constants use geometry_header, only: BASE_UNIVERSE use global + use hdf5_interface, only: file_open, file_close, read_dataset use output, only: write_message, print_particle - use output_interface, only: BinaryOutput use particle_header, only: Particle use random_lcg, only: set_particle_seed use tracking, only: transport + use hdf5, only: HID_T + implicit none private public :: run_particle_restart - type(BinaryOutput) :: pr ! Binary file - contains !=============================================================================== @@ -34,7 +34,7 @@ contains verbosity = 10 ! Initialize the particle to be tracked - call p % initialize() + call p%initialize() ! Read in the restart information call read_particle_restart(p, previous_run_mode) @@ -46,9 +46,9 @@ contains select case (previous_run_mode) case (MODE_EIGENVALUE) particle_seed = ((current_batch - 1)*gen_per_batch + & - current_gen - 1)*n_particles + p % id + current_gen - 1)*n_particles + p%id case (MODE_FIXEDSOURCE) - particle_seed = p % id + particle_seed = p%id end select call set_particle_seed(particle_seed) @@ -66,40 +66,41 @@ contains !=============================================================================== subroutine read_particle_restart(p, previous_run_mode) + type(Particle), intent(inout) :: p + integer, intent(inout) :: previous_run_mode integer :: int_scalar - integer, intent(inout) :: previous_run_mode - type(Particle), intent(inout) :: p + integer(HID_T) :: file_id ! Write meessage call write_message("Loading particle restart file " & &// trim(path_particle_restart) // "...", 1) ! Open file - call pr % file_open(path_particle_restart, 'r') + file_id = file_open(path_particle_restart, 'r') ! Read data from file - call pr % read_data(int_scalar, 'filetype') - call pr % read_data(int_scalar, 'revision') - call pr % read_data(current_batch, 'current_batch') - call pr % read_data(gen_per_batch, 'gen_per_batch') - call pr % read_data(current_gen, 'current_gen') - call pr % read_data(n_particles, 'n_particles') - call pr % read_data(previous_run_mode, 'run_mode') - call pr % read_data(p % id, 'id') - call pr % read_data(p % wgt, 'weight') - call pr % read_data(p % E, 'energy') - call pr % read_data(p % coord(1) % xyz, 'xyz', length=3) - call pr % read_data(p % coord(1) % uvw, 'uvw', length=3) + call read_dataset(file_id, 'filetype', int_scalar) + call read_dataset(file_id, 'revision', int_scalar) + call read_dataset(file_id, 'current_batch', current_batch) + call read_dataset(file_id, 'gen_per_batch', gen_per_batch) + call read_dataset(file_id, 'current_gen', current_gen) + call read_dataset(file_id, 'n_particles', n_particles) + call read_dataset(file_id, 'run_mode', previous_run_mode) + call read_dataset(file_id, 'id', p%id) + call read_dataset(file_id, 'weight', p%wgt) + call read_dataset(file_id, 'energy', p%E) + call read_dataset(file_id, 'xyz', p%coord(1)%xyz) + call read_dataset(file_id, 'uvw', p%coord(1)%uvw) ! Set particle last attributes - p % last_wgt = p % wgt - p % last_xyz = p % coord(1) % xyz - p % last_uvw = p % coord(1) % uvw - p % last_E = p % E + p%last_wgt = p%wgt + p%last_xyz = p%coord(1)%xyz + p%last_uvw = p%coord(1)%uvw + p%last_E = p%E ! Close hdf5 file - call pr % file_close() + call file_close(file_id) end subroutine read_particle_restart diff --git a/src/particle_restart_write.F90 b/src/particle_restart_write.F90 index 48b4af661..0c010b64c 100644 --- a/src/particle_restart_write.F90 +++ b/src/particle_restart_write.F90 @@ -2,17 +2,16 @@ module particle_restart_write use bank_header, only: Bank use global - use output_interface, only: BinaryOutput + use hdf5_interface use particle_header, only: Particle use string, only: to_str + use hdf5 + implicit none private public :: write_particle_restart - ! Binary output file - type(BinaryOutput) :: pr - contains !=============================================================================== @@ -20,43 +19,42 @@ contains !=============================================================================== subroutine write_particle_restart(p) - type(Particle), intent(in) :: p + integer(HID_T) :: file_id character(MAX_FILE_LEN) :: filename - type(Bank), pointer :: src => null() + type(Bank), pointer :: src ! Dont write another restart file if in particle restart mode if (run_mode == MODE_PARTICLE) return ! Set up file name filename = trim(path_output) // 'particle_' // trim(to_str(current_batch)) & - // '_' // trim(to_str(p % id)) - filename = trim(filename) // '.h5' + // '_' // trim(to_str(p%id)) // '.h5' !$omp critical (WriteParticleRestart) ! Create file - call pr % file_create(filename) + file_id = file_create(filename) ! Get information about source particle src => source_bank(current_work) ! Write data to file - call pr % write_data(FILETYPE_PARTICLE_RESTART, 'filetype') - call pr % write_data(REVISION_PARTICLE_RESTART, 'revision') - call pr % write_data(current_batch, 'current_batch') - call pr % write_data(gen_per_batch, 'gen_per_batch') - call pr % write_data(current_gen, 'current_gen') - call pr % write_data(n_particles, 'n_particles') - call pr % write_data(run_mode, 'run_mode') - call pr % write_data(p % id, 'id') - call pr % write_data(src % wgt, 'weight') - call pr % write_data(src % E, 'energy') - call pr % write_data(src % xyz, 'xyz', length = 3) - call pr % write_data(src % uvw, 'uvw', length = 3) + call write_dataset(file_id, 'filetype', FILETYPE_PARTICLE_RESTART) + call write_dataset(file_id, 'revision', REVISION_PARTICLE_RESTART) + call write_dataset(file_id, 'current_batch', current_batch) + call write_dataset(file_id, 'gen_per_batch', gen_per_batch) + call write_dataset(file_id, 'current_gen', current_gen) + call write_dataset(file_id, 'n_particles', n_particles) + call write_dataset(file_id, 'run_mode', run_mode) + call write_dataset(file_id, 'id', p%id) + call write_dataset(file_id, 'weight', src%wgt) + call write_dataset(file_id, 'energy', src%E) + call write_dataset(file_id, 'xyz', src%xyz) + call write_dataset(file_id, 'uvw', src%uvw) ! Close file - call pr % file_close() + call file_close(file_id) !$omp end critical (WriteParticleRestart) end subroutine write_particle_restart diff --git a/src/source.F90 b/src/source.F90 index 4b0de58b5..285332ef8 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -6,17 +6,20 @@ module source use geometry, only: find_cell use geometry_header, only: BASE_UNIVERSE use global + use hdf5_interface, only: file_create, file_open, file_close, read_dataset use math, only: maxwell_spectrum, watt_spectrum use output, only: write_message - use output_interface, only: BinaryOutput use particle_header, only: Particle use random_lcg, only: prn, set_particle_seed, prn_set_stream + use state_point, only: read_source_bank, write_source_bank use string, only: to_str #ifdef MPI use message_passing #endif + use hdf5, only: HID_T + implicit none contains @@ -27,12 +30,12 @@ contains subroutine initialize_source() - character(MAX_FILE_LEN) :: filename integer(8) :: i ! loop index over bank sites integer(8) :: id ! particle id integer(4) :: itmp ! temporary integer - type(Bank), pointer :: src => null() ! source bank site - type(BinaryOutput) :: sp ! statepoint/source binary file + integer(HID_T) :: file_id + character(MAX_FILE_LEN) :: filename + type(Bank), pointer :: src ! source bank site call write_message("Initializing source particles...", 6) @@ -44,10 +47,10 @@ contains &// '...', 6) ! Open the binary file - call sp % file_open(path_source, 'r', serial = .false.) + file_id = file_open(path_source, 'r', parallel=.true.) ! Read the file type - call sp % read_data(itmp, "filetype") + call read_dataset(file_id, "filetype", itmp) ! Check to make sure this is a source file if (itmp /= FILETYPE_SOURCE) then @@ -56,10 +59,10 @@ contains end if ! Read in the source bank - call sp % read_source_bank() + call read_source_bank(file_id) ! Close file - call sp % file_close() + call file_close(file_id) else ! Generation source sites from specified distribution in user input @@ -80,9 +83,9 @@ contains if (write_initial_source) then call write_message('Writing out initial source...', 1) filename = trim(path_output) // 'initial_source.h5' - call sp % file_create(filename, serial = .false.) - call sp % write_source_bank() - call sp % file_close() + file_id = file_create(filename, parallel=.true.) + call write_source_bank(file_id) + call file_close(file_id) end if end subroutine initialize_source @@ -109,28 +112,28 @@ contains integer, save :: num_resamples = 0 ! Number of resamples encountered ! Set weight to one by default - site % wgt = ONE + site%wgt = ONE ! Set the random number generator to the source stream. call prn_set_stream(STREAM_SOURCE) ! Sample position - select case (external_source % type_space) + select case (external_source%type_space) case (SRC_SPACE_BOX) ! Set particle defaults - call p % initialize() + call p%initialize() ! Repeat sampling source location until a good site has been found found = .false. do while (.not.found) ! Coordinates sampled uniformly over a box - p_min = external_source % params_space(1:3) - p_max = external_source % params_space(4:6) + p_min = external_source%params_space(1:3) + p_max = external_source%params_space(4:6) r = (/ (prn(), i = 1,3) /) - site % xyz = p_min + r*(p_max - p_min) + site%xyz = p_min + r*(p_max - p_min) ! Fill p with needed data - p % coord(1) % xyz = site % xyz - p % coord(1) % uvw = [ ONE, ZERO, ZERO ] + p%coord(1)%xyz = site%xyz + p%coord(1)%uvw = [ ONE, ZERO, ZERO ] ! Now search to see if location exists in geometry call find_cell(p, found) @@ -142,24 +145,24 @@ contains end if end if end do - call p % clear() + call p%clear() case (SRC_SPACE_FISSION) ! Repeat sampling source location until a good site has been found found = .false. do while (.not.found) ! Set particle defaults - call p % initialize() + call p%initialize() ! Coordinates sampled uniformly over a box - p_min = external_source % params_space(1:3) - p_max = external_source % params_space(4:6) + p_min = external_source%params_space(1:3) + p_max = external_source%params_space(4:6) r = (/ (prn(), i = 1,3) /) - site % xyz = p_min + r*(p_max - p_min) + site%xyz = p_min + r*(p_max - p_min) ! Fill p with needed data - p % coord(1) % xyz = site % xyz - p % coord(1) % uvw = [ ONE, ZERO, ZERO ] + p%coord(1)%xyz = site%xyz + p%coord(1)%uvw = [ ONE, ZERO, ZERO ] ! Now search to see if location exists in geometry call find_cell(p, found) @@ -171,66 +174,66 @@ contains end if cycle end if - if (p % material == MATERIAL_VOID) then + if (p%material == MATERIAL_VOID) then found = .false. cycle end if - if (.not. materials(p % material) % fissionable) found = .false. + if (.not. materials(p%material)%fissionable) found = .false. end do - call p % clear() + call p%clear() case (SRC_SPACE_POINT) ! Point source - site % xyz = external_source % params_space + site%xyz = external_source%params_space end select ! Sample angle - select case (external_source % type_angle) + select case (external_source%type_angle) case (SRC_ANGLE_ISOTROPIC) ! Sample isotropic distribution phi = TWO*PI*prn() mu = TWO*prn() - ONE - site % uvw(1) = mu - site % uvw(2) = sqrt(ONE - mu*mu) * cos(phi) - site % uvw(3) = sqrt(ONE - mu*mu) * sin(phi) + site%uvw(1) = mu + site%uvw(2) = sqrt(ONE - mu*mu) * cos(phi) + site%uvw(3) = sqrt(ONE - mu*mu) * sin(phi) case (SRC_ANGLE_MONO) ! Monodirectional source - site % uvw = external_source % params_angle + site%uvw = external_source%params_angle case default call fatal_error("No angle distribution specified for external source!") end select ! Sample energy distribution - select case (external_source % type_energy) + select case (external_source%type_energy) case (SRC_ENERGY_MONO) ! Monoenergtic source - site % E = external_source % params_energy(1) - if (site % E >= 20) then + site%E = external_source%params_energy(1) + if (site%E >= 20) then call fatal_error("Source energies above 20 MeV not allowed.") end if case (SRC_ENERGY_MAXWELL) - a = external_source % params_energy(1) + a = external_source%params_energy(1) do ! Sample Maxwellian fission spectrum - site % E = maxwell_spectrum(a) + site%E = maxwell_spectrum(a) ! resample if energy is >= 20 MeV - if (site % E < 20) exit + if (site%E < 20) exit end do case (SRC_ENERGY_WATT) - a = external_source % params_energy(1) - b = external_source % params_energy(2) + a = external_source%params_energy(1) + b = external_source%params_energy(2) do ! Sample Watt fission spectrum - site % E = watt_spectrum(a, b) + site%E = watt_spectrum(a, b) ! resample if energy is >= 20 MeV - if (site % E < 20) exit + if (site%E < 20) exit end do case default diff --git a/src/state_point.F90 b/src/state_point.F90 index 790fd58c5..084289bee 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -15,9 +15,9 @@ module state_point use constants use error, only: fatal_error, warning use global + use hdf5_interface use output, only: write_message, time_stamp use string, only: to_str, zero_padded, count_digits - use output_interface use tally_header, only: TallyObject use mesh_header, only: StructuredMesh use dict_header, only: ElemKeyValueII, ElemKeyValueCI @@ -26,9 +26,9 @@ module state_point use message_passing #endif - implicit none + use hdf5 - type(BinaryOutput) :: sp ! Statepoint/source output file + implicit none contains @@ -38,23 +38,26 @@ contains subroutine write_state_point() - character(MAX_FILE_LEN) :: filename integer :: i, j, k + integer :: n_order ! loop index for moment orders + integer :: nm_order ! loop index for Ynm moment orders integer, allocatable :: id_array(:) integer, allocatable :: key_array(:) + integer(HID_T) :: file_id + integer(HID_T) :: cmfd_group + integer(HID_T) :: tallies_group, tally_group + integer(HID_T) :: meshes_group, mesh_group + integer(HID_T) :: filter_group, moments_group + character(8) :: moment_name ! name of moment (e.g, P3) + character(MAX_FILE_LEN) :: filename type(StructuredMesh), pointer :: mesh type(TallyObject), pointer :: tally type(ElemKeyValueII), pointer :: current type(ElemKeyValueII), pointer :: next - character(8) :: moment_name ! name of moment (e.g, P3) - integer :: n_order ! loop index for moment orders - integer :: nm_order ! loop index for Ynm moment orders ! Set filename for state point filename = trim(path_output) // 'statepoint.' // & & zero_padded(current_batch, count_digits(n_max_batches)) - - ! Append appropriate extension filename = trim(filename) // '.h5' ! Write message @@ -62,145 +65,126 @@ contains if (master) then ! Create statepoint file - call sp % file_create(filename) + file_id = file_create(filename) ! Write file type - call sp % write_data(FILETYPE_STATEPOINT, "filetype") + call write_dataset(file_id, "filetype", FILETYPE_STATEPOINT) ! Write revision number for state point file - call sp % write_data(REVISION_STATEPOINT, "revision") + call write_dataset(file_id, "revision", REVISION_STATEPOINT) ! Write OpenMC version - call sp % write_data(VERSION_MAJOR, "version_major") - call sp % write_data(VERSION_MINOR, "version_minor") - call sp % write_data(VERSION_RELEASE, "version_release") + call write_dataset(file_id, "version_major", VERSION_MAJOR) + call write_dataset(file_id, "version_minor", VERSION_MINOR) + call write_dataset(file_id, "version_release", VERSION_RELEASE) ! Write current date and time - call sp % write_data(time_stamp(), "date_and_time") + call write_dataset(file_id, "date_and_time", time_stamp()) ! Write path to input - call sp % write_data(path_input, "path") + call write_dataset(file_id, "path", path_input) ! Write out random number seed - call sp % write_data(seed, "seed") + call write_dataset(file_id, "seed", seed) ! Write run information - call sp % write_data(run_mode, "run_mode") - call sp % write_data(n_particles, "n_particles") - call sp % write_data(n_batches, "n_batches") + call write_dataset(file_id, "run_mode", run_mode) + call write_dataset(file_id, "n_particles", n_particles) + call write_dataset(file_id, "n_batches", n_batches) ! Write out current batch number - call sp % write_data(current_batch, "current_batch") + call write_dataset(file_id, "current_batch", current_batch) ! Indicate whether source bank is stored in statepoint if (source_separate) then - call sp % write_data(0, "source_present") + call write_dataset(file_id, "source_present", 0) else - call sp % write_data(1, "source_present") + call write_dataset(file_id, "source_present", 1) end if ! Write out information for eigenvalue run if (run_mode == MODE_EIGENVALUE) then - call sp % write_data(n_inactive, "n_inactive") - call sp % write_data(gen_per_batch, "gen_per_batch") - call sp % write_data(k_generation, "k_generation", & - length=current_batch*gen_per_batch) - call sp % write_data(entropy, "entropy", & - length=current_batch*gen_per_batch) - call sp % write_data(k_col_abs, "k_col_abs") - call sp % write_data(k_col_tra, "k_col_tra") - call sp % write_data(k_abs_tra, "k_abs_tra") - call sp % write_data(k_combined, "k_combined", length=2) + call write_dataset(file_id, "n_inactive", n_inactive) + call write_dataset(file_id, "gen_per_batch", gen_per_batch) + call write_dataset(file_id, "k_generation", k_generation) + call write_dataset(file_id, "entropy", entropy) + call write_dataset(file_id, "k_col_abs", k_col_abs) + call write_dataset(file_id, "k_col_tra", k_col_tra) + call write_dataset(file_id, "k_abs_tra", k_abs_tra) + call write_dataset(file_id, "k_combined", k_combined) ! Write out CMFD info if (cmfd_on) then - call sp % open_group("cmfd") - call sp % close_group() - call sp % write_data(1, "cmfd_on") - call sp % write_data(cmfd % indices, "indices", length=4, group="cmfd") - call sp % write_data(cmfd % k_cmfd, "k_cmfd", length=current_batch, & - group="cmfd") - call sp % write_data(cmfd % cmfd_src, "cmfd_src", & - length=(/cmfd % indices(4), cmfd % indices(1), & - cmfd % indices(2), cmfd % indices(3)/), & - group="cmfd") - call sp % write_data(cmfd % entropy, "cmfd_entropy", & - length=current_batch, group="cmfd") - call sp % write_data(cmfd % balance, "cmfd_balance", & - length=current_batch, group="cmfd") - call sp % write_data(cmfd % dom, "cmfd_dominance", & - length = current_batch, group="cmfd") - call sp % write_data(cmfd % src_cmp, "cmfd_srccmp", & - length = current_batch, group="cmfd") + call write_dataset(file_id, "cmfd_on", 1) + + cmfd_group = create_group(file_id, "cmfd") + call write_dataset(cmfd_group, "indices", cmfd%indices) + call write_dataset(cmfd_group, "k_cmfd", cmfd%k_cmfd) + call write_dataset(cmfd_group, "cmfd_src", cmfd%cmfd_src) + call write_dataset(cmfd_group, "cmfd_entropy", cmfd%entropy) + call write_dataset(cmfd_group, "cmfd_balance", cmfd%balance) + call write_dataset(cmfd_group, "cmfd_dominance", cmfd%dom) + call write_dataset(cmfd_group, "cmfd_srccmp", cmfd%src_cmp) + call close_group(cmfd_group) else - call sp % write_data(0, "cmfd_on") + call write_dataset(file_id, "cmfd_on", 0) end if end if - call sp % open_group("tallies") - call sp % close_group() + tallies_group = create_group(file_id, "tallies") ! Write number of meshes - call sp % write_data(n_meshes, "n_meshes", group="tallies/meshes") + meshes_group = create_group(tallies_group, "meshes") + call write_dataset(meshes_group, "n_meshes", n_meshes) if (n_meshes > 0) then ! Print list of mesh IDs - current => mesh_dict % keys() + current => mesh_dict%keys() 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 + key_array(i) = current%key + id_array(i) = current%value ! Move to next mesh - next => current % next + next => current%next deallocate(current) current => next i = i + 1 end do - call sp % write_data(id_array, "ids", & - group="tallies/meshes", length=n_meshes) - call sp % write_data(key_array, "keys", & - group="tallies/meshes", length=n_meshes) + call write_dataset(meshes_group, "ids", id_array) + call write_dataset(meshes_group, "keys", key_array) deallocate(key_array) ! Write information for meshes MESH_LOOP: do i = 1, n_meshes - mesh => meshes(id_array(i)) + mesh_group = create_group(meshes_group, "mesh " // trim(to_str(mesh%id))) - call sp % write_data(mesh % id, "id", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id))) - call sp % write_data(mesh % type, "type", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id))) - call sp % write_data(mesh % n_dimension, "n_dimension", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id))) - call sp % write_data(mesh % dimension, "dimension", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id)), & - length=mesh % n_dimension) - call sp % write_data(mesh % lower_left, "lower_left", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id)), & - length=mesh % n_dimension) - call sp % write_data(mesh % upper_right, "upper_right", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id)), & - length=mesh % n_dimension) - call sp % write_data(mesh % width, "width", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id)), & - length=mesh % n_dimension) + call write_dataset(mesh_group, "id", mesh%id) + call write_dataset(mesh_group, "type", mesh%type) + call write_dataset(mesh_group, "n_dimension", mesh%n_dimension) + call write_dataset(mesh_group, "dimension", mesh%dimension) + call write_dataset(mesh_group, "lower_left", mesh%lower_left) + call write_dataset(mesh_group, "upper_right", mesh%upper_right) + call write_dataset(mesh_group, "width", mesh%width) + + call close_group(mesh_group) end do MESH_LOOP deallocate(id_array) - end if + call close_group(meshes_group) + ! Write number of tallies - call sp % write_data(n_tallies, "n_tallies", group="tallies") + call write_dataset(tallies_group, "n_tallies", n_tallies) if (n_tallies > 0) then @@ -211,14 +195,12 @@ contains ! Write all tally information except results do i = 1, n_tallies tally => tallies(i) - key_array(i) = tally % id + key_array(i) = tally%id id_array(i) = i end do - call sp % write_data(id_array, "ids", & - group="tallies", length=n_tallies) - call sp % write_data(key_array, "keys", & - group="tallies", length=n_tallies) + call write_dataset(tallies_group, "ids", id_array) + call write_dataset(tallies_group, "keys", key_array) deallocate(key_array) @@ -227,110 +209,92 @@ contains ! Get pointer to tally tally => tallies(i) + tally_group = create_group(tallies_group, "tally " // & + trim(to_str(tally%id))) - call sp % write_data(tally % estimator, "estimator", & - group="tallies/tally " // trim(to_str(tally % id))) - call sp % write_data(tally % n_realizations, "n_realizations", & - group="tallies/tally " // trim(to_str(tally % id))) - call sp % write_data(tally % n_filters, "n_filters", & - group="tallies/tally " // trim(to_str(tally % id))) + call write_dataset(tally_group, "estimator", tally%estimator) + call write_dataset(tally_group, "n_realizations", tally%n_realizations) + call write_dataset(tally_group, "n_filters", tally%n_filters) ! Write filter information - FILTER_LOOP: do j = 1, tally % n_filters + FILTER_LOOP: do j = 1, tally%n_filters + filter_group = create_group(tally_group, "filter " // & + trim(to_str(j))) - call sp % write_data(tally % filters(j) % type, "type", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j)) - call sp % write_data(tally % filters(j) % offset, "offset", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j)) - call sp % write_data(tally % filters(j) % n_bins, "n_bins", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j)) - if (tally % filters(j) % type == FILTER_ENERGYIN .or. & - tally % filters(j) % type == FILTER_ENERGYOUT) then - call sp % write_data(tally % filters(j) % real_bins, "bins", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j), & - length=size(tally % filters(j) % real_bins)) + call write_dataset(filter_group, "type", tally%filters(j)%type) + call write_dataset(filter_group, "offset", tally%filters(j)%offset) + call write_dataset(filter_group, "n_bins", tally%filters(j)%n_bins) + if (tally%filters(j)%type == FILTER_ENERGYIN .or. & + tally%filters(j)%type == FILTER_ENERGYOUT) then + call write_dataset(filter_group, "bins", & + tally%filters(j)%real_bins) else - call sp % write_data(tally % filters(j) % int_bins, "bins", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j), & - length=size(tally % filters(j) % int_bins)) + call write_dataset(filter_group, "bins", & + tally%filters(j)%int_bins) end if + call close_group(filter_group) end do FILTER_LOOP - call sp % write_data(tally % n_nuclide_bins, "n_nuclides", & - group="tallies/tally " // trim(to_str(tally % id))) + call write_dataset(tally_group, "n_nuclides", tally%n_nuclide_bins) ! Set up nuclide bin array and then write - allocate(key_array(tally % n_nuclide_bins)) - NUCLIDE_LOOP: do j = 1, tally % n_nuclide_bins - if (tally % nuclide_bins(j) > 0) then - key_array(j) = nuclides(tally % nuclide_bins(j)) % zaid + allocate(key_array(tally%n_nuclide_bins)) + NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins + if (tally%nuclide_bins(j) > 0) then + key_array(j) = nuclides(tally%nuclide_bins(j))%zaid else - key_array(j) = tally % nuclide_bins(j) + key_array(j) = tally%nuclide_bins(j) end if end do NUCLIDE_LOOP - call sp % write_data(key_array, "nuclides", & - group="tallies/tally " // trim(to_str(tally % id)), & - length=tally % n_nuclide_bins) + call write_dataset(tally_group, "nuclides", key_array) deallocate(key_array) - call sp % write_data(tally % n_score_bins, "n_score_bins", & - group="tallies/tally " // trim(to_str(tally % id))) - call sp % write_data(tally % score_bins, "score_bins", & - group="tallies/tally " // trim(to_str(tally % id)), & - length=tally % n_score_bins) - call sp % write_data(tally % n_user_score_bins, "n_user_score_bins", & - group="tallies/tally " // to_str(tally % id)) + call write_dataset(tally_group, "n_score_bins", tally%n_score_bins) + call write_dataset(tally_group, "score_bins", tally%score_bins) + call write_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) ! Write explicit moment order strings for each score bin + moments_group = create_group(tally_group, "moments") k = 1 - MOMENT_LOOP: do j = 1, tally % n_user_score_bins - select case(tally % score_bins(k)) + MOMENT_LOOP: do j = 1, tally%n_user_score_bins + select case(tally%score_bins(k)) case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - moment_name = 'P' // trim(to_str(tally % moment_order(k))) - call sp % write_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/moments") + moment_name = 'P' // trim(to_str(tally%moment_order(k))) + call write_dataset(moments_group, "order" // trim(to_str(k)), moment_name) k = k + 1 case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - do n_order = 0, tally % moment_order(k) + do n_order = 0, tally%moment_order(k) moment_name = 'P' // trim(to_str(n_order)) - call sp % write_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/moments") + call write_dataset(moments_group, "order" // trim(to_str(k)), moment_name) k = k + 1 end do case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & SCORE_TOTAL_YN) - do n_order = 0, tally % moment_order(k) + do n_order = 0, tally%moment_order(k) do nm_order = -n_order, n_order moment_name = 'Y' // trim(to_str(n_order)) // ',' // & trim(to_str(nm_order)) - call sp % write_data(moment_name, "order" // & - trim(to_str(k)), & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/moments") + call write_dataset(moments_group, "order" // & + trim(to_str(k)), moment_name) k = k + 1 end do end do case default moment_name = '' - call sp % write_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/moments") + call write_dataset(moments_group, "order" // trim(to_str(k)), & + moment_name) k = k + 1 end select - end do MOMENT_LOOP + call close_group(moments_group) + call close_group(tally_group) end do TALLY_METADATA end if + + call close_group(tallies_group) end if ! Check for the no-tally-reduction method @@ -338,47 +302,41 @@ contains ! If using the no-tally-reduction method, we need to collect tally ! results before writing them to the state point file. - call write_tally_results_nr() + call write_tally_results_nr(file_id) elseif (master) then ! Write number of global realizations - call sp % write_data(n_realizations, "n_realizations") + call write_dataset(file_id, "n_realizations", n_realizations) ! Write global tallies - call sp % write_data(N_GLOBAL_TALLIES, "n_global_tallies") - call sp % write_tally_result(global_tallies, "global_tallies", & - n1=N_GLOBAL_TALLIES, n2=1) + call write_dataset(file_id, "n_global_tallies", N_GLOBAL_TALLIES) + call write_dataset(file_id, "global_tallies", global_tallies) ! Write tallies + tallies_group = open_group(file_id, "tallies") if (tallies_on) then - ! Indicate that tallies are on - call sp % write_data(1, "tallies_present", group="tallies") + call write_dataset(tallies_group, "tallies_present", 1) ! Write all tally results TALLY_RESULTS: do i = 1, n_tallies - ! Set point to current tally tally => tallies(i) ! Write sum and sum_sq for each bin - call sp % write_tally_result(tally % results, "results", & - group="tallies/tally " // trim(to_str(tally % id)), & - n1=size(tally % results, 1), n2=size(tally % results, 2)) - + tally_group = open_group(tallies_group, "tally " // to_str(tally%id)) + call write_dataset(tally_group, "results", tally%results) + call close_group(tally_group) end do TALLY_RESULTS else - ! Indicate tallies are off - call sp % write_data(0, "tallies_present", group="tallies") - + call write_dataset(tallies_group, "tallies_present", 0) end if - ! Close the file for serial writing - call sp % file_close() - + call close_group(tallies_group) + call file_close(file_id) end if if (master .and. n_tallies > 0) then @@ -393,71 +351,64 @@ contains subroutine write_source_point() - type(BinaryOutput) :: sp + integer(HID_T) :: file_id character(MAX_FILE_LEN) :: filename ! Check to write out source for a specified batch - if (sourcepoint_batch % contains(current_batch)) then + if (sourcepoint_batch%contains(current_batch)) then ! Create or open up file if (source_separate) then - ! Set filename filename = trim(path_output) // 'source.' // & & zero_padded(current_batch, count_digits(n_max_batches)) - filename = trim(filename) // '.h5' ! Write message for new file creation call write_message("Creating source file " // trim(filename) // "...", & - &1) + 1) ! Create separate source file - call sp % file_create(filename, serial = .false.) + file_id = file_create(filename, parallel=.true.) ! Write file type - call sp % write_data(FILETYPE_SOURCE, "filetype") - + call write_dataset(file_id, "filetype", FILETYPE_SOURCE) else - ! Set filename for state point filename = trim(path_output) // 'statepoint.' // & zero_padded(current_batch, count_digits(n_max_batches)) filename = trim(filename) // '.h5' ! Reopen statepoint file in parallel - call sp % file_open(filename, 'w', serial = .false.) - + file_id = file_open(filename, 'w', parallel=.true.) end if ! Write out source - call sp % write_source_bank() + call write_source_bank(file_id) ! Close file - call sp % file_close() - + call file_close(file_id) end if ! Also check to write source separately in overwritten file if (source_latest) then ! Set filename - filename = trim(path_output) // 'source' - filename = trim(filename) // '.h5' + filename = trim(path_output) // 'source' // '.h5' ! Write message for new file creation call write_message("Creating source file " // trim(filename) // "...", 1) ! Always create this file because it will be overwritten - call sp % file_create(filename, serial = .false.) + file_id = file_create(filename, parallel=.true.) ! Write file type - call sp % write_data(FILETYPE_SOURCE, "filetype") + call write_dataset(file_id, "filetype", FILETYPE_SOURCE) ! Write out source - call sp % write_source_bank() + call write_source_bank(file_id) ! Close file - call sp % file_close() + call file_close(file_id) end if @@ -467,12 +418,14 @@ contains ! WRITE_TALLY_RESULTS_NR !=============================================================================== - subroutine write_tally_results_nr() + subroutine write_tally_results_nr(file_id) + integer(HID_T), intent(in) :: file_id integer :: i ! loop index integer :: n ! number of filter bins integer :: m ! number of score bins integer :: n_bins ! total number of bins + integer(HID_T) :: tallies_group, tally_group real(8), allocatable :: tally_temp(:,:,:) ! contiguous array of results real(8), target :: global_temp(2,N_GLOBAL_TALLIES) #ifdef MPI @@ -489,16 +442,18 @@ contains if (master) then ! Write number of realizations - call sp % write_data(n_realizations, "n_realizations") + call write_dataset(file_id, "n_realizations", n_realizations) ! Write number of global tallies - call sp % write_data(N_GLOBAL_TALLIES, "n_global_tallies") + call write_dataset(file_id, "n_global_tallies", N_GLOBAL_TALLIES) + + tallies_group = open_group(file_id, "tallies") end if ! Copy global tallies into temporary array for reducing n_bins = 2 * N_GLOBAL_TALLIES - global_temp(1,:) = global_tallies(:) % sum - global_temp(2,:) = global_tallies(:) % sum_sq + global_temp(1,:) = global_tallies(:)%sum + global_temp(2,:) = global_tallies(:)%sum_sq if (master) then ! The MPI_IN_PLACE specifier allows the master to copy values into a @@ -510,19 +465,17 @@ contains ! Transfer values to value on master if (current_batch == n_max_batches .or. satisfy_triggers) then - global_tallies(:) % sum = global_temp(1,:) - global_tallies(:) % sum_sq = global_temp(2,:) + global_tallies(:)%sum = global_temp(1,:) + global_tallies(:)%sum_sq = global_temp(2,:) end if ! Put reduced value in temporary tally result allocate(tallyresult_temp(N_GLOBAL_TALLIES, 1)) - tallyresult_temp(:,1) % sum = global_temp(1,:) - tallyresult_temp(:,1) % sum_sq = global_temp(2,:) - + tallyresult_temp(:,1)%sum = global_temp(1,:) + tallyresult_temp(:,1)%sum_sq = global_temp(2,:) ! Write out global tallies sum and sum_sq - call sp % write_tally_result(tallyresult_temp, "global_tallies", & - n1=N_GLOBAL_TALLIES, n2=1) + call write_dataset(file_id, "global_tallies", tallyresult_temp) ! Deallocate temporary tally result deallocate(tallyresult_temp) @@ -537,17 +490,17 @@ contains if (tallies_on) then ! Indicate that tallies are on if (master) then - call sp % write_data(1, "tallies_present", group="tallies") + call write_dataset(tallies_group, "tallies_present", 1) ! Build list of tally IDs - current => tally_dict % keys() + current => tally_dict%keys() allocate(id_array(n_tallies)) i = 1 do while (associated(current)) - id_array(i) = current % value + id_array(i) = current%value ! Move to next tally - next => current % next + next => current%next deallocate(current) current => next i = i + 1 @@ -561,17 +514,20 @@ contains tally => tallies(i) ! Determine size of tally results array - m = size(tally % results, 1) - n = size(tally % results, 2) + m = size(tally%results, 1) + n = size(tally%results, 2) n_bins = m*n*2 ! 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(:,:) % sum - tally_temp(2,:,:) = tally % results(:,:) % sum_sq + tally_temp(1,:,:) = tally%results(:,:)%sum + tally_temp(2,:,:) = tally%results(:,:)%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 #ifdef MPI @@ -582,18 +538,17 @@ contains ! 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(:,:) % sum = tally_temp(1,:,:) - tally % results(:,:) % sum_sq = tally_temp(2,:,:) + tally%results(:,:)%sum = tally_temp(1,:,:) + tally%results(:,:)%sum_sq = tally_temp(2,:,:) end if ! Put in temporary tally result allocate(tallyresult_temp(m,n)) - tallyresult_temp(:,:) % sum = tally_temp(1,:,:) - tallyresult_temp(:,:) % sum_sq = tally_temp(2,:,:) + tallyresult_temp(:,:)%sum = tally_temp(1,:,:) + tallyresult_temp(:,:)%sum_sq = tally_temp(2,:,:) ! Write reduced tally results to file - call sp % write_tally_result(tally % results, "results", & - group="tallies/tally " // trim(to_str(tally % id)), n1=m, n2=n) + call write_dataset(tally_group, "results", tally%results) ! Deallocate temporary tally result deallocate(tallyresult_temp) @@ -607,6 +562,8 @@ contains ! Deallocate temporary copy of tally results deallocate(tally_temp) + + if (master) call close_group(tally_group) end do TALLY_RESULTS deallocate(id_array) @@ -614,10 +571,12 @@ contains else if (master) then ! Indicate that tallies are off - call sp % write_data(0, "tallies_present", group="tallies") + call write_dataset(tallies_group, "tallies_present", 0) end if end if + if (master) call close_group(tallies_group) + end subroutine write_tally_results_nr !=============================================================================== @@ -626,45 +585,49 @@ contains subroutine load_state_point() - character(MAX_FILE_LEN) :: path_temp - character(19) :: current_time integer :: i, j, k - integer :: length(4) integer :: int_array(3) - integer, allocatable :: id_array(:) - integer, allocatable :: key_array(:) integer :: curr_key - integer, allocatable :: temp_array(:) - logical :: source_present - real(8) :: real_array(3) - type(StructuredMesh), pointer :: mesh - type(TallyObject), pointer :: tally integer :: n_order ! loop index for moment orders integer :: nm_order ! loop index for Ynm moment orders + integer, allocatable :: id_array(:) + integer, allocatable :: key_array(:) + integer, allocatable :: temp_array(:) + integer(HID_T) :: file_id + integer(HID_T) :: cmfd_group + integer(HID_T) :: tallies_group, tally_group + integer(HID_T) :: meshes_group, mesh_group + integer(HID_T) :: filter_group, moments_group + real(8) :: real_array(3) + logical :: source_present + character(MAX_FILE_LEN) :: path_temp + character(19) :: current_time character(8) :: moment_name ! name of moment (e.g, P3, Y-1,1) + type(StructuredMesh), pointer :: mesh + type(TallyObject), pointer :: tally ! Write message call write_message("Loading state point " // trim(path_state_point) & - &// "...", 1) + // "...", 1) ! Open file for reading - call sp % file_open(path_state_point, 'r', serial = .false.) + file_id = file_open(path_state_point, 'r', parallel=.true.) ! Read filetype - call sp % read_data(int_array(1), "filetype") + call read_dataset(file_id, "filetype", int_array(1)) ! Read revision number for state point file and make sure it matches with ! current version - call sp % read_data(int_array(1), "revision") + call read_dataset(file_id, "revision", int_array(1)) if (int_array(1) /= REVISION_STATEPOINT) then call fatal_error("State point version does not match current version & &in OpenMC.") end if ! Read OpenMC version - call sp % read_data(int_array(1), "version_major") - call sp % read_data(int_array(2), "version_minor") - call sp % read_data(int_array(3), "version_release") + call read_dataset(file_id, "version_major", int_array(1)) + call read_dataset(file_id, "version_minor", int_array(2)) + call read_dataset(file_id, "version_release", int_array(3)) if (int_array(1) /= VERSION_MAJOR .or. int_array(2) /= VERSION_MINOR & .or. int_array(3) /= VERSION_RELEASE) then if (master) call warning("State point file was created with a different & @@ -672,27 +635,27 @@ contains end if ! Read date and time - call sp % read_data(current_time, "date_and_time") + call read_dataset(file_id, "date_and_time", current_time) ! Read path to input - call sp % read_data(path_temp, "path") + call read_dataset(file_id, "path", path_temp) ! Read and overwrite random number seed - call sp % read_data(seed, "seed") + call read_dataset(file_id, "seed", seed) ! Read and overwrite run information except number of batches - call sp % read_data(run_mode, "run_mode") - call sp % read_data(n_particles, "n_particles") - call sp % read_data(int_array(1), "n_batches") + call read_dataset(file_id, "run_mode", run_mode) + call read_dataset(file_id, "n_particles", n_particles) + call read_dataset(file_id, "n_batches", int_array(1)) ! Take maximum of statepoint n_batches and input n_batches n_batches = max(n_batches, int_array(1)) ! Read batch number to restart at - call sp % read_data(restart_batch, "current_batch") + call read_dataset(file_id, "current_batch", restart_batch) ! Check for source in statepoint if needed - call sp % read_data(int_array(1), "source_present") + call read_dataset(file_id, "source_present", int_array(1)) if (int_array(1) == 1) then source_present = .true. else @@ -706,43 +669,45 @@ contains ! Read information specific to eigenvalue run if (run_mode == MODE_EIGENVALUE) then - call sp % read_data(int_array(1), "n_inactive") - call sp % read_data(gen_per_batch, "gen_per_batch") - call sp % read_data(k_generation, "k_generation", & - length=restart_batch*gen_per_batch) - call sp % read_data(entropy, "entropy", length=restart_batch*gen_per_batch) - call sp % read_data(k_col_abs, "k_col_abs") - call sp % read_data(k_col_tra, "k_col_tra") - call sp % read_data(k_abs_tra, "k_abs_tra") - call sp % read_data(real_array(1:2), "k_combined", length=2) + call read_dataset(file_id, "n_inactive", int_array(1)) + call read_dataset(file_id, "gen_per_batch", gen_per_batch) + call read_dataset(file_id, "k_generation", & + k_generation(1:restart_batch*gen_per_batch)) + call read_dataset(file_id, "entropy", & + entropy(1:restart_batch*gen_per_batch)) + call read_dataset(file_id, "k_col_abs", k_col_abs) + call read_dataset(file_id, "k_col_tra", k_col_tra) + call read_dataset(file_id, "k_abs_tra", k_abs_tra) + call read_dataset(file_id, "k_combined", real_array(1:2)) ! Take maximum of statepoint n_inactive and input n_inactive n_inactive = max(n_inactive, int_array(1)) ! Read in to see if CMFD was on - call sp % read_data(int_array(1), "cmfd_on") + call read_dataset(file_id, "cmfd_on", int_array(1)) ! Read in CMFD info if (int_array(1) == 1) then - call sp % read_data(cmfd % indices, "indices", length=4, group="cmfd") - call sp % read_data(cmfd % k_cmfd, "k_cmfd", length=restart_batch, & - group="cmfd") - length = cmfd % indices([4,1,2,3]) - call sp % read_data(cmfd % cmfd_src, "cmfd_src", & - length=length, group="cmfd") - call sp % read_data(cmfd % entropy, "cmfd_entropy", & - length=restart_batch, group="cmfd") - call sp % read_data(cmfd % balance, "cmfd_balance", & - length=restart_batch, group="cmfd") - call sp % read_data(cmfd % dom, "cmfd_dominance", & - length = restart_batch, group="cmfd") - call sp % read_data(cmfd % src_cmp, "cmfd_srccmp", & - length = restart_batch, group="cmfd") + cmfd_group = open_group(file_id, "cmfd") + call read_dataset(cmfd_group, "indices", cmfd%indices) + call read_dataset(cmfd_group, "k_cmfd", cmfd%k_cmfd(1:restart_batch)) + call read_dataset(cmfd_group, "cmfd_src", cmfd%cmfd_src) + call read_dataset(cmfd_group, "cmfd_entropy", & + cmfd%entropy(1:restart_batch)) + call read_dataset(cmfd_group, "cmfd_balance", & + cmfd%balance(1:restart_batch)) + call read_dataset(cmfd_group, "cmfd_dominance", & + cmfd%dom(1:restart_batch)) + call read_dataset(cmfd_group, "cmfd_srccmp", & + cmfd%src_cmp(1:restart_batch)) + call close_group(cmfd_group) end if end if ! Read number of meshes - call sp % read_data(n_meshes, "n_meshes", group="tallies/meshes") + tallies_group = open_group(file_id, "tallies") + meshes_group = open_group(tallies_group, "meshes") + call read_dataset(meshes_group, "n_meshes", n_meshes) if (n_meshes > 0) then @@ -750,10 +715,8 @@ contains allocate(id_array(n_meshes)) allocate(key_array(n_meshes)) - call sp % read_data(id_array, "ids", & - group="tallies/meshes", length=n_meshes) - call sp % read_data(key_array, "keys", & - group="tallies/meshes", length=n_meshes) + call read_dataset(meshes_group, "ids", id_array) + call read_dataset(meshes_group, "keys", key_array) ! Read and overwrite mesh information MESH_LOOP: do i = 1, n_meshes @@ -761,25 +724,16 @@ contains mesh => meshes(id_array(i)) curr_key = key_array(id_array(i)) - call sp % read_data(mesh % id, "id", & - group="tallies/meshes/mesh " // trim(to_str(curr_key))) - call sp % read_data(mesh % type, "type", & - group="tallies/meshes/mesh " // trim(to_str(curr_key))) - call sp % read_data(mesh % n_dimension, "n_dimension", & - group="tallies/meshes/mesh " // trim(to_str(meshes(i) % id))) - call sp % read_data(mesh % dimension, "dimension", & - group="tallies/meshes/mesh " // trim(to_str(curr_key)), & - length=mesh % n_dimension) - call sp % read_data(mesh % lower_left, "lower_left", & - group="tallies/meshes/mesh " // trim(to_str(curr_key)), & - length=mesh % n_dimension) - call sp % read_data(mesh % upper_right, "upper_right", & - group="tallies/meshes/mesh " // trim(to_str(curr_key)), & - length=mesh % n_dimension) - call sp % read_data(mesh % width, "width", & - group="tallies/meshes/mesh " // trim(to_str(curr_key)), & - length=meshes(i) % n_dimension) - + mesh_group = open_group(meshes_group, "mesh " // & + trim(to_str(curr_key))) + call read_dataset(mesh_group, "id", mesh%id) + call read_dataset(mesh_group, "type", mesh%type) + call read_dataset(mesh_group, "n_dimension", mesh%n_dimension) + call read_dataset(mesh_group, "dimension", mesh%dimension) + call read_dataset(mesh_group, "lower_left", mesh%lower_left) + call read_dataset(mesh_group, "upper_right", mesh%upper_right) + call read_dataset(mesh_group, "width", mesh%width) + call close_group(mesh_group) end do MESH_LOOP deallocate(id_array) @@ -787,15 +741,17 @@ contains end if + call close_group(meshes_group) + ! Read and overwrite number of tallies - call sp % read_data(n_tallies, "n_tallies", group="tallies") + call read_dataset(tallies_group, "n_tallies", n_tallies) ! Read list of tally keys-> IDs allocate(id_array(n_tallies)) allocate(key_array(n_tallies)) - call sp % read_data(id_array, "ids", group="tallies", length=n_tallies) - call sp % read_data(key_array, "keys", group="tallies", length=n_tallies) + call read_dataset(tallies_group, "ids", id_array) + call read_dataset(tallies_group, "keys", key_array) ! Read in tally metadata TALLY_METADATA: do i = 1, n_tallies @@ -803,99 +759,85 @@ contains ! Get pointer to tally tally => tallies(i) curr_key = key_array(id_array(i)) + tally_group = open_group(tallies_group, "tally " // & + trim(to_str(curr_key))) - call sp % read_data(tally % estimator, "estimator", & - group="tallies/tally " // trim(to_str(curr_key))) - call sp % read_data(tally % n_realizations, "n_realizations", & - group="tallies/tally " // trim(to_str(curr_key))) - call sp % read_data(tally % n_filters, "n_filters", & - group="tallies/tally " // trim(to_str(curr_key))) + call read_dataset(tally_group, "estimator", tally%estimator) + call read_dataset(tally_group, "n_realizations", tally%n_realizations) + call read_dataset(tally_group, "n_filters", tally%n_filters) - FILTER_LOOP: do j = 1, tally % n_filters - call sp % read_data(tally % filters(j) % type, "type", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j)) - call sp % read_data(tally % filters(j) % offset, "offset", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j)) - call sp % read_data(tally % filters(j) % n_bins, "n_bins", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j)) - if (tally % filters(j) % type == FILTER_ENERGYIN .or. & - tally % filters(j) % type == FILTER_ENERGYOUT) then - call sp % read_data(tally % filters(j) % real_bins, "bins", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j), & - length=size(tally % filters(j) % real_bins)) + FILTER_LOOP: do j = 1, tally%n_filters + filter_group = open_group(tally_group, "filter " // trim(to_str(j))) + + call read_dataset(filter_group, "type", tally%filters(j)%type) + call read_dataset(filter_group, "offset", tally%filters(j)%offset) + call read_dataset(filter_group, "n_bins", tally%filters(j)%n_bins) + if (tally%filters(j)%type == FILTER_ENERGYIN .or. & + tally%filters(j)%type == FILTER_ENERGYOUT) then + call read_dataset(filter_group, "bins", tally%filters(j)%real_bins) else - call sp % read_data(tally % filters(j) % int_bins, "bins", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j), & - length=size(tally % filters(j) % int_bins)) + call read_dataset(filter_group, "bins", tally%filters(j)%int_bins) end if + call close_group(filter_group) end do FILTER_LOOP - call sp % read_data(tally % n_nuclide_bins, "n_nuclides", & - group="tallies/tally " // trim(to_str(curr_key))) + call read_dataset(tally_group, "n_nuclides", tally%n_nuclide_bins) ! Set up nuclide bin array and then read - allocate(temp_array(tally % n_nuclide_bins)) - call sp % read_data(temp_array, "nuclides", & - group="tallies/tally " // trim(to_str(curr_key)), & - length=tally % n_nuclide_bins) + allocate(temp_array(tally%n_nuclide_bins)) + call read_dataset(tally_group, "nuclides", temp_array) - NUCLIDE_LOOP: do j = 1, tally % n_nuclide_bins + NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins if (temp_array(j) > 0) then - tally % nuclide_bins(j) = temp_array(j) + tally%nuclide_bins(j) = temp_array(j) else - tally % nuclide_bins(j) = temp_array(j) + tally%nuclide_bins(j) = temp_array(j) end if end do NUCLIDE_LOOP deallocate(temp_array) ! Write number of score bins, score bins, user score bins - call sp % read_data(tally % n_score_bins, "n_score_bins", & - group="tallies/tally " // trim(to_str(curr_key))) - call sp % read_data(tally % score_bins, "score_bins", & - group="tallies/tally " // trim(to_str(curr_key)), & - length=tally % n_score_bins) - call sp % read_data(tally % n_user_score_bins, "n_user_score_bins", & - group="tallies/tally " // trim(to_str(curr_key))) + call read_dataset(tally_group, "n_score_bins", tally%n_score_bins) + call read_dataset(tally_group, "score_bins", tally%score_bins) + call read_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) ! Read explicit moment order strings for each score bin k = 1 - MOMENT_LOOP: do j = 1, tally % n_user_score_bins - select case(tally % score_bins(k)) + moments_group = open_group(tally_group, "moments") + MOMENT_LOOP: do j = 1, tally%n_user_score_bins + select case(tally%score_bins(k)) case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - call sp % read_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(curr_key)) // "/moments") + call read_dataset(moments_group, "order" // trim(to_str(k)), & + moment_name) k = k + 1 case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - do n_order = 0, tally % moment_order(k) - call sp % read_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(curr_key)) // "/moments") + do n_order = 0, tally%moment_order(k) + call read_dataset(moments_group, "order" // trim(to_str(k)), & + moment_name) k = k + 1 end do case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & SCORE_TOTAL_YN) - do n_order = 0, tally % moment_order(k) + do n_order = 0, tally%moment_order(k) do nm_order = -n_order, n_order - call sp % read_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/moments") + call read_dataset(moments_group, "order" // trim(to_str(k)), & + moment_name) k = k + 1 end do end do case default - call sp % read_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(curr_key)) // "/moments") + call read_dataset(moments_group, "order" // trim(to_str(k)), & + moment_name) k = k + 1 end select end do MOMENT_LOOP + call close_group(moments_group) + call close_group(tally_group) + end do TALLY_METADATA ! Check to make sure source bank is present @@ -908,22 +850,21 @@ contains if (master) then ! Read number of realizations for global tallies - call sp % read_data(n_realizations, "n_realizations", collect=.false.) + call read_dataset(file_id, "n_realizations", n_realizations, indep=.true.) ! Read number of global tallies - call sp % read_data(int_array(1), "n_global_tallies", collect=.false.) + call read_dataset(file_id, "n_global_tallies", int_array(1), indep=.false.) if (int_array(1) /= N_GLOBAL_TALLIES) then call fatal_error("Number of global tallies does not match in state & &point.") end if ! Read global tally data - call sp % read_tally_result(global_tallies, "global_tallies", & - n1=N_GLOBAL_TALLIES, n2=1) + call read_dataset(file_id, "global_tallies", global_tallies) ! Check if tally results are present - call sp % read_data(int_array(1), "tallies_present", & - group="tallies", collect=.false.) + tallies_group = open_group(file_id, "tallies") + call read_dataset(file_id, "tallies_present", int_array(1), indep=.true.) ! Read in sum and sum squared if (int_array(1) == 1) then @@ -934,13 +875,14 @@ contains curr_key = key_array(id_array(i)) ! Read sum and sum_sq for each bin - call sp % read_tally_result(tally % results, "results", & - group="tallies/tally " // trim(to_str(curr_key)), & - n1=size(tally % results, 1), n2=size(tally % results, 2)) - + tally_group = open_group(tallies_group, "tally " // & + trim(to_str(curr_key))) + call read_dataset(tally_group, "results", tally%results) + call close_group(tally_group) end do TALLY_RESULTS - end if + + call close_group(tallies_group) end if deallocate(id_array) @@ -953,30 +895,186 @@ contains if (.not. source_present) then ! Close statepoint file - call sp % file_close() + call file_close(file_id) ! Write message call write_message("Loading source file " // trim(path_source_point) & - &// "...", 1) + // "...", 1) ! Open source file - call sp % file_open(path_source_point, 'r', serial = .false.) + file_id = file_open(path_source_point, 'r', parallel=.true.) ! Read file type - call sp % read_data(int_array(1), "filetype") + call read_dataset(file_id, "filetype", int_array(1)) end if ! Write out source - call sp % read_source_bank() + call read_source_bank(file_id) end if ! Close file - call sp % file_close() + call file_close(file_id) end subroutine load_state_point +!=============================================================================== +! WRITE_SOURCE_BANK writes OpenMC source_bank data +!=============================================================================== + + subroutine write_source_bank(group_id) + use bank_header, only: Bank + + integer(HID_T), intent(in) :: group_id + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HSIZE_T) :: dims(1) + type(c_ptr) :: f_ptr +#ifdef PHDF5 + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: memspace ! memory space handle + integer(HSIZE_T) :: offset(1) ! source data offset +#endif + +#ifdef PHDF5 + ! Set size of total dataspace for all procs and rank + dims(1) = n_particles + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, dspace, dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + + ! Create another data space but for each proc individually + dims(1) = work + call h5screate_simple_f(1, dims, memspace, hdf5_err) + + ! Get the individual local proc dataspace + call h5dget_space_f(dset, dspace, hdf5_err) + + ! Select hyperslab for this dataspace + offset(1) = work_index(rank) + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) + + ! Set up the property list for parallel writing + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + + ! Write data to file in parallel + call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace, & + xfer_prp=plist) + + ! Close all ids + call h5sclose_f(dspace, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call h5dclose_f(dset, hdf5_err) + call h5pclose_f(plist, hdf5_err) + +#else + + ! Set size + dims(1) = work + + ! Create dataspace + call h5screate_simple_f(1, dims, dspace, hdf5_err) + + ! Create dataset + call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, & + dspace, dset, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + + ! Write dataset to file + call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err) + + ! Close all ids + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + +#endif + + end subroutine write_source_bank + +!=============================================================================== +! READ_SOURCE_BANK reads OpenMC source_bank data +!=============================================================================== + + subroutine read_source_bank(group_id) + use bank_header, only: Bank + + integer(HID_T), intent(in) :: group_id + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr +#ifdef PHDF5 + integer :: data_xfer_mode + integer(HID_T) :: plist ! property list + integer(HID_T) :: dspace ! data space handle + integer(HID_T) :: memspace ! memory space handle + integer(HSIZE_T) :: offset(1) ! offset of data + integer(HSIZE_T) :: dims(1) +#endif + +#ifdef PHDF5 + + ! Open the dataset + call h5dopen_f(group_id, "source_bank", dset, hdf5_err) + + ! Create another data space but for each proc individually + dims(1) = work + call h5screate_simple_f(1, dims, memspace, hdf5_err) + + ! Get the individual local proc dataspace + call h5dget_space_f(dset, dspace, hdf5_err) + + ! Select hyperslab for this dataspace + offset(1) = work_index(rank) + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) + + ! Set up the property list for parallel writing + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + + ! Read data from file in parallel + call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace, & + xfer_prp=plist) + + ! Close all ids + call h5sclose_f(dspace, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call h5dclose_f(dset, hdf5_err) + call h5pclose_f(plist, hdf5_err) + +#else + + ! Open dataset + call h5dopen_f(group_id, "source_bank", dset, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + + ! Read dataset from file + call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err) + + ! Close all ids + call h5dclose_f(dset, hdf5_err) + +#endif + + end subroutine read_source_bank + subroutine read_source ! TODO write this routine ! TODO what if n_particles does not match source bank diff --git a/src/track_output.F90 b/src/track_output.F90 index d3716e9b0..d4b287800 100644 --- a/src/track_output.F90 +++ b/src/track_output.F90 @@ -6,19 +6,27 @@ module track_output use global - use output_interface, only: BinaryOutput + use hdf5_interface use particle_header, only: Particle use string, only: to_str - implicit none + use hdf5 - type, private :: TrackCoordinates + implicit none + private + + type TrackCoordinates real(8), allocatable :: coords(:,:) end type TrackCoordinates - type(TrackCoordinates), private, allocatable :: tracks(:) + type(TrackCoordinates), allocatable :: tracks(:) !$omp threadprivate(tracks) + public :: initialize_particle_track + public :: write_particle_track + public :: add_particle_track + public :: finalize_particle_track + contains !=============================================================================== @@ -43,19 +51,19 @@ contains ! Add another column to coords i = size(tracks) - if (allocated(tracks(i) % coords)) then - n_tracks = size(tracks(i) % coords, 2) + if (allocated(tracks(i)%coords)) then + n_tracks = size(tracks(i)%coords, 2) allocate(new_coords(3, n_tracks + 1)) - new_coords(:, 1:n_tracks) = tracks(i) % coords - call move_alloc(FROM=new_coords, TO=tracks(i) % coords) + new_coords(:, 1:n_tracks) = tracks(i)%coords + call move_alloc(FROM=new_coords, TO=tracks(i)%coords) else n_tracks = 0 - allocate(tracks(i) % coords(3, 1)) + allocate(tracks(i)%coords(3, 1)) end if ! Write current coordinates into the newest column. n_tracks = n_tracks + 1 - tracks(i) % coords(:, n_tracks) = p % coord(1) % xyz + tracks(i)%coords(:, n_tracks) = p%coord(1)%xyz end subroutine write_particle_track !=============================================================================== @@ -87,35 +95,32 @@ contains subroutine finalize_particle_track(p) type(Particle), intent(in) :: p - integer :: length(2) - character(MAX_FILE_LEN) :: fname - type(BinaryOutput) :: binout - integer :: i - integer, allocatable :: n_coords(:) integer :: n_particle_tracks + integer(HID_T) :: file_id + character(MAX_FILE_LEN) :: fname + integer, allocatable :: n_coords(:) fname = trim(path_output) // 'track_' // trim(to_str(current_batch)) & - // '_' // trim(to_str(current_gen)) // '_' // trim(to_str(p % id)) & + // '_' // trim(to_str(current_gen)) // '_' // trim(to_str(p%id)) & // '.h5' ! Determine total number of particles and number of coordinates for each n_particle_tracks = size(tracks) allocate(n_coords(n_particle_tracks)) do i = 1, n_particle_tracks - n_coords(i) = size(tracks(i) % coords, 2) + n_coords(i) = size(tracks(i)%coords, 2) end do !$omp critical (FinalizeParticleTrack) - call binout % file_create(fname) - call binout % write_data(n_particle_tracks, 'n_particles') - call binout % write_data(n_coords, 'n_coords', length=n_particle_tracks) + file_id = file_create(fname) + call write_dataset(file_id, 'n_particles', n_particle_tracks) + call write_dataset(file_id, 'n_coords', n_coords) do i = 1, n_particle_tracks - length(:) = [3, n_coords(i)] - call binout % write_data(tracks(i) % coords, 'coordinates_' // & - trim(to_str(i)), length=length) + call write_dataset(file_id, 'coordinates_' // trim(to_str(i)), & + tracks(i)%coords) end do - call binout % file_close() + call file_close(file_id) !$omp end critical (FinalizeParticleTrack) deallocate(tracks) end subroutine finalize_particle_track From 276dba020f87f2ccd6521030f114eb4b95592803 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Sep 2015 12:22:48 +0700 Subject: [PATCH 12/95] Fixes in source bank writing/reading to enable MPI+HDF5 (without PHDF5) --- src/hdf5_interface.F90 | 18 ++--- src/state_point.F90 | 178 ++++++++++++++++++++++------------------- 2 files changed, 104 insertions(+), 92 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 1684c352b..491337e00 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -85,11 +85,10 @@ contains logical :: parallel_ ! Check for serial option - if (present(parallel)) then - parallel_ = parallel - else - parallel_ = .false. - end if + parallel_ = .false. +#ifdef PHDF5 + if (present(parallel)) parallel_ = parallel +#endif if (parallel_) then ! Setup file access property list with parallel I/O access @@ -132,11 +131,10 @@ contains integer :: open_mode ! HDF5 open mode ! Check for serial option - if (present(parallel)) then - parallel_ = parallel - else - parallel_ = .false. - end if + parallel_ = .false. +#ifdef PHDF5 + if (present(parallel)) parallel_ = parallel +#endif ! Determine access type open_mode = H5F_ACC_RDONLY_F diff --git a/src/state_point.F90 b/src/state_point.F90 index 084289bee..aca6fafb7 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -351,65 +351,60 @@ contains subroutine write_source_point() + logical :: parallel integer(HID_T) :: file_id character(MAX_FILE_LEN) :: filename + ! When using parallel HDF5, the file is written to collectively by all + ! processes. With MPI-only, the file is opened and written by the master + ! (note that the call to write_source_bank is by all processes since slave + ! processes need to send source bank data to the master. +#ifdef PHDF5 + parallel = .true. +#else + parallel = .false. +#endif + ! Check to write out source for a specified batch if (sourcepoint_batch%contains(current_batch)) then - - ! Create or open up file if (source_separate) then - ! Set filename filename = trim(path_output) // 'source.' // & & zero_padded(current_batch, count_digits(n_max_batches)) filename = trim(filename) // '.h5' - - ! Write message for new file creation - call write_message("Creating source file " // trim(filename) // "...", & - 1) + call write_message("Creating source file " // trim(filename) & + // "...", 1) ! Create separate source file - file_id = file_create(filename, parallel=.true.) - - ! Write file type - call write_dataset(file_id, "filetype", FILETYPE_SOURCE) + if (master .or. parallel) then + file_id = file_create(filename, parallel=.true.) + call write_dataset(file_id, "filetype", FILETYPE_SOURCE) + end if else - ! Set filename for state point filename = trim(path_output) // 'statepoint.' // & zero_padded(current_batch, count_digits(n_max_batches)) filename = trim(filename) // '.h5' - ! Reopen statepoint file in parallel - file_id = file_open(filename, 'w', parallel=.true.) + if (master .or. parallel) then + file_id = file_open(filename, 'w', parallel=.true.) + end if end if - ! Write out source call write_source_bank(file_id) - - ! Close file - call file_close(file_id) + if (master .or. parallel) call file_close(file_id) end if ! Also check to write source separately in overwritten file if (source_latest) then - ! Set filename filename = trim(path_output) // 'source' // '.h5' - - ! Write message for new file creation call write_message("Creating source file " // trim(filename) // "...", 1) + if (master .or. parallel) then + file_id = file_create(filename, parallel=.true.) + call write_dataset(file_id, "filetype", FILETYPE_SOURCE) + end if - ! Always create this file because it will be overwritten - file_id = file_create(filename, parallel=.true.) - - ! Write file type - call write_dataset(file_id, "filetype", FILETYPE_SOURCE) - - ! Write out source call write_source_bank(file_id) - ! Close file - call file_close(file_id) - + if (master .or. parallel) call file_close(file_id) end if end subroutine write_source_point @@ -931,13 +926,18 @@ contains integer :: hdf5_err integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: memspace ! memory space handle + integer(HSIZE_T) :: offset(1) ! source data offset integer(HSIZE_T) :: dims(1) type(c_ptr) :: f_ptr #ifdef PHDF5 integer :: data_xfer_mode integer(HID_T) :: plist ! property list - integer(HID_T) :: memspace ! memory space handle - integer(HSIZE_T) :: offset(1) ! source data offset +#else + integer :: i +#ifdef MPI + type(Bank), allocatable, target :: temp_source(:) +#endif #endif #ifdef PHDF5 @@ -945,15 +945,11 @@ contains dims(1) = n_particles call h5screate_simple_f(1, dims, dspace, hdf5_err) call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, dspace, dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) ! Create another data space but for each proc individually dims(1) = work call h5screate_simple_f(1, dims, memspace, hdf5_err) - ! Get the individual local proc dataspace - call h5dget_space_f(dset, dspace, hdf5_err) - ! Select hyperslab for this dataspace offset(1) = work_index(rank) call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) @@ -978,25 +974,60 @@ contains #else - ! Set size - dims(1) = work + if (master) then + ! Create dataset big enough to hold all source sites + dims(1) = n_particles + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, & + dspace, dset, hdf5_err) - ! Create dataspace - call h5screate_simple_f(1, dims, dspace, hdf5_err) + ! Save source bank sites since the souce_bank array is overwritten below +#ifdef MPI + allocate(temp_source(work)) + temp_source(:) = source_bank(:) +#endif - ! Create dataset - call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, & - dspace, dset, hdf5_err) + do i = 0, n_procs - 1 + ! Create memory space + dims(1) = work_index(i+1) - work_index(i) + call h5screate_simple_f(1, dims, memspace, hdf5_err) - ! Set up pointer to data - f_ptr = c_loc(source_bank) +#ifdef MPI + ! Receive source sites from other processes + if (i > 0) then + call MPI_RECV(source_bank, int(dims(1)), MPI_BANK, i, i, & + MPI_COMM_WORLD, MPI_STATUS_IGNORE, mpi_err) + end if +#endif - ! Write dataset to file - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err) + ! Select hyperslab for this dataspace + call h5dget_space_f(dset, dspace, hdf5_err) + offset(1) = work_index(i) + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) - ! Close all ids - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) + ! Set up pointer to data and write data to hyperslab + f_ptr = c_loc(source_bank) + call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace) + + call h5sclose_f(memspace, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end do + + ! Close all ids + call h5dclose_f(dset, hdf5_err) + + ! Restore state of source bank +#ifdef MPI + source_bank(:) = temp_source(:) + deallocate(temp_source) +#endif + else +#ifdef MPI + call MPI_SEND(source_bank, int(work), MPI_BANK, 0, rank, & + MPI_COMM_WORLD, mpi_err) +#endif + end if #endif @@ -1013,18 +1044,16 @@ contains integer :: hdf5_err integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data space handle + integer(HID_T) :: memspace ! memory space handle + integer(HSIZE_T) :: dims(1) + integer(HSIZE_T) :: offset(1) ! offset of data type(c_ptr) :: f_ptr #ifdef PHDF5 integer :: data_xfer_mode integer(HID_T) :: plist ! property list - integer(HID_T) :: dspace ! data space handle - integer(HID_T) :: memspace ! memory space handle - integer(HSIZE_T) :: offset(1) ! offset of data - integer(HSIZE_T) :: dims(1) #endif -#ifdef PHDF5 - ! Open the dataset call h5dopen_f(group_id, "source_bank", dset, hdf5_err) @@ -1032,46 +1061,31 @@ contains dims(1) = work call h5screate_simple_f(1, dims, memspace, hdf5_err) - ! Get the individual local proc dataspace + ! Select hyperslab for each process call h5dget_space_f(dset, dspace, hdf5_err) - - ! Select hyperslab for this dataspace offset(1) = work_index(rank) call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) - ! Set up the property list for parallel writing - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - ! Set up pointer to data f_ptr = c_loc(source_bank) - ! Read data from file in parallel +#ifdef PHDF5 + ! Read data in parallel + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & file_space_id=dspace, mem_space_id=memspace, & xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#else + call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace) +#endif ! Close all ids call h5sclose_f(dspace, hdf5_err) call h5sclose_f(memspace, hdf5_err) call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - -#else - - ! Open dataset - call h5dopen_f(group_id, "source_bank", dset, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank) - - ! Read dataset from file - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err) - - ! Close all ids - call h5dclose_f(dset, hdf5_err) - -#endif end subroutine read_source_bank From 13c4d3ccddce0c991d3c2f989554022e45e62701 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Sep 2015 12:32:26 +0700 Subject: [PATCH 13/95] Write number of particles/batches in summary file for fixed source --- src/hdf5_summary.F90 | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/hdf5_summary.F90 b/src/hdf5_summary.F90 index e8f566c43..3b28e885d 100644 --- a/src/hdf5_summary.F90 +++ b/src/hdf5_summary.F90 @@ -33,23 +33,22 @@ contains ! Write header information call hdf5_write_header(file_id) - ! Write eigenvalue information + ! Write number of particles + call write_dataset(file_id, "n_particles", n_particles) + call write_dataset(file_id, "n_batches", n_batches) + call write_attribute_string(file_id, "n_particles", & + "description", "Number of particles per generation") + call write_attribute_string(file_id, "n_batches", & + "description", "Total number of batches") + + ! Write eigenvalue information if (run_mode == MODE_EIGENVALUE) then - - ! Write number of particles - call write_dataset(file_id, "n_particles", n_particles) - - ! Use H5LT interface to write n_batches, n_inactive, and n_active - call write_dataset(file_id, "n_batches", n_batches) + ! write number of inactive/active batches and generations/batch call write_dataset(file_id, "n_inactive", n_inactive) call write_dataset(file_id, "n_active", n_active) call write_dataset(file_id, "gen_per_batch", gen_per_batch) ! Add description of each variable - call write_attribute_string(file_id, "n_particles", & - "description", "Number of particles per generation") - call write_attribute_string(file_id, "n_batches", & - "description", "Total number of batches") call write_attribute_string(file_id, "n_inactive", & "description", "Number of inactive batches") call write_attribute_string(file_id, "n_active", & From 6d3199b7ab37ad5664ca3b810f1031d381e41f1f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Sep 2015 12:34:03 +0700 Subject: [PATCH 14/95] Get rid of unused read_source routine in state_point module --- src/state_point.F90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/state_point.F90 b/src/state_point.F90 index aca6fafb7..0267ed4ec 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -1089,8 +1089,4 @@ contains end subroutine read_source_bank - subroutine read_source -! TODO write this routine -! TODO what if n_particles does not match source bank - end subroutine read_source end module state_point From 04aecbcb948acbaeaca6cfc3c68a292db74fdcda Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Sep 2015 12:50:19 +0700 Subject: [PATCH 15/95] Remove remnants of binary files --- tests/cleanup | 4 ++-- .../test_filter_distribcell/test_filter_distribcell.py | 5 ++--- tests/test_output/test_output.py | 4 ++-- tests/test_source_file/test_source_file.py | 10 ++++------ tests/test_sourcepoint_batch/test_sourcepoint_batch.py | 7 +++---- .../test_sourcepoint_interval.py | 7 +++---- .../test_sourcepoint_latest/test_sourcepoint_latest.py | 5 ++--- .../test_statepoint_sourcesep.py | 5 ++--- tests/test_track_output/test_track_output.py | 4 ++-- 9 files changed, 22 insertions(+), 29 deletions(-) diff --git a/tests/cleanup b/tests/cleanup index 7b81d2d9d..3369c797e 100755 --- a/tests/cleanup +++ b/tests/cleanup @@ -5,6 +5,6 @@ # folders. This can occur if a previous error # occurred and the test suite was rerun without # deleting left over binary files. This will -# cause an assertion error in some of the +# cause an assertion error in some of the # tests. -find . \( -name "*.binary" -o -name "*.h5" -o -name "*.ppm" \) -exec rm -f {} \; +find . \( -name "*.h5" -o -name "*.ppm" \) -exec rm -f {} \; diff --git a/tests/test_filter_distribcell/test_filter_distribcell.py b/tests/test_filter_distribcell/test_filter_distribcell.py index 492f03dae..8370e40e7 100644 --- a/tests/test_filter_distribcell/test_filter_distribcell.py +++ b/tests/test_filter_distribcell/test_filter_distribcell.py @@ -67,9 +67,8 @@ class DistribcellTestHarness(TestHarness): statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ 'exist.' - assert statepoint[0].endswith('binary') \ - or statepoint[0].endswith('h5'), \ - 'Statepoint file is not a binary or hdf5 file.' + assert statepoint[0].endswith('h5'), \ + 'Statepoint file is not a HDF5 file.' if tallies_out_present: assert os.path.exists(os.path.join(os.getcwd(), 'tallies.out')), \ 'Tally output file does not exist.' diff --git a/tests/test_output/test_output.py b/tests/test_output/test_output.py index 1f51742ba..0225d9fed 100644 --- a/tests/test_output/test_output.py +++ b/tests/test_output/test_output.py @@ -14,8 +14,8 @@ class OutputTestHarness(TestHarness): # Check for the summary. summary = glob.glob(os.path.join(os.getcwd(), 'summary.*')) assert len(summary) == 1, 'Either multiple or no summary file exists.' - assert summary[0].endswith('out') or summary[0].endswith('h5'),\ - 'Summary file is not a binary or hdf5 file.' + assert summary[0].endswith('h5'),\ + 'Summary file is not a HDF5 file.' # Check for the cross sections. assert os.path.exists(os.path.join(os.getcwd(), 'cross_sections.out')),\ diff --git a/tests/test_source_file/test_source_file.py b/tests/test_source_file/test_source_file.py index d9aaa9a0f..d7ed8b80a 100644 --- a/tests/test_source_file/test_source_file.py +++ b/tests/test_source_file/test_source_file.py @@ -66,15 +66,13 @@ class SourceFileTestHarness(TestHarness): statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ 'exist.' - assert statepoint[0].endswith('binary') \ - or statepoint[0].endswith('h5'), \ - 'Statepoint file is not a binary or hdf5 file.' + assert statepoint[0].endswith('h5'), \ + 'Statepoint file is not a HDF5 file.' source = glob.glob(os.path.join(os.getcwd(), 'source.10.*')) assert len(source) == 1, 'Either multiple or no source files exist.' - assert source[0].endswith('binary') \ - or source[0].endswith('h5'), \ - 'Source file is not a binary or hdf5 file.' + assert source[0].endswith('h5'), \ + 'Source file is not a HDF5 file.' def _run_openmc_restart(self): # Get the name of the source file. diff --git a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py index 8cafb4108..a90223659 100644 --- a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py +++ b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py @@ -9,10 +9,9 @@ class SourcepointTestHarness(TestHarness): def _test_output_created(self): """Make sure statepoint.* files have been created.""" statepoint = glob.glob(os.path.join(os.getcwd(), 'statepoint.*')) - assert len(statepoint) == 5, '5 statepoint files must exist.' - assert statepoint[0].endswith('binary') \ - or statepoint[0].endswith('h5'), \ - 'Statepoint file is not a binary or hdf5 file.' + assert len(statepoint) == 5, '5 statepoint files must exist.' + assert statepoint[0].endswith('h5'), \ + 'Statepoint file is not a HDF5 file.' def _get_results(self): """Digest info in the statepoint and return as a string.""" diff --git a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py index 8cafb4108..a90223659 100644 --- a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py +++ b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py @@ -9,10 +9,9 @@ class SourcepointTestHarness(TestHarness): def _test_output_created(self): """Make sure statepoint.* files have been created.""" statepoint = glob.glob(os.path.join(os.getcwd(), 'statepoint.*')) - assert len(statepoint) == 5, '5 statepoint files must exist.' - assert statepoint[0].endswith('binary') \ - or statepoint[0].endswith('h5'), \ - 'Statepoint file is not a binary or hdf5 file.' + assert len(statepoint) == 5, '5 statepoint files must exist.' + assert statepoint[0].endswith('h5'), \ + 'Statepoint file is not a HDF5 file.' def _get_results(self): """Digest info in the statepoint and return as a string.""" diff --git a/tests/test_sourcepoint_latest/test_sourcepoint_latest.py b/tests/test_sourcepoint_latest/test_sourcepoint_latest.py index 5ae398462..8c04641b7 100644 --- a/tests/test_sourcepoint_latest/test_sourcepoint_latest.py +++ b/tests/test_sourcepoint_latest/test_sourcepoint_latest.py @@ -12,9 +12,8 @@ class SourcepointTestHarness(TestHarness): source = glob.glob(os.path.join(os.getcwd(), 'source.*')) assert len(source) == 1, 'Either multiple or no source files ' \ 'exist.' - assert source[0].endswith('binary') \ - or source[0].endswith('h5'), \ - 'Source file is not a binary or hdf5 file.' + assert source[0].endswith('h5'), \ + 'Source file is not a HDF5 file.' if __name__ == '__main__': diff --git a/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py b/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py index 861a04f18..acbb0180b 100644 --- a/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py +++ b/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py @@ -12,9 +12,8 @@ class SourcepointTestHarness(TestHarness): source = glob.glob(os.path.join(os.getcwd(), 'source.*')) assert len(source) == 1, 'Either multiple or no source files ' \ 'exist.' - assert source[0].endswith('binary') \ - or source[0].endswith('h5'), \ - 'Source file is not a binary or hdf5 file.' + assert source[0].endswith('h5'), \ + 'Source file is not a HDF5 file.' if __name__ == '__main__': diff --git a/tests/test_track_output/test_track_output.py b/tests/test_track_output/test_track_output.py index 31d29b742..1192d1b3a 100644 --- a/tests/test_track_output/test_track_output.py +++ b/tests/test_track_output/test_track_output.py @@ -16,8 +16,8 @@ class TrackTestHarness(TestHarness): outputs.append(glob.glob(''.join((os.getcwd(), '/track_1_1_2.*')))) for files in outputs: assert len(files) == 1, 'Multiple or no track files detected.' - assert files[0].endswith('binary') or files[0].endswith('h5'),\ - 'Track files are not binary or hdf5 files' + assert files[0].endswith('h5'),\ + 'Track files are not HDF5 files' def _get_results(self): """Digest info in the statepoint and return as a string.""" From 415f4684bc0c90875e5885c1c8ec3ef00f51ce5e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Sep 2015 15:29:05 +0700 Subject: [PATCH 16/95] Add two missing use ISO_C_BINDING statements --- src/initialize.F90 | 2 ++ src/state_point.F90 | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/initialize.F90 b/src/initialize.F90 index 29e5f8921..68fccf417 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -36,6 +36,8 @@ module initialize use hdf5 + use, intrinsic :: ISO_C_BINDING, only: c_loc + implicit none contains diff --git a/src/state_point.F90 b/src/state_point.F90 index 0267ed4ec..7688d5d33 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -28,6 +28,8 @@ module state_point use hdf5 + use, intrinsic :: ISO_C_BINDING, only: c_loc, c_ptr + implicit none contains From 40d99bac13b10069fe884848b3d266d9c0342f06 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 4 Sep 2015 15:34:29 +0700 Subject: [PATCH 17/95] Dont use -Wall with gfortran 4.6 (causes lots of unused variable warnings on Travis from HDF5 common blocks) --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 623eb0dcb..76c099d52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,10 @@ if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU) # GNU Fortran compiler options list(APPEND f90flags -cpp -std=f2008 -fbacktrace) if(debug) - list(APPEND f90flags -g -Wall -pedantic -fbounds-check + if(NOT (GCC_VERSION VERSION_LESS 4.7)) + list(APPEND f90flags -Wall) + endif() + list(APPEND f90flags -g -pedantic -fbounds-check -ffpe-trap=invalid,overflow,underflow) list(APPEND ldflags -g) endif() From e57d87ab8fe5c9ab9a13ad9ae70c612450f78b53 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 5 Sep 2015 16:22:22 +0800 Subject: [PATCH 18/95] Respond to @wbinventor comments on pull request #447 --- openmc/statepoint.py | 9 ++-- scripts/openmc-track-to-vtk | 5 --- src/initialize.F90 | 4 +- src/{hdf5_summary.F90 => summary.F90} | 59 ++++++++++++++------------- 4 files changed, 38 insertions(+), 39 deletions(-) rename src/{hdf5_summary.F90 => summary.F90} (96%) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index af423b027..06ed51c18 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -199,7 +199,7 @@ class StatePoint(object): self._n_inactive = self._f['n_inactive'].value self._gen_per_batch = self._f['gen_per_batch'].value - self._k_batch = self._f['k_generation'].value + self._k_generation = self._f['k_generation'].value self._entropy = self._f['entropy'].value self._k_col_abs = self._f['k_col_abs'].value @@ -358,7 +358,7 @@ class StatePoint(object): filter.num_bins = n_bins if FILTER_TYPES[filter_type] == 'mesh': - key = self._mesh_keys[list(self._mesh_ids).index(bins)] + key = self._mesh_keys[self._mesh_ids == bins][0] filter.mesh = self._meshes[key] # Add Filter to the Tally @@ -378,8 +378,9 @@ class StatePoint(object): tally.num_score_bins = n_score_bins - scores = [SCORE_TYPES[j] for j in self._f[ - '{0}{1}/score_bins'.format(base, tally_key)].value] + score_bins = self._f['{0}{1}/score_bins'.format( + base, tally_key)].value + scores = [SCORE_TYPES[score] for score in score_bins] n_user_scores = self._f['{0}{1}/n_user_score_bins' .format(base, tally_key)].value diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index c900c4aa5..e22a22dea 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -40,11 +40,6 @@ def main(): # Parse commandline arguments. args = _parse_args() - # Check input file extensions. - for fname in args.input: - if not fname.endswith('.h5'): - raise ValueError("Input file names must an HDF5 file.") - # Make sure that the output filename ends with '.pvtp'. if not args.out: args.out = 'tracks.pvtp' diff --git a/src/initialize.F90 b/src/initialize.F90 index 68fccf417..bd479032f 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -14,7 +14,6 @@ module initialize use global use hdf5_interface, only: file_open, read_dataset, file_close, hdf5_bank_t,& hdf5_tallyresult_t, hdf5_integer8_t - use hdf5_summary, only: hdf5_write_summary use input_xml, only: read_input_xml, read_cross_sections_xml, & cells_in_univ_dict, read_plots_xml use material_header, only: Material @@ -23,6 +22,7 @@ module initialize use random_lcg, only: initialize_prng use state_point, only: load_state_point use string, only: to_str, str_to_int, starts_with, ends_with + use summary, only: write_summary use tally_header, only: TallyObject, TallyResult, TallyFilter use tally_initialize, only: configure_tallies @@ -153,7 +153,7 @@ contains call print_plot() else ! Write summary information - if (output_summary) call hdf5_write_summary() + if (output_summary) call write_summary() ! Write cross section information if (output_xs) call write_xs_summary() diff --git a/src/hdf5_summary.F90 b/src/summary.F90 similarity index 96% rename from src/hdf5_summary.F90 rename to src/summary.F90 index 3b28e885d..cc9a909c8 100644 --- a/src/hdf5_summary.F90 +++ b/src/summary.F90 @@ -1,4 +1,4 @@ -module hdf5_summary +module summary use ace_header, only: Reaction, UrrData, Nuclide use constants @@ -16,14 +16,17 @@ module hdf5_summary use hdf5 implicit none + private + + public :: write_summary contains !=============================================================================== -! HDF5_WRITE_SUMMARY +! WRITE_SUMMARY !=============================================================================== - subroutine hdf5_write_summary() + subroutine write_summary() integer(HID_T) :: file_id @@ -31,7 +34,7 @@ contains file_id = file_create("summary.h5") ! Write header information - call hdf5_write_header(file_id) + call write_header(file_id) ! Write number of particles call write_dataset(file_id, "n_particles", n_particles) @@ -57,23 +60,23 @@ contains "description", "Number of generations per batch") end if - call hdf5_write_geometry(file_id) - call hdf5_write_materials(file_id) - call hdf5_write_nuclides(file_id) + call write_geometry(file_id) + call write_materials(file_id) + call write_nuclides(file_id) if (n_tallies > 0) then - call hdf5_write_tallies(file_id) + call write_tallies(file_id) end if ! Terminate access to the file. call file_close(file_id) - end subroutine hdf5_write_summary + end subroutine write_summary !=============================================================================== -! HDF5_WRITE_HEADER +! WRITE_HEADER !=============================================================================== - subroutine hdf5_write_header(file_id) + subroutine write_header(file_id) integer(HID_T), intent(in) :: file_id ! Write version information @@ -89,13 +92,13 @@ contains call write_attribute_string(file_id, "n_procs", "description", & "Number of MPI processes") - end subroutine hdf5_write_header + end subroutine write_header !=============================================================================== -! HDF5_WRITE_GEOMETRY +! WRITE_GEOMETRY !=============================================================================== - subroutine hdf5_write_geometry(file_id) + subroutine write_geometry(file_id) integer(HID_T), intent(in) :: file_id integer :: i, j, k, m @@ -379,13 +382,13 @@ contains call close_group(lattices_group) call close_group(geom_group) - end subroutine hdf5_write_geometry + end subroutine write_geometry !=============================================================================== -! HDF5_WRITE_MATERIALS +! WRITE_MATERIALS !=============================================================================== - subroutine hdf5_write_materials(file_id) + subroutine write_materials(file_id) integer(HID_T), intent(in) :: file_id integer :: i @@ -452,13 +455,13 @@ contains call close_group(materials_group) - end subroutine hdf5_write_materials + end subroutine write_materials !=============================================================================== -! HDF5_WRITE_TALLIES +! WRITE_TALLIES !=============================================================================== - subroutine hdf5_write_tallies(file_id) + subroutine write_tallies(file_id) integer(HID_T), intent(in) :: file_id integer :: i, j @@ -580,13 +583,13 @@ contains call close_group(tallies_group) - end subroutine hdf5_write_tallies + end subroutine write_tallies !=============================================================================== -! HDF5_WRITE_NUCLIDES +! WRITE_NUCLIDES !=============================================================================== - subroutine hdf5_write_nuclides(file_id) + subroutine write_nuclides(file_id) integer(HID_T), intent(in) :: file_id integer :: i, j @@ -689,13 +692,13 @@ contains call close_group(nuclides_group) - end subroutine hdf5_write_nuclides + end subroutine write_nuclides !=============================================================================== -! HDF5_WRITE_TIMING +! WRITE_TIMING !=============================================================================== - subroutine hdf5_write_timing(file_id) + subroutine write_timing(file_id) integer(HID_T), intent(in) :: file_id integer(8) :: total_particles @@ -748,6 +751,6 @@ contains call write_dataset(time_group, "neutrons_per_second", speed) call close_group(time_group) - end subroutine hdf5_write_timing + end subroutine write_timing -end module hdf5_summary +end module summary From 453b33264a8ea565a63c1c760b8c3fe97b29ddbc Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 11 Sep 2015 09:55:48 +0400 Subject: [PATCH 19/95] Fix use of energy filters in openmc-plot-mesh-tally --- scripts/openmc-plot-mesh-tally | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/openmc-plot-mesh-tally b/scripts/openmc-plot-mesh-tally index f925b413a..1559ea328 100755 --- a/scripts/openmc-plot-mesh-tally +++ b/scripts/openmc-plot-mesh-tally @@ -33,7 +33,7 @@ class MeshPlotter(tk.Frame): self.labels = {'cell': 'Cell:', 'cellborn': 'Cell born:', 'surface': 'Surface:', 'material': 'Material:', - 'universe': 'Universe:', 'energyin': 'Energy in:', + 'universe': 'Universe:', 'energy': 'Energy in:', 'energyout': 'Energy out:'} self.filterBoxes = {} @@ -180,9 +180,9 @@ class MeshPlotter(tk.Frame): self.filterBoxes[filterType] = combobox # Set combobox items - if filterType in ['energyin', 'energyout']: + if filterType in ['energy', 'energyout']: combobox['values'] = ['{0} to {1}'.format(*f.bins[i:i+2]) - for i in range(f.length)] + for i in range(len(f.bins) - 1)] else: combobox['values'] = [str(i) for i in f.bins] @@ -213,8 +213,13 @@ class MeshPlotter(tk.Frame): if f.type == 'mesh': mesh_filter = f continue - index = self.filterBoxes[f.type].current() - spec_list.append((f.type, (index,))) + elif f.type in ['energy', 'energyout']: + index = self.filterBoxes[f.type].current() + ebin = (f.bins[index], f.bins[index + 1]) + spec_list.append((f.type, (ebin,))) + else: + index = self.filterBoxes[f.type].current() + spec_list.append((f.type, (index,))) text = self.basisBox.get() if text == 'xy': From 517628daf1a17ccb83fe76b0c0b9d1d05c21ea86 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 11 Sep 2015 10:10:56 +0400 Subject: [PATCH 20/95] Respond to @smharper comments on pull request #447 --- src/hdf5_interface.F90 | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 491337e00..f4771d848 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1,13 +1,16 @@ module hdf5_interface - ! This module provides the high-level procedures which greatly simplify - ! writing/reading different types of data to HDF5 files. In order to get it to - ! work with gfotran 4.6, all the write__ND subroutines had to be split - ! into two procedures, one accepting an assumed-shape array and another one - ! with an explicit-shape array since in gfortran 4.6 C_LOC does not work with - ! an assumed-shape array. When we move to gfortran 4.9+, these procedures can - ! be combined into one simply accepting an assumed-shape array. +!============================================================================== +! HDF5_INTERFACE -- This module provides the high-level procedures which greatly +! simplify writing/reading different types of data to HDF5 files. In order to +! get it to work with gfotran 4.6, all the write__ND subroutines had to be +! split into two procedures, one accepting an assumed-shape array and another +! one with an explicit-shape array since in gfortran 4.6 C_LOC does not work +! with an assumed-shape array. When we move to gfortran 4.9+, these procedures +! can be combined into one simply accepting an assumed-shape array. +!============================================================================== + use error, only: fatal_error use tally_header, only: TallyResult use hdf5 @@ -138,7 +141,7 @@ contains ! Determine access type open_mode = H5F_ACC_RDONLY_F - if (trim(mode) == 'w') open_mode = H5F_ACC_RDWR_F + if (mode == 'w') open_mode = H5F_ACC_RDWR_F if (parallel_) then ! Setup file access property list with parallel I/O access @@ -192,8 +195,12 @@ contains ! Check if group exists call h5ltpath_valid_f(group_id, trim(name), .true., exists, hdf5_err) - ! Either create or open group - if (exists) call h5gopen_f(group_id, trim(name), newgroup_id, hdf5_err) + ! open group if it exists + if (exists) then + call h5gopen_f(group_id, trim(name), newgroup_id, hdf5_err) + else + call fatal_error("The group '" // trim(name) // "' does not exist.") + end if end function open_group !=============================================================================== @@ -212,8 +219,11 @@ contains call h5ltpath_valid_f(group_id, trim(name), .true., exists, hdf5_err) ! create group - if (.not. exists) & - call h5gcreate_f(group_id, trim(name), newgroup_id, hdf5_err) + if (exists) then + call fatal_error("The group '" // trim(name) // "' already exists.") + else + call h5gcreate_f(group_id, trim(name), newgroup_id, hdf5_err) + end if end function create_group !=============================================================================== From a978225ba9fb6847f5f242153027f13a89dc8f00 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 11 Sep 2015 10:11:45 +0400 Subject: [PATCH 21/95] Remove openmc-tally-convergence script --- scripts/openmc-tally-convergence | 375 ------------------------------- 1 file changed, 375 deletions(-) delete mode 100755 scripts/openmc-tally-convergence diff --git a/scripts/openmc-tally-convergence b/scripts/openmc-tally-convergence deleted file mode 100755 index 81f45fd71..000000000 --- a/scripts/openmc-tally-convergence +++ /dev/null @@ -1,375 +0,0 @@ -#!/usr/bin/env python - -# This program takes OpenMC statepoint binary files and creates a variety of -# outputs from them which should provide the user with an idea of the -# convergence behavior of all the tallies and filters defined by the user in -# tallies.xml. The program can directly plot the value and errors of each -# tally, filter, score combination; it can save these plots to a file; and -# it can also save the data used in these plots to a CSV file for importing in -# to other plotting packages such as Excel, gnuplot, MathGL, or Veusz. - -# To use the program, run this program from the working directory of the openMC -# problem to analyze. - -# The USER OPTIONS block below provides four options for the user to set: -# fileType, printxs, showImg, and savetoCSV. See the options block for more -# information. - -from __future__ import print_function -from math import sqrt, pow -from glob import glob - -import numpy as np -import scipy.stats -import matplotlib.pyplot as plt - -from openmc.statepoint import StatePoint - -##################################### USER OPTIONS - -# Set filetype (the file extension desired, without the period.) -# Options are backend dependent, but most backends support png, pdf, ps, eps -# and svg. Write "none" if no saved files are desired. -fileType = "none" - -# Set if cross-sections or reaction rates are desired printxs = True means X/S -printxs = False - -# Set if the figures should be displayed to screen or not (True means show) -showImg = False - -# Save to CSV for use in more advanced plotting programs like GNUPlot, MathGL -savetoCSV = True - -##################################### END USER OPTIONS - -## Find if tallies.xml exists. -#if glob('./tallies.xml') != None: -# # It exists -# tallyData = talliesXML('tallies.xml') -#else: -# # It does not exist. -# tallyData = None - -# Find all statepoints in this directory. -files = glob('./statepoint.*.binary') -fileNums = [] -begin = 13 -# Arrange the file list in increasing batch order -for i in range(len(files)): - end = files[i].find(".binary") - fileNums.append(int(files[i][begin:end])) -fileNums.sort() -# Re-make filenames -files = [] -for i in range(len(fileNums)): - files.append("./statepoint." + str(fileNums[i]) + ".binary") - -# Initialize arrays as needed -mean = [None for x in range(len(files))] -uncert = [None for x in range(len(files))] -scoreType = [None for x in range(len(files))] -active_batches = [None for x in range(len(files))] - -for i_batch in range(len(files)): - - # Get filename - batch_filename = files[i_batch] - - # Create StatePoint object - sp = StatePoint(batch_filename) - - # Read number of realizations for global tallies - sp.n_realizations = sp._get_int()[0] - - # Read global tallies - n_global_tallies = sp._get_int()[0] - sp.global_tallies = np.array(sp._get_double(2*n_global_tallies)) - sp.global_tallies.shape = (n_global_tallies, 2) - - # Flag indicating if tallies are present - tallies_present = sp._get_int()[0] - - # Check if tallies are present - if not tallies_present: - raise Exception("No tally data in state point!") - - # Increase the dimensionality of our main variables - mean[i_batch] = [None for x in range(len(sp.tallies))] - uncert[i_batch] = [None for x in range(len(sp.tallies))] - scoreType[i_batch] = [None for x in range(len(sp.tallies))] - - # Loop over all tallies - for i_tally, t in enumerate(sp.tallies): - # Calculate t-value for 95% two-sided CI - n = t.n_realizations - t_value = scipy.stats.t.ppf(0.975, n - 1) - - # Store the batch count - active_batches[i_batch] = n - - # Resize the 2nd dimension - mean[i_batch][i_tally] = [None for x in range(t.total_filter_bins)] - uncert[i_batch][i_tally] = [None for x in range(t.total_filter_bins)] - scoreType[i_batch][i_tally] = [None for x in range(t.total_filter_bins)] - - for i_filter in range(t.total_filter_bins): - # Resize the 3rd dimension - mean[i_batch][i_tally][i_filter] = [None for x in range(t.n_nuclides)] - uncert[i_batch][i_tally][i_filter] = [None for x in range(t.n_nuclides)] - scoreType[i_batch][i_tally][i_filter] = [None for x in range(t.n_nuclides)] - print(t.total_filter_bins,t.n_nuclides) - for i_nuclide in range(t.n_nuclides): - mean[i_batch][i_tally][i_filter][i_nuclide] = \ - [None for x in range(t.n_scores)] - uncert[i_batch][i_tally][i_filter][i_nuclide] = \ - [None for x in range(t.n_scores)] - scoreType[i_batch][i_tally][i_filter][i_nuclide] = \ - [None for x in range(t.n_scores)] - for i_score in range(t.n_scores): - scoreType[i_batch][i_tally][i_filter][i_nuclide][i_score] = \ - t.scores[i_score] - s, s2 = sp._get_double(2) - s /= n - mean[i_batch][i_tally][i_filter][i_nuclide][i_score] = s - if s != 0.0: - relative_error = t_value*sqrt((s2/n - s*s)/(n-1))/s - else: - relative_error = 0.0 - uncert[i_batch][i_tally][i_filter][i_nuclide][i_score] = relative_error - -# Reorder the data lists in to a list order more conducive for plotting: -# The indexing should be: [tally][filter][score][batch] -meanPlot = [None for x in range(len(mean[0]))] # Set to the number of tallies -uncertPlot = [None for x in range(len(mean[0]))] # Set to the number of tallies -absUncertPlot = [None for x in range(len(mean[0]))] # Set to number of tallies -filterLabel = [None for x in range(len(mean[0]))] #Set to the number of tallies -fluxLoc = [None for x in range(len(mean[0]))] # Set to the number of tallies -printxs = [False for x in range(len(mean[0]))] # Set to the number of tallies - -# Get and set the correct sizes for the rest of the dimensions -for i_tally in range(len(meanPlot)): - # Set 2nd (score) dimension - meanPlot[i_tally] = [None for x in range(len(mean[0][i_tally]))] - uncertPlot[i_tally] = [None for x in range(len(mean[0][i_tally]))] - absUncertPlot[i_tally] = [None for x in range(len(mean[0][i_tally]))] - filterLabel[i_tally] = [None for x in range(len(mean[0][i_tally]))] - - # Initialize flux location so it will be -1 if not found - fluxLoc[i_tally] = -1 - - for i_filter in range(len(meanPlot[i_tally])): - # Set 3rd (filter) dimension - meanPlot[i_tally][i_filter] = \ - [None for x in range(len(mean[0][i_tally][i_filter]))] - uncertPlot[i_tally][i_filter] = \ - [None for x in range(len(mean[0][i_tally][i_filter]))] - absUncertPlot[i_tally][i_filter] = \ - [None for x in range(len(mean[0][i_tally][i_filter]))] - filterLabel[i_tally][i_filter] = \ - [None for x in range(len(mean[0][i_tally][i_filter]))] - - for i_nuclide in range(len(meanPlot[i_tally][i_filter])): - # Set 4th (nuclide)) dimension - meanPlot[i_tally][i_filter][i_nuclide] = \ - [None for x in range(len(mean[0][i_tally][i_filter][i_nuclide]))] - uncertPlot[i_tally][i_filter][i_nuclide] = \ - [None for x in range(len(mean[0][i_tally][i_filter][i_nuclide]))] - absUncertPlot[i_tally][i_filter][i_nuclide] = \ - [None for x in range(len(mean[0][i_tally][i_filter][i_nuclide]))] - - for i_score in range(len(meanPlot[i_tally][i_filter][i_nuclide])): - # Set 5th (batch) dimension - meanPlot[i_tally][i_filter][i_nuclide][i_score] = \ - [None for x in range(len(mean))] - uncertPlot[i_tally][i_filter][i_nuclide][i_score] = \ - [None for x in range(len(mean))] - absUncertPlot[i_tally][i_filter][i_nuclide][i_score] = \ - [None for x in range(len(mean))] - - # Get filterLabel (this should be moved to its own function) - #??? How to do? - - # Set flux location if found - # all batches and all tallies will have the same score ordering, hence - # the 0's in the 1st, 3rd, and 4th dimensions. - if scoreType[0][i_tally][0][0][i_score] == 'flux': - fluxLoc[i_tally] = i_score - -# Set printxs array according to the printxs input -if printxs: - for i_tally in range(len(fluxLoc)): - if fluxLoc[i_tally] != -1: - printxs[i_tally] = True - -# Now rearrange the data as suitable, and perform xs conversion if necessary -for i_batch in range(len(mean)): - for i_tally in range(len(mean[i_batch])): - for i_filter in range(len(mean[i_batch][i_tally])): - for i_nuclide in range(len(mean[i_batch][i_tally][i_filter])): - for i_score in range(len(mean[i_batch][i_tally][i_filter][i_nuclide])): - if (printxs[i_tally] and \ - ((scoreType[0][i_tally][i_filter][i_nuclide][i_score] != 'flux') and \ - (scoreType[0][i_tally][i_filter][i_nuclide][i_score] != 'current'))): - - # Perform rate to xs conversion - # mean is mean/fluxmean - meanPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - mean[i_batch][i_tally][i_filter][i_nuclide][i_score] / \ - mean[i_batch][i_tally][i_filter][i_nuclide][fluxLoc[i_tally]] - - # Update the relative uncertainty via error propagation - uncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - sqrt(pow(uncert[i_batch][i_tally][i_filter][i_nuclide][i_score],2) \ - + pow(uncert[i_batch][i_tally][i_filter][i_nuclide][fluxLoc[i_tally]],2)) - else: - - # Do not perform rate to xs conversion - meanPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - mean[i_batch][i_tally][i_filter][i_nuclide][i_score] - uncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - uncert[i_batch][i_tally][i_filter][i_nuclide][i_score] - - # Both have the same absolute uncertainty calculation - absUncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - uncert[i_batch][i_tally][i_filter][i_nuclide][i_score] * \ - mean[i_batch][i_tally][i_filter][i_nuclide][i_score] - -# Set plotting constants -xLabel = "Batches" -xLabel = xLabel.title() # not necessary for now, but is left in to handle if -# the previous line changes - -# Begin plotting -for i_tally in range(len(meanPlot)): - # Set tally string (placeholder until I put tally labels in statePoint) - tallyStr = "Tally " + str(i_tally + 1) - - for i_filter in range(len(meanPlot[i_tally])): - - # Set filter string - filterStr = "Filter " + str(i_filter + 1) - - for i_nuclide in range(len(meanPlot[i_tally][i_filter])): - - nuclideStr = "Nuclide " + str(i_nuclide + 1) - - for i_score in range(len(meanPlot[i_tally][i_filter][i_nuclide])): - - # Set score string - scoreStr = scoreType[i_batch][i_tally][i_filter][i_nuclide][i_score] - scoreStr = scoreStr.title() - if (printxs[i_tally] and ((scoreStr != 'Flux') and \ - (scoreStr != 'Current'))): - scoreStr = scoreStr + "-XS" - - # set Title - title = "Convergence of " + scoreStr + " in " + tallyStr + " for "\ - + filterStr + " and " + nuclideStr - - # set yLabel - yLabel = scoreStr - yLabel = yLabel.title() - - # Set saving filename - fileName = "tally_" + str(i_tally + 1) + "_" + scoreStr + \ - "_filter_" + str(i_filter+1) + "_nuclide_" + str(i_nuclide+1) \ - + "." + fileType - REfileName = "tally_" + str(i_tally + 1) + "_" + scoreStr + \ - "RE_filter_" + str(i_filter+1) + "_nuclide_" + str(i_nuclide+1) \ - + "." + fileType - - # Plot mean with absolute error bars - plt.errorbar(active_batches, \ - meanPlot[i_tally][i_filter][i_nuclide][i_score][:], \ - absUncertPlot[i_tally][i_filter][i_nuclide][i_score][:],fmt='o-',aa=True) - plt.xlabel(xLabel) - plt.ylabel(yLabel) - plt.title(title) - if (fileType != 'none'): - plt.savefig(fileName) - if showImg: - plt.show() - plt.clf() - - # Plot relative uncertainty - plt.plot(active_batches, \ - uncertPlot[i_tally][i_filter][i_nuclide][i_score][:],'o-',aa=True) - plt.xlabel(xLabel) - plt.ylabel("Relative Error of " + yLabel) - plt.title("Relative Error of " + title) - if (fileType != 'none'): - plt.savefig(REfileName) - if showImg: - plt.show() - plt.clf() - -if savetoCSV: - # This block loops through each tally, and for each tally: - # Creates a new file - # Writes the scores and filters for that tally in csv format. - # The columns will be: batches,then for each filter: all the scores - # The rows, of course, are the data points per batch. - - for i_tally in range(len(meanPlot)): - # Set tally string (placeholder until I put tally labels in statePoint) - tallyStr = "Tally " + str(i_tally + 1) - CSV_filename = "./tally" + str(i_tally+1)+".csv" - # Open the file - f = open(CSV_filename, 'w') - - # Write the header line - - lineText = "Batches" - - for i_filter in range(len(meanPlot[i_tally])): - - # Set filter string - filterStr = "Filter " + str(i_filter + 1) - - for i_nuclide in range(len(meanPlot[i_tally][i_filter])): - - nuclideStr = "Nuclide " + str(i_nuclide + 1) - - for i_score in range(len(meanPlot[i_tally][i_filter][i_nuclide])): - - # Set the title - scoreStr = scoreType[i_batch][i_tally][i_filter][i_nuclide][i_score] - scoreStr = scoreStr.title() - if (printxs[i_tally] and ((scoreStr != 'Flux') and \ - (scoreStr != 'Current'))): - scoreStr = scoreStr + "-XS" - - # set header - headerText = scoreStr + " for " + filterStr + " for " + nuclideStr - - lineText = lineText + "," + headerText + \ - ",Abs Unc of " + headerText + \ - ",Rel Unc of " + headerText - - f.write(lineText + "\n") - - # Write the data lines, each row is a different batch - - for i_batch in range(len(meanPlot[i_tally][0][0][0])): - - lineText = repr(active_batches[i_batch]) - - for i_filter in range(len(meanPlot[i_tally])): - - for i_nuclide in range(len(meanPlot[i_tally][i_filter])): - - for i_score in range(len(meanPlot[i_tally][i_filter][i_nuclide])): - - fieldText = \ - repr(meanPlot[i_tally][i_filter][i_nuclide][i_score][i_batch]) + \ - "," + \ - repr(absUncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch]) +\ - "," + \ - repr(uncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch]) - - lineText = lineText + "," + fieldText - - f.write(lineText + "\n") - - From 4994493397e31ff59c4d1fee7d39778cee5569f9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 12 Sep 2015 00:31:50 +0800 Subject: [PATCH 22/95] Add two test configurations to Travis pull request runs --- tests/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/travis.sh b/tests/travis.sh index af54b4ff6..443e951cc 100755 --- a/tests/travis.sh +++ b/tests/travis.sh @@ -5,7 +5,7 @@ set -ev # Run all debug tests ./check_source.py if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - ./run_tests.py -C "^hdf5-debug$|^phdf5-debug$|^phdf5-omp-debug$" -j 2 -s + ./run_tests.py -C "^hdf5-debug$|^omp-hdf5-debug|^mpi-hdf5-debug|^phdf5-debug$|^phdf5-omp-debug$" -j 2 -s else ./run_tests.py -C "^hdf5-debug$" -j 2 fi From a569ce786b78d3c92a95129ac3fe5bf3c0f8e61a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 12 Sep 2015 12:24:27 +0700 Subject: [PATCH 23/95] Revise documentation for statepoint format --- docs/source/devguide/statepoint.rst | 229 +++++++++++++--------------- docs/source/quickinstall.rst | 4 +- docs/source/usersguide/install.rst | 64 ++++---- 3 files changed, 146 insertions(+), 151 deletions(-) diff --git a/docs/source/devguide/statepoint.rst b/docs/source/devguide/statepoint.rst index 4a1db9478..7b0862056 100644 --- a/docs/source/devguide/statepoint.rst +++ b/docs/source/devguide/statepoint.rst @@ -6,286 +6,271 @@ State Point Binary File Specifications The current revision of the statepoint binary file is 13. -**integer(4) FILETYPE_STATEPOINT** +**/filetype** (*int*) - Flags whether this file is a statepoint file or a particle restart file. + Flags what type of file this is. A value of -1 indicates a statepoint file, + a value of -2 indicates a particle restart file, and a value of -3 indicates + a source file. -**integer(4) REVISION_STATEPOINT** +**/revision** (*int*) Revision of the binary state point file. Any time a change is made in the format of the state-point file, this integer is incremented. -**integer(4) VERSION_MAJOR** +**/version_major** (*int*) Major version number for OpenMC -**integer(4) VERSION_MINOR** +**/version_minor** (*int*) Minor version number for OpenMC -**integer(4) VERSION_RELEASE** +**/version_release** (*int*) Release version number for OpenMC -**character(19) time_stamp** +**/time_stamp** (*char[19]*) Date and time the state point was written. -**character(255) path** +**/path** (*char[255]*) Absolute path to directory containing input files. -**integer(8) seed** +**/seed** (*int8_t*) Pseudo-random number generator seed. -**integer(4) run_mode** +**/run_mode** (*int*) - run mode used. The modes are described in constants.F90. + Run mode used. A value of 1 indicates a fixed-source run and a value of 2 + indicates an eigenvalue run. -**integer(8) n_particles** +**/n_particles** (*int8_t*) Number of particles used per generation. -**integer(4) current_batch** +**/n_batches** (*int*) + + Number of batches to simulate. + +**/current_batch** (*int*) The number of batches already simulated. if (run_mode == MODE_EIGENVALUE) - **integer(4) n_inactive** + **/n_inactive** (*int*) - Number of inactive batches + Number of inactive batches. - **integer(4) gen_per_batch** + **gen_per_batch** (*int*) - Number of generations per batch for criticality calculations + Number of generations per batch. - *do i = 1, current_batch \* gen_per_batch* + **/k_generation** (*double[]*) - **real(8) k_generation(i)** + k-effective for each generation simulated. - k-effective for the i-th total generation + **/entropy** (*double[]*) - *do i = 1, current_batch \* gen_per_batch* + Shannon entropy for each generation simulated - **real(8) entropy(i)** - - Shannon entropy for the i-th total generation - - **real(8) k_col_abs** + **/k_col_abs** (*double*) Sum of product of collision/absorption estimates of k-effective - **real(8) k_col_tra** + **/k_col_tra** (*double*) Sum of product of collision/track-length estimates of k-effective - **real(8) k_abs_tra** + **/k_abs_tra** (*double*) Sum of product of absorption/track-length estimates of k-effective - **real(8) k_combined(2)** + **/k_combined** (*double[2]*) Mean and standard deviation of a combined estimate of k-effective - **integer(4) cmfd_on** + **/cmfd_on** (*int*) - Flag that cmfd is on + Flag indicating whether CMFD is on (1) or off (0). if (cmfd_on) - **integer(4) cmfd % indices** + **/cmfd/indices** (*int[4]*) Indices for cmfd mesh (i,j,k,g) - **real(8) cmfd % k_cmfd(1:current_batch)** + **/cmfd/k_cmfd** (*double[]*) CMFD eigenvalues - **real(8) cmfd % src(1:G,1:I,1:J,1:K)** + **/cmfd/cmfd_src** (*double[][][][]*) CMFD fission source - **real(8) cmfd % entropy(1:current_batch)** + **/cmfd/cmfd_entropy** (*double[]*) CMFD estimate of Shannon entropy - **real(8) cmfd % balance(1:current_batch)** + **/cmfd/cmfd_balance** (*double[]*) RMS of the residual neutron balance equation on CMFD mesh - **real(8) cmfd % dom(1:current_batch)** + **/cmfd/cmfd_dominance** (*double[]*) CMFD estimate of dominance ratio - **real(8) cmfd % scr_cmp(1:current_batch)** + **/cmfd/cmfd_srccmp** (*double[]*) RMS comparison of difference between OpenMC and CMFD fission source -**integer(4) n_meshes** +**/tallies/n_meshes** (*int*) Number of meshes in tallies.xml file +**/tally/meshes/ids** (*int[]*) + + Internal unique ID of each mesh. + +**/tally/meshes/keys** (*int[]*) + + User-identified unique ID of each mesh + *do i = 1, n_meshes* - **integer(4) meshes(i) % id** + **/tallies/meshes/mesh i/id** (*int*) - Unique ID of mesh. + Unique identifier of the mesh. - **integer(4) meshes(i) % type** + **/tallies/meshes/mesh i/type** (*int*) Type of mesh. - **integer(4) meshes(i) % n_dimension** + **/tallies/meshes/mesh i/n_dimension** (*int*) Number of dimensions for mesh (2 or 3). - **integer(4) meshes(i) % dimension(:)** + **/tallies/meshes/mesh i/dimension** (*int*) Number of mesh cells in each dimension. - **real(8) meshes(i) % lower_left(:)** + **/tallies/meshes/mesh i/lower_left** (*double[]*) Coordinates of lower-left corner of mesh. - **real(8) meshes(i) % upper_right(:)** + **/tallies/meshes/mesh i/upper_right** (*double[]*) Coordinates of upper-right corner of mesh. - **real(8) meshes(i) % width(:)** + **/tallies/meshes/mesh i/width** (*double[]*) Width of each mesh cell in each dimension. -**integer(4) n_tallies** +**/tallies/n_tallies** (*int*) + + Number of user-defined tallies. + +**/tallies/ids** (*int[]*) + + Internal unique ID of each tally. + +**/tallies/keys** (*int[]*) + + User-identified unique ID of each tally. *do i = 1, n_tallies* - **integer(4) tallies(i) % id** + **/tallies/tally i/estimator** (*int*) - Unique ID of tally. + Type of tally estimator: analog (1) or tracklength (2). - **integer(4) tallies(i) % n_realizations** + **/tallies/tally i/n_realizations** (*int*) - Number of realizations for the i-th tally. + Number of realizations. - **integer(4) size(tallies(i) % scores, 1)** + **/tallies/tally i/n_filters** (*int*) - Total number of score bins for the i-th tally - - **integer(4) size(tallies(i) % scores, 2)** - - Total number of filter bins for the i-th tally - - **integer(4) tallies(i) % n_filters** + Number of filters used. *do j = 1, tallies(i) % n_filters* - **integer(4) tallies(i) % filter(j) % type** + **/tallies/tally i/filter j/type** (*int*) Type of tally filter. - **integer(4) tallies(i) % filter(j) % n_bins** + **/tallies/tally i/filter j/offset** (*int*) + + Filter offset (used for distribcell). + + **/tallies/tally i/filter j/n_bins** (*int*) Number of bins for filter. - **integer(4)/real(8) tallies(i) % filter(j) % bins(:)** + **/tallies/tally i/filter j/bins** (*int[]* or *double[]*) Value for each filter bin of this type. - **integer(4) tallies(i) % n_nuclide_bins** + **/tallies/tally i/n_nuclides** (*int*) Number of nuclide bins. If none are specified, this is just one. - *do j = 1, tallies(i) % n_nuclide_bins* + **/tallies/tally i/nuclides** (*int[]*) - **integer(4) tallies(i) % nuclide_bins(j)** + Values of specified nuclide bins (ZAID identifiers) - Values of specified nuclide bins - - **integer(4) tallies(i) % n_score_bins** + **/tallies/tally i/n_score_bins** (*int*) Number of scoring bins. - *do j = 1, tallies(i) % n_score_bins* + **/tallies/tally i/score_bins** (*int*) - **integer(4) tallies(i) % score_bins(j)** + Values of specified scoring bins (e.g. SCORE_FLUX). - Values of specified scoring bins (e.g. SCORE_FLUX). - - **integer(4) tallies(i) % n_score_bins** + **/tallies/tally i/n_user_score_bins** Number of scoring bins without accounting for those added by - the scatter-pn command. + expansions, e.g. scatter-PN. - *do j = 1, tallies(i) % n_user_score_bins* + *do J = 1, total number of moments* - **character(8) tallies(i) % moment_order(j)** + **/tallies/tally i/moments/orderJ** (*char[8]*) Tallying moment order for Legendre and spherical harmonic tally expansions (*e.g.*, 'P2', 'Y1,2', etc.). -**integer(4) source_present** +**/source_present** (*int*) Flag indicated if source bank is present in the file -**integer(4) n_realizations** +**/n_realizations** (*int*) Number of realizations for global tallies. -**integer(4) N_GLOBAL_TALLIES** +**/n_global_tallies** (*int*) - Number of global tally scores + Number of global tally scores. -*do i = 1, N_GLOBAL_TALLIES* +**/global_tallies** (Compound type) - **real(8) global_tallies(i) % sum** + Accumulated sum and sum-of-squares for each global tally. The compound type + has fields named ``sum`` and ``sum_sq``. - Accumulated sum for the i-th global tally - - **real(8) global_tallies(i) % sum_sq** - - Accumulated sum of squares for the i-th global tally - -**integer(4) tallies_on** +**tallies_present** (*int*) Flag indicated if tallies are present in the file. -if (tallies_on > 0) +*do i = 1, n_tallies* - *do i = 1, n_tallies* +**/tallies/tally i/results** (Compound type) - *do k = 1, size(tallies(i) % scores, 2)* - - *do j = 1, size(tallies(i) % scores, 1)* - - **real(8) tallies(i) % scores(j,k) % sum** - - Accumulated sum for the j-th score and k-th filter of the - i-th tally - - **real(8) tallies(i) % scores(j,k) % sum_sq** - - Accumulated sum of squares for the j-th score and k-th - filter of the i-th tally + Accumulated sum and sum-of-squares for each bin of the tally i-th tally if (run_mode == MODE_EIGENVALUE and source_present) - *do i = 1, n_particles* - - **real(8) source_bank(i) % wgt** - - Weight of the i-th source particle - - **real(8) source_bank(i) % xyz(1:3)** - - Coordinates of the i-th source particle. - - **real(8) source_bank(i) % uvw(1:3)** - - Direction of the i-th source particle - - **real(8) source_bank(i) % E** - - Energy of the i-th source particle. + **/source_bank** (Compound type) + Source bank information for each particle. The compound type has fields + ``wgt``, ``xyz``, ``uvw``, and ``E`` which represent the weight, + position, direction, and energy of the source particle, respectively. diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index b64dfebda..31ca71ffc 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -35,8 +35,8 @@ Installing from Source on Linux or Mac OS X ------------------------------------------- All OpenMC source code is hosted on GitHub_. If you have git_, the gfortran_ -compiler, and CMake_ installed, you can download and install OpenMC be entering -the following commands in a terminal: +compiler, CMake_, and HDF_ installed, you can download and install OpenMC be +entering the following commands in a terminal: .. code-block:: sh diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 7d3cda173..7b8c6e3d4 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -59,6 +59,31 @@ Prerequisites sudo apt-get install cmake + * HDF5_ Library for portable binary output format + + OpenMC uses HDF5 for binary output files. As such, you will need to have + HDF5 installed on your computer. The installed version will need to have + been compiled with the same compiler you intend to compile OpenMC with. If + you are using HDF5 in conjunction with MPI, we recommend that your HDF5 + installation be built with parallel I/O features. An example of + configuring HDF5_ is listed below:: + + FC=/opt/mpich/3.1/bin/mpif90 CC=/opt/mpich/3.1/bin/mpicc \ + ./configure --prefix=/opt/hdf5/1.8.12 --enable-fortran \ + --enable-fortran2003 --enable-parallel + + You may omit ``--enable-parallel`` if you want to compile HDF5_ in serial. + + On Debian derivatives, HDF5 and/or parallel HDF5 can be installed through + the APT package manager: + + .. code-block:: sh + + sudo apt-get install libhdf5-8 libhdf5-dev hdf5-helpers + + Note that the exact package names may vary depending on your particular + distribution and version. + .. admonition:: Optional * An MPI implementation for distributed-memory parallel runs @@ -72,20 +97,6 @@ Prerequisites sudo apt-get install mpich libmpich-dev sudo apt-get install openmpi-bin libopenmpi1.6 libopenmpi-dev - * HDF5_ Library for portable binary output format - - To compile with support for HDF5_ output (highly recommended), you will - need to have HDF5 installed on your computer. The installed version will - need to have been compiled with the same compiler you intend to compile - OpenMC with. HDF5_ must be built with parallel I/O features if you intend - to use HDF5_ with MPI. An example of configuring HDF5_ is listed below:: - - FC=/opt/mpich/3.1/bin/mpif90 CC=/opt/mpich/3.1/bin/mpicc \ - ./configure --prefix=/opt/hdf5/1.8.12 --enable-fortran \ - --enable-fortran2003 --enable-parallel - - You may omit ``--enable-parallel`` if you want to compile HDF5_ in serial. - * git_ version control software for obtaining source code .. _gfortran: http://gcc.gnu.org/wiki/GFortran @@ -194,27 +205,26 @@ command, i.e. FC=mpif90 cmake /path/to/openmc -Compiling with HDF5 -+++++++++++++++++++ - -To compile with MPI, set the :envvar:`FC` environment variable to the path to -the HDF5 Fortran wrapper. For example, in a bash shell: +Selecting HDF5 Installation ++++++++++++++++++++++++++++ +CMakeLists.txt searches for the ``h5fc`` or ``h5pfc`` HDF5 Fortran wrapper on +your PATH environment variable and subsequently uses it to determine library +locations and compile flags. If you have multiple installations of HDF5 or one +that does not appear on your PATH, you can set the HDF5_ROOT environment +variable to the root directory of the HDF5 installation, e.g. .. code-block:: sh - export FC=h5fc + export HDF5_ROOT=/opt/hdf5/1.8.15 cmake /path/to/openmc -As noted above, an environment variable can typically be set for a single -command, i.e. +This will cause CMake to search first in /opt/hdf5/1.8.15/bin for ``h5fc`` / +``h5pfc`` before it searches elsewhere. As noted above, an environment variable +can typically be set for a single command, i.e. .. code-block:: sh - FC=h5fc cmake /path/to/openmc - -To compile with support for both MPI and HDF5, use the parallel HDF5 wrapper -``h5pfc`` instead. Note that this requires that your HDF5 installation be -compiled with ``--enable-parallel``. + HDF5_ROOT=/opt/hdf5/1.8.15 cmake /path/to/openmc Compiling on Linux and Mac OS X ------------------------------- From 7fdfc1ede40f60868cc2982537f14932c95e9c4b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 12 Sep 2015 13:43:57 +0700 Subject: [PATCH 24/95] Add particle restart file format in documentation. --- docs/source/devguide/index.rst | 1 + docs/source/devguide/particle_restart.rst | 59 +++++++++++++++++++++++ docs/source/devguide/statepoint.rst | 10 ++-- 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 docs/source/devguide/particle_restart.rst diff --git a/docs/source/devguide/index.rst b/docs/source/devguide/index.rst index 03838363c..13dfc351f 100644 --- a/docs/source/devguide/index.rst +++ b/docs/source/devguide/index.rst @@ -17,5 +17,6 @@ as debugging. workflow xml-parsing statepoint + particle_restart voxel docbuild diff --git a/docs/source/devguide/particle_restart.rst b/docs/source/devguide/particle_restart.rst new file mode 100644 index 000000000..ecee81103 --- /dev/null +++ b/docs/source/devguide/particle_restart.rst @@ -0,0 +1,59 @@ +.. _devguide_particle_restart: + +============================ +Particle Restart File Format +============================ + +The current revision of the particle restart file format is 1. + +**/filetype** (*int*) + + Flags what type of file this is. A value of -1 indicates a statepoint file, + a value of -2 indicates a particle restart file, and a value of -3 indicates + a source file. + +**/revision** (*int*) + + Revision of the binary state point file. Any time a change is made in the + format of the state-point file, this integer is incremented. + +**/current_batch** (*int*) + + The number of batches already simulated. + +**/gen_per_batch** (*int*) + + Number of generations per batch. + +**/current_gen** (*int*) + + The number of generations already simulated. + +**/n_particles** (*int8_t*) + + Number of particles used per generation. + +**/run_mode** (*int*) + + Run mode used. A value of 1 indicates a fixed-source run and a value of 2 + indicates an eigenvalue run. + +**/id** (*int8_t*) + + Unique identifier of the particle. + +**/weight** (*double*) + + Weight of the particle. + +**/energy** (*double*) + + Energy of the particle in MeV. + +**/xyz** (*double[3]*) + + Position of the particle. + +**/uvw** (*double[3]*) + + Direction of the particle. diff --git a/docs/source/devguide/statepoint.rst b/docs/source/devguide/statepoint.rst index 7b0862056..de86c2254 100644 --- a/docs/source/devguide/statepoint.rst +++ b/docs/source/devguide/statepoint.rst @@ -1,10 +1,10 @@ .. _devguide_statepoint: -====================================== -State Point Binary File Specifications -====================================== +======================= +State Point File Format +======================= -The current revision of the statepoint binary file is 13. +The current revision of the statepoint file format is 13. **/filetype** (*int*) @@ -64,7 +64,7 @@ if (run_mode == MODE_EIGENVALUE) Number of inactive batches. - **gen_per_batch** (*int*) + **/gen_per_batch** (*int*) Number of generations per batch. From 1d774235aa3c610a65b07023b389056d1e6471d2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 13 Sep 2015 11:29:18 +0700 Subject: [PATCH 25/95] Add documentation on track file format. --- docs/source/devguide/index.rst | 1 + docs/source/devguide/particle_restart.rst | 8 +++--- docs/source/devguide/statepoint.rst | 8 +++--- docs/source/devguide/track.rst | 32 +++++++++++++++++++++++ src/constants.F90 | 4 ++- src/track_output.F90 | 2 ++ 6 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 docs/source/devguide/track.rst diff --git a/docs/source/devguide/index.rst b/docs/source/devguide/index.rst index 13dfc351f..3f87ecfad 100644 --- a/docs/source/devguide/index.rst +++ b/docs/source/devguide/index.rst @@ -18,5 +18,6 @@ as debugging. xml-parsing statepoint particle_restart + track voxel docbuild diff --git a/docs/source/devguide/particle_restart.rst b/docs/source/devguide/particle_restart.rst index ecee81103..bf6965558 100644 --- a/docs/source/devguide/particle_restart.rst +++ b/docs/source/devguide/particle_restart.rst @@ -9,13 +9,13 @@ The current revision of the particle restart file format is 1. **/filetype** (*int*) Flags what type of file this is. A value of -1 indicates a statepoint file, - a value of -2 indicates a particle restart file, and a value of -3 indicates - a source file. + a value of -2 indicates a particle restart file, a value of -3 indicates a + source file, and a value of -4 indicates a track file. **/revision** (*int*) - Revision of the binary state point file. Any time a change is made in the - format of the state-point file, this integer is incremented. + Revision of the particle restart file format. Any time a change is made in + the format, this integer is incremented. **/current_batch** (*int*) diff --git a/docs/source/devguide/statepoint.rst b/docs/source/devguide/statepoint.rst index de86c2254..82686ff67 100644 --- a/docs/source/devguide/statepoint.rst +++ b/docs/source/devguide/statepoint.rst @@ -9,13 +9,13 @@ The current revision of the statepoint file format is 13. **/filetype** (*int*) Flags what type of file this is. A value of -1 indicates a statepoint file, - a value of -2 indicates a particle restart file, and a value of -3 indicates - a source file. + a value of -2 indicates a particle restart file, a value of -3 indicates a + source file, and a value of -4 indicates a track file. **/revision** (*int*) - Revision of the binary state point file. Any time a change is made in the - format of the state-point file, this integer is incremented. + Revision of the state point file format. Any time a change is made in the + format, this integer is incremented. **/version_major** (*int*) diff --git a/docs/source/devguide/track.rst b/docs/source/devguide/track.rst new file mode 100644 index 000000000..afa27adfd --- /dev/null +++ b/docs/source/devguide/track.rst @@ -0,0 +1,32 @@ +.. _devguide_track: + +================= +Track File Format +================= + +The current revision of the particle track file format is 1. + +**/filetype** (*int*) + + Flags what type of file this is. A value of -1 indicates a statepoint file, + a value of -2 indicates a particle restart file, a value of -3 indicates a + source file, and a value of -4 indicates a track file. + +**/revision** (*int*) + + Revision of the track file format. Any time a change is made in the format, + this integer is incremented. + +**/n_particles** (*int*) + + Number of particles for which tracks are recorded. + +**/n_coords** (*int[]*) + + Number of coordinates for each particle. + +*do i = 1, n_particles* + + **/coordinates_i** (*double[][3]*) + + (x,y,z) coordinates for the *i*-th particle. diff --git a/src/constants.F90 b/src/constants.F90 index 38bedf022..9a89542af 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -13,12 +13,14 @@ module constants ! Revision numbers for binary files integer, parameter :: REVISION_STATEPOINT = 13 integer, parameter :: REVISION_PARTICLE_RESTART = 1 + integer, parameter :: REVISION_TRACK = 1 ! Binary file types integer, parameter :: & FILETYPE_STATEPOINT = -1, & FILETYPE_PARTICLE_RESTART = -2, & - FILETYPE_SOURCE = -3 + FILETYPE_SOURCE = -3, & + FILETYPE_TRACK = -4 ! ============================================================================ ! ADJUSTABLE PARAMETERS diff --git a/src/track_output.F90 b/src/track_output.F90 index d4b287800..f4018cde3 100644 --- a/src/track_output.F90 +++ b/src/track_output.F90 @@ -114,6 +114,8 @@ contains !$omp critical (FinalizeParticleTrack) file_id = file_create(fname) + call write_dataset(file_id, 'filetype', FILETYPE_TRACK) + call write_dataset(file_id, 'revision', REVISION_TRACK) call write_dataset(file_id, 'n_particles', n_particle_tracks) call write_dataset(file_id, 'n_coords', n_coords) do i = 1, n_particle_tracks From f13c4c7218103e7d7be9902ae8646e3f8ad95156 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 13 Sep 2015 11:36:55 +0700 Subject: [PATCH 26/95] Add source file format in documentation. --- docs/source/devguide/index.rst | 1 + docs/source/devguide/source.rst | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 docs/source/devguide/source.rst diff --git a/docs/source/devguide/index.rst b/docs/source/devguide/index.rst index 3f87ecfad..02015cfb4 100644 --- a/docs/source/devguide/index.rst +++ b/docs/source/devguide/index.rst @@ -17,6 +17,7 @@ as debugging. workflow xml-parsing statepoint + source particle_restart track voxel diff --git a/docs/source/devguide/source.rst b/docs/source/devguide/source.rst new file mode 100644 index 000000000..20457fb11 --- /dev/null +++ b/docs/source/devguide/source.rst @@ -0,0 +1,21 @@ +.. _devguide_source: + +================== +Source File Format +================== + +Normally, source data is stored in a state point file. However, it is possible +to request that the source be written separately, in which case the format used +is that documented here. + +**/filetype** (*int*) + + Flags what type of file this is. A value of -1 indicates a statepoint file, + a value of -2 indicates a particle restart file, a value of -3 indicates a + source file, and a value of -4 indicates a track file. + +**/source_bank** (Compound type) + + Source bank information for each particle. The compound type has fields + ``wgt``, ``xyz``, ``uvw``, and ``E`` which represent the weight, position, + direction, and energy of the source particle, respectively. From c2e8144a5672c4e1a7a1a7ac4f8906356ca071d1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 13 Sep 2015 12:08:00 +0700 Subject: [PATCH 27/95] Move output file formats to user's guide. --- docs/source/devguide/index.rst | 4 ---- docs/source/usersguide/index.rst | 3 ++- docs/source/usersguide/output/index.rst | 14 ++++++++++++++ .../output}/particle_restart.rst | 2 +- .../{devguide => usersguide/output}/source.rst | 2 +- .../{devguide => usersguide/output}/statepoint.rst | 2 +- .../{devguide => usersguide/output}/track.rst | 2 +- docs/source/usersguide/processing.rst | 2 +- 8 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 docs/source/usersguide/output/index.rst rename docs/source/{devguide => usersguide/output}/particle_restart.rst (97%) rename docs/source/{devguide => usersguide/output}/source.rst (96%) rename docs/source/{devguide => usersguide/output}/statepoint.rst (99%) rename docs/source/{devguide => usersguide/output}/track.rst (97%) diff --git a/docs/source/devguide/index.rst b/docs/source/devguide/index.rst index 02015cfb4..e73d8ba70 100644 --- a/docs/source/devguide/index.rst +++ b/docs/source/devguide/index.rst @@ -16,9 +16,5 @@ as debugging. styleguide workflow xml-parsing - statepoint - source - particle_restart - track voxel docbuild diff --git a/docs/source/usersguide/index.rst b/docs/source/usersguide/index.rst index 675ed4081..5a7e7addf 100644 --- a/docs/source/usersguide/index.rst +++ b/docs/source/usersguide/index.rst @@ -5,7 +5,7 @@ User's Guide ============ Welcome to the OpenMC User's Guide! This tutorial will guide you through the -essential aspects of using OpenMC to perform neutronic simulations. +essential aspects of using OpenMC to perform simulations. .. toctree:: :numbered: @@ -14,5 +14,6 @@ essential aspects of using OpenMC to perform neutronic simulations. beginners install input + output/index processing troubleshoot diff --git a/docs/source/usersguide/output/index.rst b/docs/source/usersguide/output/index.rst new file mode 100644 index 000000000..1eb85e9d5 --- /dev/null +++ b/docs/source/usersguide/output/index.rst @@ -0,0 +1,14 @@ +.. _usersguide_output: + +=================== +Output File Formats +=================== + +.. toctree:: + :numbered: + :maxdepth: 3 + + statepoint + source + particle_restart + track diff --git a/docs/source/devguide/particle_restart.rst b/docs/source/usersguide/output/particle_restart.rst similarity index 97% rename from docs/source/devguide/particle_restart.rst rename to docs/source/usersguide/output/particle_restart.rst index bf6965558..12ab3237f 100644 --- a/docs/source/devguide/particle_restart.rst +++ b/docs/source/usersguide/output/particle_restart.rst @@ -1,4 +1,4 @@ -.. _devguide_particle_restart: +.. _usersguide_particle_restart: ============================ Particle Restart File Format diff --git a/docs/source/devguide/source.rst b/docs/source/usersguide/output/source.rst similarity index 96% rename from docs/source/devguide/source.rst rename to docs/source/usersguide/output/source.rst index 20457fb11..cc8e71a67 100644 --- a/docs/source/devguide/source.rst +++ b/docs/source/usersguide/output/source.rst @@ -1,4 +1,4 @@ -.. _devguide_source: +.. _usersguide_source: ================== Source File Format diff --git a/docs/source/devguide/statepoint.rst b/docs/source/usersguide/output/statepoint.rst similarity index 99% rename from docs/source/devguide/statepoint.rst rename to docs/source/usersguide/output/statepoint.rst index 82686ff67..b17bdca02 100644 --- a/docs/source/devguide/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -1,4 +1,4 @@ -.. _devguide_statepoint: +.. _usersguide_statepoint: ======================= State Point File Format diff --git a/docs/source/devguide/track.rst b/docs/source/usersguide/output/track.rst similarity index 97% rename from docs/source/devguide/track.rst rename to docs/source/usersguide/output/track.rst index afa27adfd..9a85ac7ea 100644 --- a/docs/source/devguide/track.rst +++ b/docs/source/usersguide/output/track.rst @@ -1,4 +1,4 @@ -.. _devguide_track: +.. _usersguide_track: ================= Track File Format diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst index e773cf156..a6e9875ce 100644 --- a/docs/source/usersguide/processing.rst +++ b/docs/source/usersguide/processing.rst @@ -194,7 +194,7 @@ Data Extraction --------------- A great deal of information is available in statepoint files (See -:ref:`devguide_statepoint`), most of which is easily extracted by the provided +:ref:`usersguide_statepoint`), most of which is easily extracted by the provided utility statepoint.py. This utility provides a Python class to load statepoints and extract data - it is used in many of the provided plotting utilities, and can be used in user-created scripts to carry out manipulations of the data. To From b1f4597e2361baf6c8eac2085b26ad00418e0096 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 13 Sep 2015 12:08:18 +0700 Subject: [PATCH 28/95] unset a few variables in FindHDF5.cmake --- cmake/Modules/FindHDF5.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/Modules/FindHDF5.cmake b/cmake/Modules/FindHDF5.cmake index 08ba0abaf..287e10e5b 100644 --- a/cmake/Modules/FindHDF5.cmake +++ b/cmake/Modules/FindHDF5.cmake @@ -136,6 +136,10 @@ find_program( HDF5_Fortran_COMPILER_EXECUTABLE DOC "HDF5 Fortran Wrapper compiler. Used only to detect HDF5 compile flags." ) mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE ) +unset(HDF5_C_COMPILER_NAMES) +unset(HDF5_CXX_COMPILER_NAMES) +unset(HDF5_Fortran_COMPILER_NAMES) + find_program( HDF5_DIFF_EXECUTABLE NAMES h5diff HINTS ENV HDF5_ROOT From 590df6e62d44fef5523b9707d7c8b3c5d157e5da Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 13 Sep 2015 12:20:58 +0700 Subject: [PATCH 29/95] Check that HDF5 groups are closed successfully. --- src/hdf5_interface.F90 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index f4771d848..5e0734648 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -236,6 +236,9 @@ contains integer :: hdf5_err ! HDF5 error code call h5gclose_f(group_id, hdf5_err) + if (hdf5_err < 0) then + call fatal_error("Unable to close HDF5 group.") + end if end subroutine close_group !=============================================================================== From 13113ca82000fa6ad86b5980424dc9e4d28e5f39 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 14 Sep 2015 10:48:19 +0700 Subject: [PATCH 30/95] Fixes in FindHDF5.cmake for Intel Xeon Phi. Before, -lz -ldl -lm -lrt would be turned into absolute paths. This doesn't work for the Xeon Phi where we need to cross-compile. The Intel compiler automatically adds the libraries with the correct architecture as long as -l arguments are passed as is. --- cmake/Modules/FindHDF5.cmake | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cmake/Modules/FindHDF5.cmake b/cmake/Modules/FindHDF5.cmake index 287e10e5b..7492ea750 100644 --- a/cmake/Modules/FindHDF5.cmake +++ b/cmake/Modules/FindHDF5.cmake @@ -292,12 +292,8 @@ if( NOT HDF5_FOUND ) mark_as_advanced( HDF5_${LANGUAGE}_INCLUDE_DIR ) list( APPEND HDF5_INCLUDE_DIRS ${HDF5_${LANGUAGE}_INCLUDE_DIR} ) - set( HDF5_${LANGUAGE}_LIBRARY_NAMES - ${HDF5_${LANGUAGE}_LIBRARY_NAMES_INIT} - ${HDF5_${LANGUAGE}_LIBRARY_NAMES} ) - # find the HDF5 libraries - foreach( LIB ${HDF5_${LANGUAGE}_LIBRARY_NAMES} ) + foreach( LIB ${HDF5_${LANGUAGE}_LIBRARY_NAMES_INIT} ) if( UNIX AND HDF5_USE_STATIC_LIBRARIES ) # According to bug 1643 on the CMake bug tracker, this is the # preferred method for searching for a static library. @@ -325,6 +321,14 @@ if( NOT HDF5_FOUND ) endforeach() list( APPEND HDF5_LIBRARY_DIRS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} ) + # When the wrapper lists a library with -l, e.g. -lz, simply use it as + # is. If find_library is called for these libraries, you end up with + # local libraries that will not be suitable when cross-compiling for the + # Intel Xeon Phi. + foreach(LIBNAME ${HDF5_${LANGUAGE}_LIBRARY_NAMES}) + list(APPEND HDF5_${LANGUAGE}_LIBRARIES "-l${LIBNAME}") + endforeach() + # Append the libraries for this language binding to the list of all # required libraries. list(APPEND HDF5_LIBRARIES ${HDF5_${LANGUAGE}_LIBRARIES}) From 6242b80c106a6db418486bf993a2dc10731b86ae Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 14 Sep 2015 15:32:49 +0700 Subject: [PATCH 31/95] Add installation instructions for the Xeon Phi. --- docs/source/quickinstall.rst | 2 +- docs/source/usersguide/install.rst | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index 31ca71ffc..9ce752be7 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -35,7 +35,7 @@ Installing from Source on Linux or Mac OS X ------------------------------------------- All OpenMC source code is hosted on GitHub_. If you have git_, the gfortran_ -compiler, CMake_, and HDF_ installed, you can download and install OpenMC be +compiler, CMake_, and HDF5_ installed, you can download and install OpenMC be entering the following commands in a terminal: .. code-block:: sh diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 7b8c6e3d4..dcf990bda 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -318,6 +318,25 @@ This will build an executable named ``openmc``. .. _MinGW: http://www.mingw.org .. _SourceForge: http://sourceforge.net/projects/mingw +Compiling for the Intel Xeon Phi +-------------------------------- + +In order to build OpenMC for the Intel Xeon Phi using the Intel Fortran +compiler, it is necessary to specify that all objects be compiled with the +``-mmic`` flag as follows: + +.. code-block:: sh + + mkdir build && cd build + FC=ifort FFLAGS=-mmic cmake -Dopenmp=on .. + make + +Note that unless an HDF5 build for the Intel Xeon Phi is already on your target +machine, you will need to cross-compile HDF5 for the Xeon Phi. An `example +script`_ to build zlib and HDF5 provides several necessary workarounds. + +.. _example script: https://github.com/paulromano/install-scripts/blob/master/install-hdf5-mic + Testing Build ------------- From f1b4e0ae7f2a806a4381dde286f44bd1765208a8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 14 Sep 2015 16:47:00 +0700 Subject: [PATCH 32/95] Avoid bug with PGI Fortran compiler. Apparently the PGI Fortran compiler (15.7) doesn't like variable names that are the same as module names. --- src/initialize.F90 | 36 ++++++++++++++++++------------------ src/state_point.F90 | 38 +++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/initialize.F90 b/src/initialize.F90 index bd479032f..48985a718 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -930,7 +930,7 @@ contains integer :: i, j ! Tally, filter loop counters integer :: n_filt ! Number of filters originally in tally logical :: count_all ! Count all cells - type(TallyObject), pointer :: tally ! Current tally + type(TallyObject), pointer :: t ! Current tally type(Universe), pointer :: univ ! Pointer to universe type(Cell), pointer :: c ! Pointer to cell integer, allocatable :: univ_list(:) ! Target offsets @@ -943,18 +943,18 @@ contains do i = 1, n_tallies ! Get pointer to tally - tally => tallies(i) + t => tallies(i) - n_filt = tally%n_filters + n_filt = t%n_filters ! Loop over the filters to determine how many additional filters ! need to be added to this tally - do j = 1, tally%n_filters + do j = 1, t%n_filters ! Determine type of filter - if (tally%filters(j)%type == FILTER_DISTRIBCELL) then + if (t%filters(j)%type == FILTER_DISTRIBCELL) then count_all = .true. - if (size(tally%filters(j)%int_bins) > 1) then + if (size(t%filters(j)%int_bins) > 1) then call fatal_error("A distribcell filter was specified with & &multiple bins. This feature is not supported.") end if @@ -975,15 +975,15 @@ contains do i = 1, n_tallies ! Get pointer to tally - tally => tallies(i) + t => tallies(i) ! Initialize the filters - do j = 1, tally%n_filters + do j = 1, t%n_filters ! Set the number of bins to the number of instances of the cell - if (tally%filters(j)%type == FILTER_DISTRIBCELL) then - c => cells(tally%filters(j)%int_bins(1)) - tally%filters(j)%n_bins = c%instances + if (t%filters(j)%type == FILTER_DISTRIBCELL) then + c => cells(t%filters(j)%int_bins(1)) + t%filters(j)%n_bins = c%instances end if end do @@ -1024,7 +1024,7 @@ contains type(SetInt) :: cell_list ! distribells to track type(Universe), pointer :: univ ! pointer to universe class(Lattice), pointer :: lat ! pointer to lattice - type(TallyObject), pointer :: tally ! pointer to tally + type(TallyObject), pointer :: t ! pointer to tally type(TallyFilter), pointer :: filter ! pointer to filter ! Begin gathering list of cells in distribcell tallies @@ -1032,10 +1032,10 @@ contains ! Populate list of distribcells to track do i = 1, n_tallies - tally => tallies(i) + t => tallies(i) - do j = 1, tally%n_filters - filter => tally%filters(j) + do j = 1, t%n_filters + filter => t%filters(j) if (filter%type == FILTER_DISTRIBCELL) then if (.not. cell_list%contains(filter%int_bins(1))) then @@ -1079,10 +1079,10 @@ contains ! Loop over all tallies do l = 1, n_tallies - tally => tallies(l) + t => tallies(l) - do m = 1, tally%n_filters - filter => tally%filters(m) + do m = 1, t%n_filters + filter => t%filters(m) ! Loop over only distribcell filters ! If filter points to cell we just found, set offset index diff --git a/src/state_point.F90 b/src/state_point.F90 index 7688d5d33..691d0567e 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -52,7 +52,7 @@ contains integer(HID_T) :: filter_group, moments_group character(8) :: moment_name ! name of moment (e.g, P3) character(MAX_FILE_LEN) :: filename - type(StructuredMesh), pointer :: mesh + type(StructuredMesh), pointer :: meshp type(TallyObject), pointer :: tally type(ElemKeyValueII), pointer :: current type(ElemKeyValueII), pointer :: next @@ -166,16 +166,16 @@ contains ! Write information for meshes MESH_LOOP: do i = 1, n_meshes - mesh => meshes(id_array(i)) - mesh_group = create_group(meshes_group, "mesh " // trim(to_str(mesh%id))) + meshp => meshes(id_array(i)) + mesh_group = create_group(meshes_group, "mesh " // trim(to_str(meshp%id))) - call write_dataset(mesh_group, "id", mesh%id) - call write_dataset(mesh_group, "type", mesh%type) - call write_dataset(mesh_group, "n_dimension", mesh%n_dimension) - call write_dataset(mesh_group, "dimension", mesh%dimension) - call write_dataset(mesh_group, "lower_left", mesh%lower_left) - call write_dataset(mesh_group, "upper_right", mesh%upper_right) - call write_dataset(mesh_group, "width", mesh%width) + call write_dataset(mesh_group, "id", meshp%id) + call write_dataset(mesh_group, "type", meshp%type) + call write_dataset(mesh_group, "n_dimension", meshp%n_dimension) + 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) call close_group(mesh_group) end do MESH_LOOP @@ -600,7 +600,7 @@ contains character(MAX_FILE_LEN) :: path_temp character(19) :: current_time character(8) :: moment_name ! name of moment (e.g, P3, Y-1,1) - type(StructuredMesh), pointer :: mesh + type(StructuredMesh), pointer :: meshp type(TallyObject), pointer :: tally ! Write message @@ -718,18 +718,18 @@ contains ! Read and overwrite mesh information MESH_LOOP: do i = 1, n_meshes - mesh => meshes(id_array(i)) + meshp => meshes(id_array(i)) curr_key = key_array(id_array(i)) mesh_group = open_group(meshes_group, "mesh " // & trim(to_str(curr_key))) - call read_dataset(mesh_group, "id", mesh%id) - call read_dataset(mesh_group, "type", mesh%type) - call read_dataset(mesh_group, "n_dimension", mesh%n_dimension) - call read_dataset(mesh_group, "dimension", mesh%dimension) - call read_dataset(mesh_group, "lower_left", mesh%lower_left) - call read_dataset(mesh_group, "upper_right", mesh%upper_right) - call read_dataset(mesh_group, "width", mesh%width) + call read_dataset(mesh_group, "id", meshp%id) + call read_dataset(mesh_group, "type", meshp%type) + call read_dataset(mesh_group, "n_dimension", meshp%n_dimension) + call read_dataset(mesh_group, "dimension", meshp%dimension) + call read_dataset(mesh_group, "lower_left", meshp%lower_left) + call read_dataset(mesh_group, "upper_right", meshp%upper_right) + call read_dataset(mesh_group, "width", meshp%width) call close_group(mesh_group) end do MESH_LOOP From 63a378bd93fb10f343e21062bad3f4c4cc63d72c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 14 Sep 2015 20:36:51 +0700 Subject: [PATCH 33/95] Make sure -L flags from HDF5 wrapper are passed --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 76c099d52..36501c918 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -262,6 +262,11 @@ else() target_compile_options(${program} PUBLIC ${f90flags}) endif() +# Add HDF5 library directories to link line with -L +foreach(LIBDIR ${HDF5_LIBRARY_DIRS}) + list(APPEND ldflags "-L${LIBDIR}") +endforeach() + # target_link_libraries treats any arguments starting with - but not -l as # linker flags. Thus, we can pass both linker flags and libraries together. target_link_libraries(${program} ${ldflags} ${HDF5_LIBRARIES} fox_dom) From 61ed62b8cf7a560fa5e196341372744f2e47eb3a Mon Sep 17 00:00:00 2001 From: Will Boyd Date: Mon, 14 Sep 2015 17:47:52 -0400 Subject: [PATCH 34/95] Hotfix for Python summary API resulting from changes made in f8bfa401cb42cd034084cb09e6edf98e3e3749f2 --- openmc/summary.py | 81 ++++++++++++++++++++++++----------------------- src/summary.F90 | 2 +- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/openmc/summary.py b/openmc/summary.py index 7f9d5387e..60041ce82 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -31,18 +31,18 @@ class Summary(object): def _read_metadata(self): # Read OpenMC version - self.version = [self._f['version_major'][0], - self._f['version_minor'][0], - self._f['version_release'][0]] + self.version = [self._f['version_major'].value, + self._f['version_minor'].value, + self._f['version_release'].value] # Read date and time self.date_and_time = self._f['date_and_time'][...] - self.n_batches = self._f['n_batches'][0] - self.n_particles = self._f['n_particles'][0] - self.n_active = self._f['n_active'][0] - self.n_inactive = self._f['n_inactive'][0] - self.gen_per_batch = self._f['gen_per_batch'][0] - self.n_procs = self._f['n_procs'][0] + self.n_batches = self._f['n_batches'].value + self.n_particles = self._f['n_particles'].value + self.n_active = self._f['n_active'].value + self.n_inactive = self._f['n_inactive'].value + self.gen_per_batch = self._f['gen_per_batch'].value + self.n_procs = self._f['n_procs'].value def _read_geometry(self): # Read in and initialize the Materials and Geometry @@ -55,7 +55,7 @@ class Summary(object): self._finalize_geometry() def _read_nuclides(self): - self.n_nuclides = self._f['nuclides/n_nuclides'][0] + self.n_nuclides = self._f['nuclides/n_nuclides'] # Initialize dictionary for each Nuclide # Keys - Nuclide ZAIDs @@ -66,9 +66,9 @@ class Summary(object): if key == 'n_nuclides': continue - index = self._f['nuclides'][key]['index'][0] + index = self._f['nuclides'][key]['index'].value alias = self._f['nuclides'][key]['alias'][0] - zaid = self._f['nuclides'][key]['zaid'][0] + zaid = self._f['nuclides'][key]['zaid'].value # Read the Nuclide's name (e.g., 'H-1' or 'U-235') name = alias.split('.')[0] @@ -84,7 +84,7 @@ class Summary(object): self.nuclides[zaid].zaid = zaid def _read_materials(self): - self.n_materials = self._f['materials/n_materials'][0] + self.n_materials = self._f['n_materials'].value # Initialize dictionary for each Material # Keys - Material keys @@ -96,19 +96,20 @@ class Summary(object): continue material_id = int(key.lstrip('material ')) - index = self._f['materials'][key]['index'][0] + index = self._f['materials'][key]['index'].value name = self._f['materials'][key]['name'][0] - density = self._f['materials'][key]['atom_density'][0] + density = self._f['materials'][key]['atom_density'].value nuc_densities = self._f['materials'][key]['nuclide_densities'][...] nuclides = self._f['materials'][key]['nuclides'][...] - n_sab = self._f['materials'][key]['n_sab'][0] + n_sab = self._f['materials'][key]['n_sab'].value sab_names = [] sab_xs = [] # Read the names of the S(a,b) tables for this Material for i in range(1, n_sab+1): - sab_table = self._f['materials'][key]['sab_tables'][str(i)][0] + sab_table = \ + self._f['materials'][key]['sab_tables'][str(i)].value # Read the cross-section identifiers for each S(a,b) table sab_names.append(sab_table.split('.')[0]) @@ -140,7 +141,7 @@ class Summary(object): self.materials[index] = material def _read_surfaces(self): - self.n_surfaces = self._f['geometry/n_surfaces'][0] + self.n_surfaces = self._f['geometry/n_surfaces'].value # Initialize dictionary for each Surface # Keys - Surface keys @@ -152,9 +153,9 @@ class Summary(object): continue surface_id = int(key.lstrip('surface ')) - index = self._f['geometry/surfaces'][key]['index'][0] + index = self._f['geometry/surfaces'][key]['index'].value name = self._f['geometry/surfaces'][key]['name'][0] - surf_type = self._f['geometry/surfaces'][key]['type'][...][0] + surf_type = self._f['geometry/surfaces'][key]['type'][...] bc = self._f['geometry/surfaces'][key]['boundary_condition'][...][0] coeffs = self._f['geometry/surfaces'][key]['coefficients'][...] @@ -220,7 +221,7 @@ class Summary(object): self.surfaces[index] = surface def _read_cells(self): - self.n_cells = self._f['geometry/n_cells'][0] + self.n_cells = self._f['geometry/n_cells'].value # Initialize dictionary for each Cell # Keys - Cell keys @@ -240,16 +241,16 @@ class Summary(object): continue cell_id = int(key.lstrip('cell ')) - index = self._f['geometry/cells'][key]['index'][0] + index = self._f['geometry/cells'][key]['index'].value name = self._f['geometry/cells'][key]['name'][0] fill_type = self._f['geometry/cells'][key]['fill_type'][...][0] if fill_type == 'normal': - fill = self._f['geometry/cells'][key]['material'][0] + fill = self._f['geometry/cells'][key]['material'].value elif fill_type == 'universe': - fill = self._f['geometry/cells'][key]['fill'][0] + fill = self._f['geometry/cells'][key]['fill'].value else: - fill = self._f['geometry/cells'][key]['lattice'][0] + fill = self._f['geometry/cells'][key]['lattice'].value if 'surfaces' in self._f['geometry/cells'][key].keys(): surfaces = self._f['geometry/cells'][key]['surfaces'][...] @@ -264,7 +265,7 @@ class Summary(object): if maps > 0: offset = self._f['geometry/cells'][key]['offset'][...] - cell.set_offset(offset) + cell.offsets = offset translated = self._f['geometry/cells'][key]['translated'][0] if translated: @@ -295,7 +296,7 @@ class Summary(object): self.cells[index] = cell def _read_universes(self): - self.n_universes = self._f['geometry/n_universes'][0] + self.n_universes = self._f['geometry/n_universes'].value # Initialize dictionary for each Universe # Keys - Universe keys @@ -307,7 +308,7 @@ class Summary(object): continue universe_id = int(key.lstrip('universe ')) - index = self._f['geometry/universes'][key]['index'][0] + index = self._f['geometry/universes'][key]['index'].value cells = self._f['geometry/universes'][key]['cells'][...] # Create this Universe @@ -322,7 +323,7 @@ class Summary(object): self.universes[index] = universe def _read_lattices(self): - self.n_lattices = self._f['geometry/n_lattices'][0] + self.n_lattices = self._f['geometry/n_lattices'].value # Initialize lattices for each Lattice # Keys - Lattice keys @@ -334,11 +335,11 @@ class Summary(object): continue lattice_id = int(key.lstrip('lattice ')) - index = self._f['geometry/lattices'][key]['index'][0] - name = self._f['geometry/lattices'][key]['name'][0] + index = self._f['geometry/lattices'][key]['index'].value + name = self._f['geometry/lattices'][key]['name'][...][0] lattice_type = self._f['geometry/lattices'][key]['type'][...][0] - maps = self._f['geometry/lattices'][key]['maps'][0] - offset_size = self._f['geometry/lattices'][key]['offset_size'][0] + maps = self._f['geometry/lattices'][key]['maps'].value + offset_size = self._f['geometry/lattices'][key]['offset_size'].value if offset_size > 0: offsets = self._f['geometry/lattices'][key]['offsets'][...] @@ -348,7 +349,7 @@ class Summary(object): lower_left = \ self._f['geometry/lattices'][key]['lower_left'][...] pitch = self._f['geometry/lattices'][key]['pitch'][...] - outer = self._f['geometry/lattices'][key]['outer'][0] + outer = self._f['geometry/lattices'][key]['outer'].value universe_ids = \ self._f['geometry/lattices'][key]['universes'][...] @@ -521,7 +522,7 @@ class Summary(object): self.n_tallies = 0 return - self.n_tallies = self._f['tallies/n_tallies'][0] + self.n_tallies = self._f['tallies/n_tallies'].value # OpenMC Tally keys all_keys = self._f['tallies/'].keys() @@ -536,9 +537,9 @@ class Summary(object): subbase = '{0}{1}'.format(base, tally_id) # Read Tally name metadata - name_size = self._f['{0}/name_size'.format(subbase)][0] + name_size = self._f['{0}/name_size'.format(subbase)][...] if (name_size > 0): - tally_name = self._f['{0}/name'.format(subbase)][0] + tally_name = self._f['{0}/name'.format(subbase)][...][0] tally_name = tally_name.lstrip('[\'') tally_name = tally_name.rstrip('\']') else: @@ -555,7 +556,7 @@ class Summary(object): tally.num_score_bins = num_score_bins # Read filter metadata - num_filters = self._f['{0}/n_filters'.format(subbase)][0] + num_filters = self._f['{0}/n_filters'.format(subbase)].value # Initialize all Filters for j in range(1, num_filters+1): @@ -563,11 +564,11 @@ class Summary(object): subsubbase = '{0}/filter {1}'.format(subbase, j) # Read filter type (e.g., "cell", "energy", etc.) - filter_type_code = self._f['{0}/type'.format(subsubbase)][0] + filter_type_code = self._f['{0}/type'.format(subsubbase)].value filter_type = openmc.FILTER_TYPES[filter_type_code] # Read the filter bins - num_bins = self._f['{0}/n_bins'.format(subsubbase)][0] + num_bins = self._f['{0}/n_bins'.format(subsubbase)].value bins = self._f['{0}/bins'.format(subsubbase)][...] # Create Filter object diff --git a/src/summary.F90 b/src/summary.F90 index cc9a909c8..0147230a0 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -191,7 +191,7 @@ contains ! WRITE INFORMATION ON SURFACES ! Create surfaces group - surfaces_group = create_group(file_id, "surfaces") + surfaces_group = create_group(geom_group, "surfaces") ! Write information on each surface SURFACE_LOOP: do i = 1, n_surfaces From ba659b3f0cd1634e54362fc2c672d410ea239d31 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 14 Sep 2015 20:45:21 -0400 Subject: [PATCH 35/95] Fix PyAPI filter for numpy isinstance bug --- openmc/filter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 5a8190676..b9b6df36b 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -7,7 +7,7 @@ import numpy as np from openmc import Mesh from openmc.constants import * from openmc.checkvalue import check_type, check_iterable_type, \ - check_greater_than + check_greater_than, _isinstance class Filter(object): """A filter used to constrain a tally to a specific criterion, e.g. only tally @@ -126,7 +126,7 @@ class Filter(object): raise ValueError(msg) # If the bin edge is a single value, it is a Cell, Material, etc. ID - if not isinstance(bins, Iterable): + if not _isinstance(bins, Iterable): bins = [bins] # If the bins are in a collection, convert it to a list @@ -141,7 +141,7 @@ class Filter(object): elif self._type in ['energy', 'energyout']: for edge in bins: - if not isinstance(edge, Real): + if not _isinstance(edge, Real): msg = 'Unable to add bin edge "{0}" to a "{1}" Filter ' \ 'since it is a non-integer or floating point ' \ 'value'.format(edge, self.type) @@ -165,7 +165,7 @@ class Filter(object): msg = 'Unable to add bins "{0}" to a mesh Filter since ' \ 'only a single mesh can be used per tally'.format(bins) raise ValueError(msg) - elif not isinstance(bins[0], Integral): + elif not _isinstance(bins[0], Integral): msg = 'Unable to add bin "{0}" to mesh Filter since it ' \ 'is a non-integer'.format(bins[0]) raise ValueError(msg) From b9379e3c8667d062ec6511ad07f2525ea0b2f5ef Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 14 Sep 2015 21:05:58 -0400 Subject: [PATCH 36/95] Make test cleanup source file --- .../test_statepoint_sourcesep/test_statepoint_sourcesep.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py b/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py index acbb0180b..157210de6 100644 --- a/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py +++ b/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py @@ -15,6 +15,13 @@ class SourcepointTestHarness(TestHarness): assert source[0].endswith('h5'), \ 'Source file is not a HDF5 file.' + def _cleanup(self): + TestHarness._cleanup(self) + output = glob.glob(os.path.join(os.getcwd(), 'source.*')) + for f in output: + if os.path.exists(f): + os.remove(f) + if __name__ == '__main__': harness = SourcepointTestHarness('statepoint.10.*') From fb518a4d7ce663f371723a1d470908ad98b7cd03 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 14 Sep 2015 21:42:25 -0400 Subject: [PATCH 37/95] Make os and glob imports explicit --- tests/test_entropy/test_entropy.py | 3 +++ tests/test_filter_distribcell/test_filter_distribcell.py | 2 ++ tests/test_fixed_source/test_fixed_source.py | 3 +++ tests/test_output/test_output.py | 3 +++ tests/test_source_file/test_source_file.py | 3 +++ tests/test_sourcepoint_batch/test_sourcepoint_batch.py | 3 +++ tests/test_sourcepoint_interval/test_sourcepoint_interval.py | 3 +++ tests/test_sourcepoint_latest/test_sourcepoint_latest.py | 3 +++ tests/test_statepoint_restart/test_statepoint_restart.py | 3 +++ tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py | 3 +++ tests/test_track_output/test_track_output.py | 2 ++ 11 files changed, 31 insertions(+) diff --git a/tests/test_entropy/test_entropy.py b/tests/test_entropy/test_entropy.py index 4657101ad..9b13fd3dd 100644 --- a/tests/test_entropy/test_entropy.py +++ b/tests/test_entropy/test_entropy.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_filter_distribcell/test_filter_distribcell.py b/tests/test_filter_distribcell/test_filter_distribcell.py index 8370e40e7..541d6b6af 100644 --- a/tests/test_filter_distribcell/test_filter_distribcell.py +++ b/tests/test_filter_distribcell/test_filter_distribcell.py @@ -1,6 +1,8 @@ #!/usr/bin/env python +import glob import hashlib +import os import sys sys.path.insert(0, '..') diff --git a/tests/test_fixed_source/test_fixed_source.py b/tests/test_fixed_source/test_fixed_source.py index e96a3ad8f..1f154a465 100644 --- a/tests/test_fixed_source/test_fixed_source.py +++ b/tests/test_fixed_source/test_fixed_source.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_output/test_output.py b/tests/test_output/test_output.py index 0225d9fed..b37b7d07b 100644 --- a/tests/test_output/test_output.py +++ b/tests/test_output/test_output.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_source_file/test_source_file.py b/tests/test_source_file/test_source_file.py index d7ed8b80a..fae6b2a72 100644 --- a/tests/test_source_file/test_source_file.py +++ b/tests/test_source_file/test_source_file.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py index a90223659..521e3bb4b 100644 --- a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py +++ b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py index a90223659..521e3bb4b 100644 --- a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py +++ b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_sourcepoint_latest/test_sourcepoint_latest.py b/tests/test_sourcepoint_latest/test_sourcepoint_latest.py index 8c04641b7..7d0af89b9 100644 --- a/tests/test_sourcepoint_latest/test_sourcepoint_latest.py +++ b/tests/test_sourcepoint_latest/test_sourcepoint_latest.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_statepoint_restart/test_statepoint_restart.py b/tests/test_statepoint_restart/test_statepoint_restart.py index 0420dbddf..dd42dc8ff 100644 --- a/tests/test_statepoint_restart/test_statepoint_restart.py +++ b/tests/test_statepoint_restart/test_statepoint_restart.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py b/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py index 157210de6..c7221c90c 100644 --- a/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py +++ b/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py @@ -1,6 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys + sys.path.insert(0, '..') from testing_harness import * diff --git a/tests/test_track_output/test_track_output.py b/tests/test_track_output/test_track_output.py index 1192d1b3a..dc0eb1a69 100644 --- a/tests/test_track_output/test_track_output.py +++ b/tests/test_track_output/test_track_output.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +import glob +import os import shutil import sys From 3eee7a7301cf394f56e2ceb47e4689c07f6bfd27 Mon Sep 17 00:00:00 2001 From: Will Boyd Date: Tue, 15 Sep 2015 00:05:55 -0400 Subject: [PATCH 38/95] Hotfix for translations, rotations in Summary Python API --- openmc/summary.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/summary.py b/openmc/summary.py index 60041ce82..6fb487414 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -261,20 +261,20 @@ class Summary(object): cell = openmc.Cell(cell_id=cell_id, name=name) if fill_type == 'universe': - maps = self._f['geometry/cells'][key]['maps'][0] + maps = self._f['geometry/cells'][key]['maps'].value if maps > 0: offset = self._f['geometry/cells'][key]['offset'][...] cell.offsets = offset - translated = self._f['geometry/cells'][key]['translated'][0] + translated = self._f['geometry/cells'][key]['translated'].value if translated: translation = \ self._f['geometry/cells'][key]['translation'][...] translation = np.asarray(translation, dtype=np.float64) cell.translation = translation - rotated = self._f['geometry/cells'][key]['rotated'][0] + rotated = self._f['geometry/cells'][key]['rotated'].value if rotated: rotation = \ self._f['geometry/cells'][key]['rotation'][...] From 8b877960a7a583961ff351472216ad3528942522 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 07:10:36 +0700 Subject: [PATCH 39/95] Read/write strings in hdf5_interface as C null-terminated strings. --- openmc/statepoint.py | 10 ++--- openmc/summary.py | 18 ++++---- src/hdf5_interface.F90 | 95 +++++++++++++++++++++++------------------- 3 files changed, 66 insertions(+), 57 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 06ed51c18..986d624f9 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -170,10 +170,10 @@ class StatePoint(object): self._f['version_release'].value] # Read date and time - self._date_and_time = self._f['date_and_time'].value[0] + self._date_and_time = self._f['date_and_time'].value.decode() # Read path - self._path = self._f['path'].value[0].strip() + self._path = self._f['path'].value.decode() # Read random number seed self._seed = self._f['seed'].value @@ -398,10 +398,8 @@ class StatePoint(object): # Extract the moment order string for each score for k in range(len(scores)): - moment = str(self._f['{0}order{1}'.format( - subbase, k+1)].value[0]) - moment = moment.lstrip('[\'') - moment = moment.rstrip('\']') + moment = self._f['{0}order{1}'.format( + subbase, k+1)].value.decode() # Remove extra whitespace moment.replace(" ", "") diff --git a/openmc/summary.py b/openmc/summary.py index 6fb487414..088ff29d1 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -67,7 +67,7 @@ class Summary(object): continue index = self._f['nuclides'][key]['index'].value - alias = self._f['nuclides'][key]['alias'][0] + alias = self._f['nuclides'][key]['alias'].value.decode() zaid = self._f['nuclides'][key]['zaid'].value # Read the Nuclide's name (e.g., 'H-1' or 'U-235') @@ -97,7 +97,7 @@ class Summary(object): material_id = int(key.lstrip('material ')) index = self._f['materials'][key]['index'].value - name = self._f['materials'][key]['name'][0] + name = self._f['materials'][key]['name'].value.decode() density = self._f['materials'][key]['atom_density'].value nuc_densities = self._f['materials'][key]['nuclide_densities'][...] nuclides = self._f['materials'][key]['nuclides'][...] @@ -154,9 +154,9 @@ class Summary(object): surface_id = int(key.lstrip('surface ')) index = self._f['geometry/surfaces'][key]['index'].value - name = self._f['geometry/surfaces'][key]['name'][0] - surf_type = self._f['geometry/surfaces'][key]['type'][...] - bc = self._f['geometry/surfaces'][key]['boundary_condition'][...][0] + name = self._f['geometry/surfaces'][key]['name'].value.decode() + surf_type = self._f['geometry/surfaces'][key]['type'].value.decode() + bc = self._f['geometry/surfaces'][key]['boundary_condition'].value.decode() coeffs = self._f['geometry/surfaces'][key]['coefficients'][...] # Create the Surface based on its type @@ -242,8 +242,8 @@ class Summary(object): cell_id = int(key.lstrip('cell ')) index = self._f['geometry/cells'][key]['index'].value - name = self._f['geometry/cells'][key]['name'][0] - fill_type = self._f['geometry/cells'][key]['fill_type'][...][0] + name = self._f['geometry/cells'][key]['name'].value.decode() + fill_type = self._f['geometry/cells'][key]['fill_type'].value.decode() if fill_type == 'normal': fill = self._f['geometry/cells'][key]['material'].value @@ -336,8 +336,8 @@ class Summary(object): lattice_id = int(key.lstrip('lattice ')) index = self._f['geometry/lattices'][key]['index'].value - name = self._f['geometry/lattices'][key]['name'][...][0] - lattice_type = self._f['geometry/lattices'][key]['type'][...][0] + name = self._f['geometry/lattices'][key]['name'].value.decode() + lattice_type = self._f['geometry/lattices'][key]['type'].value.decode() maps = self._f['geometry/lattices'][key]['maps'].value offset_size = self._f['geometry/lattices'][key]['offset_size'].value diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 5e0734648..aa7e762f3 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1469,10 +1469,9 @@ contains subroutine write_string(group_id, name, buffer, indep) integer(HID_T), intent(in) :: group_id character(*), intent(in) :: name ! name for data - character(*), intent(in) :: buffer ! read data to here + character(*), intent(in), target :: buffer ! read data to here logical, intent(in), optional :: indep ! independent I/O - integer :: n integer :: hdf5_err integer :: data_xfer_mode #ifdef PHDF5 @@ -1480,9 +1479,10 @@ contains #endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle - integer(HSIZE_T) :: dims1(1) - integer(HSIZE_T) :: dims2(2) - character(len=len_trim(buffer)), dimension(1) :: str_tmp + integer(HID_T) :: filetype + integer(HID_T) :: memtype + integer(HSIZE_T) :: n + type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O data_xfer_mode = H5FD_MPIO_COLLECTIVE_F @@ -1490,37 +1490,37 @@ contains if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F end if - ! Insert null character at end of string when writing - call h5tset_strpad_f(H5T_STRING, H5T_STR_NULLPAD_F, hdf5_err) - - ! Create the dataspace and dataset - dims1(1) = 1 - call h5screate_simple_f(1, dims1, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_STRING, dspace, dset, hdf5_err) - - ! Set up dimesnions of string to write + ! Create datatype for HDF5 file based on C char n = len_trim(buffer) - dims2(:) = [n, 1] ! full array of strings to write - dims1(1) = n ! length of string + call h5tcopy_f(H5T_C_S1, filetype, hdf5_err) + call h5tset_size_f(filetype, n + 1, hdf5_err) - ! Copy over string buffer to a rank 1 array - str_tmp(1) = buffer + ! Create datatype in memory based on Fortran character + call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) + if (n > 0) call h5tset_size_f(memtype, n, hdf5_err) + + ! Create dataspace/dataset + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), filetype, dspace, dset, hdf5_err) + + ! Get pointer to start of string + f_ptr = c_loc(buffer(1:1)) if (using_mpio_device(group_id)) then #ifdef PHDF5 call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace, xfer_prp=plist) + if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err, xfer_prp=plist) call h5pclose_f(plist, hdf5_err) #endif else - call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace) + if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err) end if call h5dclose_f(dset, hdf5_err) call h5sclose_f(dspace, hdf5_err) + call h5tclose_f(memtype, hdf5_err) + call h5tclose_f(filetype, hdf5_err) end subroutine write_string !=============================================================================== @@ -1529,11 +1529,10 @@ contains subroutine read_string(group_id, name, buffer, indep) integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name for data - character(*), intent(inout) :: buffer ! read data to here - logical, intent(in), optional :: indep ! independent I/O + character(*), intent(in) :: name ! name for data + character(*), intent(inout), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O - integer :: n integer :: hdf5_err integer :: data_xfer_mode #ifdef PHDF5 @@ -1541,9 +1540,11 @@ contains #endif integer(HID_T) :: dset ! data set handle integer(HID_T) :: dspace ! data or file space handle - integer(HSIZE_T) :: dims1(1) - integer(HSIZE_T) :: dims2(2) - character(len=len_trim(buffer)), dimension(1) :: str_tmp + integer(HID_T) :: filetype + integer(HID_T) :: memtype + integer(HSIZE_T) :: size + integer(HSIZE_T) :: n + type(c_ptr) :: f_ptr ! Set up collective vs. independent I/O data_xfer_mode = H5FD_MPIO_COLLECTIVE_F @@ -1551,32 +1552,42 @@ contains if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F end if - ! Set up dimesnions of string to write - n = len_trim(buffer) - dims2(:) = [n, 1] ! full array of strings to write - dims1(1) = n ! length of string - + ! Get dataset and dataspace call h5dopen_f(group_id, trim(name), dset, hdf5_err) call h5dget_space_f(dset, dspace, hdf5_err) + ! Make sure buffer is large enough + call h5dget_type_f(dset, filetype, hdf5_err) + call h5tget_size_f(filetype, size, hdf5_err) + if (size > len(buffer) + 1) then + call fatal_error("Character buffer is not long enough to & + &read HDF5 string.") + end if + + ! Get datatype in memory based on Fortran character + n = len(buffer) + call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) + call h5tset_size_f(memtype, n, hdf5_err) + + ! Get pointer to start of string + f_ptr = c_loc(buffer(1:1)) + if (using_mpio_device(group_id)) then #ifdef PHDF5 call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace, xfer_prp=plist) + call h5dread_f(dset, memtype, f_ptr, hdf5_err, mem_space_id=dspace, & + xfer_prp=plist) call h5pclose_f(plist, hdf5_err) #endif else - call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace) + call h5dread_f(dset, memtype, f_ptr, hdf5_err, mem_space_id=dspace) end if - ! Copy over buffer - buffer = str_tmp(1) - - ! Close dataset call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5tclose_f(filetype, hdf5_err) + call h5tclose_f(memtype, hdf5_err) end subroutine read_string !=============================================================================== From bc5bdeccc65cff81ae6c27fc25398849bafe852c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 07:36:19 +0700 Subject: [PATCH 40/95] Remove unused procedures in output module related to summary --- src/output.F90 | 688 ------------------------------------------------- 1 file changed, 688 deletions(-) diff --git a/src/output.F90 b/src/output.F90 index 2ddbf6499..6c7834b9b 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -315,694 +315,6 @@ contains end subroutine print_particle -!=============================================================================== -! PRINT_REACTION displays the attributes of a reaction -!=============================================================================== - - subroutine print_reaction(rxn) - - type(Reaction), pointer :: rxn - - write(ou,*) 'Reaction ' // reaction_name(rxn % MT) - write(ou,*) ' MT = ' // to_str(rxn % MT) - write(ou,*) ' Q-value = ' // to_str(rxn % Q_value) - write(ou,*) ' Multiplicity = ' // to_str(rxn % multiplicity) - write(ou,*) ' Threshold = ' // to_str(rxn % threshold) - if (rxn % has_energy_dist) then - write(ou,*) ' Energy: Law ' // to_str(rxn % edist % law) - end if - write(ou,*) - - end subroutine print_reaction - -!=============================================================================== -! PRINT_CELL displays the attributes of a cell -!=============================================================================== - - subroutine print_cell(c, unit) - - type(Cell), pointer :: c - integer, optional :: unit ! specified unit to write to - - integer :: index_cell ! index in cells array - integer :: i ! loop index for surfaces - integer :: index_surf ! index in surfaces array - integer :: unit_ ! unit to write to - character(MAX_LINE_LEN) :: string - type(Universe), pointer :: u => null() - class(Lattice), pointer :: l => null() - type(Material), pointer :: m => null() - - ! Set unit to stdout if not already set - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write user-specified id for cell - write(unit_,*) 'Cell ' // to_str(c % id) - - ! Write user-specified name for cell - write(unit_,*) ' Name = ' // c % name - - ! Find index in cells array and write - index_cell = cell_dict % get_key(c % id) - write(unit_,*) ' Array Index = ' // to_str(index_cell) - - ! Write what universe this cell is in - u => universes(c % universe) - write(unit_,*) ' Universe = ' // to_str(u % id) - - ! Write information on fill for cell - select case (c % type) - case (CELL_NORMAL) - write(unit_,*) ' Fill = NONE' - case (CELL_FILL) - u => universes(c % fill) - write(unit_,*) ' Fill = Universe ' // to_str(u % id) - case (CELL_LATTICE) - l => lattices(c % fill) % obj - write(unit_,*) ' Fill = Lattice ' // to_str(l % id) - end select - - ! Write information on material - if (c % material == 0) then - write(unit_,*) ' Material = NONE' - elseif (c % material == MATERIAL_VOID) then - write(unit_,*) ' Material = Void' - else - m => materials(c % material) - write(unit_,*) ' Material = ' // to_str(m % id) - end if - - ! Write surface specification - string = "" - do i = 1, c % n_surfaces - select case (c % surfaces(i)) - case (OP_LEFT_PAREN) - string = trim(string) // ' (' - case (OP_RIGHT_PAREN) - string = trim(string) // ' )' - case (OP_UNION) - string = trim(string) // ' :' - case (OP_DIFFERENCE) - string = trim(string) // ' !' - case default - index_surf = abs(c % surfaces(i)) - string = trim(string) // ' ' // to_str(sign(& - surfaces(index_surf) % id, c % surfaces(i))) - end select - end do - write(unit_,*) ' Surface Specification:' // trim(string) - write(unit_,*) - - end subroutine print_cell - -!=============================================================================== -! PRINT_UNIVERSE displays the attributes of a universe -!=============================================================================== - - subroutine print_universe(univ, unit) - - type(Universe), pointer :: univ - integer, optional :: unit - - integer :: i ! loop index for cells in this universe - integer :: unit_ ! unit to write to - character(MAX_LINE_LEN) :: string - type(Cell), pointer :: c => null() - type(Universe), pointer :: base_u => null() - - ! Set default unit to stdout if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Get a pointer to the base universe - base_u => universes(BASE_UNIVERSE) - - ! Write user-specified id for this universe - write(unit_,*) 'Universe ' // to_str(univ % id) - - ! If this is the base universe, indicate so - if (associated(univ, base_u)) then - write(unit_,*) ' Base Universe' - end if - - ! Write list of cells in this universe - string = "" - do i = 1, univ % n_cells - c => cells(univ % cells(i)) - string = trim(string) // ' ' // to_str(c % id) - end do - write(unit_,*) ' Cells =' // trim(string) - write(unit_,*) - - end subroutine print_universe - -!=============================================================================== -! PRINT_LATTICE displays the attributes of a lattice -!=============================================================================== - - subroutine print_lattice(lat, unit) - - class(Lattice), pointer :: lat - integer, optional :: unit - - integer :: unit_ ! unit to write to - - ! set default unit if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write information about lattice - write(unit_,*) 'Lattice ' // to_str(lat % id) - - ! Write user-specified name for lattice - write(unit_,*) ' Name = ' // lat % name - - select type(lat) - type is (RectLattice) - ! Write dimension of lattice. - if (lat % is_3d) then - write(unit_, *) ' Dimension = ' // to_str(lat % n_cells(1)) & - &// ' ' // to_str(lat % n_cells(2)) // ' ' & - &// to_str(lat % n_cells(3)) - else - write(unit_, *) ' Dimension = ' // to_str(lat % n_cells(1)) & - &// ' ' // to_str(lat % n_cells(2)) - end if - - ! Write lower-left coordinates of lattice. - if (lat % is_3d) then - write(unit_, *) ' Lower-left = ' // to_str(lat % lower_left(1)) & - &// ' ' // to_str(lat % lower_left(2)) // ' ' & - &// to_str(lat % lower_left(3)) - else - write(unit_, *) ' Lower-left = ' // to_str(lat % lower_left(1)) & - &// ' ' // to_str(lat % lower_left(2)) - end if - - ! Write lattice pitch along each axis. - if (lat % is_3d) then - write(unit_, *) ' Pitch = ' // to_str(lat % pitch(1)) & - &// ' ' // to_str(lat % pitch(2)) // ' ' & - &// to_str(lat % pitch(3)) - else - write(unit_, *) ' Pitch = ' // to_str(lat % pitch(1)) & - &// ' ' // to_str(lat % pitch(2)) - end if - write(unit_,*) - - type is (HexLattice) - ! Write dimension of lattice. - write(unit_,*) ' N-rings = ' // to_str(lat % n_rings) - if (lat % is_3d) write(unit_,*) ' N-axial = ' // to_str(lat % n_axial) - - ! Write center coordinates of lattice. - if (lat % is_3d) then - write(unit_, *) ' Center = ' // to_str(lat % center(1)) & - &// ' ' // to_str(lat % center(2)) // ' ' & - &// to_str(lat % center(3)) - else - write(unit_, *) ' Center = ' // to_str(lat % center(1)) & - &// ' ' // to_str(lat % center(2)) - end if - - ! Write lattice pitch along each axis. - if (lat % is_3d) then - write(unit_, *) ' Pitch = ' // to_str(lat % pitch(1)) & - &// ' ' // to_str(lat % pitch(2)) - else - write(unit_, *) ' Pitch = ' // to_str(lat % pitch(1)) - end if - write(unit_,*) - end select - - - end subroutine print_lattice - -!=============================================================================== -! PRINT_SURFACE displays the attributes of a surface -!=============================================================================== - - subroutine print_surface(surf, unit) - - type(Surface), pointer :: surf - integer, optional :: unit ! specified unit to write to - - integer :: i ! loop index for coefficients - integer :: unit_ ! unit to write to - character(MAX_LINE_LEN) :: string - type(Cell), pointer :: c => null() - - ! set default unit if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write user-specified id of surface - write(unit_,*) 'Surface ' // to_str(surf % id) - - ! Write user-specified name for surface - write(unit_,*) ' Name = ' // surf % name - - ! Write type of surface - select case (surf % type) - case (SURF_PX) - string = "X Plane" - case (SURF_PY) - string = "Y Plane" - case (SURF_PZ) - string = "Z Plane" - case (SURF_PLANE) - string = "Plane" - case (SURF_CYL_X) - string = "X Cylinder" - case (SURF_CYL_Y) - string = "Y Cylinder" - case (SURF_CYL_Z) - string = "Z Cylinder" - case (SURF_SPHERE) - string = "Sphere" - case (SURF_CONE_X) - string = "X Cone" - case (SURF_CONE_Y) - string = "Y Cone" - case (SURF_CONE_Z) - string = "Z Cone" - end select - write(unit_,*) ' Type = ' // trim(string) - - ! Write coefficients for this surface - string = "" - do i = 1, size(surf % coeffs) - string = trim(string) // ' ' // to_str(surf % coeffs(i), 4) - end do - write(unit_,*) ' Coefficients = ' // trim(string) - - ! Write neighboring cells on positive side of this surface - string = "" - if (allocated(surf % neighbor_pos)) then - do i = 1, size(surf % neighbor_pos) - c => cells(abs(surf % neighbor_pos(i))) - string = trim(string) // ' ' // to_str(& - sign(c % id, surf % neighbor_pos(i))) - end do - end if - write(unit_,*) ' Positive Neighbors = ' // trim(string) - - ! Write neighboring cells on negative side of this surface - string = "" - if (allocated(surf % neighbor_neg)) then - do i = 1, size(surf % neighbor_neg) - c => cells(abs(surf % neighbor_neg(i))) - string = trim(string) // ' ' // to_str(& - sign(c % id, surf % neighbor_neg(i))) - end do - end if - write(unit_,*) ' Negative Neighbors =' // trim(string) - - ! Write boundary condition for this surface - select case (surf % bc) - case (BC_TRANSMIT) - write(unit_,*) ' Boundary Condition = Transmission' - case (BC_VACUUM) - write(unit_,*) ' Boundary Condition = Vacuum' - case (BC_REFLECT) - write(unit_,*) ' Boundary Condition = Reflective' - case (BC_PERIODIC) - write(unit_,*) ' Boundary Condition = Periodic' - end select - write(unit_,*) - - end subroutine print_surface - -!=============================================================================== -! PRINT_MATERIAL displays the attributes of a material -!=============================================================================== - - subroutine print_material(mat, unit) - - type(Material), pointer :: mat - integer, optional :: unit - - integer :: i ! loop index for nuclides - integer :: unit_ ! unit to write to - real(8) :: density ! density in atom/b-cm - character(MAX_LINE_LEN) :: string - type(Nuclide), pointer :: nuc => null() - - ! set default unit to stdout if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write identifier for material - write(unit_,*) 'Material ' // to_str(mat % id) - - ! Write user-specified name for material - write(unit_,*) ' Name = ' // mat % name - - ! Write total atom density in atom/b-cm - write(unit_,*) ' Atom Density = ' // trim(to_str(mat % density)) & - // ' atom/b-cm' - - ! Write atom density for each nuclide in material - write(unit_,*) ' Nuclides:' - do i = 1, mat % n_nuclides - nuc => nuclides(mat % nuclide(i)) - density = mat % atom_density(i) - string = ' ' // trim(nuc % name) // ' = ' // & - trim(to_str(density)) // ' atom/b-cm' - write(unit_,*) trim(string) - end do - - ! Write information on S(a,b) table - if (mat % n_sab > 0) then - write(unit_,*) ' S(a,b) tables:' - do i = 1, mat % n_sab - write(unit_,*) ' ' // trim(& - sab_tables(mat % i_sab_tables(i)) % name) - end do - end if - write(unit_,*) - - end subroutine print_material - -!=============================================================================== -! PRINT_TALLY displays the attributes of a tally -!=============================================================================== - - subroutine print_tally(t, unit) - - type(TallyObject), pointer :: t - integer, optional :: unit - - integer :: i ! index for filter or score bins - integer :: j ! index in filters array - integer :: id ! user-specified id - integer :: unit_ ! unit to write to - integer :: n ! moment order to include in name - character(MAX_LINE_LEN) :: string - character(MAX_WORD_LEN) :: pn_string - type(Cell), pointer :: c => null() - type(Surface), pointer :: s => null() - type(Universe), pointer :: u => null() - type(Material), pointer :: m => null() - type(StructuredMesh), pointer :: sm => null() - - ! set default unit to stdout if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write user-specified id of tally - write(unit_,*) 'Tally ' // to_str(t % id) - - ! Write the type of tally - select case(t % type) - case (TALLY_VOLUME) - write(unit_,*) ' Type: Volume' - case (TALLY_SURFACE_CURRENT) - write(unit_,*) ' Type: Surface Current' - end select - - ! Write the estimator used - select case(t % estimator) - case(ESTIMATOR_ANALOG) - write(unit_,*) ' Estimator: Analog' - case(ESTIMATOR_TRACKLENGTH) - write(unit_,*) ' Estimator: Track-length' - end select - - ! Write any cells bins if present - j = t % find_filter(FILTER_DISTRIBCELL) - if (j > 0) then - string = "" - id = t % filters(j) % int_bins(1) - c => cells(id) - string = trim(string) // ' ' // trim(to_str(c % id)) - write(unit_, *) ' Distribcell Bins:' // trim(string) - end if - - ! Write any cells bins if present - j = t % find_filter(FILTER_CELL) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - c => cells(id) - string = trim(string) // ' ' // trim(to_str(c % id)) - end do - write(unit_, *) ' Cell Bins:' // trim(string) - end if - - ! Write any surface bins if present - j = t % find_filter(FILTER_SURFACE) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - s => surfaces(id) - string = trim(string) // ' ' // trim(to_str(s % id)) - end do - write(unit_, *) ' Surface Bins:' // trim(string) - end if - - ! Write any universe bins if present - j = t % find_filter(FILTER_UNIVERSE) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - u => universes(id) - string = trim(string) // ' ' // trim(to_str(u % id)) - end do - write(unit_, *) ' Universe Bins:' // trim(string) - end if - - ! Write any material bins if present - j = t % find_filter(FILTER_MATERIAL) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - m => materials(id) - string = trim(string) // ' ' // trim(to_str(m % id)) - end do - write(unit_, *) ' Material Bins:' // trim(string) - end if - - ! Write any mesh bins if present - j = t % find_filter(FILTER_MESH) - if (j > 0) then - string = "" - id = t % filters(j) % int_bins(1) - sm => meshes(id) - string = trim(string) // ' ' // trim(to_str(sm % dimension(1))) - do i = 2, sm % n_dimension - string = trim(string) // ' x ' // trim(to_str(sm % dimension(i))) - end do - write(unit_, *) ' Mesh Bins:' // trim(string) - end if - - ! Write any birth region bins if present - j = t % find_filter(FILTER_CELLBORN) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - c => cells(id) - string = trim(string) // ' ' // trim(to_str(c % id)) - end do - write(unit_, *) ' Birth Region Bins:' // trim(string) - end if - - ! Write any incoming energy bins if present - j = t % find_filter(FILTER_ENERGYIN) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins + 1 - string = trim(string) // ' ' // trim(to_str(& - t % filters(j) % real_bins(i))) - end do - write(unit_,*) ' Incoming Energy Bins:' // trim(string) - end if - - ! Write any outgoing energy bins if present - j = t % find_filter(FILTER_ENERGYOUT) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins + 1 - string = trim(string) // ' ' // trim(to_str(& - t % filters(j) % real_bins(i))) - end do - write(unit_,*) ' Outgoing Energy Bins:' // trim(string) - end if - - ! Write nuclides bins - write(unit_,fmt='(1X,A)',advance='no') ' Nuclide Bins:' - do i = 1, t % n_nuclide_bins - if (t % nuclide_bins(i) == -1) then - write(unit_,fmt='(A)',advance='no') ' total' - else - write(unit_,fmt='(A)',advance='no') ' ' // trim(adjustl(& - nuclides(t % nuclide_bins(i)) % name)) - end if - if (mod(i,4) == 0 .and. i /= t % n_nuclide_bins) & - write(unit_,'(/18X)',advance='no') - end do - write(unit_,*) - - ! Write score bins - string = "" - j = 0 - do i = 1, t % n_user_score_bins - j = j + 1 - select case (t % score_bins(j)) - case (SCORE_FLUX) - string = trim(string) // ' flux' - case (SCORE_FLUX_YN) - pn_string = ' flux' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' flux-y' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_TOTAL) - string = trim(string) // ' total' - case (SCORE_TOTAL_YN) - pn_string = ' total' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' total-y' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_SCATTER) - string = trim(string) // ' scatter' - case (SCORE_NU_SCATTER) - string = trim(string) // ' nu-scatter' - case (SCORE_SCATTER_N) - pn_string = ' scatter-' // trim(to_str(t % moment_order(j))) - string = trim(string) // pn_string - case (SCORE_SCATTER_PN) - pn_string = ' scatter' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' scatter-p' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_NU_SCATTER_N) - pn_string = ' nu-scatter-' // trim(to_str(t % moment_order(j))) - string = trim(string) // pn_string - case (SCORE_NU_SCATTER_PN) - pn_string = ' nu-scatter' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' nu-scatter-p' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_SCATTER_YN) - pn_string = ' scatter' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' scatter-y' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_NU_SCATTER_YN) - pn_string = ' nu-scatter' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' nu-scatter-y' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_TRANSPORT) - string = trim(string) // ' transport' - case (SCORE_N_1N) - string = trim(string) // ' n1n' - case (SCORE_ABSORPTION) - string = trim(string) // ' absorption' - case (SCORE_FISSION) - string = trim(string) // ' fission' - case (SCORE_NU_FISSION) - string = trim(string) // ' nu-fission' - case (SCORE_KAPPA_FISSION) - string = trim(string) // ' kappa-fission' - case (SCORE_CURRENT) - string = trim(string) // ' current' - case default - string = trim(string) // ' ' // reaction_name(t % score_bins(j)) - end select - end do - write(unit_,*) ' Scores:' // trim(string) - write(unit_,*) - - end subroutine print_tally - -!=============================================================================== -! PRINT_GEOMETRY displays the attributes of all cells, surfaces, universes, -! surfaces, and lattices read in the input files. -!=============================================================================== - - subroutine print_geometry() - - integer :: i ! loop index for various arrays - type(Surface), pointer :: s => null() - type(Cell), pointer :: c => null() - type(Universe), pointer :: u => null() - class(Lattice), pointer :: l => null() - - ! print summary of surfaces - call header("SURFACE SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_surfaces - s => surfaces(i) - call print_surface(s, unit=UNIT_SUMMARY) - end do - - ! print summary of cells - call header("CELL SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_cells - c => cells(i) - call print_cell(c, unit=UNIT_SUMMARY) - end do - - ! print summary of universes - call header("UNIVERSE SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_universes - u => universes(i) - call print_universe(u, unit=UNIT_SUMMARY) - end do - - ! print summary of lattices - if (n_lattices > 0) then - call header("LATTICE SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_lattices - l => lattices(i) % obj - call print_lattice(l, unit=UNIT_SUMMARY) - end do - end if - - end subroutine print_geometry - !=============================================================================== ! PRINT_NUCLIDE displays information about a continuous-energy neutron ! cross_section table and its reactions and secondary angle/energy distributions From 241fe3860b543ef637630ac6f6d4d8e19e016bae Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 08:31:41 +0700 Subject: [PATCH 41/95] Consistently use NEWUNIT for opening files with Fortran I/O --- src/ace.F90 | 24 ++++++++-------- src/constants.F90 | 8 ------ src/output.F90 | 72 ++++++++++++++++++++++++----------------------- src/plot.F90 | 22 ++++++++------- 4 files changed, 61 insertions(+), 65 deletions(-) diff --git a/src/ace.F90 b/src/ace.F90 index 0dd92ea2c..cccc57092 100644 --- a/src/ace.F90 +++ b/src/ace.F90 @@ -234,7 +234,7 @@ contains integer :: location ! location of ACE table integer :: entries ! number of entries on each record integer :: length ! length of ACE table - integer :: in = 7 ! file unit + integer :: unit_ace ! file unit integer :: zaids(16) ! list of ZAIDs (only used for S(a,b)) integer :: filetype ! filetype (ASCII or BINARY) real(8) :: kT ! temperature of table @@ -277,14 +277,14 @@ contains ! READ ACE TABLE IN ASCII FORMAT ! Find location of table - open(UNIT=in, FILE=filename, STATUS='old', ACTION='read') - rewind(UNIT=in) + open(NEWUNIT=unit_ace, FILE=filename, STATUS='old', ACTION='read') + rewind(UNIT=unit_ace) do i = 1, location - 1 - read(UNIT=in, FMT=*) + read(UNIT=unit_ace, FMT=*) end do ! Read first line of header - read(UNIT=in, FMT='(A10,2G12.0,1X,A10)') name, awr, kT, date_ + read(UNIT=unit_ace, FMT='(A10,2G12.0,1X,A10)') name, awr, kT, date_ ! Check that correct xs was found -- if cross_sections.xml is broken, the ! location of the table may be wrong @@ -294,7 +294,7 @@ contains end if ! Read more header and NXS and JXS - read(UNIT=in, FMT=100) comment, mat, & + read(UNIT=unit_ace, FMT=100) comment, mat, & (zaids(i), awrs(i), i=1,16), NXS, JXS 100 format(A70,A10/4(I7,F11.0)/4(I7,F11.0)/4(I7,F11.0)/4(I7,F11.0)/& ,8I9/8I9/8I9/8I9/8I9/8I9) @@ -304,21 +304,21 @@ contains allocate(XSS(length)) ! Read XSS array - read(UNIT=in, FMT='(4G20.0)') XSS + read(UNIT=unit_ace, FMT='(4G20.0)') XSS ! Close ACE file - close(UNIT=in) + close(UNIT=unit_ace) elseif (filetype == BINARY) then ! ======================================================================= ! READ ACE TABLE IN BINARY FORMAT ! Open ACE file - open(UNIT=in, FILE=filename, STATUS='old', ACTION='read', & + open(NEWUNIT=unit_ace, FILE=filename, STATUS='old', ACTION='read', & ACCESS='direct', RECL=record_length) ! Read all header information - read(UNIT=in, REC=location) name, awr, kT, date_, & + read(UNIT=unit_ace, REC=location) name, awr, kT, date_, & comment, mat, (zaids(i), awrs(i), i=1,16), NXS, JXS ! determine table length @@ -329,11 +329,11 @@ contains do i = 1, (length + entries - 1)/entries j1 = 1 + (i-1)*entries j2 = min(length, j1 + entries - 1) - read(UNIT=IN, REC=location + i) (XSS(j), j=j1,j2) + read(UNIT=UNIT_ACE, REC=location + i) (XSS(j), j=j1,j2) end do ! Close ACE file - close(UNIT=in) + close(UNIT=unit_ace) end if ! ========================================================================== diff --git a/src/constants.F90 b/src/constants.F90 index 9a89542af..5eba50f6d 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -394,14 +394,6 @@ module constants MODE_PLOTTING = 3, & ! Plotting mode MODE_PARTICLE = 4 ! Particle restart mode - ! Unit numbers - integer, parameter :: UNIT_SUMMARY = 11 ! unit # for writing summary file - integer, parameter :: UNIT_TALLY = 12 ! unit # for writing tally file - integer, parameter :: UNIT_PLOT = 13 ! unit # for writing plot file - integer, parameter :: UNIT_XS = 14 ! unit # for writing xs summary file - integer, parameter :: UNIT_PARTICLE = 15 ! unit # for writing particle restart - integer, parameter :: UNIT_OUTPUT = 16 ! unit # for writing output - !============================================================================= ! CMFD CONSTANTS diff --git a/src/output.F90 b/src/output.F90 index 6c7834b9b..73b8e595d 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -524,7 +524,8 @@ contains subroutine write_xs_summary() - integer :: i ! loop index + integer :: i ! loop index + integer :: unit_xs ! cross_sections.out file unit character(MAX_FILE_LEN) :: path ! path of summary file type(Nuclide), pointer :: nuc => null() type(SAlphaBeta), pointer :: sab => null() @@ -533,17 +534,17 @@ contains path = trim(path_output) // "cross_sections.out" ! Open log file for writing - open(UNIT=UNIT_XS, FILE=path, STATUS='replace', ACTION='write') + open(NEWUNIT=unit_xs, FILE=path, STATUS='replace', ACTION='write') ! Write header - call header("CROSS SECTION TABLES", unit=UNIT_XS) + call header("CROSS SECTION TABLES", unit=unit_xs) NUCLIDE_LOOP: do i = 1, n_nuclides_total ! Get pointer to nuclide nuc => nuclides(i) ! Print information about nuclide - call print_nuclide(nuc, unit=UNIT_XS) + call print_nuclide(nuc, unit=unit_xs) end do NUCLIDE_LOOP SAB_TABLES_LOOP: do i = 1, n_sab_tables @@ -551,11 +552,11 @@ contains sab => sab_tables(i) ! Print information about S(a,b) table - call print_sab_table(sab, unit=UNIT_XS) + call print_sab_table(sab, unit=unit_xs) end do SAB_TABLES_LOOP ! Close cross section summary file - close(UNIT_XS) + close(unit_xs) end subroutine write_xs_summary @@ -936,6 +937,7 @@ contains integer :: i_listing ! index in xs_listings array integer :: n_order ! loop index for moment orders integer :: nm_order ! loop index for Ynm moment orders + integer :: unit_tally ! tallies.out file unit real(8) :: t_value ! t-values for confidence intervals real(8) :: alpha ! significance level for CI character(MAX_FILE_LEN) :: filename ! name of output file @@ -984,7 +986,7 @@ contains filename = trim(path_output) // "tallies.out" ! Open tally file for writing - open(FILE=filename, UNIT=UNIT_TALLY, STATUS='replace', ACTION='write') + open(FILE=filename, NEWUNIT=unit_tally, STATUS='replace', ACTION='write') ! Calculate t-value for confidence intervals if (confidence_intervals) then @@ -1008,16 +1010,16 @@ contains ! Write header block if (t % name == "") then - call header("TALLY " // trim(to_str(t % id)), unit=UNIT_TALLY, & + call header("TALLY " // trim(to_str(t % id)), unit=unit_tally, & level=3) else call header("TALLY " // trim(to_str(t % id)) // ": " & - // trim(t % name), unit=UNIT_TALLY, level=3) + // trim(t % name), unit=unit_tally, level=3) endif ! Handle surface current tallies separately if (t % type == TALLY_SURFACE_CURRENT) then - call write_surface_current(t) + call write_surface_current(t, unit_tally) cycle end if @@ -1060,7 +1062,7 @@ contains ! Print current filter information type = t % filters(j) % type - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A)') repeat(" ", indent), & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), & trim(filter_name(type)), trim(get_label(t, j)) indent = indent + 2 j = j + 1 @@ -1071,7 +1073,7 @@ contains ! Print filter information if (t % n_filters > 0) then type = t % filters(j) % type - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A)') repeat(" ", indent), & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), & trim(filter_name(type)), trim(get_label(t, j)) end if @@ -1092,11 +1094,11 @@ contains ! Write label for nuclide i_nuclide = t % nuclide_bins(n) if (i_nuclide == -1) then - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A)') repeat(" ", indent), & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), & "Total Material" else i_listing = nuclides(i_nuclide) % listing - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A)') repeat(" ", indent), & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), & trim(xs_listings(i_listing) % alias) end if @@ -1109,7 +1111,7 @@ contains case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) score_name = 'P' // trim(to_str(t % moment_order(k))) // " " // & score_names(abs(t % score_bins(k))) - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & to_str(t % results(score_index,filter_index) % sum), & trim(to_str(t % results(score_index,filter_index) % sum_sq)) @@ -1119,7 +1121,7 @@ contains score_index = score_index + 1 score_name = 'P' // trim(to_str(n_order)) // " " //& score_names(abs(t % score_bins(k))) - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & to_str(t % results(score_index,filter_index) % sum), & trim(to_str(t % results(score_index,filter_index) & @@ -1135,7 +1137,7 @@ contains score_name = 'Y' // trim(to_str(n_order)) // ',' // & trim(to_str(nm_order)) // " " & // score_names(abs(t % score_bins(k))) - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & to_str(t % results(score_index,filter_index) % sum), & trim(to_str(t % results(score_index,filter_index)& @@ -1149,7 +1151,7 @@ contains else score_name = score_names(abs(t % score_bins(k))) end if - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & to_str(t % results(score_index,filter_index) % sum), & trim(to_str(t % results(score_index,filter_index) % sum_sq)) @@ -1166,7 +1168,7 @@ contains end do TALLY_LOOP - close(UNIT=UNIT_TALLY) + close(UNIT=unit_tally) end subroutine write_tallies @@ -1175,9 +1177,9 @@ contains ! tallies.out file. !=============================================================================== - subroutine write_surface_current(t) - + subroutine write_surface_current(t, unit_tally) type(TallyObject), pointer :: t + integer, intent(in) :: unit_tally integer :: i ! mesh index for x integer :: j ! mesh index for y @@ -1221,7 +1223,7 @@ contains do k = 1, m % dimension(3) ! Write mesh cell index string = string(1:len2+1) // trim(to_str(k)) // ")" - write(UNIT=UNIT_TALLY, FMT='(1X,A)') trim(string) + write(UNIT=unit_tally, FMT='(1X,A)') trim(string) do l = 1, n if (print_ebin) then @@ -1229,7 +1231,7 @@ contains matching_bins(i_filter_ein) = l ! Write incoming energy bin - write(UNIT=UNIT_TALLY, FMT='(3X,A,1X,A)') & + write(UNIT=unit_tally, FMT='(3X,A,1X,A)') & "Incoming Energy", trim(get_label(t, i_filter_ein)) end if @@ -1238,14 +1240,14 @@ contains mesh_indices_to_bin(m, (/ i-1, j, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_RIGHT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Left", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_RIGHT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Left", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -1255,14 +1257,14 @@ contains mesh_indices_to_bin(m, (/ i, j, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_RIGHT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Right", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_RIGHT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Right", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -1272,14 +1274,14 @@ contains mesh_indices_to_bin(m, (/ i, j-1, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_FRONT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Back", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_FRONT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Back", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -1289,14 +1291,14 @@ contains mesh_indices_to_bin(m, (/ i, j, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_FRONT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Front", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_FRONT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Front", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -1306,14 +1308,14 @@ contains mesh_indices_to_bin(m, (/ i, j, k-1 /) + 1, .true.) matching_bins(i_filter_surf) = IN_TOP filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Bottom", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_TOP filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Bottom", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -1323,14 +1325,14 @@ contains mesh_indices_to_bin(m, (/ i, j, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_TOP filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Top", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_TOP filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Top", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) diff --git a/src/plot.F90 b/src/plot.F90 index e507b6093..cd4e8642e 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -305,25 +305,26 @@ contains integer :: i ! loop index for height integer :: j ! loop index for width + integer :: unit_plot ! Open PPM file for writing - open(UNIT=UNIT_PLOT, FILE=pl % path_plot) + open(NEWUNIT=unit_plot, FILE=pl % path_plot) ! Write header - write(UNIT_PLOT, '(A2)') 'P6' - write(UNIT_PLOT, '(I0,'' '',I0)') img%width, img%height - write(UNIT_PLOT, '(A)') '255' + write(unit_plot, '(A2)') 'P6' + write(unit_plot, '(I0,'' '',I0)') img%width, img%height + write(unit_plot, '(A)') '255' ! Write color for each pixel do j = 1, img % height do i = 1, img % width - write(UNIT_PLOT, '(3A1)', advance='no') achar(img%red(i,j)), & + write(unit_plot, '(3A1)', advance='no') achar(img%red(i,j)), & achar(img%green(i,j)), achar(img%blue(i,j)) end do end do ! Close plot file - close(UNIT=UNIT_PLOT) + close(UNIT=unit_plot) end subroutine output_ppm @@ -346,6 +347,7 @@ contains integer :: x, y, z ! voxel location indices integer :: rgb(3) ! colors (red, green, blue) from 0-255 integer :: id ! id of cell or material + integer :: unit_plot ! voxel file unit real(8) :: vox(3) ! x, y, and z voxel widths real(8) :: ll(3) ! lower left starting point for each sweep direction type(Particle) :: p @@ -364,11 +366,11 @@ contains p % coord(1) % universe = BASE_UNIVERSE ! Open binary plot file for writing - open(UNIT=UNIT_PLOT, FILE=pl % path_plot, STATUS='replace', & + open(NEWUNIT=unit_plot, FILE=pl % path_plot, STATUS='replace', & ACCESS='stream') ! write plot header info - write(UNIT_PLOT) pl % pixels, vox, ll + write(unit_plot) pl % pixels, vox, ll ! move to center of voxels ll = ll + vox / TWO @@ -382,7 +384,7 @@ contains call position_rgb(p, pl, rgb, id) ! write to plot file - write(UNIT_PLOT) id + write(unit_plot) id ! advance particle in z direction p % coord(1) % xyz(3) = p % coord(1) % xyz(3) + vox(3) @@ -402,7 +404,7 @@ contains end do - close(UNIT_PLOT) + close(unit_plot) end subroutine create_3d_dump From 53fc6ff9f27c5639980be8aac11ad6ca5d66053f Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Mon, 14 Sep 2015 20:36:55 -0400 Subject: [PATCH 42/95] Add collision estimator --- src/constants.F90 | 3 +- src/global.F90 | 5 +- src/input_xml.F90 | 12 +++ src/tally.F90 | 253 ++++++++++++++++++++++++++++++++++------------ src/tracking.F90 | 3 +- 5 files changed, 208 insertions(+), 68 deletions(-) diff --git a/src/constants.F90 b/src/constants.F90 index 9a89542af..e95f944d7 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -251,7 +251,8 @@ module constants ! Tally estimator types integer, parameter :: & ESTIMATOR_ANALOG = 1, & - ESTIMATOR_TRACKLENGTH = 2 + ESTIMATOR_TRACKLENGTH = 2, & + ESTIMATOR_COLLISION = 3 ! Event types for tallies integer, parameter :: & diff --git a/src/global.F90 b/src/global.F90 index 0c5e38212..adc8f17da 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -106,9 +106,11 @@ module global type(SetInt) :: active_analog_tallies type(SetInt) :: active_tracklength_tallies type(SetInt) :: active_current_tallies + type(SetInt) :: active_collision_tallies type(SetInt) :: active_tallies !$omp threadprivate(active_analog_tallies, active_tracklength_tallies, & -!$omp& active_current_tallies, active_tallies) +!$omp& active_current_tallies, active_collision_tallies, & +!$omp& active_tallies) ! Global tallies ! 1) collision estimate of k-eff @@ -487,6 +489,7 @@ contains call active_analog_tallies % clear() call active_tracklength_tallies % clear() call active_current_tallies % clear() + call active_collision_tallies % clear() call active_tallies % clear() ! Deallocate track_identifiers diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 5c939a394..d5a932ff6 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3138,6 +3138,18 @@ contains ! Set estimator to track-length estimator t % estimator = ESTIMATOR_TRACKLENGTH + case ('collision') + ! If the estimator was set to an analog estimator, this means the + ! tally needs post-collision information + if (t % estimator == ESTIMATOR_ANALOG) then + call fatal_error("Cannot use collision estimator for tally " & + &// to_str(t % id)) + end if + + ! Set estimator to collision estimator + t % estimator = ESTIMATOR_COLLISION + write(*, *) t % estimator + case default call fatal_error("Invalid estimator '" // trim(temp_str) & &// "' on tally " // to_str(t % id)) diff --git a/src/tally.F90 b/src/tally.F90 index e78e58f28..9f9ae7765 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -81,8 +81,8 @@ contains case (SCORE_FLUX, SCORE_FLUX_YN) if (t % estimator == ESTIMATOR_ANALOG) then ! All events score to a flux bin. We actually use a collision - ! estimator since there is no way to count 'events' exactly for - ! the flux + ! estimator in place of an analog one since there is no way to count + ! 'events' exactly for the flux if (survival_biasing) then ! We need to account for the fact that some weight was already ! absorbed @@ -92,7 +92,8 @@ contains end if score = score / material_xs % total - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & + t % estimator == ESTIMATOR_COLLISION) then ! For flux, we need no cross section score = flux end if @@ -111,7 +112,8 @@ contains score = p % last_wgt end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & + t % estimator == ESTIMATOR_COLLISION) then if (i_nuclide > 0) then score = micro_xs(i_nuclide) % total * atom_density * flux else @@ -129,8 +131,9 @@ contains ! reaction rate score = p % last_wgt - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then - ! Note SCORE_SCATTER_N not available for tracklength. + else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & + t % estimator == ESTIMATOR_COLLISION) then + ! Note SCORE_SCATTER_N not available for tracklength/collision. if (i_nuclide > 0) then score = (micro_xs(i_nuclide) % total & - micro_xs(i_nuclide) % absorption) * atom_density * flux @@ -240,7 +243,8 @@ contains score = p % last_wgt end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & + t % estimator == ESTIMATOR_COLLISION) then if (i_nuclide > 0) then score = micro_xs(i_nuclide) % absorption * atom_density * flux else @@ -271,7 +275,8 @@ contains / micro_xs(p % event_nuclide) % absorption end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & + t % estimator == ESTIMATOR_COLLISION) then if (i_nuclide > 0) then score = micro_xs(i_nuclide) % fission * atom_density * flux else @@ -314,7 +319,8 @@ contains score = keff * p % wgt_bank end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & + t % estimator == ESTIMATOR_COLLISION) then if (i_nuclide > 0) then score = micro_xs(i_nuclide) % nu_fission * atom_density * flux else @@ -347,7 +353,8 @@ contains micro_xs(p % event_nuclide) % absorption end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & + t % estimator == ESTIMATOR_COLLISION) then if (i_nuclide > 0) then score = micro_xs(i_nuclide) % kappa_fission * atom_density * flux else @@ -368,7 +375,8 @@ contains if (p % event_MT /= score_bin) cycle SCORE_LOOP score = p % last_wgt - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & + t % estimator == ESTIMATOR_COLLISION) then ! Any other cross section has to be calculated on-the-fly. For ! cross sections that are used often (e.g. n2n, ngamma, etc. for ! depletion), it might make sense to optimize this section or @@ -484,7 +492,8 @@ contains case(SCORE_FLUX_YN, SCORE_TOTAL_YN) score_index = score_index - 1 num_nm = 1 - if (t % estimator == ESTIMATOR_ANALOG) then + if (t % estimator == ESTIMATOR_ANALOG .or. & + t % estimator == ESTIMATOR_COLLISION) then uvw = p % last_uvw else if (t % estimator == ESTIMATOR_TRACKLENGTH) then uvw = p % coord(1) % uvw @@ -536,6 +545,59 @@ contains end do SCORE_LOOP end subroutine score_general +!=============================================================================== +! SCORE_ALL_NUCLIDES tallies individual nuclide reaction rates specifically when +! the user requests all. +!=============================================================================== + + subroutine score_all_nuclides(p, i_tally, flux, filter_index) + + type(Particle), intent(in) :: p + integer, intent(in) :: i_tally + real(8), intent(in) :: flux + integer, intent(in) :: filter_index + + integer :: i ! loop index for nuclides in material + integer :: i_nuclide ! index in nuclides array + real(8) :: atom_density ! atom density of single nuclide in atom/b-cm + type(TallyObject), pointer :: t + type(Material), pointer :: mat + + ! Get pointer to tally + t => tallies(i_tally) + + ! Get pointer to current material. We need this in order to determine what + ! nuclides are in the material + mat => materials(p % material) + + ! ========================================================================== + ! SCORE ALL INDIVIDUAL NUCLIDE REACTION RATES + + NUCLIDE_LOOP: do i = 1, mat % n_nuclides + + ! Determine index in nuclides array and atom density for i-th nuclide in + ! current material + i_nuclide = mat % nuclide(i) + atom_density = mat % atom_density(i) + + ! Determine score for each bin + call score_general(p, t, (i_nuclide-1)*t % n_score_bins, filter_index, & + i_nuclide, atom_density, flux) + + end do NUCLIDE_LOOP + + ! ========================================================================== + ! SCORE TOTAL MATERIAL REACTION RATES + + i_nuclide = -1 + atom_density = ZERO + + ! Determine score for each bin + call score_general(p, t, n_nuclides_total*t % n_score_bins, filter_index, & + i_nuclide, atom_density, flux) + + end subroutine score_all_nuclides + !=============================================================================== ! SCORE_ANALOG_TALLY keeps track of how many events occur in a specified cell, ! energy range, etc. Note that since these are "analog" tallies, they are only @@ -819,59 +881,6 @@ contains end subroutine score_tracklength_tally -!=============================================================================== -! SCORE_ALL_NUCLIDES tallies individual nuclide reaction rates specifically when -! the user requests all. -!=============================================================================== - - subroutine score_all_nuclides(p, i_tally, flux, filter_index) - - type(Particle), intent(in) :: p - integer, intent(in) :: i_tally - real(8), intent(in) :: flux - integer, intent(in) :: filter_index - - integer :: i ! loop index for nuclides in material - integer :: i_nuclide ! index in nuclides array - real(8) :: atom_density ! atom density of single nuclide in atom/b-cm - type(TallyObject), pointer :: t - type(Material), pointer :: mat - - ! Get pointer to tally - t => tallies(i_tally) - - ! Get pointer to current material. We need this in order to determine what - ! nuclides are in the material - mat => materials(p % material) - - ! ========================================================================== - ! SCORE ALL INDIVIDUAL NUCLIDE REACTION RATES - - NUCLIDE_LOOP: do i = 1, mat % n_nuclides - - ! Determine index in nuclides array and atom density for i-th nuclide in - ! current material - i_nuclide = mat % nuclide(i) - atom_density = mat % atom_density(i) - - ! Determine score for each bin - call score_general(p, t, (i_nuclide-1)*t % n_score_bins, filter_index, & - i_nuclide, atom_density, flux) - - end do NUCLIDE_LOOP - - ! ========================================================================== - ! SCORE TOTAL MATERIAL REACTION RATES - - i_nuclide = -1 - atom_density = ZERO - - ! Determine score for each bin - call score_general(p, t, n_nuclides_total*t % n_score_bins, filter_index, & - i_nuclide, atom_density, flux) - - end subroutine score_all_nuclides - !=============================================================================== ! SCORE_TL_ON_MESH calculate fluxes and reaction rates based on the track-length ! estimate of the flux specifically for tallies that have mesh filters. For @@ -1119,6 +1128,118 @@ contains end subroutine score_tl_on_mesh +!=============================================================================== +! SCORE_COLLISION_TALLY calculates fluxes and reaction rates based on the +! 1/Sigma_t estimate of the flux. This is triggered after every collision. It +! is invalid for tallies that require post-collison information because it can +! score reactions that didn't actually occur, and we don't a priori know what +! the outcome will be for reactions that we didn't sample. +!=============================================================================== + + subroutine score_collision_tally(p) + + type(Particle), intent(in) :: p + + integer :: i + integer :: i_tally + integer :: j ! loop index for scoring bins + integer :: k ! loop index for nuclide bins + integer :: filter_index ! single index for single bin + integer :: i_nuclide ! index in nuclides array (from bins) + real(8) :: flux ! collision estimate of flux + real(8) :: atom_density ! atom density of single nuclide + ! in atom/b-cm + logical :: found_bin ! scoring bin found? + type(TallyObject), pointer :: t + type(Material), pointer :: mat + + ! Determine collision estimate of flux + if (survival_biasing) then + ! We need to account for the fact that some weight was already absorbed + flux = (p % last_wgt + p % absorb_wgt) / material_xs % total + else + flux = p % last_wgt / material_xs % total + end if + + ! A loop over all tallies is necessary because we need to simultaneously + ! determine different filter bins for the same tally in order to score to it + + TALLY_LOOP: do i = 1, active_collision_tallies % size() + ! Get index of tally and pointer to tally + i_tally = active_collision_tallies % get_item(i) + t => tallies(i_tally) + + ! ======================================================================= + ! DETERMINE SCORING BIN COMBINATION + + call get_scoring_bins(p, i_tally, found_bin) + if (.not. found_bin) cycle + + ! ======================================================================= + ! CALCULATE RESULTS AND ACCUMULATE TALLY + + ! If we have made it here, we have a scoring combination of bins for this + ! tally -- now we need to determine where in the results array we should + ! be accumulating the tally values + + ! Determine scoring index for this filter combination + filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 + + if (t % all_nuclides) then + if (p % material /= MATERIAL_VOID) then + call score_all_nuclides(p, i_tally, flux, filter_index) + end if + else + + NUCLIDE_BIN_LOOP: do k = 1, t % n_nuclide_bins + ! Get index of nuclide in nuclides array + i_nuclide = t % nuclide_bins(k) + + if (i_nuclide > 0) then + if (p % material /= MATERIAL_VOID) then + ! Get pointer to current material + mat => materials(p % material) + + ! Determine if nuclide is actually in material + NUCLIDE_MAT_LOOP: do j = 1, mat % n_nuclides + ! If index of nuclide matches the j-th nuclide listed in the + ! material, break out of the loop + if (i_nuclide == mat % nuclide(j)) exit + + ! If we've reached the last nuclide in the material, it means + ! the specified nuclide to be tallied is not in this material + if (j == mat % n_nuclides) then + cycle NUCLIDE_BIN_LOOP + end if + end do NUCLIDE_MAT_LOOP + + atom_density = mat % atom_density(j) + else + atom_density = ZERO + end if + end if + + ! Determine score for each bin + call score_general(p, t, (k-1)*t % n_score_bins, filter_index, & + i_nuclide, atom_density, flux) + + end do NUCLIDE_BIN_LOOP + end if + + ! If the user has specified that we can assume all tallies are spatially + ! separate, this implies that once a tally has been scored to, we needn't + ! check the others. This cuts down on overhead when there are many + ! tallies specified + + if (assume_separate) exit TALLY_LOOP + + end do TALLY_LOOP + + ! Reset tally map positioning + position = 0 + + end subroutine score_collision_tally + !=============================================================================== ! GET_SCORING_BINS determines a combination of filter bins that should be scored ! for a tally based on the particle's current attributes. @@ -1873,6 +1994,8 @@ contains call active_analog_tallies % add(i_user_tallies + i) elseif (user_tallies(i) % estimator == ESTIMATOR_TRACKLENGTH) then call active_tracklength_tallies % add(i_user_tallies + i) + elseif (user_tallies(i) % estimator == ESTIMATOR_COLLISION) then + call active_collision_tallies % add(i_user_tallies + i) end if elseif (user_tallies(i) % type == TALLY_SURFACE_CURRENT) then call active_current_tallies % add(i_user_tallies + i) diff --git a/src/tracking.F90 b/src/tracking.F90 index 173babd2f..81f01b411 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -13,7 +13,7 @@ module tracking use random_lcg, only: prn use string, only: to_str use tally, only: score_analog_tally, score_tracklength_tally, & - score_surface_current + score_collision_tally, score_surface_current use track_output, only: initialize_particle_track, write_particle_track, & add_particle_track, finalize_particle_track @@ -157,6 +157,7 @@ contains ! has occurred rather than before because we need information on the ! outgoing energy for any tallies with an outgoing energy filter + if (active_collision_tallies % size() > 0) call score_collision_tally(p) if (active_analog_tallies % size() > 0) call score_analog_tally(p) ! Reset banked weight during collision From fe0f94c814fe0f1c9b0c8d9ab4296c8f3996ae7a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 10:28:43 +0700 Subject: [PATCH 43/95] Add procedures to read/write 1D string arrays in hdf5_interface. --- src/hdf5_interface.F90 | 196 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 180 insertions(+), 16 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index aa7e762f3..656039d19 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -41,6 +41,7 @@ module hdf5_interface module procedure write_integer_4D module procedure write_long module procedure write_string + module procedure write_string_1D module procedure write_tally_result_1D module procedure write_tally_result_2D end interface write_dataset @@ -58,6 +59,7 @@ module hdf5_interface module procedure read_integer_4D module procedure read_long module procedure read_string + module procedure read_string_1D module procedure read_tally_result_1D module procedure read_tally_result_2D end interface read_dataset @@ -329,7 +331,7 @@ contains end subroutine read_double !=============================================================================== -! WRITE_DOUBLE_1DARRAY writes double precision 1-D array data +! WRITE_DOUBLE_1D writes double precision 1-D array data !=============================================================================== subroutine write_double_1D(group_id, name, buffer, indep) @@ -391,7 +393,7 @@ contains end subroutine write_double_1D_explicit !=============================================================================== -! READ_DOUBLE_1DARRAY reads double precision 1-D array data +! READ_DOUBLE_1D reads double precision 1-D array data !=============================================================================== subroutine read_double_1D(group_id, name, buffer, indep) @@ -449,7 +451,7 @@ contains end subroutine read_double_1D_explicit !=============================================================================== -! WRITE_DOUBLE_2DARRAY writes double precision 2-D array data +! WRITE_DOUBLE_2D writes double precision 2-D array data !=============================================================================== subroutine write_double_2D(group_id, name, buffer, indep) @@ -511,7 +513,7 @@ contains end subroutine write_double_2D_explicit !=============================================================================== -! READ_DOUBLE_2DARRAY reads double precision 2-D array data +! READ_DOUBLE_2D reads double precision 2-D array data !=============================================================================== subroutine read_double_2D(group_id, name, buffer, indep) @@ -569,7 +571,7 @@ contains end subroutine read_double_2D_explicit !=============================================================================== -! WRITE_DOUBLE_3DARRAY writes double precision 3-D array data +! WRITE_DOUBLE_3D writes double precision 3-D array data !=============================================================================== subroutine write_double_3D(group_id, name, buffer, indep) @@ -631,7 +633,7 @@ contains end subroutine write_double_3D_explicit !=============================================================================== -! READ_DOUBLE_3DARRAY reads double precision 3-D array data +! READ_DOUBLE_3D reads double precision 3-D array data !=============================================================================== subroutine read_double_3D(group_id, name, buffer, indep) @@ -689,7 +691,7 @@ contains end subroutine read_double_3D_explicit !=============================================================================== -! WRITE_DOUBLE_4DARRAY writes double precision 4-D array data +! WRITE_DOUBLE_4D writes double precision 4-D array data !=============================================================================== subroutine write_double_4D(group_id, name, buffer, indep) @@ -751,7 +753,7 @@ contains end subroutine write_double_4D_explicit !=============================================================================== -! READ_DOUBLE_4DARRAY reads double precision 4-D array data +! READ_DOUBLE_4D reads double precision 4-D array data !=============================================================================== subroutine read_double_4D(group_id, name, buffer, indep) @@ -896,7 +898,7 @@ contains end subroutine read_integer !=============================================================================== -! WRITE_INTEGER_1DARRAY writes integer precision 1-D array data +! WRITE_INTEGER_1D writes integer precision 1-D array data !=============================================================================== subroutine write_integer_1D(group_id, name, buffer, indep) @@ -958,7 +960,7 @@ contains end subroutine write_integer_1D_explicit !=============================================================================== -! READ_INTEGER_1DARRAY reads integer precision 1-D array data +! READ_INTEGER_1D reads integer precision 1-D array data !=============================================================================== subroutine read_integer_1D(group_id, name, buffer, indep) @@ -1016,7 +1018,7 @@ contains end subroutine read_integer_1D_explicit !=============================================================================== -! WRITE_INTEGER_2DARRAY writes integer precision 2-D array data +! WRITE_INTEGER_2D writes integer precision 2-D array data !=============================================================================== subroutine write_integer_2D(group_id, name, buffer, indep) @@ -1078,7 +1080,7 @@ contains end subroutine write_integer_2D_explicit !=============================================================================== -! READ_INTEGER_2DARRAY reads integer precision 2-D array data +! READ_INTEGER_2D reads integer precision 2-D array data !=============================================================================== subroutine read_integer_2D(group_id, name, buffer, indep) @@ -1136,7 +1138,7 @@ contains end subroutine read_integer_2D_explicit !=============================================================================== -! WRITE_INTEGER_3DARRAY writes integer precision 3-D array data +! WRITE_INTEGER_3D writes integer precision 3-D array data !=============================================================================== subroutine write_integer_3D(group_id, name, buffer, indep) @@ -1198,7 +1200,7 @@ contains end subroutine write_integer_3D_explicit !=============================================================================== -! READ_INTEGER_3DARRAY reads integer precision 3-D array data +! READ_INTEGER_3D reads integer precision 3-D array data !=============================================================================== subroutine read_integer_3D(group_id, name, buffer, indep) @@ -1256,7 +1258,7 @@ contains end subroutine read_integer_3D_explicit !=============================================================================== -! WRITE_INTEGER_4DARRAY writes integer precision 4-D array data +! WRITE_INTEGER_4D writes integer precision 4-D array data !=============================================================================== subroutine write_integer_4D(group_id, name, buffer, indep) @@ -1318,7 +1320,7 @@ contains end subroutine write_integer_4D_explicit !=============================================================================== -! READ_INTEGER_4DARRAY reads integer precision 4-D array data +! READ_INTEGER_4D reads integer precision 4-D array data !=============================================================================== subroutine read_integer_4D(group_id, name, buffer, indep) @@ -1590,6 +1592,168 @@ contains call h5tclose_f(memtype, hdf5_err) end subroutine read_string +!=============================================================================== +! WRITE_STRING_1D writes string 1-D array data +!=============================================================================== + + subroutine write_string_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + character(*), intent(in), target :: buffer(:) ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_string_1D_explicit(group_id, dims, name, buffer, indep) + else + call write_string_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_string_1D + + subroutine write_string_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name + character(*), intent(in), target :: buffer(dims(1)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: filetype + integer(HID_T) :: memtype + integer(HSIZE_T) :: n + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Create datatype for HDF5 file based on C char + n = maxval(len_trim(buffer)) + call h5tcopy_f(H5T_C_S1, filetype, hdf5_err) + call h5tset_size_f(filetype, n + 1, hdf5_err) + + ! Create datatype in memory based on Fortran character + call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) + call h5tset_size_f(memtype, int(len(buffer(1)), HSIZE_T), hdf5_err) + + ! Create dataspace/dataset + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), filetype, dspace, dset, hdf5_err) + + ! Get pointer to start of string + f_ptr = c_loc(buffer(1)(1:1)) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5tclose_f(memtype, hdf5_err) + call h5tclose_f(filetype, hdf5_err) + end subroutine write_string_1D_explicit + +!=============================================================================== +! READ_STRING_1D reads string 1-D array data +!=============================================================================== + + subroutine read_string_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name + character(*), intent(inout), target :: buffer(:) + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_string_1D_explicit(group_id, dims, name, buffer, indep) + else + call read_string_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_string_1D + + subroutine read_string_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name + character(*), intent(inout), target :: buffer(dims(1)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: filetype + integer(HID_T) :: memtype + integer(HSIZE_T) :: size + integer(HSIZE_T) :: n + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Get dataset and dataspace + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + call h5dget_space_f(dset, dspace, hdf5_err) + + ! Make sure buffer is large enough + call h5dget_type_f(dset, filetype, hdf5_err) + call h5tget_size_f(filetype, size, hdf5_err) + if (size > len(buffer(1)) + 1) then + call fatal_error("Character buffer is not long enough to & + &read HDF5 string array.") + end if + + ! Get datatype in memory based on Fortran character + n = len(buffer(1)) + call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) + call h5tset_size_f(memtype, n, hdf5_err) + + ! Get pointer to start of string + f_ptr = c_loc(buffer(1)(1:1)) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, memtype, f_ptr, hdf5_err, mem_space_id=dspace, & + xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, memtype, f_ptr, hdf5_err, mem_space_id=dspace) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5tclose_f(filetype, hdf5_err) + call h5tclose_f(memtype, hdf5_err) + end subroutine read_string_1D_explicit + !=============================================================================== ! WRITE_ATTRIBUTE_STRING !=============================================================================== From 4bf34de6f72593a0728428e357b1902f78dfcad8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 11:09:12 +0700 Subject: [PATCH 44/95] Write moment orders as an array of strings in statepoint files --- docs/source/usersguide/output/statepoint.rst | 14 ++-- openmc/statepoint.py | 21 ++---- src/constants.F90 | 2 +- src/state_point.F90 | 69 ++++---------------- 4 files changed, 27 insertions(+), 79 deletions(-) diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index b17bdca02..7d0767095 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -29,11 +29,11 @@ The current revision of the statepoint file format is 13. Release version number for OpenMC -**/time_stamp** (*char[19]*) +**/time_stamp** (*char[]*) Date and time the state point was written. -**/path** (*char[255]*) +**/path** (*char[]*) Absolute path to directory containing input files. @@ -228,17 +228,15 @@ if (run_mode == MODE_EIGENVALUE) Values of specified scoring bins (e.g. SCORE_FLUX). - **/tallies/tally i/n_user_score_bins** + **/tallies/tally i/n_user_score_bins** (*int*) Number of scoring bins without accounting for those added by expansions, e.g. scatter-PN. - *do J = 1, total number of moments* + **/tallies/tally i/moment_orders** (*char[][]*) - **/tallies/tally i/moments/orderJ** (*char[8]*) - - Tallying moment order for Legendre and spherical - harmonic tally expansions (*e.g.*, 'P2', 'Y1,2', etc.). + Tallying moment orders for Legendre and spherical harmonic tally + expansions (*e.g.*, 'P2', 'Y1,2', etc.). **/source_present** (*int*) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 986d624f9..c0003ad52 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -161,7 +161,7 @@ class StatePoint(object): # Read statepoint revision self._revision = self._f['revision'].value - if self._revision != 13: + if self._revision != 14: raise Exception('Statepoint Revision is not consistent.') # Read OpenMC version @@ -393,27 +393,18 @@ class StatePoint(object): filter.stride *= tally.filters[j].num_bins # Read scattering moment order strings (e.g., P3, Y-1,2, etc.) - moments = [] - subbase = '{0}{1}/moments/'.format(base, tally_key) - - # Extract the moment order string for each score - for k in range(len(scores)): - moment = self._f['{0}order{1}'.format( - subbase, k+1)].value.decode() - - # Remove extra whitespace - moment.replace(" ", "") - moments.append(moment) + moments = self._f['{0}{1}/moment_orders'.format( + base, tally_key)].value # Add the scores to the Tally for j, score in enumerate(scores): # If this is a scattering moment, insert the scattering order if '-n' in score: - score = score.replace('-n', '-' + str(moments[j])) + score = score.replace('-n', '-' + moments[j].decode()) elif '-pn' in score: - score = score.replace('-pn', '-' + str(moments[j])) + score = score.replace('-pn', '-' + moments[j].decode()) elif '-yn' in score: - score = score.replace('-yn', '-' + str(moments[j])) + score = score.replace('-yn', '-' + moments[j].decode()) tally.add_score(score) diff --git a/src/constants.F90 b/src/constants.F90 index 5eba50f6d..6be1326a8 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -11,7 +11,7 @@ module constants integer, parameter :: VERSION_RELEASE = 0 ! Revision numbers for binary files - integer, parameter :: REVISION_STATEPOINT = 13 + integer, parameter :: REVISION_STATEPOINT = 14 integer, parameter :: REVISION_PARTICLE_RESTART = 1 integer, parameter :: REVISION_TRACK = 1 diff --git a/src/state_point.F90 b/src/state_point.F90 index 691d0567e..bf43a1e83 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -49,8 +49,8 @@ contains integer(HID_T) :: cmfd_group integer(HID_T) :: tallies_group, tally_group integer(HID_T) :: meshes_group, mesh_group - integer(HID_T) :: filter_group, moments_group - character(8) :: moment_name ! name of moment (e.g, P3) + integer(HID_T) :: filter_group + character(8), allocatable :: moment_names(:) ! names of moments (e.g, P3) character(MAX_FILE_LEN) :: filename type(StructuredMesh), pointer :: meshp type(TallyObject), pointer :: tally @@ -257,40 +257,36 @@ contains call write_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) ! Write explicit moment order strings for each score bin - moments_group = create_group(tally_group, "moments") k = 1 + allocate(moment_names(tally%n_score_bins)) MOMENT_LOOP: do j = 1, tally%n_user_score_bins select case(tally%score_bins(k)) case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - moment_name = 'P' // trim(to_str(tally%moment_order(k))) - call write_dataset(moments_group, "order" // trim(to_str(k)), moment_name) + moment_names(k) = 'P' // trim(to_str(tally%moment_order(k))) k = k + 1 case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) do n_order = 0, tally%moment_order(k) - moment_name = 'P' // trim(to_str(n_order)) - call write_dataset(moments_group, "order" // trim(to_str(k)), moment_name) + moment_names(k) = 'P' // trim(to_str(n_order)) k = k + 1 end do case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & - SCORE_TOTAL_YN) + SCORE_TOTAL_YN) do n_order = 0, tally%moment_order(k) do nm_order = -n_order, n_order - moment_name = 'Y' // trim(to_str(n_order)) // ',' // & + moment_names(k) = 'Y' // trim(to_str(n_order)) // ',' // & trim(to_str(nm_order)) - call write_dataset(moments_group, "order" // & - trim(to_str(k)), moment_name) - k = k + 1 + k = k + 1 end do end do case default - moment_name = '' - call write_dataset(moments_group, "order" // trim(to_str(k)), & - moment_name) + moment_names(k) = '' k = k + 1 end select end do MOMENT_LOOP - call close_group(moments_group) + call write_dataset(tally_group, "moment_orders", moment_names) + deallocate(moment_names) + call close_group(tally_group) end do TALLY_METADATA @@ -582,11 +578,9 @@ contains subroutine load_state_point() - integer :: i, j, k + integer :: i, j integer :: int_array(3) integer :: curr_key - integer :: n_order ! loop index for moment orders - integer :: nm_order ! loop index for Ynm moment orders integer, allocatable :: id_array(:) integer, allocatable :: key_array(:) integer, allocatable :: temp_array(:) @@ -594,12 +588,11 @@ contains integer(HID_T) :: cmfd_group integer(HID_T) :: tallies_group, tally_group integer(HID_T) :: meshes_group, mesh_group - integer(HID_T) :: filter_group, moments_group + integer(HID_T) :: filter_group real(8) :: real_array(3) logical :: source_present character(MAX_FILE_LEN) :: path_temp character(19) :: current_time - character(8) :: moment_name ! name of moment (e.g, P3, Y-1,1) type(StructuredMesh), pointer :: meshp type(TallyObject), pointer :: tally @@ -800,41 +793,7 @@ contains call read_dataset(tally_group, "score_bins", tally%score_bins) call read_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) - ! Read explicit moment order strings for each score bin - k = 1 - moments_group = open_group(tally_group, "moments") - MOMENT_LOOP: do j = 1, tally%n_user_score_bins - select case(tally%score_bins(k)) - case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - call read_dataset(moments_group, "order" // trim(to_str(k)), & - moment_name) - k = k + 1 - case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - do n_order = 0, tally%moment_order(k) - call read_dataset(moments_group, "order" // trim(to_str(k)), & - moment_name) - k = k + 1 - end do - case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & - SCORE_TOTAL_YN) - do n_order = 0, tally%moment_order(k) - do nm_order = -n_order, n_order - call read_dataset(moments_group, "order" // trim(to_str(k)), & - moment_name) - k = k + 1 - end do - end do - case default - call read_dataset(moments_group, "order" // trim(to_str(k)), & - moment_name) - k = k + 1 - end select - - end do MOMENT_LOOP - - call close_group(moments_group) call close_group(tally_group) - end do TALLY_METADATA ! Check to make sure source bank is present From 2c4f7f113e8d1a64c5e8493298248c14c63df38c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 14:22:55 +0700 Subject: [PATCH 45/95] Restructured most of openmc.statepoint.StatePoint to read values on demand from properties. --- docs/source/usersguide/output/statepoint.rst | 2 +- openmc/constants.py | 5 + openmc/statepoint.py | 747 ++++++++++-------- tests/test_entropy/test_entropy.py | 2 +- tests/test_fixed_source/test_fixed_source.py | 4 +- .../test_sourcepoint_batch.py | 3 +- .../test_sourcepoint_interval.py | 3 +- tests/testing_harness.py | 14 +- 8 files changed, 419 insertions(+), 361 deletions(-) diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index 7d0767095..b2003f26a 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -29,7 +29,7 @@ The current revision of the statepoint file format is 13. Release version number for OpenMC -**/time_stamp** (*char[]*) +**/date_and_time** (*char[]*) Date and time the state point was written. diff --git a/openmc/constants.py b/openmc/constants.py index a6b535e6d..b8020f3da 100644 --- a/openmc/constants.py +++ b/openmc/constants.py @@ -1,5 +1,10 @@ """Dictionaries of integer-to-string mappings from openmc/src/constants.F90""" +RUN_TYPES = {1: 'fixed source', + 2: 'k-eigenvalue', + 3: 'plot', + 4: 'particle restart'} + SURFACE_TYPES = {1: 'x-plane', 2: 'y-plane', 3: 'z-plane', diff --git a/openmc/statepoint.py b/openmc/statepoint.py index c0003ad52..e60b045e4 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -65,28 +65,71 @@ class StatePoint(object): Attributes ---------- + cmfd_on : bool + Indicate whether CMFD is active + cmfd_balance : ndarray + Residual neutron balance for each batch + cmfd_dominance + Dominance ratio for each batch + cmfd_entropy : ndarray + Shannon entropy of CMFD fission source for each batch + cmfd_indices : ndarray + Number of CMFD mesh cells and energy groups. The first three indices + correspond to the x-, y-, and z- spatial directions and the fourth index + is the number of energy groups. + cmfd_srccmp : ndarray + Root-mean-square difference between OpenMC and CMFD fission source for + each batch + cmfd_src : ndarray + CMFD fission source distribution over all mesh cells and energy groups. + current_batch : int + Number of batches simulated + date_and_time : str + Date and time when simulation began + entropy : ndarray + Shannon entropy of fission source at each batch + gen_per_batch : int + Number of fission generations per batch + global_tallies : ndarray + Global tallies and their uncertainties k_combined : list Combined estimator for k-effective and its uncertainty - n_particles : int - Number of particles per generation + k_col_abs : float + Cross-product of collision and absorption estimates of k-effective + k_col_tra : float + Cross-product of collision and tracklength estimates of k-effective + k_abs_tra : float + Cross-product of absorption and tracklength estimates of k-effective + k_generation : ndarray + Estimate of k-effective for each batch/generation + meshes : dict + Dictionary whose keys are mesh IDs and whose values are Mesh objects n_batches : int Number of batches - current_batch : - Number of batches simulated - results : bool - Indicate whether tally results have been read + n_inactive : int + Number of inactive batches + n_particles : int + Number of particles per generation + n_realizations : int + Number of tally realizations + path : str + Working directory for simulation + run_mode : str + Simulation run mode, e.g. 'k-eigenvalue' + seed : int + Pseudorandom number generator seed source : ndarray of SourceSite Array of source sites - with_summary : bool - Indicate whether statepoint data has been linked against a summary file + source_present : bool + Indicate whether source sites are present tallies : dict Dictionary whose keys are tally IDs and whose values are Tally objects tallies_present : bool Indicate whether user-defined tallies are present - global_tallies : ndarray - Global tallies and their uncertainties - n_realizations : int - Number of tally realizations + version: tuple of int + Version of OpenMC + with_summary : bool + Indicate whether statepoint data has been linked against a summary file """ @@ -94,322 +137,381 @@ class StatePoint(object): import h5py self._f = h5py.File(filename, 'r') + # Ensure filetype and revision are correct + if 'filetype' not in self._f or self._f['filetype'].value != -1: + raise IOError('{} is not a statepoint file.'.format(filename)) + if self._f['revision'].value != 14: + raise IOError('Statepoint revision is not consistent.') + # Set flags for what data has been read - self._results = False - self._source = False + self._meshes_read = False + self._tallies_read = False + self._results_read = False + self._source_read = False self._with_summary = False - # Read all metadata - self._read_metadata() - - # Read information about tally meshes - self._read_meshes() - - # Read tally metadata - self._read_tallies() - def close(self): self._f.close() @property - def k_combined(self): - return self._k_combined + def cmfd_on(self): + return self._f['cmfd_on'].value > 0 @property - def n_particles(self): - return self._n_particles + def cmfd_balance(self): + if self.cmfd_on: + return self._f['cmfd/cmfd_balance'].value + else: + return None @property - def n_batches(self): - return self._n_batches + def cmfd_dominance(self): + if self.cmfd_on: + return self._f['cmfd/cmfd_dominance'].value + else: + return None + + @property + def cmfd_entropy(self): + if self.cmfd_on: + return self._f['cmfd/cmfd_entropy'].value + else: + return None + + @property + def cmfd_indices(self): + if self.cmfd_on: + return self._f['cmfd/indices'].value + else: + return None + + @property + def cmfd_src(self): + if self.cmfd_on: + data = self._f['cmfd/cmfd_src'].value + return np.reshape(data, tuple(self.cmfd_indices), order='F') + else: + return None + + @property + def cmfd_srccmp(self): + if self.cmfd_on: + return self._f['cmfd/cmfd_srccmp'].value + else: + return None @property def current_batch(self): - return self._current_batch + return self._f['current_batch'].value @property - def results(self): - return self._results + def date_and_time(self): + return self._f['date_and_time'].value.decode() + + @property + def entropy(self): + if self.run_mode == 'k-eigenvalue': + return self._f['entropy'].value + else: + return None + + @property + def gen_per_batch(self): + if self.run_mode == 'k-eigenvalue': + return self._f['gen_per_batch'].value + else: + return None + + @property + def global_tallies(self): + data = self._f['global_tallies'].value + return np.column_stack((data['sum'], data['sum_sq'])) + + @property + def k_cmfd(self): + if self.cmfd_on: + return self._f['cmfd/k_cmfd'].value + else: + return None + + @property + def k_generation(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_generation']/value + else: + return None + + @property + def k_combined(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_combined'].value + else: + return None + + @property + def k_col_abs(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_col_abs'].value + else: + return None + + @property + def k_col_tra(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_col_tra'].value + else: + return None + + @property + def k_abs_tra(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_abs_tra'].value + else: + return None + + @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/n_meshes'].value + + # 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 = [] + + # Build dictionary of Meshes + base = 'tallies/meshes/mesh ' + + # Iterate over all Meshes + for mesh_key in mesh_keys: + # Read the user-specified Mesh ID and type + mesh_id = self._f['{0}{1}/id'.format(base, mesh_key)].value + mesh_type = self._f['{0}{1}/type'.format(base, mesh_key)].value + + # Read the mesh dimensions, lower-left coordinates, + # upper-right coordinates, and width of each mesh cell + dimension = self._f['{0}{1}/dimension'.format(base, mesh_key)].value + lower_left = self._f['{0}{1}/lower_left'.format(base, mesh_key)].value + upper_right = self._f['{0}{1}/upper_right'.format(base, mesh_key)].value + width = self._f['{0}{1}/width'.format(base, mesh_key)].value + + # Create the Mesh and assign properties to it + mesh = openmc.Mesh(mesh_id) + + mesh.dimension = dimension + mesh.width = width + mesh.lower_left = lower_left + mesh.upper_right = upper_right + + #FIXME: Set the mesh type to 'rectangular' by default + mesh.type = 'rectangular' + + # Add mesh to the global dictionary of all Meshes + self._meshes[mesh_id] = mesh + + return self._meshes + + @property + def n_batches(self): + return self._f['n_batches'].value + + @property + def n_inactive(self): + if self.run_mode == 'k-eigenvalue': + return self._f['n_inactive'].value + else: + return None + + @property + def n_particles(self): + return self._f['n_particles'].value + + @property + def n_realizations(self): + return self._f['n_realizations'].value + + @property + def path(self): + return self._f['path'].value.decode() + + @property + def run_mode(self): + return RUN_TYPES[self._f['run_mode'].value] + + @property + def seed(self): + return self._f['seed'].value @property def source(self): - return self._source + if self.source_present: + if not self._source_read: + # Initialize a NumPy array for the source sites + source_sites = self._f['source_bank'].value + self._source = np.empty_like(source_sites, dtype=SourceSite) + + # Create SourceSite objects for each particle + for i, site in enumerate(source_sites): + s = SourceSite() + s._weight, s._xyz, s._uvw, s._E = site + self._source[i] = s + self._source_read = True + return self._source + else: + return None @property - def with_summary(self): - return self._with_summary + def source_present(self): + return self._f['source_present'] > 0 @property def tallies(self): + if not self._tallies_read: + # Initialize dictionary for tallies + self._tallies = {} + + # Read the number of tallies + n_tallies = self._f['tallies/n_tallies'].value + + # 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 + else: + tally_keys = [] + + base = 'tallies/tally ' + + # Iterate over all Tallies + for tally_key in tally_keys: + + # Read integer Tally estimator type code (analog or tracklength) + estimator_type = self._f['{0}{1}/estimator'.format(base, tally_key)].value + + # Read the Tally size specifications + n_realizations = self._f['{0}{1}/n_realizations'.format(base, tally_key)].value + + # Create Tally object and assign basic properties + tally = openmc.Tally(tally_key) + tally.estimator = ESTIMATOR_TYPES[estimator_type] + tally.num_realizations = n_realizations + + # Read the number of Filters + n_filters = self._f['{0}{1}/n_filters'.format(base, tally_key)].value + + subbase = '{0}{1}/filter '.format(base, tally_key) + + # Initialize all Filters + for j in range(1, n_filters+1): + + # Read the integer Filter type code + filter_type = self._f['{0}{1}/type'.format(subbase, j)].value + + # Read the Filter offset + offset = self._f['{0}{1}/offset'.format(subbase, j)].value + + n_bins = self._f['{0}{1}/n_bins'.format(subbase, j)].value + + if n_bins <= 0: + msg = 'Unable to create Filter "{0}" for Tally ID="{1}" ' \ + 'since no bins were specified'.format(j, tally_key) + raise ValueError(msg) + + # Read the bin values + if FILTER_TYPES[filter_type] in ['energy', 'energyout']: + bins = self._f['{0}{1}/bins'.format(subbase, j)].value + + elif FILTER_TYPES[filter_type] in ['mesh', 'distribcell']: + bins = self._f['{0}{1}/bins'.format(subbase, j)].value + + else: + bins = self._f['{0}{1}/bins'.format(subbase, j)].value + + # Create Filter object + filter = openmc.Filter(FILTER_TYPES[filter_type], bins) + filter.offset = offset + filter.num_bins = n_bins + + if FILTER_TYPES[filter_type] == 'mesh': + mesh_ids = self._f['tallies/meshes/ids'].value + mesh_keys = self._f['tallies/meshes/keys'].value + + key = mesh_keys[mesh_ids == bins][0] + filter.mesh = self.meshes[key] + + # Add Filter to the Tally + tally.add_filter(filter) + + # Read Nuclide bins + n_nuclides = self._f['{0}{1}/n_nuclides'.format(base, tally_key)].value + + nuclide_zaids = self._f['{0}{1}/nuclides'.format(base, tally_key)].value + + # Add all Nuclides to the Tally + for nuclide_zaid in nuclide_zaids: + tally.add_nuclide(nuclide_zaid) + + # Read score bins + n_score_bins = self._f['{0}{1}/n_score_bins'.format(base, tally_key)].value + + tally.num_score_bins = n_score_bins + + score_bins = self._f['{0}{1}/score_bins'.format( + base, tally_key)].value + scores = [SCORE_TYPES[score] for score in score_bins] + n_user_scores = self._f['{0}{1}/n_user_score_bins' + .format(base, tally_key)].value + + # Compute and set the filter strides + for i in range(n_filters): + filter = tally.filters[i] + filter.stride = n_score_bins * n_nuclides + + for j in range(i+1, n_filters): + filter.stride *= tally.filters[j].num_bins + + # Read scattering moment order strings (e.g., P3, Y-1,2, etc.) + moments = self._f['{0}{1}/moment_orders'.format( + base, tally_key)].value + + # Add the scores to the Tally + for j, score in enumerate(scores): + # If this is a scattering moment, insert the scattering order + if '-n' in score: + score = score.replace('-n', '-' + moments[j].decode()) + elif '-pn' in score: + score = score.replace('-pn', '-' + moments[j].decode()) + elif '-yn' in score: + score = score.replace('-yn', '-' + moments[j].decode()) + + tally.add_score(score) + + # Add Tally to the global dictionary of all Tallies + self._tallies[tally_key] = tally + return self._tallies @property def tallies_present(self): - return self._tallies_present + return self._f['tallies/tallies_present'].value @property - def global_tallies(self): - return self._global_tallies + def version(self): + return (self._f['version_major'].value, + self._f['version_minor'].value, + self._f['version_release'].value) @property - def n_realizations(self): - return self._n_realizations - - def _read_metadata(self): - # Read filetype - self._filetype = self._f['filetype'].value - - # Read statepoint revision - self._revision = self._f['revision'].value - if self._revision != 14: - raise Exception('Statepoint Revision is not consistent.') - - # Read OpenMC version - self._version = [self._f['version_major'].value, - self._f['version_minor'].value, - self._f['version_release'].value] - - # Read date and time - self._date_and_time = self._f['date_and_time'].value.decode() - - # Read path - self._path = self._f['path'].value.decode() - - # Read random number seed - self._seed = self._f['seed'].value - - # Read run information - self._run_mode = self._f['run_mode'].value - self._n_particles = self._f['n_particles'].value - self._n_batches = self._f['n_batches'].value - - # Read current batch - self._current_batch = self._f['current_batch'].value - - # Read whether or not the source site distribution is present - self._source_present = self._f['source_present'].value - - # Read criticality information - if self._run_mode == 2: - self._read_criticality() - - def _read_criticality(self): - # Read criticality information - if self._run_mode == 2: - - self._n_inactive = self._f['n_inactive'].value - self._gen_per_batch = self._f['gen_per_batch'].value - self._k_generation = self._f['k_generation'].value - self._entropy = self._f['entropy'].value - - self._k_col_abs = self._f['k_col_abs'].value - self._k_col_tra = self._f['k_col_tra'].value - self._k_abs_tra = self._f['k_abs_tra'].value - self._k_combined = self._f['k_combined'].value - - # Read CMFD information (if used) - self._read_cmfd() - - def _read_cmfd(self): - base = 'cmfd' - - # Read CMFD information - self._cmfd_on = self._f['cmfd_on'].value - - if self._cmfd_on == 1: - self._cmfd_indices = self._f['{0}/indices'.format(base)].value - self._k_cmfd = self._f['{0}/k_cmfd'.format(base)].value - self._cmfd_src = self._f['{0}/cmfd_src'.format(base)].value - self._cmfd_src = np.reshape(self._cmfd_src, tuple(self._cmfd_indices), - order='F') - self._cmfd_entropy = self._f['{0}/cmfd_entropy'.format(base)].value - self._cmfd_balance = self._f['{0}/cmfd_balance'.format(base)].value - self._cmfd_dominance = self._f['{0}/cmfd_dominance'.format(base)].value - self._cmfd_srccmp = self._f['{0}/cmfd_srccmp'.format(base)].value - - def _read_meshes(self): - # Initialize dictionaries for the Meshes - # Keys - Mesh IDs - # Values - Mesh objects - self._meshes = {} - - # Read the number of Meshes - self._n_meshes = self._f['tallies/meshes/n_meshes'].value - - # Read a list of the IDs for each Mesh - if self._n_meshes > 0: - - # OpenMC Mesh IDs (redefined internally from user definitions) - self._mesh_ids = self._f['tallies/meshes/ids'].value - - # User-defined Mesh IDs - self._mesh_keys = self._f['tallies/meshes/keys'].value - - else: - self._mesh_keys = [] - self._mesh_ids = [] - - # Build dictionary of Meshes - base = 'tallies/meshes/mesh ' - - # Iterate over all Meshes - for mesh_key in self._mesh_keys: - - # Read the user-specified Mesh ID and type - mesh_id = self._f['{0}{1}/id'.format(base, mesh_key)].value - mesh_type = self._f['{0}{1}/type'.format(base, mesh_key)].value - - # Get the Mesh dimension - n_dimension = self._f['{0}{1}/n_dimension'.format(base, mesh_key)].value - - # Read the mesh dimensions, lower-left coordinates, - # upper-right coordinates, and width of each mesh cell - dimension = self._f['{0}{1}/dimension'.format(base, mesh_key)].value - lower_left = self._f['{0}{1}/lower_left'.format(base, mesh_key)].value - upper_right = self._f['{0}{1}/upper_right'.format(base, mesh_key)].value - width = self._f['{0}{1}/width'.format(base, mesh_key)].value - - # Create the Mesh and assign properties to it - mesh = openmc.Mesh(mesh_id) - - mesh.dimension = dimension - mesh.width = width - mesh.lower_left = lower_left - mesh.upper_right = upper_right - - #FIXME: Set the mesh type to 'rectangular' by default - mesh.type = 'rectangular' - - # Add mesh to the global dictionary of all Meshes - self._meshes[mesh_id] = mesh - - def _read_tallies(self): - # Initialize dictionaries for the Tallies - # Keys - Tally IDs - # Values - Tally objects - self._tallies = {} - - # Read the number of tallies - self._n_tallies = self._f['/tallies/n_tallies'].value - - # Read a list of the IDs for each Tally - if self._n_tallies > 0: - - # OpenMC Tally IDs (redefined internally from user definitions) - self._tally_ids = self._f['tallies/ids'].value - - # User-defined Tally IDs - self._tally_keys = self._f['tallies/keys'].value - - else: - self._tally_keys = [] - self._tally_ids = [] - - base = 'tallies/tally ' - - # Iterate over all Tallies - for tally_key in self._tally_keys: - - # Read integer Tally estimator type code (analog or tracklength) - estimator_type = self._f['{0}{1}/estimator'.format(base, tally_key)].value - - # Read the Tally size specifications - n_realizations = self._f['{0}{1}/n_realizations'.format(base, tally_key)].value - - # Create Tally object and assign basic properties - tally = openmc.Tally(tally_key) - tally.estimator = ESTIMATOR_TYPES[estimator_type] - tally.num_realizations = n_realizations - - # Read the number of Filters - n_filters = self._f['{0}{1}/n_filters'.format(base, tally_key)].value - - subbase = '{0}{1}/filter '.format(base, tally_key) - - # Initialize all Filters - for j in range(1, n_filters+1): - - # Read the integer Filter type code - filter_type = self._f['{0}{1}/type'.format(subbase, j)].value - - # Read the Filter offset - offset = self._f['{0}{1}/offset'.format(subbase, j)].value - - n_bins = self._f['{0}{1}/n_bins'.format(subbase, j)].value - - if n_bins <= 0: - msg = 'Unable to create Filter "{0}" for Tally ID="{1}" ' \ - 'since no bins were specified'.format(j, tally_key) - raise ValueError(msg) - - # Read the bin values - if FILTER_TYPES[filter_type] in ['energy', 'energyout']: - bins = self._f['{0}{1}/bins'.format(subbase, j)].value - - elif FILTER_TYPES[filter_type] in ['mesh', 'distribcell']: - bins = self._f['{0}{1}/bins'.format(subbase, j)].value - - else: - bins = self._f['{0}{1}/bins'.format(subbase, j)].value - - # Create Filter object - filter = openmc.Filter(FILTER_TYPES[filter_type], bins) - filter.offset = offset - filter.num_bins = n_bins - - if FILTER_TYPES[filter_type] == 'mesh': - key = self._mesh_keys[self._mesh_ids == bins][0] - filter.mesh = self._meshes[key] - - # Add Filter to the Tally - tally.add_filter(filter) - - # Read Nuclide bins - n_nuclides = self._f['{0}{1}/n_nuclides'.format(base, tally_key)].value - - nuclide_zaids = self._f['{0}{1}/nuclides'.format(base, tally_key)].value - - # Add all Nuclides to the Tally - for nuclide_zaid in nuclide_zaids: - tally.add_nuclide(nuclide_zaid) - - # Read score bins - n_score_bins = self._f['{0}{1}/n_score_bins'.format(base, tally_key)].value - - tally.num_score_bins = n_score_bins - - score_bins = self._f['{0}{1}/score_bins'.format( - base, tally_key)].value - scores = [SCORE_TYPES[score] for score in score_bins] - n_user_scores = self._f['{0}{1}/n_user_score_bins' - .format(base, tally_key)].value - - # Compute and set the filter strides - for i in range(n_filters): - filter = tally.filters[i] - filter.stride = n_score_bins * n_nuclides - - for j in range(i+1, n_filters): - filter.stride *= tally.filters[j].num_bins - - # Read scattering moment order strings (e.g., P3, Y-1,2, etc.) - moments = self._f['{0}{1}/moment_orders'.format( - base, tally_key)].value - - # Add the scores to the Tally - for j, score in enumerate(scores): - # If this is a scattering moment, insert the scattering order - if '-n' in score: - score = score.replace('-n', '-' + moments[j].decode()) - elif '-pn' in score: - score = score.replace('-pn', '-' + moments[j].decode()) - elif '-yn' in score: - score = score.replace('-yn', '-' + moments[j].decode()) - - tally.add_score(score) - - # Add Tally to the global dictionary of all Tallies - self.tallies[tally_key] = tally + def with_summary(self): + return self._with_summary def read_results(self): """Read tally results and store them in the ``tallies`` attribute. No results @@ -417,28 +519,13 @@ class StatePoint(object): """ - # Number of realizations for global Tallies - self._n_realizations = self._f['n_realizations'].value - - # Read global Tallies - n_global_tallies = self._f['n_global_tallies'].value - - data = self._f['global_tallies'].value - self._global_tallies = np.column_stack((data['sum'], data['sum_sq'])) - - # Flag indicating if Tallies are present - self._tallies_present = self._f['tallies/tallies_present'].value - base = 'tallies/tally ' # Read Tally results - if self._tallies_present: + if self.tallies_present: # Iterate over and extract the results for all Tallies - for tally_key in self._tally_keys: - - # Get this Tally - tally = self._tallies[tally_key] + for tally_key, tally in self.tallies.items(): # Compute the total number of bins for this Tally num_tot_bins = tally.num_bins @@ -465,39 +552,7 @@ class StatePoint(object): tally.sum_sq = sum_sq # Indicate that Tally results have been read - self._results = True - - def read_source(self): - """Read and store source sites from the statepoint file. By default, source - sites are not loaded upon initialization. - - """ - - # Check whether Tally results have been read - if not self._results: - self.read_results() - - # Check if source bank is in statepoint - if not self._source_present: - print('Unable to read source since it is not in statepoint file') - return - - # Initialize a NumPy array for the source sites - self._source = np.empty(self._n_particles, dtype=SourceSite) - - # For HDF5 state points, copy entire bank - source_sites = self._f['source_bank'].value - - # Initialize SourceSite object for each particle - for i in range(self._n_particles): - # Initialize new source site - site = SourceSite() - - # Read position, angle, and energy - site._weight, site._xyz, site._uvw, site._E = source_sites[i] - - # Store the source site in the NumPy array - self._source[i] = site + self._results_read = True def compute_ci(self, confidence=0.95): """Computes confidence intervals for each Tally bin. diff --git a/tests/test_entropy/test_entropy.py b/tests/test_entropy/test_entropy.py index 9b13fd3dd..cf8503abe 100644 --- a/tests/test_entropy/test_entropy.py +++ b/tests/test_entropy/test_entropy.py @@ -23,7 +23,7 @@ class EntropyTestHarness(TestHarness): # Write out entropy data. outstr += 'entropy:\n' - results = ['{0:12.6E}'.format(x) for x in sp._entropy] + results = ['{0:12.6E}'.format(x) for x in sp.entropy] outstr += '\n'.join(results) + '\n' return outstr diff --git a/tests/test_fixed_source/test_fixed_source.py b/tests/test_fixed_source/test_fixed_source.py index 1f154a465..32cceaf55 100644 --- a/tests/test_fixed_source/test_fixed_source.py +++ b/tests/test_fixed_source/test_fixed_source.py @@ -32,8 +32,8 @@ class FixedSourceTestHarness(TestHarness): tally_num += 1 outstr += 'leakage:\n' - outstr += '{0:12.6E}'.format(sp._global_tallies[3][0]) + '\n' - outstr += '{0:12.6E}'.format(sp._global_tallies[3][1]) + '\n' + outstr += '{0:12.6E}'.format(sp.global_tallies[3][0]) + '\n' + outstr += '{0:12.6E}'.format(sp.global_tallies[3][1]) + '\n' return outstr diff --git a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py index 521e3bb4b..83bb5062c 100644 --- a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py +++ b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py @@ -22,13 +22,12 @@ class SourcepointTestHarness(TestHarness): statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) sp.read_results() - sp.read_source() # Get the eigenvalue information. outstr = TestHarness._get_results(self) # Add the source information. - xyz = sp._source[0]._xyz + xyz = sp.source[0].xyz outstr += ' '.join(['{0:12.6E}'.format(x) for x in xyz]) outstr += "\n" diff --git a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py index 521e3bb4b..83bb5062c 100644 --- a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py +++ b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py @@ -22,13 +22,12 @@ class SourcepointTestHarness(TestHarness): statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) sp.read_results() - sp.read_source() # Get the eigenvalue information. outstr = TestHarness._get_results(self) # Add the source information. - xyz = sp._source[0]._xyz + xyz = sp.source[0].xyz outstr += ' '.join(['{0:12.6E}'.format(x) for x in xyz]) outstr += "\n" diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 2059c46da..05896a214 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -211,19 +211,19 @@ class CMFDTestHarness(TestHarness): # Write out CMFD data. outstr += 'cmfd indices\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._cmfd_indices]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.cmfd_indices]) outstr += '\nk cmfd\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._k_cmfd]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.k_cmfd]) outstr += '\ncmfd entropy\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._cmfd_entropy]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.cmfd_entropy]) outstr += '\ncmfd balance\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._cmfd_balance]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.cmfd_balance]) outstr += '\ncmfd dominance ratio\n' - outstr += '\n'.join(['{0:10.3E}'.format(x) for x in sp._cmfd_dominance]) + outstr += '\n'.join(['{0:10.3E}'.format(x) for x in sp.cmfd_dominance]) outstr += '\ncmfd openmc source comparison\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._cmfd_srccmp]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.cmfd_srccmp]) outstr += '\ncmfd source\n' - cmfdsrc = np.reshape(sp._cmfd_src, np.product(sp._cmfd_indices), + cmfdsrc = np.reshape(sp.cmfd_src, np.product(sp.cmfd_indices), order='F') outstr += '\n'.join(['{0:12.6E}'.format(x) for x in cmfdsrc]) outstr += '\n' From aac5eb6f52f007763ccf478fccaf354361136acf Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 14:32:41 +0700 Subject: [PATCH 46/95] Restructure openmc.particle_restart to read values on demand --- openmc/particle_restart.py | 66 ++++++++++++------- .../results_true.dat | 2 +- .../results_true.dat | 2 +- tests/testing_harness.py | 2 +- 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py index 846c7d566..b09ca0f41 100644 --- a/openmc/particle_restart.py +++ b/openmc/particle_restart.py @@ -1,5 +1,7 @@ import struct +from openmc.constants import RUN_TYPES + class Particle(object): """Information used to restart a specific particle that caused a simulation to @@ -12,10 +14,6 @@ class Particle(object): Attributes ---------- - filetype : int - Integer indicating the file type - revision : int - Revision of the particle restart format current_batch : int The batch containing the particle gen_per_batch : int @@ -43,28 +41,48 @@ class Particle(object): import h5py self._f = h5py.File(filename, 'r') - # Read all metadata - self._read_data() + # Ensure filetype and revision are correct + if 'filetype' not in self._f or self._f['filetype'].value != -2: + raise IOError('{} is not a particle restart file.'.format(filename)) + if self._f['revision'].value != 1: + raise IOError('Particle restart file revision is not consistent.') - def _read_data(self): - # Read filetype - self.filetype = self._f['filetype'].value + @property + def current_batch(self): + return self._f['current_batch'].value - # Read statepoint revision - self.revision = self._f['revision'].value + @property + def current_gen(self): + return self._f['current_gen'].value - # Read current batch - self.current_batch = self._f['current_batch'].value + @property + def energy(self): + return self._f['energy'].value - # Read run information - self.gen_per_batch = self._f['gen_per_batch'].value - self.current_gen = self._f['current_gen'].value - self.n_particles = self._f['n_particles'].value - self.run_mode = self._f['run_mode'].value + @property + def gen_per_batch(self): + return self._f['gen_per_batch'].value - # Read particle properties - self.id = self._f['id'].value - self.weight = self._f['weight'].value - self.energy = self._f['energy'].value - self.xyz = self._f['xyz'].value - self.uvw = self._f['uvw'].value + @property + def id(self): + return self._f['id'].value + + @property + def n_particles(self): + return self._f['n_particles'].value + + @property + def run_mode(self): + return RUN_TYPES[self._f['run_mode'].value] + + @property + def uvw(self): + return self._f['uvw'].value + + @property + def weight(self): + return self._f['weight'].value + + @property + def xyz(self): + return self._f['xyz'].value diff --git a/tests/test_particle_restart_eigval/results_true.dat b/tests/test_particle_restart_eigval/results_true.dat index bbc23fb6e..f34397853 100644 --- a/tests/test_particle_restart_eigval/results_true.dat +++ b/tests/test_particle_restart_eigval/results_true.dat @@ -5,7 +5,7 @@ current gen: particle id: 5.550000E+02 run mode: -2.000000E+00 +k-eigenvalue particle weight: 1.000000E+00 particle energy: diff --git a/tests/test_particle_restart_fixed/results_true.dat b/tests/test_particle_restart_fixed/results_true.dat index 701c3e133..de42a0c68 100644 --- a/tests/test_particle_restart_fixed/results_true.dat +++ b/tests/test_particle_restart_fixed/results_true.dat @@ -5,7 +5,7 @@ current gen: particle id: 9.280000E+02 run mode: -1.000000E+00 +fixed source particle weight: 1.000000E+00 particle energy: diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 05896a214..20edb49d8 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -256,7 +256,7 @@ class ParticleRestartTestHarness(TestHarness): outstr += 'particle id:\n' outstr += "{0:12.6E}\n".format(p.id) outstr += 'run mode:\n' - outstr += "{0:12.6E}\n".format(p.run_mode) + outstr += "{0}\n".format(p.run_mode) outstr += 'particle weight:\n' outstr += "{0:12.6E}\n".format(p.weight) outstr += 'particle energy:\n' From 97a7582c447f4fd881b654daeabbf489442254ce Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 16:19:12 +0700 Subject: [PATCH 47/95] Determine Tally.sum, sum_sq, mean, std_dev on demand. No more read_results()! --- openmc/statepoint.py | 47 ++--------- openmc/summary.py | 10 +-- openmc/tallies.py | 79 ++++++++++++------- tests/test_entropy/test_entropy.py | 1 - tests/test_fixed_source/test_fixed_source.py | 11 ++- .../test_sourcepoint_batch.py | 1 - .../test_sourcepoint_interval.py | 1 - tests/testing_harness.py | 12 ++- 8 files changed, 67 insertions(+), 95 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index e60b045e4..001828414 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -146,7 +146,6 @@ class StatePoint(object): # Set flags for what data has been read self._meshes_read = False self._tallies_read = False - self._results_read = False self._source_read = False self._with_summary = False @@ -317,6 +316,8 @@ class StatePoint(object): # Add mesh to the global dictionary of all Meshes self._meshes[mesh_id] = mesh + self._meshes_read = True + return self._meshes @property @@ -401,6 +402,7 @@ class StatePoint(object): # Create Tally object and assign basic properties tally = openmc.Tally(tally_key) + tally._statepoint = self tally.estimator = ESTIMATOR_TYPES[estimator_type] tally.num_realizations = n_realizations @@ -497,6 +499,8 @@ class StatePoint(object): # Add Tally to the global dictionary of all Tallies self._tallies[tally_key] = tally + self._tallies_read = True + return self._tallies @property @@ -513,47 +517,6 @@ class StatePoint(object): def with_summary(self): return self._with_summary - def read_results(self): - """Read tally results and store them in the ``tallies`` attribute. No results - are read when the statepoint is instantiated. - - """ - - base = 'tallies/tally ' - - # Read Tally results - if self.tallies_present: - - # Iterate over and extract the results for all Tallies - for tally_key, tally in self.tallies.items(): - - # Compute the total number of bins for this Tally - num_tot_bins = tally.num_bins - - # Extract Tally data from the file - data = self._f['{0}{1}/results'.format(base, tally_key)].value - sum = data['sum'] - sum_sq = data['sum_sq'] - - # Define a routine to convert 0 to 1 - def nonzero(val): - return 1 if not val else val - - # Reshape the results arrays - new_shape = (nonzero(tally.num_filter_bins), - nonzero(tally.num_nuclides), - nonzero(tally.num_score_bins)) - - sum = np.reshape(sum, new_shape) - sum_sq = np.reshape(sum_sq, new_shape) - - # Set the data for this Tally - tally.sum = sum - tally.sum_sq = sum_sq - - # Indicate that Tally results have been read - self._results_read = True - def compute_ci(self, confidence=0.95): """Computes confidence intervals for each Tally bin. diff --git a/openmc/summary.py b/openmc/summary.py index 088ff29d1..8b5e5710a 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -532,18 +532,11 @@ class Summary(object): # Iterate over all Tallies for tally_key in tally_keys: - tally_id = int(tally_key.strip('tally ')) subbase = '{0}{1}'.format(base, tally_id) # Read Tally name metadata - name_size = self._f['{0}/name_size'.format(subbase)][...] - if (name_size > 0): - tally_name = self._f['{0}/name'.format(subbase)][...][0] - tally_name = tally_name.lstrip('[\'') - tally_name = tally_name.rstrip('\']') - else: - tally_name = '' + tally_name = self._f['{0}/name'.format(subbase)].value.decode() # Create Tally object and assign basic properties tally = openmc.Tally(tally_id, tally_name) @@ -560,7 +553,6 @@ class Summary(object): # Initialize all Filters for j in range(1, num_filters+1): - subsubbase = '{0}/filter {1}'.format(subbase, j) # Read filter type (e.g., "cell", "energy", etc.) diff --git a/openmc/tallies.py b/openmc/tallies.py index 003acd943..25cc554ee 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -103,6 +103,9 @@ class Tally(object): self._with_batch_statistics = False self._derived = False + self._statepoint = None + self._results_read = False + def __deepcopy__(self, memo): existing = memo.get(id(self)) @@ -121,6 +124,8 @@ class Tally(object): clone._with_summary = self.with_summary clone._with_batch_statistics = self.with_batch_statistics clone._derived = self.derived + clone._statepoint = self._statepoint + clone._results_read = self._results_read clone._filters = [] for filter in self.filters: @@ -259,24 +264,66 @@ class Tally(object): @property def sum(self): + if not self._statepoint: + return None + + if not self._results_read: + # Extract Tally data from the file + data = self._statepoint._f['tallies/tally {0}/results'.format( + self.id)].value + sum = data['sum'] + sum_sq = data['sum_sq'] + + # Define a routine to convert 0 to 1 + def nonzero(val): + return 1 if not val else val + + # Reshape the results arrays + new_shape = (nonzero(self.num_filter_bins), + nonzero(self.num_nuclides), + nonzero(self.num_score_bins)) + + sum = np.reshape(sum, new_shape) + sum_sq = np.reshape(sum_sq, new_shape) + + # Set the data for this Tally + self._sum = sum + self._sum_sq = sum_sq + + # Indicate that Tally results have been read + self._results_read = True + return self._sum @property def sum_sq(self): + if not self._statepoint: + return None + + if not self._results_read: + # Force reading of sum and sum_sq + self.sum + return self._sum_sq @property def mean(self): - # Compute the mean if needed if self._mean is None: - self.compute_mean() + if not self._statepoint: + return None + + self._mean = self.sum / self.num_realizations return self._mean @property def std_dev(self): - # Compute the standard deviation if needed if self._std_dev is None: - self.compute_std_dev() + if not self._statepoint: + return None + + n = self.num_realizations + self._std_dev = np.sqrt((self.sum_sq/n - self.mean**2)/(n - 1)) + self.with_batch_statistics = True return self._std_dev @property @@ -456,30 +503,6 @@ class Tally(object): self._nuclides.remove(nuclide) - def compute_mean(self): - """Compute the sample mean for each bin in the tally""" - - # Calculate sample mean - self._mean = self.sum / self.num_realizations - - def compute_std_dev(self, t_value=1.0): - """Compute the sample standard deviation for each bin in the tally - - Parameters - ---------- - t_value : float, optional - Student's t-value applied to the uncertainty. Defaults to 1.0, - meaning the reported value is the sample standard deviation. - - """ - - # Calculate sample standard deviation - self.compute_mean() - self._std_dev = np.sqrt((self.sum_sq / self.num_realizations - - self.mean**2) / (self.num_realizations - 1)) - self._std_dev *= t_value - self.with_batch_statistics = True - def __repr__(self): string = 'Tally\n' string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self.id) diff --git a/tests/test_entropy/test_entropy.py b/tests/test_entropy/test_entropy.py index cf8503abe..43c17da14 100644 --- a/tests/test_entropy/test_entropy.py +++ b/tests/test_entropy/test_entropy.py @@ -14,7 +14,6 @@ class EntropyTestHarness(TestHarness): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Write out k-combined. outstr = 'k-combined:\n' diff --git a/tests/test_fixed_source/test_fixed_source.py b/tests/test_fixed_source/test_fixed_source.py index 32cceaf55..0595ea1db 100644 --- a/tests/test_fixed_source/test_fixed_source.py +++ b/tests/test_fixed_source/test_fixed_source.py @@ -14,17 +14,16 @@ class FixedSourceTestHarness(TestHarness): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Write out tally data. outstr = '' if self._tallies: tally_num = 1 - for tally_ind in sp._tallies: - tally = sp._tallies[tally_ind] - results = np.zeros((tally._sum.size*2, )) - results[0::2] = tally._sum.ravel() - results[1::2] = tally._sum_sq.ravel() + for tally_ind in sp.tallies: + tally = sp.tallies[tally_ind] + results = np.zeros((tally.sum.size*2, )) + results[0::2] = tally.sum.ravel() + results[1::2] = tally.sum_sq.ravel() results = ['{0:12.6E}'.format(x) for x in results] outstr += 'tally ' + str(tally_num) + ':\n' diff --git a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py index 83bb5062c..59a4702e1 100644 --- a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py +++ b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py @@ -21,7 +21,6 @@ class SourcepointTestHarness(TestHarness): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Get the eigenvalue information. outstr = TestHarness._get_results(self) diff --git a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py index 83bb5062c..59a4702e1 100644 --- a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py +++ b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py @@ -21,7 +21,6 @@ class SourcepointTestHarness(TestHarness): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Get the eigenvalue information. outstr = TestHarness._get_results(self) diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 20edb49d8..3dcbee667 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -93,7 +93,6 @@ class TestHarness(object): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Write out k-combined. outstr = 'k-combined:\n' @@ -103,11 +102,11 @@ class TestHarness(object): # Write out tally data. if self._tallies: tally_num = 1 - for tally_ind in sp._tallies: - tally = sp._tallies[tally_ind] - results = np.zeros((tally._sum.size*2, )) - results[0::2] = tally._sum.ravel() - results[1::2] = tally._sum_sq.ravel() + for tally_ind in sp.tallies: + tally = sp.tallies[tally_ind] + results = np.zeros((tally.sum.size*2, )) + results[0::2] = tally.sum.ravel() + results[1::2] = tally.sum_sq.ravel() results = ['{0:12.6E}'.format(x) for x in results] outstr += 'tally ' + str(tally_num) + ':\n' @@ -204,7 +203,6 @@ class CMFDTestHarness(TestHarness): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Write out the eigenvalue and tallies. outstr = TestHarness._get_results(self) From 9bd1dc0cb906aed33d1424b877c1b36f2a4fcb96 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 16:50:11 +0700 Subject: [PATCH 48/95] Get rid of SourceSite class and just use ndarray with compound datatype --- openmc/statepoint.py | 67 ++----------------- .../test_sourcepoint_batch.py | 2 +- .../test_sourcepoint_interval.py | 2 +- 3 files changed, 7 insertions(+), 64 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 001828414..fc4fc5ee1 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -11,53 +11,6 @@ if sys.version > '3': long = int -class SourceSite(object): - """A single source site produced from fission. - - Attributes - ---------- - weight : float - Weight of the particle arising from the site - xyz : list of float - Cartesian coordinates of the site - uvw : list of float - Directional cosines for particles emerging from the site - E : float - Energy of the emerging particle in MeV - - """ - - def __init__(self): - self._weight = None - self._xyz = None - self._uvw = None - self._E = None - - def __repr__(self): - string = 'SourceSite\n' - string += '{0: <16}{1}{2}\n'.format('\tweight', '=\t', self._weight) - string += '{0: <16}{1}{2}\n'.format('\tE', '=\t', self._E) - string += '{0: <16}{1}{2}\n'.format('\t(x,y,z)', '=\t', self._xyz) - string += '{0: <16}{1}{2}\n'.format('\t(u,v,w)', '=\t', self._uvw) - return string - - @property - def weight(self): - return self._weight - - @property - def xyz(self): - return self._xyz - - @property - def uvw(self): - return self._uvw - - @property - def E(self): - return self._E - - class StatePoint(object): """State information on a simulation at a certain point in time (at the end of a given batch). Statepoints can be used to analyze tally results as well as @@ -118,8 +71,10 @@ class StatePoint(object): Simulation run mode, e.g. 'k-eigenvalue' seed : int Pseudorandom number generator seed - source : ndarray of SourceSite - Array of source sites + source : ndarray of compound datatype + Array of source sites. The compound datatype has fields 'wgt', 'xyz', + 'uvw', and 'E' corresponding to the weight, position, direction, and + energy of the source site. source_present : bool Indicate whether source sites are present tallies : dict @@ -146,7 +101,6 @@ class StatePoint(object): # Set flags for what data has been read self._meshes_read = False self._tallies_read = False - self._source_read = False self._with_summary = False def close(self): @@ -354,18 +308,7 @@ class StatePoint(object): @property def source(self): if self.source_present: - if not self._source_read: - # Initialize a NumPy array for the source sites - source_sites = self._f['source_bank'].value - self._source = np.empty_like(source_sites, dtype=SourceSite) - - # Create SourceSite objects for each particle - for i, site in enumerate(source_sites): - s = SourceSite() - s._weight, s._xyz, s._uvw, s._E = site - self._source[i] = s - self._source_read = True - return self._source + return self._f['source_bank'].value else: return None diff --git a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py index 59a4702e1..a306b9aa7 100644 --- a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py +++ b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py @@ -26,7 +26,7 @@ class SourcepointTestHarness(TestHarness): outstr = TestHarness._get_results(self) # Add the source information. - xyz = sp.source[0].xyz + xyz = sp.source[0]['xyz'] outstr += ' '.join(['{0:12.6E}'.format(x) for x in xyz]) outstr += "\n" diff --git a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py index 59a4702e1..a306b9aa7 100644 --- a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py +++ b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py @@ -26,7 +26,7 @@ class SourcepointTestHarness(TestHarness): outstr = TestHarness._get_results(self) # Add the source information. - xyz = sp.source[0].xyz + xyz = sp.source[0]['xyz'] outstr += ' '.join(['{0:12.6E}'.format(x) for x in xyz]) outstr += "\n" From 0b9aa2815b3dbdfa5031f9edf26d5dd3522153bb Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 18:37:12 +0700 Subject: [PATCH 49/95] Update Jupyter notebooks in documentation --- .../examples/pandas-dataframes.ipynb | 669 +++++++++--------- .../pythonapi/examples/tally-arithmetic.ipynb | 276 ++++---- 2 files changed, 472 insertions(+), 473 deletions(-) diff --git a/docs/source/pythonapi/examples/pandas-dataframes.ipynb b/docs/source/pythonapi/examples/pandas-dataframes.ipynb index 24c5c00a0..384fa7620 100644 --- a/docs/source/pythonapi/examples/pandas-dataframes.ipynb +++ b/docs/source/pythonapi/examples/pandas-dataframes.ipynb @@ -374,7 +374,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAAPZSURB\nVGje7Zs7buMwEIZ9iey50gyNjQpXKTYudIScgkdQYTfut1idwkdQkQNsYQO2Qj0sPiVK+mlQDmwg\nwIcgg8Cc4fCTSK5W4OeFkM8rHv+2I/rgxPZEPZgR7XtQxKdXYuUXJSUnBQ/9WCgo4vOSJ+WFUvF7\nE08mlia+rn7VcKXP8sRszFX8b2MdX2y6v1Tw6MZUw4H4ojfIjD8mvn/qRL5p4+vvlMqvp2EhR8WB\nzfiz20hXORmP9fi/bM9EeUFvV5H/0yRkeSbiGRfFJErxD9ENdz7Mbhig/h89fvtFdMiI/ePUIXV4\nlXju8K3DKv9NThOZ3q2KmUy6grxFES8rjeyic+FFQav+ncg3fXjH+Ts+/iibztFqOiZuZP/Z3Oaf\nPX40NGgST2r+uvQkXXp6cKvmr+r0e1Eef5um3+JHP3IFF1D/seNZJgaDmvY0Gav1s+2f1fqpIcub\nlfKGt6apotG/NVx3SInWtLX+7Vg/Pv1YqOsnun6JSVdOXT/X7vk75f938QP+8OmSBs0fXtymMhJb\nf8qlPynYmpKCh7OB1fzNalOj1sl0ZAruHLiA+RM73pDe/VjMVP89+aTXwjyc/x5n+u991895/utr\nJTy8/06TXh0r/5JOa2JmYmqi4r/vUm/H4wLmT+z4anhr05X+q6KUXhtzr/9qSff5L5uMT//V/NdU\n4YuBTPa/8P67l/6r44ds+hYuoP5jx9ciy6XTWlibBrmx8V/TdMfjkP+6pOsu/lvM9N90sf7r+f6m\n/65n+S8p/itN15v0UkW3/+48+PRfJX6S9Joo4g+G/1qYG9KroqP/WypcuvyXPf13wH89/hHef7MB\n6R3Cqn55U4rv4kfH3zaSgQuYP7HjVf89tXrbO+hfLdr+Ozv/SP1dgtQ/Ov8C+i/3+q/Zf2D/HWi6\nbjT6rym9I/v/03/b+LHS4cTg/utTsV7/net/Afzz4f0XGX84/2j9xZ4/sePR/of2X7D/o+vPo/sv\n6h9B/Bfxr9j1Hz2eN/hO8/wfff4A848+f/1A/530/I0+/8PvH9D3H9HnT+R49P0b+v4PfP/4E/wX\nfP8Mvf9G37/D/ovuP8SeP7Hj0f0vdP8tqP9O339cyv7p3P1fdP8Z3v9G999j13/seMax8x/o+ZN7\n+O+E8zdP/8XOf8Hnz9Dzb7HnT+x49PxlCp7/BM+fOv13wvnXBfivt2lMvD8TyH/Hnb+Gz3+j589j\nz5/Y8ej9h4D+W7qQmf57efqv239n3T+C7z+h969i13/seMax+3/o/cMcu/8Y2H9n3p+J6r98pv8m\n4fwXuH+M3n+OO3++AX9clR+4PhbRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA4LTA4VDA5OjI2\nOjM4KzA3OjAwuRKYlgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wOC0wOFQwOToyNjozOCswNzow\nMMhPICoAAAAASUVORK5CYII=\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JEAsWB/wc/iEAAAPZSURBVGje7Zs7buMwEIZ9iey5\n0gyNjQpXKTYudIScgkdQYTfut1idwkdQkQNsYQO2Qj0sPiVK+mlQDmwgwIcgg8Cc4fCTSK5W4OeF\nkM8rHv+2I/rgxPZEPZgR7XtQxKdXYuUXJSUnBQ/9WCgo4vOSJ+WFUvF7E08mlia+rn7VcKXP8sRs\nzFX8b2MdX2y6v1Tw6MZUw4H4ojfIjD8mvn/qRL5p4+vvlMqvp2EhR8WBzfiz20hXORmP9fi/bM9E\neUFvV5H/0yRkeSbiGRfFJErxD9ENdz7Mbhig/h89fvtFdMiI/ePUIXV4lXju8K3DKv9NThOZ3q2K\nmUy6grxFES8rjeyic+FFQav+ncg3fXjH+Ts+/iibztFqOiZuZP/Z3OafPX40NGgST2r+uvQkXXp6\ncKvmr+r0e1Eef5um3+JHP3IFF1D/seNZJgaDmvY0Gav1s+2f1fqpIcublfKGt6apotG/NVx3SInW\ntLX+7Vg/Pv1YqOsnun6JSVdOXT/X7vk75f938QP+8OmSBs0fXtymMhJbf8qlPynYmpKCh7OB1fzN\nalOj1sl0ZAruHLiA+RM73pDe/VjMVP89+aTXwjyc/x5n+u991895/utrJTy8/06TXh0r/5JOa2Jm\nYmqi4r/vUm/H4wLmT+z4anhr05X+q6KUXhtzr/9qSff5L5uMT//V/NdU4YuBTPa/8P67l/6r44ds\n+hYuoP5jx9ciy6XTWlibBrmx8V/TdMfjkP+6pOsu/lvM9N90sf7r+f6m/65n+S8p/itN15v0UkW3\n/+48+PRfJX6S9Joo4g+G/1qYG9KroqP/WypcuvyXPf13wH89/hHef7MB6R3Cqn55U4rv4kfH3zaS\ngQuYP7HjVf89tXrbO+hfLdr+Ozv/SP1dgtQ/Ov8C+i/3+q/Zf2D/HWi6bjT6rym9I/v/03/b+LHS\n4cTg/utTsV7/net/Afzz4f0XGX84/2j9xZ4/sePR/of2X7D/o+vPo/sv6h9B/Bfxr9j1Hz2eN/hO\n8/wfff4A848+f/1A/530/I0+/8PvH9D3H9HnT+R49P0b+v4PfP/4E/wXfP8Mvf9G37/D/ovuP8Se\nP7Hj0f0vdP8tqP9O339cyv7p3P1fdP8Z3v9G999j13/seMax8x/o+ZN7+O+E8zdP/8XOf8Hnz9Dz\nb7HnT+x49PxlCp7/BM+fOv13wvnXBfivt2lMvD8TyH/Hnb+Gz3+j589jz5/Y8ej9h4D+W7qQmf57\nefqv239n3T+C7z+h969i13/seMax+3/o/cMcu/8Y2H9n3p+J6r98pv8m4fwXuH+M3n+OO3++AX9c\nlR+4PhbRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA5LTE2VDE4OjE5OjQ5KzA3OjAwTRYi9AAA\nACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wOS0xNlQxODoxOTo0OSswNzowMDxLmkgAAAAASUVORK5C\nYII=\n", "text/plain": [ "" ] @@ -562,9 +562,9 @@ "\n", " Copyright: 2011-2015 Massachusetts Institute of Technology\n", " License: http://mit-crpg.github.io/openmc/license.html\n", - " Version: 0.6.2\n", - " Date/Time: 2015-08-11 13:40:43\n", - " MPI Processes: 4\n", + " Version: 0.7.0\n", + " Git SHA1: 36a516ed8125ab8a86d8c9b3aee4bd4bc2db859c\n", + " Date/Time: 2015-09-16 18:22:08\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -590,38 +590,39 @@ "\n", " Bat./Gen. k Average k \n", " ========= ======== ==================== \n", - " 1/1 0.60069 \n", - " 2/1 0.62857 \n", - " 3/1 0.69431 \n", - " 4/1 0.65935 \n", - " 5/1 0.68092 \n", - " 6/1 0.64791 \n", - " 7/1 0.65859 0.65325 +/- 0.00534\n", - " 8/1 0.67381 0.66010 +/- 0.00752\n", - " 9/1 0.74149 0.68045 +/- 0.02103\n", - " 10/1 0.68244 0.68085 +/- 0.01629\n", - " 11/1 0.68068 0.68082 +/- 0.01330\n", - " 12/1 0.70394 0.68412 +/- 0.01172\n", - " 13/1 0.68624 0.68439 +/- 0.01015\n", - " 14/1 0.65667 0.68131 +/- 0.00947\n", - " 15/1 0.70080 0.68326 +/- 0.00869\n", - " 16/1 0.69639 0.68445 +/- 0.00795\n", - " 17/1 0.68786 0.68474 +/- 0.00726\n", - " 18/1 0.63698 0.68106 +/- 0.00762\n", - " 19/1 0.62785 0.67726 +/- 0.00802\n", - " 20/1 0.65759 0.67595 +/- 0.00758\n", - " Triggers unsatisfied, max unc./thresh. is 1.20713 for absorption in tally 10002\n", - " The estimated number of batches is 27\n", + " 1/1 0.59998 \n", + " 2/1 0.65473 \n", + " 3/1 0.67452 \n", + " 4/1 0.66458 \n", + " 5/1 0.70093 \n", + " 6/1 0.70726 \n", + " 7/1 0.65977 0.68351 +/- 0.02375\n", + " 8/1 0.68457 0.68387 +/- 0.01372\n", + " 9/1 0.70024 0.68796 +/- 0.01053\n", + " 10/1 0.64895 0.68016 +/- 0.01128\n", + " 11/1 0.68744 0.68137 +/- 0.00929\n", + " 12/1 0.68037 0.68123 +/- 0.00786\n", + " 13/1 0.64865 0.67715 +/- 0.00793\n", + " 14/1 0.71415 0.68127 +/- 0.00811\n", + " 15/1 0.65717 0.67886 +/- 0.00764\n", + " 16/1 0.71598 0.68223 +/- 0.00769\n", + " 17/1 0.67285 0.68145 +/- 0.00707\n", + " 18/1 0.69329 0.68236 +/- 0.00656\n", + " 19/1 0.65696 0.68055 +/- 0.00634\n", + " 20/1 0.65500 0.67884 +/- 0.00615\n", + " Triggers unsatisfied, max unc./thresh. is 1.21110 for absorption in tally 10002\n", + " The estimated number of batches is 28\n", " Creating state point statepoint.020.h5...\n", - " 21/1 0.68391 0.67645 +/- 0.00711\n", - " 22/1 0.69243 0.67739 +/- 0.00674\n", - " 23/1 0.65491 0.67614 +/- 0.00648\n", - " 24/1 0.64021 0.67425 +/- 0.00641\n", - " 25/1 0.72281 0.67668 +/- 0.00655\n", - " 26/1 0.71261 0.67839 +/- 0.00646\n", - " 27/1 0.69503 0.67914 +/- 0.00621\n", - " Triggers satisfied for batch 27\n", - " Creating state point statepoint.027.h5...\n", + " 21/1 0.67090 0.67835 +/- 0.00577\n", + " 22/1 0.69025 0.67905 +/- 0.00546\n", + " 23/1 0.66113 0.67805 +/- 0.00525\n", + " 24/1 0.67934 0.67812 +/- 0.00496\n", + " 25/1 0.67203 0.67781 +/- 0.00472\n", + " 26/1 0.66928 0.67741 +/- 0.00451\n", + " 27/1 0.70271 0.67856 +/- 0.00445\n", + " 28/1 0.70233 0.67959 +/- 0.00437\n", + " Triggers satisfied for batch 28\n", + " Creating state point statepoint.028.h5...\n", "\n", " ===========================================================================\n", " ======================> SIMULATION FINISHED <======================\n", @@ -630,28 +631,28 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 9.7300E-01 seconds\n", - " Reading cross sections = 3.0300E-01 seconds\n", - " Total time in simulation = 5.9130E+00 seconds\n", - " Time in transport only = 5.4000E+00 seconds\n", - " Time in inactive batches = 7.7300E-01 seconds\n", - " Time in active batches = 5.1400E+00 seconds\n", - " Time synchronizing fission bank = 4.4600E-01 seconds\n", - " Sampling source sites = 0.0000E+00 seconds\n", + " Total time for initialization = 5.5700E-01 seconds\n", + " Reading cross sections = 1.8900E-01 seconds\n", + " Total time in simulation = 1.1416E+01 seconds\n", + " Time in transport only = 1.1395E+01 seconds\n", + " Time in inactive batches = 1.4590E+00 seconds\n", + " Time in active batches = 9.9570E+00 seconds\n", + " Time synchronizing fission bank = 4.0000E-03 seconds\n", + " Sampling source sites = 4.0000E-03 seconds\n", " SEND/RECV source sites = 0.0000E+00 seconds\n", - " Time accumulating tallies = 9.0000E-03 seconds\n", + " Time accumulating tallies = 1.0000E-03 seconds\n", " Total time for finalization = 0.0000E+00 seconds\n", - " Total time elapsed = 6.8870E+00 seconds\n", - " Calculation Rate (inactive) = 16170.8 neutrons/second\n", - " Calculation Rate (active) = 7295.72 neutrons/second\n", + " Total time elapsed = 1.1985E+01 seconds\n", + " Calculation Rate (inactive) = 8567.51 neutrons/second\n", + " Calculation Rate (active) = 3766.19 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 0.68117 +/- 0.00597\n", - " k-effective (Track-length) = 0.67914 +/- 0.00621\n", - " k-effective (Absorption) = 0.67898 +/- 0.00471\n", - " Combined k-effective = 0.67922 +/- 0.00479\n", - " Leakage Fraction = 0.34264 +/- 0.00301\n", + " k-effective (Collision) = 0.68196 +/- 0.00427\n", + " k-effective (Track-length) = 0.67959 +/- 0.00437\n", + " k-effective (Absorption) = 0.67957 +/- 0.00402\n", + " Combined k-effective = 0.67943 +/- 0.00295\n", + " Leakage Fraction = 0.34370 +/- 0.00201\n", "\n" ] }, @@ -671,7 +672,7 @@ "!rm statepoint.*\n", "\n", "# Run OpenMC with MPI!\n", - "executor.run_simulation(mpi_procs=4)" + "executor.run_simulation()" ] }, { @@ -694,9 +695,7 @@ "statepoints = glob.glob('statepoint.*.h5')\n", "\n", "# Load the last statepoint file\n", - "sp = StatePoint(statepoints[-1])\n", - "sp.read_results()\n", - "sp.compute_stdev()" + "sp = StatePoint(statepoints[-1])" ] }, { @@ -770,13 +769,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.14583021]]\n", + "[[[ 0.15044911]]\n", "\n", - " [[ 0.07846909]]\n", + " [[ 0.09149973]]\n", "\n", - " [[ 0.33705448]]\n", + " [[ 0.27611475]]\n", "\n", - " [[ 0.15150059]]]\n" + " [[ 0.12476673]]]\n" ] } ], @@ -840,7 +839,7 @@ " 0.0e+00 - 6.3e-07\n", " fission\n", " 0.000236\n", - " 0.000034\n", + " 0.000035\n", " \n", " \n", " 1\n", @@ -849,8 +848,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " nu-fission\n", - " 0.000576\n", - " 0.000084\n", + " 0.000574\n", + " 0.000086\n", " \n", " \n", " 2\n", @@ -859,8 +858,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " fission\n", - " 0.000069\n", - " 0.000004\n", + " 0.000072\n", + " 0.000006\n", " \n", " \n", " 3\n", @@ -869,8 +868,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " nu-fission\n", - " 0.000183\n", - " 0.000011\n", + " 0.000190\n", + " 0.000014\n", " \n", " \n", " 4\n", @@ -879,8 +878,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " fission\n", - " 0.000366\n", - " 0.000052\n", + " 0.000451\n", + " 0.000058\n", " \n", " \n", " 5\n", @@ -889,8 +888,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " nu-fission\n", - " 0.000892\n", - " 0.000127\n", + " 0.001100\n", + " 0.000141\n", " \n", " \n", " 6\n", @@ -899,8 +898,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " fission\n", - " 0.000109\n", - " 0.000009\n", + " 0.000095\n", + " 0.000006\n", " \n", " \n", " 7\n", @@ -909,8 +908,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " nu-fission\n", - " 0.000284\n", - " 0.000021\n", + " 0.000250\n", + " 0.000016\n", " \n", " \n", " 8\n", @@ -919,8 +918,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " fission\n", - " 0.000540\n", - " 0.000058\n", + " 0.000575\n", + " 0.000080\n", " \n", " \n", " 9\n", @@ -929,8 +928,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " nu-fission\n", - " 0.001316\n", - " 0.000141\n", + " 0.001401\n", + " 0.000194\n", " \n", " \n", " 10\n", @@ -939,8 +938,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " fission\n", - " 0.000144\n", - " 0.000017\n", + " 0.000134\n", + " 0.000011\n", " \n", " \n", " 11\n", @@ -949,8 +948,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " nu-fission\n", - " 0.000376\n", - " 0.000041\n", + " 0.000353\n", + " 0.000028\n", " \n", " \n", " 12\n", @@ -959,8 +958,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " fission\n", - " 0.000830\n", - " 0.000085\n", + " 0.000655\n", + " 0.000071\n", " \n", " \n", " 13\n", @@ -969,8 +968,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " nu-fission\n", - " 0.002022\n", - " 0.000207\n", + " 0.001596\n", + " 0.000174\n", " \n", " \n", " 14\n", @@ -979,8 +978,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " fission\n", - " 0.000168\n", - " 0.000013\n", + " 0.000149\n", + " 0.000009\n", " \n", " \n", " 15\n", @@ -989,8 +988,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " nu-fission\n", - " 0.000434\n", - " 0.000034\n", + " 0.000391\n", + " 0.000023\n", " \n", " \n", " 16\n", @@ -999,8 +998,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " fission\n", - " 0.000738\n", - " 0.000043\n", + " 0.000781\n", + " 0.000078\n", " \n", " \n", " 17\n", @@ -1009,8 +1008,8 @@ " 1\n", " 0.0e+00 - 6.3e-07\n", " nu-fission\n", - " 0.001799\n", - " 0.000105\n", + " 0.001903\n", + " 0.000191\n", " \n", " \n", " 18\n", @@ -1019,8 +1018,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " fission\n", - " 0.000186\n", - " 0.000010\n", + " 0.000185\n", + " 0.000009\n", " \n", " \n", " 19\n", @@ -1029,8 +1028,8 @@ " 1\n", " 6.3e-07 - 2.0e+01\n", " nu-fission\n", - " 0.000486\n", - " 0.000026\n", + " 0.000484\n", + " 0.000024\n", " \n", " \n", "\n", @@ -1040,26 +1039,26 @@ " mesh 1 energy [MeV] score mean std. dev.\n", " x y z \n", "bin \n", - "0 1 1 1 0.0e+00 - 6.3e-07 fission 0.000236 0.000034\n", - "1 1 1 1 0.0e+00 - 6.3e-07 nu-fission 0.000576 0.000084\n", - "2 1 1 1 6.3e-07 - 2.0e+01 fission 0.000069 0.000004\n", - "3 1 1 1 6.3e-07 - 2.0e+01 nu-fission 0.000183 0.000011\n", - "4 1 2 1 0.0e+00 - 6.3e-07 fission 0.000366 0.000052\n", - "5 1 2 1 0.0e+00 - 6.3e-07 nu-fission 0.000892 0.000127\n", - "6 1 2 1 6.3e-07 - 2.0e+01 fission 0.000109 0.000009\n", - "7 1 2 1 6.3e-07 - 2.0e+01 nu-fission 0.000284 0.000021\n", - "8 1 3 1 0.0e+00 - 6.3e-07 fission 0.000540 0.000058\n", - "9 1 3 1 0.0e+00 - 6.3e-07 nu-fission 0.001316 0.000141\n", - "10 1 3 1 6.3e-07 - 2.0e+01 fission 0.000144 0.000017\n", - "11 1 3 1 6.3e-07 - 2.0e+01 nu-fission 0.000376 0.000041\n", - "12 1 4 1 0.0e+00 - 6.3e-07 fission 0.000830 0.000085\n", - "13 1 4 1 0.0e+00 - 6.3e-07 nu-fission 0.002022 0.000207\n", - "14 1 4 1 6.3e-07 - 2.0e+01 fission 0.000168 0.000013\n", - "15 1 4 1 6.3e-07 - 2.0e+01 nu-fission 0.000434 0.000034\n", - "16 1 5 1 0.0e+00 - 6.3e-07 fission 0.000738 0.000043\n", - "17 1 5 1 0.0e+00 - 6.3e-07 nu-fission 0.001799 0.000105\n", - "18 1 5 1 6.3e-07 - 2.0e+01 fission 0.000186 0.000010\n", - "19 1 5 1 6.3e-07 - 2.0e+01 nu-fission 0.000486 0.000026" + "0 1 1 1 0.0e+00 - 6.3e-07 fission 0.000236 0.000035\n", + "1 1 1 1 0.0e+00 - 6.3e-07 nu-fission 0.000574 0.000086\n", + "2 1 1 1 6.3e-07 - 2.0e+01 fission 0.000072 0.000006\n", + "3 1 1 1 6.3e-07 - 2.0e+01 nu-fission 0.000190 0.000014\n", + "4 1 2 1 0.0e+00 - 6.3e-07 fission 0.000451 0.000058\n", + "5 1 2 1 0.0e+00 - 6.3e-07 nu-fission 0.001100 0.000141\n", + "6 1 2 1 6.3e-07 - 2.0e+01 fission 0.000095 0.000006\n", + "7 1 2 1 6.3e-07 - 2.0e+01 nu-fission 0.000250 0.000016\n", + "8 1 3 1 0.0e+00 - 6.3e-07 fission 0.000575 0.000080\n", + "9 1 3 1 0.0e+00 - 6.3e-07 nu-fission 0.001401 0.000194\n", + "10 1 3 1 6.3e-07 - 2.0e+01 fission 0.000134 0.000011\n", + "11 1 3 1 6.3e-07 - 2.0e+01 nu-fission 0.000353 0.000028\n", + "12 1 4 1 0.0e+00 - 6.3e-07 fission 0.000655 0.000071\n", + "13 1 4 1 0.0e+00 - 6.3e-07 nu-fission 0.001596 0.000174\n", + "14 1 4 1 6.3e-07 - 2.0e+01 fission 0.000149 0.000009\n", + "15 1 4 1 6.3e-07 - 2.0e+01 nu-fission 0.000391 0.000023\n", + "16 1 5 1 0.0e+00 - 6.3e-07 fission 0.000781 0.000078\n", + "17 1 5 1 0.0e+00 - 6.3e-07 nu-fission 0.001903 0.000191\n", + "18 1 5 1 6.3e-07 - 2.0e+01 fission 0.000185 0.000009\n", + "19 1 5 1 6.3e-07 - 2.0e+01 nu-fission 0.000484 0.000024" ] }, "execution_count": 25, @@ -1084,9 +1083,9 @@ "outputs": [ { "data": { - "image/png": "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\nAAAAAElFTkSuQmCC\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1109,7 +1108,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 27, @@ -1118,9 +1117,9 @@ }, { "data": { - "image/png": "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\nTkSuQmCC\n", + "image/png": "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\nEvx/rHWCrxSlro8AAAAASUVORK5CYII=\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1166,7 +1165,7 @@ "\tFilters =\t\n", " \t\tcell\t[10000]\n", "\tNuclides =\tU-235 U-238 \n", - "\tScores =\t['scatter-Y0,0', 'scatter-Y1,-1', 'scatter-Y1,0', 'scatter-Y1,1', 'scatter-Y2,-2', 'scatter-Y2,-1', 'scatter-Y2,0', 'scatter-Y2,1', 'scatter-Y2,2']\n", + "\tScores =\t[u'scatter-Y0,0', u'scatter-Y1,-1', u'scatter-Y1,0', u'scatter-Y1,1', u'scatter-Y2,-2', u'scatter-Y2,-1', u'scatter-Y2,0', u'scatter-Y2,1', u'scatter-Y2,2']\n", "\tEstimator =\tanalog\n", "\n" ] @@ -1217,143 +1216,143 @@ " U-235\n", " scatter-Y0,0\n", " 0.036453\n", - " 0.000941\n", + " 0.001219\n", " \n", " \n", " 1\n", " 10000\n", " U-235\n", " scatter-Y1,-1\n", - " -0.000725\n", - " 0.000261\n", + " 0.000302\n", + " 0.000314\n", " \n", " \n", " 2\n", " 10000\n", " U-235\n", " scatter-Y1,0\n", - " -0.000088\n", - " 0.000408\n", + " -0.000006\n", + " 0.000347\n", " \n", " \n", " 3\n", " 10000\n", " U-235\n", " scatter-Y1,1\n", - " 0.000986\n", - " 0.000412\n", + " 0.000244\n", + " 0.000286\n", " \n", " \n", " 4\n", " 10000\n", " U-235\n", " scatter-Y2,-2\n", - " 0.000098\n", - " 0.000204\n", + " 0.000184\n", + " 0.000211\n", " \n", " \n", " 5\n", " 10000\n", " U-235\n", " scatter-Y2,-1\n", - " -0.000358\n", - " 0.000247\n", + " 0.000067\n", + " 0.000173\n", " \n", " \n", " 6\n", " 10000\n", " U-235\n", " scatter-Y2,0\n", - " 0.000197\n", - " 0.000140\n", + " 0.000353\n", + " 0.000210\n", " \n", " \n", " 7\n", " 10000\n", " U-235\n", " scatter-Y2,1\n", - " -0.000084\n", - " 0.000196\n", + " -0.000266\n", + " 0.000263\n", " \n", " \n", " 8\n", " 10000\n", " U-235\n", " scatter-Y2,2\n", - " 0.000052\n", - " 0.000168\n", + " -0.000246\n", + " 0.000153\n", " \n", " \n", " 9\n", " 10000\n", " U-238\n", " scatter-Y0,0\n", - " 2.325600\n", - " 0.015545\n", + " 2.315893\n", + " 0.008243\n", " \n", " \n", " 10\n", " 10000\n", " U-238\n", " scatter-Y1,-1\n", - " -0.030089\n", - " 0.002460\n", + " -0.022028\n", + " 0.002316\n", " \n", " \n", " 11\n", " 10000\n", " U-238\n", " scatter-Y1,0\n", - " -0.004451\n", - " 0.003663\n", + " -0.003426\n", + " 0.002651\n", " \n", " \n", " 12\n", " 10000\n", " U-238\n", " scatter-Y1,1\n", - " 0.020832\n", - " 0.002831\n", + " 0.026620\n", + " 0.002084\n", " \n", " \n", " 13\n", " 10000\n", " U-238\n", " scatter-Y2,-2\n", - " -0.004149\n", - " 0.001530\n", + " -0.001295\n", + " 0.001627\n", " \n", " \n", " 14\n", " 10000\n", " U-238\n", " scatter-Y2,-1\n", - " 0.000735\n", - " 0.001729\n", + " 0.000759\n", + " 0.001426\n", " \n", " \n", " 15\n", " 10000\n", " U-238\n", " scatter-Y2,0\n", - " 0.003431\n", - " 0.002098\n", + " 0.005513\n", + " 0.001983\n", " \n", " \n", " 16\n", " 10000\n", " U-238\n", " scatter-Y2,1\n", - " 0.000385\n", - " 0.001263\n", + " 0.000431\n", + " 0.001862\n", " \n", " \n", " 17\n", " 10000\n", " U-238\n", " scatter-Y2,2\n", - " 0.000002\n", - " 0.001718\n", + " -0.001962\n", + " 0.001222\n", " \n", " \n", "\n", @@ -1362,24 +1361,24 @@ "text/plain": [ " cell nuclide score mean std. dev.\n", "bin \n", - "0 10000 U-235 scatter-Y0,0 0.036453 0.000941\n", - "1 10000 U-235 scatter-Y1,-1 -0.000725 0.000261\n", - "2 10000 U-235 scatter-Y1,0 -0.000088 0.000408\n", - "3 10000 U-235 scatter-Y1,1 0.000986 0.000412\n", - "4 10000 U-235 scatter-Y2,-2 0.000098 0.000204\n", - "5 10000 U-235 scatter-Y2,-1 -0.000358 0.000247\n", - "6 10000 U-235 scatter-Y2,0 0.000197 0.000140\n", - "7 10000 U-235 scatter-Y2,1 -0.000084 0.000196\n", - "8 10000 U-235 scatter-Y2,2 0.000052 0.000168\n", - "9 10000 U-238 scatter-Y0,0 2.325600 0.015545\n", - "10 10000 U-238 scatter-Y1,-1 -0.030089 0.002460\n", - "11 10000 U-238 scatter-Y1,0 -0.004451 0.003663\n", - "12 10000 U-238 scatter-Y1,1 0.020832 0.002831\n", - "13 10000 U-238 scatter-Y2,-2 -0.004149 0.001530\n", - "14 10000 U-238 scatter-Y2,-1 0.000735 0.001729\n", - "15 10000 U-238 scatter-Y2,0 0.003431 0.002098\n", - "16 10000 U-238 scatter-Y2,1 0.000385 0.001263\n", - "17 10000 U-238 scatter-Y2,2 0.000002 0.001718" + "0 10000 U-235 scatter-Y0,0 0.036453 0.001219\n", + "1 10000 U-235 scatter-Y1,-1 0.000302 0.000314\n", + "2 10000 U-235 scatter-Y1,0 -0.000006 0.000347\n", + "3 10000 U-235 scatter-Y1,1 0.000244 0.000286\n", + "4 10000 U-235 scatter-Y2,-2 0.000184 0.000211\n", + "5 10000 U-235 scatter-Y2,-1 0.000067 0.000173\n", + "6 10000 U-235 scatter-Y2,0 0.000353 0.000210\n", + "7 10000 U-235 scatter-Y2,1 -0.000266 0.000263\n", + "8 10000 U-235 scatter-Y2,2 -0.000246 0.000153\n", + "9 10000 U-238 scatter-Y0,0 2.315893 0.008243\n", + "10 10000 U-238 scatter-Y1,-1 -0.022028 0.002316\n", + "11 10000 U-238 scatter-Y1,0 -0.003426 0.002651\n", + "12 10000 U-238 scatter-Y1,1 0.026620 0.002084\n", + "13 10000 U-238 scatter-Y2,-2 -0.001295 0.001627\n", + "14 10000 U-238 scatter-Y2,-1 0.000759 0.001426\n", + "15 10000 U-238 scatter-Y2,0 0.005513 0.001983\n", + "16 10000 U-238 scatter-Y2,1 0.000431 0.001862\n", + "17 10000 U-238 scatter-Y2,2 -0.001962 0.001222" ] }, "execution_count": 29, @@ -1413,8 +1412,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.00171834 0.01554515]\n", - " [ 0.00016768 0.00094081]]]\n" + "[[[ 0.00122163 0.00824348]\n", + " [ 0.00015287 0.00121882]]]\n" ] } ], @@ -1482,25 +1481,25 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.04682759]]\n", + "[[[ 0.0400168 ]]\n", "\n", - " [[ 0.03205271]]\n", + " [[ 0.05233031]]\n", "\n", - " [[ 0.03592433]]\n", + " [[ 0.03819276]]\n", "\n", - " [[ 0.02417979]]\n", + " [[ 0.02900783]]\n", "\n", - " [[ 0.02524314]]\n", + " [[ 0.03176394]]\n", "\n", - " [[ 0.02390359]]\n", + " [[ 0.03046477]]\n", "\n", - " [[ 0.0274475 ]]\n", + " [[ 0.03864163]]\n", "\n", - " [[ 0.02827721]]\n", + " [[ 0.02455132]]\n", "\n", - " [[ 0.0231313 ]]\n", + " [[ 0.02282716]]\n", "\n", - " [[ 0.01898386]]]\n" + " [[ 0.02162945]]]\n" ] } ], @@ -1552,141 +1551,141 @@ " 558\n", " 279\n", " absorption\n", - " 0.000095\n", - " 0.000009\n", + " 0.000085\n", + " 0.000008\n", " \n", " \n", " 559\n", " 279\n", " scatter\n", - " 0.013611\n", - " 0.000544\n", + " 0.013429\n", + " 0.000449\n", " \n", " \n", " 560\n", " 280\n", " absorption\n", - " 0.000096\n", - " 0.000009\n", + " 0.000095\n", + " 0.000014\n", " \n", " \n", " 561\n", " 280\n", " scatter\n", - " 0.013999\n", - " 0.000568\n", + " 0.014770\n", + " 0.000783\n", " \n", " \n", " 562\n", " 281\n", " absorption\n", - " 0.000117\n", - " 0.000015\n", + " 0.000107\n", + " 0.000013\n", " \n", " \n", " 563\n", " 281\n", " scatter\n", - " 0.015951\n", - " 0.000682\n", + " 0.015044\n", + " 0.000605\n", " \n", " \n", " 564\n", " 282\n", " absorption\n", - " 0.000104\n", - " 0.000011\n", + " 0.000110\n", + " 0.000010\n", " \n", " \n", " 565\n", " 282\n", " scatter\n", - " 0.016057\n", - " 0.000574\n", + " 0.016090\n", + " 0.000795\n", " \n", " \n", " 566\n", " 283\n", " absorption\n", - " 0.000117\n", - " 0.000013\n", + " 0.000121\n", + " 0.000012\n", " \n", " \n", " 567\n", " 283\n", " scatter\n", - " 0.015997\n", - " 0.000706\n", + " 0.017010\n", + " 0.000793\n", " \n", " \n", " 568\n", " 284\n", " absorption\n", - " 0.000108\n", + " 0.000110\n", " 0.000007\n", " \n", " \n", " 569\n", " 284\n", " scatter\n", - " 0.016720\n", - " 0.000639\n", + " 0.017010\n", + " 0.000430\n", " \n", " \n", " 570\n", " 285\n", " absorption\n", - " 0.000116\n", - " 0.000008\n", + " 0.000112\n", + " 0.000007\n", " \n", " \n", " 571\n", " 285\n", " scatter\n", - " 0.017764\n", - " 0.000639\n", + " 0.017499\n", + " 0.000615\n", " \n", " \n", " 572\n", " 286\n", " absorption\n", - " 0.000111\n", - " 0.000014\n", + " 0.000127\n", + " 0.000016\n", " \n", " \n", " 573\n", " 286\n", " scatter\n", - " 0.018101\n", - " 0.000766\n", + " 0.017716\n", + " 0.000690\n", " \n", " \n", " 574\n", " 287\n", " absorption\n", - " 0.000115\n", - " 0.000012\n", + " 0.000119\n", + " 0.000013\n", " \n", " \n", " 575\n", " 287\n", " scatter\n", - " 0.018411\n", - " 0.000655\n", + " 0.018041\n", + " 0.000702\n", " \n", " \n", " 576\n", " 288\n", " absorption\n", - " 0.000138\n", - " 0.000014\n", + " 0.000125\n", + " 0.000013\n", " \n", " \n", " 577\n", " 288\n", " scatter\n", - " 0.019154\n", - " 0.000763\n", + " 0.018212\n", + " 0.000715\n", " \n", " \n", "\n", @@ -1695,26 +1694,26 @@ "text/plain": [ " distribcell score mean std. dev.\n", "bin \n", - "558 279 absorption 0.000095 0.000009\n", - "559 279 scatter 0.013611 0.000544\n", - "560 280 absorption 0.000096 0.000009\n", - "561 280 scatter 0.013999 0.000568\n", - "562 281 absorption 0.000117 0.000015\n", - "563 281 scatter 0.015951 0.000682\n", - "564 282 absorption 0.000104 0.000011\n", - "565 282 scatter 0.016057 0.000574\n", - "566 283 absorption 0.000117 0.000013\n", - "567 283 scatter 0.015997 0.000706\n", - "568 284 absorption 0.000108 0.000007\n", - "569 284 scatter 0.016720 0.000639\n", - "570 285 absorption 0.000116 0.000008\n", - "571 285 scatter 0.017764 0.000639\n", - "572 286 absorption 0.000111 0.000014\n", - "573 286 scatter 0.018101 0.000766\n", - "574 287 absorption 0.000115 0.000012\n", - "575 287 scatter 0.018411 0.000655\n", - "576 288 absorption 0.000138 0.000014\n", - "577 288 scatter 0.019154 0.000763" + "558 279 absorption 0.000085 0.000008\n", + "559 279 scatter 0.013429 0.000449\n", + "560 280 absorption 0.000095 0.000014\n", + "561 280 scatter 0.014770 0.000783\n", + "562 281 absorption 0.000107 0.000013\n", + "563 281 scatter 0.015044 0.000605\n", + "564 282 absorption 0.000110 0.000010\n", + "565 282 scatter 0.016090 0.000795\n", + "566 283 absorption 0.000121 0.000012\n", + "567 283 scatter 0.017010 0.000793\n", + "568 284 absorption 0.000110 0.000007\n", + "569 284 scatter 0.017010 0.000430\n", + "570 285 absorption 0.000112 0.000007\n", + "571 285 scatter 0.017499 0.000615\n", + "572 286 absorption 0.000127 0.000016\n", + "573 286 scatter 0.017716 0.000690\n", + "574 287 absorption 0.000119 0.000013\n", + "575 287 scatter 0.018041 0.000702\n", + "576 288 absorption 0.000125 0.000013\n", + "577 288 scatter 0.018212 0.000715" ] }, "execution_count": 33, @@ -1816,8 +1815,8 @@ " 10000\n", " 0\n", " absorption\n", - " 0.000122\n", - " 0.000010\n", + " 0.000136\n", + " 0.000017\n", " \n", " \n", " 1\n", @@ -1831,8 +1830,8 @@ " 10000\n", " 0\n", " scatter\n", - " 0.018596\n", - " 0.000871\n", + " 0.018504\n", + " 0.000740\n", " \n", " \n", " 2\n", @@ -1846,8 +1845,8 @@ " 10000\n", " 1\n", " absorption\n", - " 0.000206\n", - " 0.000014\n", + " 0.000231\n", + " 0.000031\n", " \n", " \n", " 3\n", @@ -1861,8 +1860,8 @@ " 10000\n", " 1\n", " scatter\n", - " 0.029733\n", - " 0.000953\n", + " 0.029149\n", + " 0.001525\n", " \n", " \n", " 4\n", @@ -1876,8 +1875,8 @@ " 10000\n", " 2\n", " absorption\n", - " 0.000280\n", - " 0.000018\n", + " 0.000306\n", + " 0.000032\n", " \n", " \n", " 5\n", @@ -1891,8 +1890,8 @@ " 10000\n", " 2\n", " scatter\n", - " 0.038494\n", - " 0.001383\n", + " 0.039770\n", + " 0.001519\n", " \n", " \n", " 6\n", @@ -1906,8 +1905,8 @@ " 10000\n", " 3\n", " absorption\n", - " 0.000384\n", - " 0.000026\n", + " 0.000339\n", + " 0.000028\n", " \n", " \n", " 7\n", @@ -1921,8 +1920,8 @@ " 10000\n", " 3\n", " scatter\n", - " 0.048839\n", - " 0.001181\n", + " 0.046708\n", + " 0.001355\n", " \n", " \n", " 8\n", @@ -1936,8 +1935,8 @@ " 10000\n", " 4\n", " absorption\n", - " 0.000457\n", - " 0.000023\n", + " 0.000433\n", + " 0.000031\n", " \n", " \n", " 9\n", @@ -1951,8 +1950,8 @@ " 10000\n", " 4\n", " scatter\n", - " 0.058061\n", - " 0.001466\n", + " 0.056359\n", + " 0.001790\n", " \n", " \n", " 10\n", @@ -1966,8 +1965,8 @@ " 10000\n", " 5\n", " absorption\n", - " 0.000494\n", - " 0.000026\n", + " 0.000538\n", + " 0.000028\n", " \n", " \n", " 11\n", @@ -1981,8 +1980,8 @@ " 10000\n", " 5\n", " scatter\n", - " 0.065874\n", - " 0.001575\n", + " 0.064943\n", + " 0.001978\n", " \n", " \n", " 12\n", @@ -1996,8 +1995,8 @@ " 10000\n", " 6\n", " absorption\n", - " 0.000490\n", - " 0.000032\n", + " 0.000588\n", + " 0.000028\n", " \n", " \n", " 13\n", @@ -2011,8 +2010,8 @@ " 10000\n", " 6\n", " scatter\n", - " 0.072420\n", - " 0.001988\n", + " 0.070231\n", + " 0.002714\n", " \n", " \n", " 14\n", @@ -2026,8 +2025,8 @@ " 10000\n", " 7\n", " absorption\n", - " 0.000605\n", - " 0.000042\n", + " 0.000670\n", + " 0.000041\n", " \n", " \n", " 15\n", @@ -2041,8 +2040,8 @@ " 10000\n", " 7\n", " scatter\n", - " 0.078802\n", - " 0.002228\n", + " 0.075852\n", + " 0.001862\n", " \n", " \n", " 16\n", @@ -2056,8 +2055,8 @@ " 10000\n", " 8\n", " absorption\n", - " 0.000627\n", - " 0.000037\n", + " 0.000745\n", + " 0.000039\n", " \n", " \n", " 17\n", @@ -2071,8 +2070,8 @@ " 10000\n", " 8\n", " scatter\n", - " 0.083684\n", - " 0.001936\n", + " 0.086234\n", + " 0.001968\n", " \n", " \n", " 18\n", @@ -2086,8 +2085,8 @@ " 10000\n", " 9\n", " absorption\n", - " 0.000711\n", - " 0.000040\n", + " 0.000731\n", + " 0.000039\n", " \n", " \n", " 19\n", @@ -2101,8 +2100,8 @@ " 10000\n", " 9\n", " scatter\n", - " 0.088989\n", - " 0.001689\n", + " 0.090448\n", + " 0.001956\n", " \n", " \n", "\n", @@ -2138,26 +2137,26 @@ " \n", " \n", "bin \n", - "0 0.000122 0.000010 \n", - "1 0.018596 0.000871 \n", - "2 0.000206 0.000014 \n", - "3 0.029733 0.000953 \n", - "4 0.000280 0.000018 \n", - "5 0.038494 0.001383 \n", - "6 0.000384 0.000026 \n", - "7 0.048839 0.001181 \n", - "8 0.000457 0.000023 \n", - "9 0.058061 0.001466 \n", - "10 0.000494 0.000026 \n", - "11 0.065874 0.001575 \n", - "12 0.000490 0.000032 \n", - "13 0.072420 0.001988 \n", - "14 0.000605 0.000042 \n", - "15 0.078802 0.002228 \n", - "16 0.000627 0.000037 \n", - "17 0.083684 0.001936 \n", - "18 0.000711 0.000040 \n", - "19 0.088989 0.001689 " + "0 0.000136 0.000017 \n", + "1 0.018504 0.000740 \n", + "2 0.000231 0.000031 \n", + "3 0.029149 0.001525 \n", + "4 0.000306 0.000032 \n", + "5 0.039770 0.001519 \n", + "6 0.000339 0.000028 \n", + "7 0.046708 0.001355 \n", + "8 0.000433 0.000031 \n", + "9 0.056359 0.001790 \n", + "10 0.000538 0.000028 \n", + "11 0.064943 0.001978 \n", + "12 0.000588 0.000028 \n", + "13 0.070231 0.002714 \n", + "14 0.000670 0.000041 \n", + "15 0.075852 0.001862 \n", + "16 0.000745 0.000039 \n", + "17 0.086234 0.001968 \n", + "18 0.000731 0.000039 \n", + "19 0.090448 0.001956 " ] }, "execution_count": 34, @@ -2210,38 +2209,38 @@ " \n", " \n", " mean\n", - " 0.000414\n", + " 0.000416\n", " 0.000025\n", " \n", " \n", " std\n", - " 0.000241\n", - " 0.000010\n", + " 0.000238\n", + " 0.000011\n", " \n", " \n", " min\n", - " 0.000013\n", - " 0.000003\n", + " 0.000023\n", + " 0.000004\n", " \n", " \n", " 25%\n", - " 0.000204\n", + " 0.000206\n", " 0.000017\n", " \n", " \n", " 50%\n", - " 0.000387\n", + " 0.000391\n", " 0.000024\n", " \n", " \n", " 75%\n", - " 0.000594\n", + " 0.000626\n", " 0.000031\n", " \n", " \n", " max\n", - " 0.000919\n", - " 0.000060\n", + " 0.000928\n", + " 0.000061\n", " \n", " \n", "\n", @@ -2252,13 +2251,13 @@ " \n", " \n", "count 289.000000 289.000000\n", - "mean 0.000414 0.000025\n", - "std 0.000241 0.000010\n", - "min 0.000013 0.000003\n", - "25% 0.000204 0.000017\n", - "50% 0.000387 0.000024\n", - "75% 0.000594 0.000031\n", - "max 0.000919 0.000060" + "mean 0.000416 0.000025\n", + "std 0.000238 0.000011\n", + "min 0.000023 0.000004\n", + "25% 0.000206 0.000017\n", + "50% 0.000391 0.000024\n", + "75% 0.000626 0.000031\n", + "max 0.000928 0.000061" ] }, "execution_count": 35, @@ -2293,7 +2292,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Mann-Whitney Test p-value: 0.378626583393\n" + "Mann-Whitney Test p-value: 0.474494586047\n" ] } ], @@ -2331,7 +2330,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Mann-Whitney Test p-value: 7.18782749267e-43\n" + "Mann-Whitney Test p-value: 1.364780046e-41\n" ] } ], @@ -2377,7 +2376,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 38, @@ -2386,9 +2385,9 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -2415,7 +2414,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 39, @@ -2424,9 +2423,9 @@ }, { "data": { - "image/png": "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\ngXbt2u1+pgym9cts2bx+2bxuiaJRUkVkp8Lx9rJOnz59oo6QEInasVyWioKIlCtZHzxSNcks2Oo+\nEhGRGBUFERGJUVEQEZEYFQUREYlRURCRjFJQUMD48eNjj0eOHEmTJk344IMPyMnJIS8vj7y8PJo2\nbcqZZ57JuHHjdmhfr1692Hx5eXlcf/31qV6NtKWiICIZxcxiR98MGzaMa6+9ljfffJNWrVoBUFxc\nzJo1a5gyZQonn3wy55xzDsOGDduu/euvv86aNWtit4ceeiiSdUlHKgoiknHcnUcffZSBAwcyZswY\njjnmmB3m2Weffbj++usZNGgQt9xySwQpM5OKgohknCFDhnD77bfzzjvv0KlTp13Oe84557B06VJm\nzJgRm6bzL8qnk9dEpFLsjsScQOW3V+wD2t0ZN24c3bp1o3379rudv3nz5gCsXLky1v7ss8+mRo3/\nfPzdd999XH755RXKka1UFESkUir6YZ4oZsY///lP7rrrLq644goef/zxXc7/ww8/ANCkSZNY+1df\nfZVu3bolPWsmUveRiGSc/Px8xo8fz4cffsg111yzy3lffvll8vPzOfjgg1OULrOpKIhIRmrWrBnj\nx4/nrbfe4sYbb4xN37a/YMmSJTz88MPceeed3HPPPdu11T6F8qn7SEQyVsuWLXnnnXc44YQTWLx4\nMQCNGjXC3alfvz5HH300L774Iqeccsp27c4880xyc3Njj0855RRGjRqV0uzpSkVBRDLK3Llzt3tc\nUFDA/PnzASgsLKxwe9meuo9ERCRGRUFERGJUFEREJEZFQUREYlQUREQkRkVBRERiVBRERCRGRUFE\nRGJUFEQkq7Rv354PPvgg6hgZS0VBROKy7YpnybzFo+zlOAGeeuopfvGLXwAwbdo0TjjhhF0uY968\neeTk5FBSUlK5X0YW0zAXIlIByRxILr6iUJECsjvJGhhv69at242tlEm0pSAiWaWgoIB33nkHgEmT\nJnHUUUfRsGFDmjZtysCBAwFiWxKNGjUiLy+PTz/9FHfn7rvvpqCggPz8fC6++GJWr14dW+7w4cNp\n3bo1e+21V2y+ba8zaNAgzjvvPPr27UvDhg0ZNmwYn332GcceeyyNGzemefPmXHfddWzevDm2vJyc\nHB555BEOPPBAGjRowG233cbs2bM59thjadSoET179txu/lRRURCRjLOrb/iltyJuuOEGBgwYQHFx\n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\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -2459,7 +2458,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.8" + "version": "2.7.9" } }, "nbformat": 4, diff --git a/docs/source/pythonapi/examples/tally-arithmetic.ipynb b/docs/source/pythonapi/examples/tally-arithmetic.ipynb index 2b1205204..0ff2e5f58 100644 --- a/docs/source/pythonapi/examples/tally-arithmetic.ipynb +++ b/docs/source/pythonapi/examples/tally-arithmetic.ipynb @@ -358,7 +358,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAALKSURB\nVGje7dpLcqQwDAbgHHE2YeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmN\nP+HDhw8fPnz48Kf6VH9G+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4\nzPji99z0/AJ4n1lfvJ6fnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6\npA0wfln+ho/fwgYYn19C/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tN\nDbSGz7T0SBEWw4vLXzbQ6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X5\n8wZaxWd1+fMGiuFvir8bvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV\n873hB8UnM3xzANtf8nb4dwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7\nT/ppARBvp48UwJnelT5SACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4/\n/Jve+fhsH6Ctv7n8PTzjvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V\n32/o9+fl389Xnx+g5x/o+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6\n/4Le/6D3T/D9V67Y/ZsVQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/\ngPs/0P4TtP8F7r9J3AIO9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTu\nf4X7b+H+X7T/+BPuf3aM8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIw\nMTUtMDgtMDZUMTY6NDM6MTMrMDc6MDBtUQj+AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA4LTA2\nVDE2OjQzOjEzKzA3OjAwHAywQgAAAABJRU5ErkJggg==\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JEAsiA0Bbyc8AAALKSURBVGje7dpLcqQwDAbgHHE2\nYeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\nnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\nvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\ndwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\nACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\nvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\nQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTUtMDktMTZUMTg6MzE6\nMzUrMDc6MDDLyLisAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA5LTE2VDE4OjMxOjM1KzA3OjAw\nupUAEAAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] @@ -569,7 +569,8 @@ " Copyright: 2011-2015 Massachusetts Institute of Technology\n", " License: http://mit-crpg.github.io/openmc/license.html\n", " Version: 0.7.0\n", - " Date/Time: 2015-08-15 10:52:49\n", + " Git SHA1: 36a516ed8125ab8a86d8c9b3aee4bd4bc2db859c\n", + " Date/Time: 2015-09-16 18:34:04\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -595,26 +596,26 @@ "\n", " Bat./Gen. k Average k \n", " ========= ======== ==================== \n", - " 1/1 1.00465 \n", - " 2/1 1.05814 \n", - " 3/1 1.05114 \n", - " 4/1 1.09189 \n", - " 5/1 1.03731 \n", - " 6/1 1.03510 \n", - " 7/1 1.09378 1.06444 +/- 0.02934\n", - " 8/1 1.04522 1.05803 +/- 0.01811\n", - " 9/1 1.06557 1.05992 +/- 0.01294\n", - " 10/1 1.05757 1.05945 +/- 0.01004\n", - " 11/1 1.04858 1.05764 +/- 0.00839\n", - " 12/1 1.01832 1.05202 +/- 0.00905\n", - " 13/1 1.05822 1.05279 +/- 0.00787\n", - " 14/1 1.07684 1.05547 +/- 0.00744\n", - " 15/1 1.00349 1.05027 +/- 0.00844\n", - " 16/1 1.06969 1.05203 +/- 0.00784\n", - " 17/1 1.06377 1.05301 +/- 0.00722\n", - " 18/1 1.02897 1.05116 +/- 0.00690\n", - " 19/1 1.00685 1.04800 +/- 0.00713\n", - " 20/1 1.02644 1.04656 +/- 0.00679\n", + " 1/1 1.00279 \n", + " 2/1 1.03320 \n", + " 3/1 1.04467 \n", + " 4/1 1.09693 \n", + " 5/1 1.05008 \n", + " 6/1 1.08426 \n", + " 7/1 1.05363 1.06894 +/- 0.01531\n", + " 8/1 0.97961 1.03917 +/- 0.03106\n", + " 9/1 1.06444 1.04549 +/- 0.02285\n", + " 10/1 1.08345 1.05308 +/- 0.01926\n", + " 11/1 1.06871 1.05568 +/- 0.01594\n", + " 12/1 1.03183 1.05228 +/- 0.01390\n", + " 13/1 1.04486 1.05135 +/- 0.01207\n", + " 14/1 1.06468 1.05283 +/- 0.01075\n", + " 15/1 1.04185 1.05173 +/- 0.00968\n", + " 16/1 1.01268 1.04818 +/- 0.00944\n", + " 17/1 1.04129 1.04761 +/- 0.00864\n", + " 18/1 1.01127 1.04481 +/- 0.00843\n", + " 19/1 1.03738 1.04428 +/- 0.00782\n", + " 20/1 1.04410 1.04427 +/- 0.00728\n", " Creating state point statepoint.20.h5...\n", "\n", " ===========================================================================\n", @@ -624,27 +625,27 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 4.4100E-01 seconds\n", - " Reading cross sections = 1.1300E-01 seconds\n", - " Total time in simulation = 1.8418E+01 seconds\n", - " Time in transport only = 1.8403E+01 seconds\n", - " Time in inactive batches = 2.1070E+00 seconds\n", - " Time in active batches = 1.6311E+01 seconds\n", - " Time synchronizing fission bank = 2.0000E-03 seconds\n", - " Sampling source sites = 2.0000E-03 seconds\n", + " Total time for initialization = 5.2100E-01 seconds\n", + " Reading cross sections = 1.7200E-01 seconds\n", + " Total time in simulation = 1.5669E+01 seconds\n", + " Time in transport only = 1.5663E+01 seconds\n", + " Time in inactive batches = 2.1160E+00 seconds\n", + " Time in active batches = 1.3553E+01 seconds\n", + " Time synchronizing fission bank = 0.0000E+00 seconds\n", + " Sampling source sites = 0.0000E+00 seconds\n", " SEND/RECV source sites = 0.0000E+00 seconds\n", " Time accumulating tallies = 0.0000E+00 seconds\n", " Total time for finalization = 1.0000E-03 seconds\n", - " Total time elapsed = 1.8861E+01 seconds\n", - " Calculation Rate (inactive) = 5932.61 neutrons/second\n", - " Calculation Rate (active) = 2299.06 neutrons/second\n", + " Total time elapsed = 1.6203E+01 seconds\n", + " Calculation Rate (inactive) = 5907.37 neutrons/second\n", + " Calculation Rate (active) = 2766.91 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 1.04599 +/- 0.00622\n", - " k-effective (Track-length) = 1.04656 +/- 0.00679\n", - " k-effective (Absorption) = 1.04614 +/- 0.00461\n", - " Combined k-effective = 1.04651 +/- 0.00368\n", + " k-effective (Collision) = 1.04044 +/- 0.00527\n", + " k-effective (Track-length) = 1.04427 +/- 0.00728\n", + " k-effective (Absorption) = 1.04794 +/- 0.00535\n", + " Combined k-effective = 1.04628 +/- 0.00467\n", " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] @@ -692,8 +693,7 @@ "outputs": [], "source": [ "# Load the statepoint file\n", - "sp = StatePoint('statepoint.20.h5')\n", - "sp.read_results()" + "sp = StatePoint('statepoint.20.h5')" ] }, { @@ -759,8 +759,8 @@ " 0\n", " total\n", " (nu-fission / absorption)\n", - " 1.042726\n", - " 0.008661\n", + " 1.046353\n", + " 0.00935\n", " \n", " \n", "\n", @@ -769,7 +769,7 @@ "text/plain": [ " nuclide score mean std. dev.\n", "bin \n", - "0 total (nu-fission / absorption) 1.042726 0.008661" + "0 total (nu-fission / absorption) 1.046353 0.00935" ] }, "execution_count": 26, @@ -827,17 +827,17 @@ " 0\n", " total\n", " absorption\n", - " 0.958874\n", - " 0.007146\n", + " 0.95873\n", + " 0.00774\n", " \n", " \n", "\n", "" ], "text/plain": [ - " nuclide score mean std. dev.\n", - "bin \n", - "0 total absorption 0.958874 0.007146" + " nuclide score mean std. dev.\n", + "bin \n", + "0 total absorption 0.95873 0.00774" ] }, "execution_count": 27, @@ -893,17 +893,17 @@ " 0\n", " total\n", " nu-fission\n", - " 1.09186\n", - " 0.010424\n", + " 1.091622\n", + " 0.011163\n", " \n", " \n", "\n", "" ], "text/plain": [ - " nuclide score mean std. dev.\n", - "bin \n", - "0 total nu-fission 1.09186 0.010424" + " nuclide score mean std. dev.\n", + "bin \n", + "0 total nu-fission 1.091622 0.011163" ] }, "execution_count": 28, @@ -966,8 +966,8 @@ " 10000\n", " total\n", " absorption\n", - " 0.802921\n", - " 0.006109\n", + " 0.802012\n", + " 0.006609\n", " \n", " \n", "\n", @@ -976,7 +976,7 @@ "text/plain": [ " energy [MeV] cell nuclide score mean std. dev.\n", "bin \n", - "0 0.0e+00 - 6.2e-01 10000 total absorption 0.802921 0.006109" + "0 0.0e+00 - 6.2e-01 10000 total absorption 0.802012 0.006609" ] }, "execution_count": 29, @@ -1037,8 +1037,8 @@ " 10000\n", " total\n", " (nu-fission / absorption)\n", - " 1.240421\n", - " 0.010978\n", + " 1.246604\n", + " 0.011825\n", " \n", " \n", "\n", @@ -1047,11 +1047,11 @@ "text/plain": [ " energy [MeV] cell nuclide score mean \\\n", "bin \n", - "0 0.0e+00 - 6.2e-01 10000 total (nu-fission / absorption) 1.240421 \n", + "0 0.0e+00 - 6.2e-01 10000 total (nu-fission / absorption) 1.246604 \n", "\n", " std. dev. \n", "bin \n", - "0 0.010978 " + "0 0.011825 " ] }, "execution_count": 30, @@ -1105,8 +1105,8 @@ " 0\n", " total\n", " (((absorption * nu-fission) * absorption) * (n...\n", - " 1.042726\n", - " 0.017538\n", + " 1.046353\n", + " 0.01894\n", " \n", " \n", "\n", @@ -1115,11 +1115,11 @@ "text/plain": [ " nuclide score mean \\\n", "bin \n", - "0 total (((absorption * nu-fission) * absorption) * (n... 1.042726 \n", + "0 total (((absorption * nu-fission) * absorption) * (n... 1.046353 \n", "\n", " std. dev. \n", "bin \n", - "0 0.017538 " + "0 0.01894 " ] }, "execution_count": 31, @@ -1197,7 +1197,7 @@ " (U-238 / total)\n", " (nu-fission / flux)\n", " 0.000001\n", - " 6.985151e-09\n", + " 6.859257e-09\n", " \n", " \n", " 1\n", @@ -1205,8 +1205,8 @@ " 0.0e+00 - 6.3e-07\n", " (U-238 / total)\n", " (scatter / flux)\n", - " 0.209988\n", - " 2.206753e-03\n", + " 0.209986\n", + " 1.966887e-03\n", " \n", " \n", " 2\n", @@ -1214,8 +1214,8 @@ " 0.0e+00 - 6.3e-07\n", " (U-235 / total)\n", " (nu-fission / flux)\n", - " 0.355276\n", - " 3.741612e-03\n", + " 0.355667\n", + " 3.717881e-03\n", " \n", " \n", " 3\n", @@ -1224,7 +1224,7 @@ " (U-235 / total)\n", " (scatter / flux)\n", " 0.005555\n", - " 5.842517e-05\n", + " 5.218094e-05\n", " \n", " \n", " 4\n", @@ -1232,8 +1232,8 @@ " 6.3e-07 - 2.0e+01\n", " (U-238 / total)\n", " (nu-fission / flux)\n", - " 0.007229\n", - " 5.951357e-05\n", + " 0.007165\n", + " 5.625590e-05\n", " \n", " \n", " 5\n", @@ -1241,8 +1241,8 @@ " 6.3e-07 - 2.0e+01\n", " (U-238 / total)\n", " (scatter / flux)\n", - " 0.227642\n", - " 9.496469e-04\n", + " 0.227653\n", + " 8.544314e-04\n", " \n", " \n", " 6\n", @@ -1250,8 +1250,8 @@ " 6.3e-07 - 2.0e+01\n", " (U-235 / total)\n", " (nu-fission / flux)\n", - " 0.008076\n", - " 5.699123e-05\n", + " 0.008089\n", + " 5.080374e-05\n", " \n", " \n", " 7\n", @@ -1259,8 +1259,8 @@ " 6.3e-07 - 2.0e+01\n", " (U-235 / total)\n", " (scatter / flux)\n", - " 0.003369\n", - " 1.369755e-05\n", + " 0.003370\n", + " 1.361116e-05\n", " \n", " \n", "\n", @@ -1270,24 +1270,24 @@ " cell energy [MeV] nuclide score mean \\\n", "bin \n", "0 10000 0.0e+00 - 6.3e-07 (U-238 / total) (nu-fission / flux) 0.000001 \n", - "1 10000 0.0e+00 - 6.3e-07 (U-238 / total) (scatter / flux) 0.209988 \n", - "2 10000 0.0e+00 - 6.3e-07 (U-235 / total) (nu-fission / flux) 0.355276 \n", + "1 10000 0.0e+00 - 6.3e-07 (U-238 / total) (scatter / flux) 0.209986 \n", + "2 10000 0.0e+00 - 6.3e-07 (U-235 / total) (nu-fission / flux) 0.355667 \n", "3 10000 0.0e+00 - 6.3e-07 (U-235 / total) (scatter / flux) 0.005555 \n", - "4 10000 6.3e-07 - 2.0e+01 (U-238 / total) (nu-fission / flux) 0.007229 \n", - "5 10000 6.3e-07 - 2.0e+01 (U-238 / total) (scatter / flux) 0.227642 \n", - "6 10000 6.3e-07 - 2.0e+01 (U-235 / total) (nu-fission / flux) 0.008076 \n", - "7 10000 6.3e-07 - 2.0e+01 (U-235 / total) (scatter / flux) 0.003369 \n", + "4 10000 6.3e-07 - 2.0e+01 (U-238 / total) (nu-fission / flux) 0.007165 \n", + "5 10000 6.3e-07 - 2.0e+01 (U-238 / total) (scatter / flux) 0.227653 \n", + "6 10000 6.3e-07 - 2.0e+01 (U-235 / total) (nu-fission / flux) 0.008089 \n", + "7 10000 6.3e-07 - 2.0e+01 (U-235 / total) (scatter / flux) 0.003370 \n", "\n", " std. dev. \n", "bin \n", - "0 6.985151e-09 \n", - "1 2.206753e-03 \n", - "2 3.741612e-03 \n", - "3 5.842517e-05 \n", - "4 5.951357e-05 \n", - "5 9.496469e-04 \n", - "6 5.699123e-05 \n", - "7 1.369755e-05 " + "0 6.859257e-09 \n", + "1 1.966887e-03 \n", + "2 3.717881e-03 \n", + "3 5.218094e-05 \n", + "4 5.625590e-05 \n", + "5 8.544314e-04 \n", + "6 5.080374e-05 \n", + "7 1.361116e-05 " ] }, "execution_count": 33, @@ -1318,11 +1318,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 6.63809296e-07]\n", - " [ 3.55275544e-01]]\n", + "[[[ 6.64174599e-07]\n", + " [ 3.55666541e-01]]\n", "\n", - " [[ 7.22895528e-03]\n", - " [ 8.07565148e-03]]]\n" + " [[ 7.16505734e-03]\n", + " [ 8.08949336e-03]]]\n" ] } ], @@ -1350,9 +1350,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.00555505]]\n", + "[[[ 0.00555465]]\n", "\n", - " [[ 0.0033688 ]]]\n" + " [[ 0.00337011]]]\n" ] } ], @@ -1374,8 +1374,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.2276418]\n", - " [ 0.0033688]]]\n" + "[[[ 0.22765348]\n", + " [ 0.00337011]]]\n" ] } ], @@ -1434,7 +1434,7 @@ " U-238\n", " nu-fission\n", " 0.000002\n", - " 1.211808e-08\n", + " 1.284890e-08\n", " \n", " \n", " 1\n", @@ -1442,8 +1442,8 @@ " 0.0e+00 - 6.3e-07\n", " U-235\n", " nu-fission\n", - " 0.870360\n", - " 6.496431e-03\n", + " 0.867982\n", + " 7.022256e-03\n", " \n", " \n", " 2\n", @@ -1451,8 +1451,8 @@ " 6.3e-07 - 2.0e+01\n", " U-238\n", " nu-fission\n", - " 0.083226\n", - " 6.367951e-04\n", + " 0.082801\n", + " 6.087096e-04\n", " \n", " \n", " 3\n", @@ -1460,8 +1460,8 @@ " 6.3e-07 - 2.0e+01\n", " U-235\n", " nu-fission\n", - " 0.092974\n", - " 5.921990e-04\n", + " 0.093484\n", + " 5.275039e-04\n", " \n", " \n", "\n", @@ -1470,10 +1470,10 @@ "text/plain": [ " cell energy [MeV] nuclide score mean std. dev.\n", "bin \n", - "0 10000 0.0e+00 - 6.3e-07 U-238 nu-fission 0.000002 1.211808e-08\n", - "1 10000 0.0e+00 - 6.3e-07 U-235 nu-fission 0.870360 6.496431e-03\n", - "2 10000 6.3e-07 - 2.0e+01 U-238 nu-fission 0.083226 6.367951e-04\n", - "3 10000 6.3e-07 - 2.0e+01 U-235 nu-fission 0.092974 5.921990e-04" + "0 10000 0.0e+00 - 6.3e-07 U-238 nu-fission 0.000002 1.284890e-08\n", + "1 10000 0.0e+00 - 6.3e-07 U-235 nu-fission 0.867982 7.022256e-03\n", + "2 10000 6.3e-07 - 2.0e+01 U-238 nu-fission 0.082801 6.087096e-04\n", + "3 10000 6.3e-07 - 2.0e+01 U-235 nu-fission 0.093484 5.275039e-04" ] }, "execution_count": 37, @@ -1526,8 +1526,8 @@ " 1.0e-08 - 1.1e-07\n", " H-1\n", " scatter\n", - " 4.638428\n", - " 0.034134\n", + " 4.620525\n", + " 0.038249\n", " \n", " \n", " 1\n", @@ -1535,8 +1535,8 @@ " 1.1e-07 - 1.2e-06\n", " H-1\n", " scatter\n", - " 2.050818\n", - " 0.010745\n", + " 2.036841\n", + " 0.013203\n", " \n", " \n", " 2\n", @@ -1544,8 +1544,8 @@ " 1.2e-06 - 1.3e-05\n", " H-1\n", " scatter\n", - " 1.656905\n", - " 0.009480\n", + " 1.659916\n", + " 0.010107\n", " \n", " \n", " 3\n", @@ -1553,8 +1553,8 @@ " 1.3e-05 - 1.4e-04\n", " H-1\n", " scatter\n", - " 1.870808\n", - " 0.011883\n", + " 1.861546\n", + " 0.013328\n", " \n", " \n", " 4\n", @@ -1562,8 +1562,8 @@ " 1.4e-04 - 1.5e-03\n", " H-1\n", " scatter\n", - " 2.045621\n", - " 0.011414\n", + " 2.049664\n", + " 0.008215\n", " \n", " \n", " 5\n", @@ -1571,8 +1571,8 @@ " 1.5e-03 - 1.6e-02\n", " H-1\n", " scatter\n", - " 2.163297\n", - " 0.008725\n", + " 2.162157\n", + " 0.010245\n", " \n", " \n", " 6\n", @@ -1580,8 +1580,8 @@ " 1.6e-02 - 1.7e-01\n", " H-1\n", " scatter\n", - " 2.202045\n", - " 0.013500\n", + " 2.224496\n", + " 0.013796\n", " \n", " \n", " 7\n", @@ -1589,8 +1589,8 @@ " 1.7e-01 - 1.9e+00\n", " H-1\n", " scatter\n", - " 1.996977\n", - " 0.010791\n", + " 1.997585\n", + " 0.009161\n", " \n", " \n", " 8\n", @@ -1598,8 +1598,8 @@ " 1.9e+00 - 2.0e+01\n", " H-1\n", " scatter\n", - " 0.370890\n", - " 0.003597\n", + " 0.373472\n", + " 0.003922\n", " \n", " \n", "\n", @@ -1608,15 +1608,15 @@ "text/plain": [ " cell energy [MeV] nuclide score mean std. dev.\n", "bin \n", - "0 10002 1.0e-08 - 1.1e-07 H-1 scatter 4.638428 0.034134\n", - "1 10002 1.1e-07 - 1.2e-06 H-1 scatter 2.050818 0.010745\n", - "2 10002 1.2e-06 - 1.3e-05 H-1 scatter 1.656905 0.009480\n", - "3 10002 1.3e-05 - 1.4e-04 H-1 scatter 1.870808 0.011883\n", - "4 10002 1.4e-04 - 1.5e-03 H-1 scatter 2.045621 0.011414\n", - "5 10002 1.5e-03 - 1.6e-02 H-1 scatter 2.163297 0.008725\n", - "6 10002 1.6e-02 - 1.7e-01 H-1 scatter 2.202045 0.013500\n", - "7 10002 1.7e-01 - 1.9e+00 H-1 scatter 1.996977 0.010791\n", - "8 10002 1.9e+00 - 2.0e+01 H-1 scatter 0.370890 0.003597" + "0 10002 1.0e-08 - 1.1e-07 H-1 scatter 4.620525 0.038249\n", + "1 10002 1.1e-07 - 1.2e-06 H-1 scatter 2.036841 0.013203\n", + "2 10002 1.2e-06 - 1.3e-05 H-1 scatter 1.659916 0.010107\n", + "3 10002 1.3e-05 - 1.4e-04 H-1 scatter 1.861546 0.013328\n", + "4 10002 1.4e-04 - 1.5e-03 H-1 scatter 2.049664 0.008215\n", + "5 10002 1.5e-03 - 1.6e-02 H-1 scatter 2.162157 0.010245\n", + "6 10002 1.6e-02 - 1.7e-01 H-1 scatter 2.224496 0.013796\n", + "7 10002 1.7e-01 - 1.9e+00 H-1 scatter 1.997585 0.009161\n", + "8 10002 1.9e+00 - 2.0e+01 H-1 scatter 0.373472 0.003922" ] }, "execution_count": 38, @@ -1649,7 +1649,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.8" + "version": "2.7.9" } }, "nbformat": 4, From c99c1f18708ad1bfca9c04299f68eb3e47adb6d3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 16 Sep 2015 18:48:28 +0700 Subject: [PATCH 50/95] Fix bug with source_present --- openmc/statepoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index fc4fc5ee1..126d6b97e 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -314,7 +314,7 @@ class StatePoint(object): @property def source_present(self): - return self._f['source_present'] > 0 + return self._f['source_present'].value > 0 @property def tallies(self): From 9ced99197b14e73d0f71909818d3290d0c23a59c Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Wed, 16 Sep 2015 18:04:44 -0400 Subject: [PATCH 51/95] Add collision estimator to PyAPI --- openmc/constants.py | 3 ++- openmc/statepoint.py | 2 +- openmc/tallies.py | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openmc/constants.py b/openmc/constants.py index a6b535e6d..73da05a71 100644 --- a/openmc/constants.py +++ b/openmc/constants.py @@ -25,7 +25,8 @@ LATTICE_TYPES = {1: 'rectangular', 2: 'hexagonal'} ESTIMATOR_TYPES = {1: 'analog', - 2: 'tracklength'} + 2: 'tracklength', + 3: 'collision'} FILTER_TYPES = {1: 'universe', 2: 'material', diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 06ed51c18..e2efef6e0 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -310,7 +310,7 @@ class StatePoint(object): # Iterate over all Tallies for tally_key in self._tally_keys: - # Read integer Tally estimator type code (analog or tracklength) + # Read integer Tally estimator type code (analog, tracklength, or collision) estimator_type = self._f['{0}{1}/estimator'.format(base, tally_key)].value # Read the Tally size specifications diff --git a/openmc/tallies.py b/openmc/tallies.py index 003acd943..c968e68c9 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -52,7 +52,7 @@ class Tally(object): List of nuclides to score results for scores : list of str List of defined scores, e.g. 'flux', 'fission', etc. - estimator : {'analog', 'tracklength'} + estimator : {'analog', 'tracklength', 'collision'} Type of estimator for the tally triggers : list of openmc.trigger.Trigger List of tally triggers @@ -289,7 +289,8 @@ class Tally(object): @estimator.setter def estimator(self, estimator): - check_value('estimator', estimator, ['analog', 'tracklength']) + check_value('estimator', estimator, + ['analog', 'tracklength', 'collision']) self._estimator = estimator def add_trigger(self, trigger): From 8b67fa7a92115bac589dec698e5b513c02580f37 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 17 Sep 2015 07:12:05 +0700 Subject: [PATCH 52/95] Use structured array for global tallies with mean and std_dev fields --- openmc/statepoint.py | 80 ++++++-------------- tests/test_fixed_source/test_fixed_source.py | 5 +- 2 files changed, 25 insertions(+), 60 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 126d6b97e..5c71b3f5b 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -43,8 +43,9 @@ class StatePoint(object): Shannon entropy of fission source at each batch gen_per_batch : int Number of fission generations per batch - global_tallies : ndarray - Global tallies and their uncertainties + global_tallies : ndarray of compound datatype + Global tallies for k-effective estimates and leakage. The compound + datatype has fields 'name', 'sum', 'sum_sq', 'mean', and 'std_dev'. k_combined : list Combined estimator for k-effective and its uncertainty k_col_abs : float @@ -102,6 +103,7 @@ class StatePoint(object): self._meshes_read = False self._tallies_read = False self._with_summary = False + self._global_tallies = None def close(self): self._f.close() @@ -177,8 +179,24 @@ class StatePoint(object): @property def global_tallies(self): - data = self._f['global_tallies'].value - return np.column_stack((data['sum'], data['sum_sq'])) + if self._global_tallies is None: + data = self._f['global_tallies'].value + gt = np.zeros_like(data, dtype=[ + ('name', 'a14'), ('sum', 'f8'), ('sum_sq', 'f8'), + ('mean', 'f8'), ('std_dev', 'f8')]) + gt['name'] = ['k-collision', 'k-absorption', 'k-tracklength', + 'leakage'] + gt['sum'] = data['sum'] + gt['sum_sq'] = data['sum_sq'] + + # Calculate mean and sample standard deviation of mean + n = self.n_realizations + gt['mean'] = gt['sum']/n + gt['std_dev'] = np.sqrt((gt['sum_sq']/n - gt['mean']**2)/(n - 1)) + + self._global_tallies = gt + + return self._global_tallies @property def k_cmfd(self): @@ -460,60 +478,6 @@ class StatePoint(object): def with_summary(self): return self._with_summary - def compute_ci(self, confidence=0.95): - """Computes confidence intervals for each Tally bin. - - This method is equivalent to calling compute_stdev(...) when the - confidence is known as opposed to its corresponding t value. - - Parameters - ---------- - confidence : float, optional - Confidence level. Defaults to 0.95. - - """ - - # Determine significance level and percentile for two-sided CI - alpha = 1 - confidence - percentile = 1 - alpha/2 - - # Calculate t-value - t_value = scipy.stats.t.ppf(percentile, self._n_realizations - 1) - self.compute_stdev(t_value) - - def compute_stdev(self, t_value=1.0): - """Computes the sample mean and the standard deviation of the mean - for each Tally bin. - - Parameters - ---------- - t_value : float, optional - Student's t-value applied to the uncertainty. Defaults to 1.0, - meaning the reported value is the sample standard deviation. - - """ - - # Determine number of realizations - n = self._n_realizations - - # Calculate the standard deviation for each global tally - for i in range(len(self._global_tallies)): - - # Get sum and sum of squares - s, s2 = self._global_tallies[i] - - # Calculate sample mean and replace value - s /= n - self._global_tallies[i, 0] = s - - # Calculate standard deviation - if s != 0.0: - self._global_tallies[i, 1] = t_value * np.sqrt((s2 / n - s**2) / (n-1)) - - # Calculate sample mean and standard deviation for user-defined Tallies - for tally_id, tally in self.tallies.items(): - tally.compute_std_dev(t_value) - def get_tally(self, scores=[], filters=[], nuclides=[], name=None, id=None, estimator=None): """Finds and returns a Tally object with certain properties. diff --git a/tests/test_fixed_source/test_fixed_source.py b/tests/test_fixed_source/test_fixed_source.py index 0595ea1db..c3bd34856 100644 --- a/tests/test_fixed_source/test_fixed_source.py +++ b/tests/test_fixed_source/test_fixed_source.py @@ -30,9 +30,10 @@ class FixedSourceTestHarness(TestHarness): outstr += '\n'.join(results) + '\n' tally_num += 1 + gt = sp.global_tallies outstr += 'leakage:\n' - outstr += '{0:12.6E}'.format(sp.global_tallies[3][0]) + '\n' - outstr += '{0:12.6E}'.format(sp.global_tallies[3][1]) + '\n' + outstr += '{0:12.6E}'.format(gt[gt['name'] == b'leakage'][0]['sum']) + '\n' + outstr += '{0:12.6E}'.format(gt[gt['name'] == b'leakage'][0]['sum_sq']) + '\n' return outstr From 3274cf3f6dcdccfa5dd55135f699bfeb33cbe03a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 17 Sep 2015 12:47:20 +0700 Subject: [PATCH 53/95] Use HDF5 format for voxel file rather than raw binary --- docs/source/usersguide/output/index.rst | 1 + scripts/openmc-voxel-to-silovtk | 69 +++++++++---------------- src/constants.F90 | 3 +- src/plot.F90 | 54 +++++++++++++++---- 4 files changed, 72 insertions(+), 55 deletions(-) diff --git a/docs/source/usersguide/output/index.rst b/docs/source/usersguide/output/index.rst index 1eb85e9d5..161a8de2d 100644 --- a/docs/source/usersguide/output/index.rst +++ b/docs/source/usersguide/output/index.rst @@ -12,3 +12,4 @@ Output File Formats source particle_restart track + voxel diff --git a/scripts/openmc-voxel-to-silovtk b/scripts/openmc-voxel-to-silovtk index eb052c75f..1329b6b6c 100755 --- a/scripts/openmc-voxel-to-silovtk +++ b/scripts/openmc-voxel-to-silovtk @@ -1,9 +1,11 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python from __future__ import division, print_function import struct import sys +import numpy as np +import h5py def parse_options(): """Process command line arguments""" @@ -22,14 +24,16 @@ def parse_options(): return parsed -def main(file_, o): - print(file_) - fh = open(file_, 'rb') - header = get_header(fh) - meshparms = (header['dimension'] + header['lower_left'] + - header['upper_right']) - nx, ny, nz = meshparms[:3] - ll = header['lower_left'] +def main(filename, o): + # Read data from voxel file + fh = h5py.File(filename, 'r') + dimension = fh['num_voxels'].value + width = fh['voxel_width'].value + lower_left = fh['lower_left'].value + voxel_data = fh['data'].value + + nx, ny, nz = dimension + upper_right = lower_left + width*dimension if o.vtk: try: @@ -40,13 +44,10 @@ def main(file_, o): 'See: http://www.vtk.org/') return - origin = [(l + w*n/2.) for n, l, w in - zip((nx, ny, nz), ll, header['width'])] - grid = vtk.vtkImageData() grid.SetDimensions(nx+1, ny+1, nz+1) - grid.SetOrigin(*ll) - grid.SetSpacing(*header['width']) + grid.SetOrigin(*lower_left) + grid.SetSpacing(*width) data = vtk.vtkDoubleArray() data.SetName("id") @@ -57,8 +58,7 @@ def main(file_, o): for y in range(ny): for z in range(nz): i = z*nx*ny + y*nx + x - id_ = get_int(fh)[0] - data.SetValue(i, id_) + data.SetValue(i, voxel_data[x,y,z]) grid.GetCellData().AddArray(data) writer = vtk.vtkXMLImageDataWriter() @@ -81,44 +81,23 @@ def main(file_, o): if not o.output.endswith(".silo"): o.output += ".silo" silomesh.init_silo(o.output) - silomesh.init_mesh('plot', *meshparms) + meshparams = list(map(int, dimension)) + list(map(float, lower_left)) + \ + list(map(float, upper_right)) + silomesh.init_mesh('plot', *meshparams) silomesh.init_var("id") - for x in range(1, nx+1): + for x in range(nx): sys.stdout.write(" {0}%\r".format(int(x/nx*100))) sys.stdout.flush() - for y in range(1, ny+1): - for z in range(1, nz+1): - id_ = get_int(fh)[0] - silomesh.set_value(float(id_), x, y, z) + for y in range(ny): + for z in range(nz): + silomesh.set_value(float(voxel_data[x,y,z]), + x + 1, y + 1, z + 1) print() silomesh.finalize_var() silomesh.finalize_mesh() silomesh.finalize_silo() -def get_header(file_): - nx, ny, nz = get_int(file_, 3) - wx, wy, wz = get_double(file_, 3) - lx, ly, lz = get_double(file_, 3) - header = {'dimension': [nx, ny, nz], 'width': [wx, wy, wz], - 'lower_left': [lx, ly, lz], - 'upper_right': [lx+wx*nx, ly+wy*ny, lz+wz*nz]} - return header - - -def get_data(file_, n, typeCode, size): - return list(struct.unpack('={0}{1}'.format(n, typeCode), - file_.read(n*size))) - - -def get_int(file_, n=1, path=None): - return get_data(file_, n, 'i', 4) - - -def get_double(file_, n=1, path=None): - return get_data(file_, n, 'd', 8) - - if __name__ == '__main__': (options, args) = parse_options() if args: diff --git a/src/constants.F90 b/src/constants.F90 index 6be1326a8..3d7ca890d 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -20,7 +20,8 @@ module constants FILETYPE_STATEPOINT = -1, & FILETYPE_PARTICLE_RESTART = -2, & FILETYPE_SOURCE = -3, & - FILETYPE_TRACK = -4 + FILETYPE_TRACK = -4, & + FILETYPE_VOXEL = -5 ! ============================================================================ ! ADJUSTABLE PARAMETERS diff --git a/src/plot.F90 b/src/plot.F90 index cd4e8642e..e5b265c5c 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -5,6 +5,7 @@ module plot use geometry, only: find_cell, check_cell_overlap use geometry_header, only: Cell, BASE_UNIVERSE use global + use hdf5_interface use mesh, only: get_mesh_indices use output, only: write_message use particle_header, only: Particle, LocalCoord @@ -14,6 +15,8 @@ module plot use progress_header, only: ProgressBar use string, only: to_str + use hdf5 + implicit none contains @@ -347,11 +350,20 @@ contains integer :: x, y, z ! voxel location indices integer :: rgb(3) ! colors (red, green, blue) from 0-255 integer :: id ! id of cell or material - integer :: unit_plot ! voxel file unit + integer :: hdf5_err + integer, target :: data(pl%pixels(3),pl%pixels(2)) + integer(HID_T) :: file_id + integer(HID_T) :: dspace + integeR(HID_T) :: memspace + integer(HID_T) :: dset + integer(HSIZE_T) :: dims(3) + integer(HSIZE_T) :: dims_slab(3) + integer(HSIZE_T) :: offset(3) real(8) :: vox(3) ! x, y, and z voxel widths real(8) :: ll(3) ! lower left starting point for each sweep direction type(Particle) :: p type(ProgressBar) :: progress + type(c_ptr) :: f_ptr ! compute voxel widths in each direction vox = pl % width/dble(pl % pixels) @@ -366,11 +378,30 @@ contains p % coord(1) % universe = BASE_UNIVERSE ! Open binary plot file for writing - open(NEWUNIT=unit_plot, FILE=pl % path_plot, STATUS='replace', & - ACCESS='stream') + file_id = file_create(pl%path_plot) ! write plot header info - write(unit_plot) pl % pixels, vox, ll + call write_dataset(file_id, "filetype", FILETYPE_VOXEL) + call write_dataset(file_id, "num_voxels", pl%pixels) + call write_dataset(file_id, "voxel_width", vox) + call write_dataset(file_id, "lower_left", ll) + + ! Create dataset for voxel data -- note that the dimensions are reversed + ! since we want the order in the file to be z, y, x + dims(:) = [pl%pixels(3), pl%pixels(2), pl%pixels(1)] + call h5screate_simple_f(3, dims, dspace, hdf5_err) + call h5dcreate_f(file_id, "data", H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) + + ! Create another dataspace for 2D array in memory + dims_slab(1) = pl%pixels(3) + dims_slab(2) = pl%pixels(2) + dims_slab(3) = 1 + call h5screate_simple_f(2, dims_slab(1:2), memspace, hdf5_err) + + ! Initialize offset and get pointer to data + offset(:) = 0 + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims_slab, hdf5_err) + f_ptr = c_loc(data) ! move to center of voxels ll = ll + vox / TWO @@ -379,22 +410,19 @@ contains call progress % set_value(dble(x)/dble(pl % pixels(1))*100) do y = 1, pl % pixels(2) do z = 1, pl % pixels(3) - ! get voxel color call position_rgb(p, pl, rgb, id) ! write to plot file - write(unit_plot) id + data(z,y) = id ! advance particle in z direction p % coord(1) % xyz(3) = p % coord(1) % xyz(3) + vox(3) - end do ! advance particle in y direction p % coord(1) % xyz(2) = p % coord(1) % xyz(2) + vox(2) p % coord(1) % xyz(3) = ll(3) - end do ! advance particle in y direction @@ -402,9 +430,17 @@ contains p % coord(1) % xyz(2) = ll(2) p % coord(1) % xyz(3) = ll(3) + ! Write to HDF5 dataset + offset(3) = x - 1 + call h5soffset_simple_f(dspace, offset, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, & + mem_space_id=memspace, file_space_id=dspace) end do - close(unit_plot) + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call file_close(file_id) end subroutine create_3d_dump From 3df61825cc8c93656ed1458c34fca14000884e73 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 17 Sep 2015 13:11:40 +0700 Subject: [PATCH 54/95] Make filetype a string in HDF5 files. --- .../usersguide/output/particle_restart.rst | 6 ++--- docs/source/usersguide/output/source.rst | 6 ++--- docs/source/usersguide/output/statepoint.rst | 6 ++--- docs/source/usersguide/output/track.rst | 6 ++--- docs/source/usersguide/output/voxel.rst | 25 +++++++++++++++++++ openmc/particle_restart.py | 3 ++- openmc/statepoint.py | 3 ++- src/constants.F90 | 8 ------ src/initialize.F90 | 8 +++--- src/particle_restart_write.F90 | 2 +- src/plot.F90 | 2 +- src/source.F90 | 6 ++--- src/state_point.F90 | 6 ++--- src/track_output.F90 | 2 +- 14 files changed, 50 insertions(+), 39 deletions(-) create mode 100644 docs/source/usersguide/output/voxel.rst diff --git a/docs/source/usersguide/output/particle_restart.rst b/docs/source/usersguide/output/particle_restart.rst index 12ab3237f..e0d89a515 100644 --- a/docs/source/usersguide/output/particle_restart.rst +++ b/docs/source/usersguide/output/particle_restart.rst @@ -6,11 +6,9 @@ Particle Restart File Format The current revision of the particle restart file format is 1. -**/filetype** (*int*) +**/filetype** (*char[]*) - Flags what type of file this is. A value of -1 indicates a statepoint file, - a value of -2 indicates a particle restart file, a value of -3 indicates a - source file, and a value of -4 indicates a track file. + String indicating the type of file. **/revision** (*int*) diff --git a/docs/source/usersguide/output/source.rst b/docs/source/usersguide/output/source.rst index cc8e71a67..2981b0f66 100644 --- a/docs/source/usersguide/output/source.rst +++ b/docs/source/usersguide/output/source.rst @@ -8,11 +8,9 @@ Normally, source data is stored in a state point file. However, it is possible to request that the source be written separately, in which case the format used is that documented here. -**/filetype** (*int*) +**/filetype** (*char[]*) - Flags what type of file this is. A value of -1 indicates a statepoint file, - a value of -2 indicates a particle restart file, a value of -3 indicates a - source file, and a value of -4 indicates a track file. + String indicating the type of file. **/source_bank** (Compound type) diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index b2003f26a..66fcce27f 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -6,11 +6,9 @@ State Point File Format The current revision of the statepoint file format is 13. -**/filetype** (*int*) +**/filetype** (*char[]*) - Flags what type of file this is. A value of -1 indicates a statepoint file, - a value of -2 indicates a particle restart file, a value of -3 indicates a - source file, and a value of -4 indicates a track file. + String indicating the type of file. **/revision** (*int*) diff --git a/docs/source/usersguide/output/track.rst b/docs/source/usersguide/output/track.rst index 9a85ac7ea..d3c7a27d8 100644 --- a/docs/source/usersguide/output/track.rst +++ b/docs/source/usersguide/output/track.rst @@ -6,11 +6,9 @@ Track File Format The current revision of the particle track file format is 1. -**/filetype** (*int*) +**/filetype** (*char[]*) - Flags what type of file this is. A value of -1 indicates a statepoint file, - a value of -2 indicates a particle restart file, a value of -3 indicates a - source file, and a value of -4 indicates a track file. + String indicating the type of file. **/revision** (*int*) diff --git a/docs/source/usersguide/output/voxel.rst b/docs/source/usersguide/output/voxel.rst new file mode 100644 index 000000000..bcdcd8eb1 --- /dev/null +++ b/docs/source/usersguide/output/voxel.rst @@ -0,0 +1,25 @@ +.. _usersguide_voxel: + +================= +Voxel File Format +================= + +**/filetype** (*char[]*) + + String indicating the type of file. + +**/num_voxels** (*int[3]*) + + Number of voxels in the x-, y-, and z- directions. + +**/voxel_width** (*double[3]*) + + Width of a voxel in centimeters. + +**/lower_left** (*double[3]*) + + Cartesian coordinates of the lower-left corner of the plot. + +**/data** (*int[][][]*) + + Data for each voxel that represents a material or cell ID. diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py index b09ca0f41..3ab294585 100644 --- a/openmc/particle_restart.py +++ b/openmc/particle_restart.py @@ -42,7 +42,8 @@ class Particle(object): self._f = h5py.File(filename, 'r') # Ensure filetype and revision are correct - if 'filetype' not in self._f or self._f['filetype'].value != -2: + if 'filetype' not in self._f or self._f[ + 'filetype'].value.decode() != 'particle restart': raise IOError('{} is not a particle restart file.'.format(filename)) if self._f['revision'].value != 1: raise IOError('Particle restart file revision is not consistent.') diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 5c71b3f5b..9583563d5 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -94,7 +94,8 @@ class StatePoint(object): self._f = h5py.File(filename, 'r') # Ensure filetype and revision are correct - if 'filetype' not in self._f or self._f['filetype'].value != -1: + if 'filetype' not in self._f or self._f[ + 'filetype'].value.decode() != 'statepoint': raise IOError('{} is not a statepoint file.'.format(filename)) if self._f['revision'].value != 14: raise IOError('Statepoint revision is not consistent.') diff --git a/src/constants.F90 b/src/constants.F90 index 3d7ca890d..01dd6148a 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -15,14 +15,6 @@ module constants integer, parameter :: REVISION_PARTICLE_RESTART = 1 integer, parameter :: REVISION_TRACK = 1 - ! Binary file types - integer, parameter :: & - FILETYPE_STATEPOINT = -1, & - FILETYPE_PARTICLE_RESTART = -2, & - FILETYPE_SOURCE = -3, & - FILETYPE_TRACK = -4, & - FILETYPE_VOXEL = -5 - ! ============================================================================ ! ADJUSTABLE PARAMETERS diff --git a/src/initialize.F90 b/src/initialize.F90 index 48985a718..86242c753 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -321,7 +321,7 @@ contains integer :: i ! loop index integer :: argc ! number of command line arguments integer :: last_flag ! index of last flag - integer :: filetype + character(MAX_WORD_LEN) :: filetype integer(HID_T) :: file_id character(MAX_WORD_LEN), allocatable :: argv(:) ! command line arguments @@ -366,10 +366,10 @@ contains ! Set path and flag for type of run select case (filetype) - case (FILETYPE_STATEPOINT) + case ('statepoint') path_state_point = argv(i) restart_run = .true. - case (FILETYPE_PARTICLE_RESTART) + case ('particle restart') path_particle_restart = argv(i) particle_restart_run = .true. case default @@ -389,7 +389,7 @@ contains file_id = file_open(argv(i), 'r', parallel=.true.) call read_dataset(file_id, 'filetype', filetype) call file_close(file_id) - if (filetype /= FILETYPE_SOURCE) then + if (filetype /= 'source') then call fatal_error("Second file after restart flag must be a & &source file") end if diff --git a/src/particle_restart_write.F90 b/src/particle_restart_write.F90 index 0c010b64c..8b19bb879 100644 --- a/src/particle_restart_write.F90 +++ b/src/particle_restart_write.F90 @@ -40,7 +40,7 @@ contains src => source_bank(current_work) ! Write data to file - call write_dataset(file_id, 'filetype', FILETYPE_PARTICLE_RESTART) + call write_dataset(file_id, 'filetype', 'particle restart') call write_dataset(file_id, 'revision', REVISION_PARTICLE_RESTART) call write_dataset(file_id, 'current_batch', current_batch) call write_dataset(file_id, 'gen_per_batch', gen_per_batch) diff --git a/src/plot.F90 b/src/plot.F90 index e5b265c5c..d8c255c34 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -381,7 +381,7 @@ contains file_id = file_create(pl%path_plot) ! write plot header info - call write_dataset(file_id, "filetype", FILETYPE_VOXEL) + call write_dataset(file_id, "filetype", 'voxel') call write_dataset(file_id, "num_voxels", pl%pixels) call write_dataset(file_id, "voxel_width", vox) call write_dataset(file_id, "lower_left", ll) diff --git a/src/source.F90 b/src/source.F90 index 285332ef8..c46174947 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -32,8 +32,8 @@ contains integer(8) :: i ! loop index over bank sites integer(8) :: id ! particle id - integer(4) :: itmp ! temporary integer integer(HID_T) :: file_id + character(MAX_WORD_LEN) :: filetype character(MAX_FILE_LEN) :: filename type(Bank), pointer :: src ! source bank site @@ -50,10 +50,10 @@ contains file_id = file_open(path_source, 'r', parallel=.true.) ! Read the file type - call read_dataset(file_id, "filetype", itmp) + call read_dataset(file_id, "filetype", filetype) ! Check to make sure this is a source file - if (itmp /= FILETYPE_SOURCE) then + if (filetype /= 'source') then call fatal_error("Specified starting source file not a source file & &type.") end if diff --git a/src/state_point.F90 b/src/state_point.F90 index bf43a1e83..97375c89c 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -70,7 +70,7 @@ contains file_id = file_create(filename) ! Write file type - call write_dataset(file_id, "filetype", FILETYPE_STATEPOINT) + call write_dataset(file_id, "filetype", 'statepoint') ! Write revision number for state point file call write_dataset(file_id, "revision", REVISION_STATEPOINT) @@ -375,7 +375,7 @@ contains ! Create separate source file if (master .or. parallel) then file_id = file_create(filename, parallel=.true.) - call write_dataset(file_id, "filetype", FILETYPE_SOURCE) + call write_dataset(file_id, "filetype", 'source') end if else filename = trim(path_output) // 'statepoint.' // & @@ -397,7 +397,7 @@ contains call write_message("Creating source file " // trim(filename) // "...", 1) if (master .or. parallel) then file_id = file_create(filename, parallel=.true.) - call write_dataset(file_id, "filetype", FILETYPE_SOURCE) + call write_dataset(file_id, "filetype", 'source') end if call write_source_bank(file_id) diff --git a/src/track_output.F90 b/src/track_output.F90 index f4018cde3..1665ac25e 100644 --- a/src/track_output.F90 +++ b/src/track_output.F90 @@ -114,7 +114,7 @@ contains !$omp critical (FinalizeParticleTrack) file_id = file_create(fname) - call write_dataset(file_id, 'filetype', FILETYPE_TRACK) + call write_dataset(file_id, 'filetype', 'track') call write_dataset(file_id, 'revision', REVISION_TRACK) call write_dataset(file_id, 'n_particles', n_particle_tracks) call write_dataset(file_id, 'n_coords', n_coords) From 333ce8034086be92ceb9de55047654d30f426526 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 17 Sep 2015 15:50:47 -0400 Subject: [PATCH 55/95] Add collision estimator to docs --- docs/source/usersguide/input.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 93e8236ec..34d3f7df4 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1278,14 +1278,16 @@ The ```` element accepts the following sub-elements: *Default*: total :estimator: - The estimator element is used to force the use of either ``analog`` or - ``tracklength`` tally estimation. ''analog'' is generally less efficient - though it can be used with every score type. ''tracklength'' is generally - the most efficient, though its usage is restricted to tallies that do not - score particle information which requires a collision to have occured, such - as a scattering tally which utilizes outgoing energy filters. + The estimator element is used to force the use of either ``analog``, + ``collision``, or ``tracklength`` tally estimation. ``analog`` is generally + the least efficient though it can be used with every score type. + ``tracklength`` is generally the most efficient, but neither ``tracklength`` + nor ``collision`` can be used to score a tally that requires post-collision + information. For example, a scattering tally with outgoing energy filters + cannot be used with ``tracklength`` or ``collision`` because the code will + not know the outgoing energy distribution. - *Default*: ``tracklength`` but will revert to analog if necessary. + *Default*: ``tracklength`` but will revert to ``analog`` if necessary. :scores: A space-separated list of the desired responses to be accumulated. Accepted From 9c3f77fe904dc5b5fd0b995fe298b5e1c85089fb Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 17 Sep 2015 16:20:15 -0400 Subject: [PATCH 56/95] Add collision estimator tests --- tests/test_score_MT/results_true.dat | 66 ++ tests/test_score_MT/tallies.xml | 14 +- tests/test_score_absorption/results_true.dat | 9 + tests/test_score_absorption/tallies.xml | 8 +- tests/test_score_fission/results_true.dat | 9 + tests/test_score_fission/tallies.xml | 8 +- tests/test_score_flux/results_true.dat | 26 + tests/test_score_flux/tallies.xml | 14 +- tests/test_score_flux_yn/results_true.dat | 866 ++++++++++++++++++ tests/test_score_flux_yn/tallies.xml | 12 + .../test_score_kappafission/results_true.dat | 18 + tests/test_score_kappafission/tallies.xml | 14 +- tests/test_score_nufission/results_true.dat | 18 + tests/test_score_nufission/tallies.xml | 14 +- tests/test_score_scatter/results_true.dat | 18 + tests/test_score_scatter/tallies.xml | 14 +- tests/test_score_total/results_true.dat | 18 + tests/test_score_total/tallies.xml | 14 +- tests/test_score_total_yn/results_true.dat | 802 ++++++++++++++++ tests/test_score_total_yn/tallies.xml | 14 + 20 files changed, 1968 insertions(+), 8 deletions(-) diff --git a/tests/test_score_MT/results_true.dat b/tests/test_score_MT/results_true.dat index 248f6657d..4b1c1af26 100644 --- a/tests/test_score_MT/results_true.dat +++ b/tests/test_score_MT/results_true.dat @@ -33,3 +33,69 @@ tally 1: 2.080857E-09 6.101318E-02 8.452067E-04 +tally 2: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-01 +2.440000E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.000000E-02 +6.000000E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +tally 3: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.724026E-03 +1.684945E-05 +5.724026E-03 +1.684945E-05 +3.250298E-01 +2.370870E-02 +1.083784E+00 +2.568556E-01 +4.449887E-05 +1.980149E-09 +4.449887E-05 +1.980149E-09 +3.526275E-02 +2.863085E-04 +1.417358E-02 +4.375519E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.106469E-05 +8.605176E-10 +6.204277E-02 +8.555398E-04 diff --git a/tests/test_score_MT/tallies.xml b/tests/test_score_MT/tallies.xml index ef7ff8dd8..5e66ae929 100644 --- a/tests/test_score_MT/tallies.xml +++ b/tests/test_score_MT/tallies.xml @@ -6,4 +6,16 @@ n2n 16 51 102 - \ No newline at end of file + + + n2n 16 51 102 + analog + + + + + n2n 16 51 102 + collision + + + diff --git a/tests/test_score_absorption/results_true.dat b/tests/test_score_absorption/results_true.dat index bacbf26a3..9370a146f 100644 --- a/tests/test_score_absorption/results_true.dat +++ b/tests/test_score_absorption/results_true.dat @@ -18,3 +18,12 @@ tally 2: 0.000000E+00 4.000000E-01 4.240000E-02 +tally 3: +0.000000E+00 +0.000000E+00 +1.990713E+00 +8.557870E-01 +1.427399E-02 +4.420707E-05 +2.968053E-01 +1.960663E-02 diff --git a/tests/test_score_absorption/tallies.xml b/tests/test_score_absorption/tallies.xml index 8cbcef251..8b2dc2931 100644 --- a/tests/test_score_absorption/tallies.xml +++ b/tests/test_score_absorption/tallies.xml @@ -12,4 +12,10 @@ absorption - \ No newline at end of file + + + collision + absorption + + + diff --git a/tests/test_score_fission/results_true.dat b/tests/test_score_fission/results_true.dat index 904c0d889..86b31aaaf 100644 --- a/tests/test_score_fission/results_true.dat +++ b/tests/test_score_fission/results_true.dat @@ -18,3 +18,12 @@ tally 2: 0.000000E+00 9.923196E-01 2.067216E-01 +tally 3: +9.036254E-01 +1.746552E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.912744E-01 +2.192705E-01 diff --git a/tests/test_score_fission/tallies.xml b/tests/test_score_fission/tallies.xml index d56614bdf..a8b57f911 100644 --- a/tests/test_score_fission/tallies.xml +++ b/tests/test_score_fission/tallies.xml @@ -12,4 +12,10 @@ fission - \ No newline at end of file + + + collision + fission + + + diff --git a/tests/test_score_flux/results_true.dat b/tests/test_score_flux/results_true.dat index 31e1d9292..31ca238d4 100644 --- a/tests/test_score_flux/results_true.dat +++ b/tests/test_score_flux/results_true.dat @@ -13,3 +13,29 @@ tally 1: 2.880575E+01 5.605671E+01 6.804062E+02 +tally 2: +3.077754E+01 +2.017424E+02 +1.172238E+01 +3.139127E+01 +5.231699E+01 +5.870469E+02 +3.259142E+01 +2.336719E+02 +1.040924E+01 +2.432332E+01 +5.709679E+01 +6.978668E+02 +tally 3: +3.077754E+01 +2.017424E+02 +1.172238E+01 +3.139127E+01 +5.231699E+01 +5.870469E+02 +3.259142E+01 +2.336719E+02 +1.040924E+01 +2.432332E+01 +5.709679E+01 +6.978668E+02 diff --git a/tests/test_score_flux/tallies.xml b/tests/test_score_flux/tallies.xml index 30bef7174..bcde40c75 100644 --- a/tests/test_score_flux/tallies.xml +++ b/tests/test_score_flux/tallies.xml @@ -6,4 +6,16 @@ flux - \ No newline at end of file + + + flux + analog + + + + + flux + collision + + + diff --git a/tests/test_score_flux_yn/results_true.dat b/tests/test_score_flux_yn/results_true.dat index 2e5df97cf..937f810ea 100644 --- a/tests/test_score_flux_yn/results_true.dat +++ b/tests/test_score_flux_yn/results_true.dat @@ -446,3 +446,869 @@ tally 2: 1.093913E-01 2.235961E-01 5.449263E-02 +tally 3: +3.077754E+01 +2.017424E+02 +-4.040800E-01 +5.606719E-01 +-5.238239E-01 +4.460714E-01 +1.155164E-01 +1.686786E-01 +-1.972294E-01 +2.912851E-01 +4.908524E-01 +1.374195E-01 +-1.467088E-02 +1.080839E-01 +6.749037E-02 +1.397361E-01 +4.136479E-03 +9.237632E-02 +-3.742305E-01 +9.917374E-02 +5.374208E-01 +2.530961E-01 +2.270996E-01 +9.415721E-02 +-4.568867E-02 +1.277446E-01 +1.581716E-01 +6.217155E-02 +4.667840E-01 +1.143380E-01 +9.684270E-02 +7.302998E-02 +8.366629E-01 +1.797483E-01 +-5.657893E-01 +2.553910E-01 +-2.351441E-02 +4.395513E-02 +7.843306E-01 +1.466478E-01 +4.617856E-02 +1.154681E-02 +1.431343E-01 +3.531062E-02 +4.625825E-01 +6.235642E-02 +-8.837342E-02 +6.231694E-02 +-3.766755E-01 +6.412261E-02 +1.995226E-01 +1.743990E-01 +-2.498625E-02 +8.897536E-02 +-1.039315E-01 +1.868672E-01 +6.712910E-01 +2.084042E-01 +5.805639E-02 +4.049580E-02 +1.603677E-01 +4.280033E-02 +3.909878E-01 +7.726018E-02 +9.878354E-02 +4.630595E-02 +-2.389983E-01 +3.528604E-02 +1.641046E-01 +1.669859E-01 +-2.351986E-02 +1.048794E-02 +1.172238E+01 +3.139127E+01 +-1.057733E+00 +2.820672E-01 +5.708838E-02 +6.224675E-02 +2.492981E-02 +1.827498E-01 +-1.339268E-01 +1.968929E-02 +2.363867E-01 +3.028587E-02 +-2.867841E-01 +2.680318E-02 +-2.352784E-01 +1.895006E-02 +4.365572E-01 +1.883240E-01 +-3.388837E-01 +7.209932E-02 +3.488374E-01 +6.640137E-02 +-3.343893E-01 +4.149634E-02 +-4.575314E-01 +7.461614E-02 +4.436881E-01 +1.325092E-01 +3.394853E-01 +2.987173E-02 +-2.633936E-02 +6.171428E-02 +9.994191E-02 +6.447641E-02 +-1.618840E-01 +3.497845E-02 +-1.290678E-01 +3.735394E-02 +9.852126E-03 +2.963925E-02 +-1.656539E-01 +4.190396E-02 +-2.292763E-01 +7.045480E-02 +-4.616824E-03 +1.926690E-02 +-1.960839E-01 +1.396042E-02 +-2.133526E-02 +5.189823E-02 +2.933136E-01 +5.721356E-02 +-1.084914E-01 +2.448532E-02 +-4.778583E-01 +7.644033E-02 +1.736901E-01 +6.630467E-02 +-5.460801E-02 +1.510381E-02 +1.106093E-01 +1.590306E-02 +1.659501E-01 +5.983218E-02 +1.343781E-02 +2.751294E-02 +2.052693E-01 +3.478581E-02 +-1.006298E-01 +1.815313E-02 +-2.563766E-01 +3.045246E-02 +5.231699E+01 +5.870469E+02 +-6.102587E-01 +5.930968E-01 +1.184182E+00 +1.364433E+00 +-6.362263E-02 +8.852514E-01 +-4.844978E-01 +1.751923E-01 +8.223413E-01 +2.436206E-01 +-9.656506E-01 +3.513566E-01 +2.710494E-01 +7.170772E-01 +4.792482E-01 +2.551569E-01 +-1.266077E-01 +2.824778E-01 +6.389964E-01 +2.501483E-01 +8.915816E-01 +3.557431E-01 +-1.007448E+00 +5.743018E-01 +3.528444E-01 +2.428078E-01 +-5.833000E-01 +3.733648E-01 +-4.660289E-01 +6.567263E-02 +5.856088E-01 +2.336146E-01 +3.836351E-02 +7.665403E-02 +-6.721211E-01 +2.651780E-01 +5.725993E-01 +2.101026E-01 +-2.130594E-01 +1.855350E-02 +2.607168E-01 +1.564288E-01 +-3.399382E-02 +3.067656E-02 +-1.228976E+00 +6.554836E-01 +-2.962235E-01 +1.808511E-01 +5.521675E-01 +1.722073E-01 +-1.658751E-01 +1.994119E-02 +-2.671896E-01 +1.343320E-01 +-2.325282E-01 +4.677656E-02 +-3.380310E-01 +1.703532E-01 +-3.571853E-01 +1.140525E-01 +3.836770E-02 +8.586429E-02 +7.328263E-01 +1.567227E-01 +4.840110E-02 +2.718471E-02 +5.654783E-01 +3.645579E-01 +-3.027585E-01 +1.407867E-01 +3.259142E+01 +2.336719E+02 +3.053294E-01 +2.086257E-01 +-7.563597E-01 +2.816768E-01 +-3.039288E-01 +2.855043E-01 +-2.648323E-01 +1.883784E-01 +2.665933E-01 +1.782353E-01 +1.978960E-01 +1.419567E-01 +1.228712E-01 +1.913946E-01 +-9.152681E-03 +1.324681E-01 +-5.707326E-01 +1.092067E-01 +2.326858E-01 +6.731743E-02 +-5.170241E-01 +1.353439E-01 +-4.064026E-01 +9.715030E-02 +-1.142031E-01 +7.748788E-02 +2.928039E-01 +2.716157E-01 +-1.721186E-01 +1.447738E-01 +6.452116E-01 +1.821975E-01 +-5.697276E-01 +1.047333E-01 +-9.640967E-02 +1.139327E-01 +-4.509832E-01 +2.079493E-01 +-2.134684E-02 +2.907667E-01 +-2.434868E-01 +1.235397E-01 +2.550330E-01 +2.979627E-01 +9.598615E-01 +3.140885E-01 +1.218430E-01 +6.283872E-02 +2.412915E-01 +1.907292E-02 +-2.236667E-01 +4.379414E-02 +2.844474E-01 +2.965692E-02 +1.618860E-01 +8.293785E-03 +-1.265583E-01 +4.515449E-02 +6.356127E-02 +1.358134E-02 +-3.844886E-01 +8.600010E-02 +-1.942739E-01 +7.516022E-02 +1.765511E-01 +3.522611E-02 +-3.433188E-01 +3.456066E-02 +-1.501983E-01 +5.633844E-02 +1.040924E+01 +2.432332E+01 +-4.138270E-01 +1.309129E-01 +-3.151106E-01 +1.286964E-01 +9.213222E-02 +6.189454E-02 +-2.746107E-01 +8.103949E-02 +-9.781742E-02 +3.783736E-02 +-1.178371E-01 +3.242332E-02 +-5.837932E-01 +2.059491E-01 +-7.338223E-03 +8.012203E-02 +5.628994E-02 +2.190669E-02 +8.155585E-02 +1.039007E-01 +6.052048E-02 +4.339463E-02 +-1.157646E-02 +1.839000E-02 +-2.641673E-01 +4.737589E-02 +-8.531135E-02 +5.432766E-02 +6.036555E-01 +1.190329E-01 +-3.149976E-01 +5.735264E-02 +-8.456340E-02 +4.563143E-03 +2.224065E-01 +6.600030E-02 +9.562392E-03 +1.843524E-02 +-2.400599E-01 +3.182217E-02 +-6.534941E-01 +1.180315E-01 +4.371157E-01 +9.076666E-02 +3.257455E-02 +2.936184E-02 +-8.788428E-02 +1.923293E-02 +-2.604776E-01 +3.660313E-02 +-6.315350E-02 +1.503534E-02 +5.609294E-01 +8.783528E-02 +-7.363672E-01 +1.789210E-01 +2.883575E-01 +6.478578E-02 +-3.302954E-02 +1.517946E-02 +-3.234157E-01 +4.418920E-02 +2.846318E-01 +2.712085E-02 +-3.227536E-01 +5.062832E-02 +4.391474E-01 +5.548002E-02 +1.322988E-01 +2.995854E-02 +5.709679E+01 +6.978668E+02 +2.859201E-02 +1.094507E+00 +6.058587E-01 +6.079927E-01 +7.553798E-02 +1.131607E+00 +-5.851206E-01 +1.215663E+00 +8.266012E-02 +9.031287E-01 +-7.088368E-01 +3.984608E-01 +-4.414986E-01 +1.502417E-01 +2.241998E-01 +3.228823E-01 +-7.328574E-01 +2.430448E-01 +-8.070160E-01 +1.767265E-01 +-1.154449E-01 +8.739303E-03 +-3.787161E-01 +4.728756E-01 +-1.743577E-01 +1.091245E-01 +2.878137E-01 +2.724285E-01 +2.128994E-01 +4.440539E-01 +9.495567E-01 +3.622719E-01 +1.422950E-01 +5.309223E-02 +1.323659E-01 +1.911979E-01 +-1.303752E-01 +5.710728E-01 +-4.611294E-02 +4.086632E-02 +5.937879E-01 +1.006156E-01 +-3.558925E-01 +2.998983E-01 +1.175971E+00 +5.323321E-01 +2.426485E-01 +1.497265E-01 +7.805090E-02 +5.060214E-02 +-2.914577E-01 +2.233355E-01 +1.053098E-01 +6.693123E-02 +4.541315E-01 +1.328340E-01 +-6.290732E-02 +8.910616E-02 +7.371592E-01 +1.980732E-01 +5.804701E-01 +1.711949E-01 +-6.642202E-01 +1.131866E-01 +1.779818E-01 +6.530190E-02 +-5.224739E-01 +2.534102E-01 +-1.824905E-01 +2.910309E-02 +tally 4: +3.077754E+01 +2.017424E+02 +-4.040800E-01 +5.606719E-01 +-5.238239E-01 +4.460714E-01 +1.155164E-01 +1.686786E-01 +-1.972294E-01 +2.912851E-01 +4.908524E-01 +1.374195E-01 +-1.467088E-02 +1.080839E-01 +6.749037E-02 +1.397361E-01 +4.136479E-03 +9.237632E-02 +-3.742305E-01 +9.917374E-02 +5.374208E-01 +2.530961E-01 +2.270996E-01 +9.415721E-02 +-4.568867E-02 +1.277446E-01 +1.581716E-01 +6.217155E-02 +4.667840E-01 +1.143380E-01 +9.684270E-02 +7.302998E-02 +8.366629E-01 +1.797483E-01 +-5.657893E-01 +2.553910E-01 +-2.351441E-02 +4.395513E-02 +7.843306E-01 +1.466478E-01 +4.617856E-02 +1.154681E-02 +1.431343E-01 +3.531062E-02 +4.625825E-01 +6.235642E-02 +-8.837342E-02 +6.231694E-02 +-3.766755E-01 +6.412261E-02 +1.995226E-01 +1.743990E-01 +-2.498625E-02 +8.897536E-02 +-1.039315E-01 +1.868672E-01 +6.712910E-01 +2.084042E-01 +5.805639E-02 +4.049580E-02 +1.603677E-01 +4.280033E-02 +3.909878E-01 +7.726018E-02 +9.878354E-02 +4.630595E-02 +-2.389983E-01 +3.528604E-02 +1.641046E-01 +1.669859E-01 +-2.351986E-02 +1.048794E-02 +1.172238E+01 +3.139127E+01 +-1.057733E+00 +2.820672E-01 +5.708838E-02 +6.224675E-02 +2.492981E-02 +1.827498E-01 +-1.339268E-01 +1.968929E-02 +2.363867E-01 +3.028587E-02 +-2.867841E-01 +2.680318E-02 +-2.352784E-01 +1.895006E-02 +4.365572E-01 +1.883240E-01 +-3.388837E-01 +7.209932E-02 +3.488374E-01 +6.640137E-02 +-3.343893E-01 +4.149634E-02 +-4.575314E-01 +7.461614E-02 +4.436881E-01 +1.325092E-01 +3.394853E-01 +2.987173E-02 +-2.633936E-02 +6.171428E-02 +9.994191E-02 +6.447641E-02 +-1.618840E-01 +3.497845E-02 +-1.290678E-01 +3.735394E-02 +9.852126E-03 +2.963925E-02 +-1.656539E-01 +4.190396E-02 +-2.292763E-01 +7.045480E-02 +-4.616824E-03 +1.926690E-02 +-1.960839E-01 +1.396042E-02 +-2.133526E-02 +5.189823E-02 +2.933136E-01 +5.721356E-02 +-1.084914E-01 +2.448532E-02 +-4.778583E-01 +7.644033E-02 +1.736901E-01 +6.630467E-02 +-5.460801E-02 +1.510381E-02 +1.106093E-01 +1.590306E-02 +1.659501E-01 +5.983218E-02 +1.343781E-02 +2.751294E-02 +2.052693E-01 +3.478581E-02 +-1.006298E-01 +1.815313E-02 +-2.563766E-01 +3.045246E-02 +5.231699E+01 +5.870469E+02 +-6.102587E-01 +5.930968E-01 +1.184182E+00 +1.364433E+00 +-6.362263E-02 +8.852514E-01 +-4.844978E-01 +1.751923E-01 +8.223413E-01 +2.436206E-01 +-9.656506E-01 +3.513566E-01 +2.710494E-01 +7.170772E-01 +4.792482E-01 +2.551569E-01 +-1.266077E-01 +2.824778E-01 +6.389964E-01 +2.501483E-01 +8.915816E-01 +3.557431E-01 +-1.007448E+00 +5.743018E-01 +3.528444E-01 +2.428078E-01 +-5.833000E-01 +3.733648E-01 +-4.660289E-01 +6.567263E-02 +5.856088E-01 +2.336146E-01 +3.836351E-02 +7.665403E-02 +-6.721211E-01 +2.651780E-01 +5.725993E-01 +2.101026E-01 +-2.130594E-01 +1.855350E-02 +2.607168E-01 +1.564288E-01 +-3.399382E-02 +3.067656E-02 +-1.228976E+00 +6.554836E-01 +-2.962235E-01 +1.808511E-01 +5.521675E-01 +1.722073E-01 +-1.658751E-01 +1.994119E-02 +-2.671896E-01 +1.343320E-01 +-2.325282E-01 +4.677656E-02 +-3.380310E-01 +1.703532E-01 +-3.571853E-01 +1.140525E-01 +3.836770E-02 +8.586429E-02 +7.328263E-01 +1.567227E-01 +4.840110E-02 +2.718471E-02 +5.654783E-01 +3.645579E-01 +-3.027585E-01 +1.407867E-01 +3.259142E+01 +2.336719E+02 +3.053294E-01 +2.086257E-01 +-7.563597E-01 +2.816768E-01 +-3.039288E-01 +2.855043E-01 +-2.648323E-01 +1.883784E-01 +2.665933E-01 +1.782353E-01 +1.978960E-01 +1.419567E-01 +1.228712E-01 +1.913946E-01 +-9.152681E-03 +1.324681E-01 +-5.707326E-01 +1.092067E-01 +2.326858E-01 +6.731743E-02 +-5.170241E-01 +1.353439E-01 +-4.064026E-01 +9.715030E-02 +-1.142031E-01 +7.748788E-02 +2.928039E-01 +2.716157E-01 +-1.721186E-01 +1.447738E-01 +6.452116E-01 +1.821975E-01 +-5.697276E-01 +1.047333E-01 +-9.640967E-02 +1.139327E-01 +-4.509832E-01 +2.079493E-01 +-2.134684E-02 +2.907667E-01 +-2.434868E-01 +1.235397E-01 +2.550330E-01 +2.979627E-01 +9.598615E-01 +3.140885E-01 +1.218430E-01 +6.283872E-02 +2.412915E-01 +1.907292E-02 +-2.236667E-01 +4.379414E-02 +2.844474E-01 +2.965692E-02 +1.618860E-01 +8.293785E-03 +-1.265583E-01 +4.515449E-02 +6.356127E-02 +1.358134E-02 +-3.844886E-01 +8.600010E-02 +-1.942739E-01 +7.516022E-02 +1.765511E-01 +3.522611E-02 +-3.433188E-01 +3.456066E-02 +-1.501983E-01 +5.633844E-02 +1.040924E+01 +2.432332E+01 +-4.138270E-01 +1.309129E-01 +-3.151106E-01 +1.286964E-01 +9.213222E-02 +6.189454E-02 +-2.746107E-01 +8.103949E-02 +-9.781742E-02 +3.783736E-02 +-1.178371E-01 +3.242332E-02 +-5.837932E-01 +2.059491E-01 +-7.338223E-03 +8.012203E-02 +5.628994E-02 +2.190669E-02 +8.155585E-02 +1.039007E-01 +6.052048E-02 +4.339463E-02 +-1.157646E-02 +1.839000E-02 +-2.641673E-01 +4.737589E-02 +-8.531135E-02 +5.432766E-02 +6.036555E-01 +1.190329E-01 +-3.149976E-01 +5.735264E-02 +-8.456340E-02 +4.563143E-03 +2.224065E-01 +6.600030E-02 +9.562392E-03 +1.843524E-02 +-2.400599E-01 +3.182217E-02 +-6.534941E-01 +1.180315E-01 +4.371157E-01 +9.076666E-02 +3.257455E-02 +2.936184E-02 +-8.788428E-02 +1.923293E-02 +-2.604776E-01 +3.660313E-02 +-6.315350E-02 +1.503534E-02 +5.609294E-01 +8.783528E-02 +-7.363672E-01 +1.789210E-01 +2.883575E-01 +6.478578E-02 +-3.302954E-02 +1.517946E-02 +-3.234157E-01 +4.418920E-02 +2.846318E-01 +2.712085E-02 +-3.227536E-01 +5.062832E-02 +4.391474E-01 +5.548002E-02 +1.322988E-01 +2.995854E-02 +5.709679E+01 +6.978668E+02 +2.859201E-02 +1.094507E+00 +6.058587E-01 +6.079927E-01 +7.553798E-02 +1.131607E+00 +-5.851206E-01 +1.215663E+00 +8.266012E-02 +9.031287E-01 +-7.088368E-01 +3.984608E-01 +-4.414986E-01 +1.502417E-01 +2.241998E-01 +3.228823E-01 +-7.328574E-01 +2.430448E-01 +-8.070160E-01 +1.767265E-01 +-1.154449E-01 +8.739303E-03 +-3.787161E-01 +4.728756E-01 +-1.743577E-01 +1.091245E-01 +2.878137E-01 +2.724285E-01 +2.128994E-01 +4.440539E-01 +9.495567E-01 +3.622719E-01 +1.422950E-01 +5.309223E-02 +1.323659E-01 +1.911979E-01 +-1.303752E-01 +5.710728E-01 +-4.611294E-02 +4.086632E-02 +5.937879E-01 +1.006156E-01 +-3.558925E-01 +2.998983E-01 +1.175971E+00 +5.323321E-01 +2.426485E-01 +1.497265E-01 +7.805090E-02 +5.060214E-02 +-2.914577E-01 +2.233355E-01 +1.053098E-01 +6.693123E-02 +4.541315E-01 +1.328340E-01 +-6.290732E-02 +8.910616E-02 +7.371592E-01 +1.980732E-01 +5.804701E-01 +1.711949E-01 +-6.642202E-01 +1.131866E-01 +1.779818E-01 +6.530190E-02 +-5.224739E-01 +2.534102E-01 +-1.824905E-01 +2.910309E-02 diff --git a/tests/test_score_flux_yn/tallies.xml b/tests/test_score_flux_yn/tallies.xml index 71301d0e7..e9f08bd4e 100644 --- a/tests/test_score_flux_yn/tallies.xml +++ b/tests/test_score_flux_yn/tallies.xml @@ -10,5 +10,17 @@ flux-y5 + + + + flux-y5 + analog + + + + + flux-y5 + collision + diff --git a/tests/test_score_kappafission/results_true.dat b/tests/test_score_kappafission/results_true.dat index dadcdd281..e992b4b68 100644 --- a/tests/test_score_kappafission/results_true.dat +++ b/tests/test_score_kappafission/results_true.dat @@ -9,3 +9,21 @@ tally 1: 0.000000E+00 2.035912E+02 8.999693E+03 +tally 2: +1.765331E+02 +6.974050E+03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.938441E+02 +7.888708E+03 +tally 3: +1.770125E+02 +6.702714E+03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.942246E+02 +8.416720E+03 diff --git a/tests/test_score_kappafission/tallies.xml b/tests/test_score_kappafission/tallies.xml index 1b63fdeeb..8fe5d5c84 100644 --- a/tests/test_score_kappafission/tallies.xml +++ b/tests/test_score_kappafission/tallies.xml @@ -6,4 +6,16 @@ kappa-fission - \ No newline at end of file + + + kappa-fission + analog + + + + + kappa-fission + collision + + + diff --git a/tests/test_score_nufission/results_true.dat b/tests/test_score_nufission/results_true.dat index 5d0b44662..33c4ff9fb 100644 --- a/tests/test_score_nufission/results_true.dat +++ b/tests/test_score_nufission/results_true.dat @@ -9,3 +9,21 @@ tally 1: 0.000000E+00 2.733038E+00 1.616903E+00 +tally 2: +2.296157E+00 +1.167084E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.679940E+00 +1.498454E+00 +tally 3: +2.381373E+00 +1.213497E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.607077E+00 +1.513932E+00 diff --git a/tests/test_score_nufission/tallies.xml b/tests/test_score_nufission/tallies.xml index d3e6963f3..2812a00b5 100644 --- a/tests/test_score_nufission/tallies.xml +++ b/tests/test_score_nufission/tallies.xml @@ -6,4 +6,16 @@ nu-fission - \ No newline at end of file + + + nu-fission + analog + + + + + nu-fission + collision + + + diff --git a/tests/test_score_scatter/results_true.dat b/tests/test_score_scatter/results_true.dat index 5f0ae8b1d..21d7d83c2 100644 --- a/tests/test_score_scatter/results_true.dat +++ b/tests/test_score_scatter/results_true.dat @@ -9,3 +9,21 @@ tally 1: 1.814004E+00 4.059013E+01 3.609499E+02 +tally 2: +0.000000E+00 +0.000000E+00 +1.169000E+01 +2.915330E+01 +3.200000E+00 +2.342600E+00 +4.064000E+01 +3.595168E+02 +tally 3: +0.000000E+00 +0.000000E+00 +1.172929E+01 +2.935812E+01 +3.185726E+00 +2.323517E+00 +4.074319E+01 +3.614902E+02 diff --git a/tests/test_score_scatter/tallies.xml b/tests/test_score_scatter/tallies.xml index a4425c0f2..b6eb73b50 100644 --- a/tests/test_score_scatter/tallies.xml +++ b/tests/test_score_scatter/tallies.xml @@ -6,4 +6,16 @@ scatter - \ No newline at end of file + + + scatter + analog + + + + + scatter + collision + + + diff --git a/tests/test_score_total/results_true.dat b/tests/test_score_total/results_true.dat index f3aa5d89b..e782fd9d0 100644 --- a/tests/test_score_total/results_true.dat +++ b/tests/test_score_total/results_true.dat @@ -9,3 +9,21 @@ tally 1: 1.831649E+00 4.088282E+01 3.662539E+02 +tally 2: +0.000000E+00 +0.000000E+00 +1.372000E+01 +4.018980E+01 +3.200000E+00 +2.342600E+00 +4.104000E+01 +3.668254E+02 +tally 3: +0.000000E+00 +0.000000E+00 +1.372000E+01 +4.018980E+01 +3.200000E+00 +2.342600E+00 +4.104000E+01 +3.668254E+02 diff --git a/tests/test_score_total/tallies.xml b/tests/test_score_total/tallies.xml index 815b84c14..02286f96c 100644 --- a/tests/test_score_total/tallies.xml +++ b/tests/test_score_total/tallies.xml @@ -6,4 +6,16 @@ total - \ No newline at end of file + + + total + analog + + + + + total + collision + + + diff --git a/tests/test_score_total_yn/results_true.dat b/tests/test_score_total_yn/results_true.dat index bcfdb9080..28a4b1627 100644 --- a/tests/test_score_total_yn/results_true.dat +++ b/tests/test_score_total_yn/results_true.dat @@ -410,3 +410,805 @@ tally 2: 3.130205E-02 -3.695818E-01 4.703480E-02 +tally 3: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.200000E-01 +1.152000E-01 +-9.800486E-03 +5.637123E-04 +-2.018554E-02 +4.617738E-04 +-6.271657E-03 +8.252833E-04 +-8.231683E-03 +3.035447E-03 +-2.566508E-02 +1.108829E-03 +2.748466E-03 +1.641191E-03 +6.833190E-03 +5.993876E-04 +3.392213E-02 +2.143714E-03 +3.105616E-02 +1.012625E-03 +-5.473567E-02 +1.615531E-03 +-1.435523E-02 +1.095690E-03 +4.579564E-03 +6.451444E-04 +-1.570409E-02 +3.833387E-04 +1.633422E-02 +2.144997E-03 +-7.438775E-03 +6.441846E-04 +5.440025E-04 +1.290719E-04 +-1.687899E-02 +1.606230E-03 +3.315902E-02 +1.061759E-03 +-1.184684E-02 +4.312573E-04 +-4.732586E-02 +1.387994E-03 +-1.563538E-02 +3.316015E-04 +3.681927E-02 +5.403320E-04 +2.928507E-03 +5.761742E-04 +-3.519362E-02 +6.725185E-04 +1.372000E+01 +4.018980E+01 +-2.015212E-01 +1.072884E-01 +-2.606953E-01 +4.894468E-02 +7.537153E-02 +2.216346E-02 +-3.818524E-02 +6.301675E-02 +2.386335E-01 +1.931104E-02 +-1.872805E-02 +1.265896E-02 +3.732943E-02 +2.347696E-02 +-8.857050E-02 +1.636275E-02 +-1.718450E-01 +1.043488E-02 +1.526226E-01 +2.435399E-02 +7.344765E-02 +1.541644E-02 +-9.819186E-03 +1.473467E-02 +-8.215914E-03 +1.463085E-02 +2.197504E-01 +2.244815E-02 +2.521002E-02 +8.206540E-03 +3.677974E-01 +3.982027E-02 +-1.934606E-01 +3.440019E-02 +1.050141E-01 +2.346980E-02 +2.458487E-01 +1.861429E-02 +4.226131E-02 +2.690841E-03 +3.174234E-02 +1.867018E-02 +2.284995E-01 +1.190246E-02 +-7.894573E-03 +3.715471E-03 +-1.593928E-01 +1.391828E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.200000E+00 +2.342600E+00 +-2.991985E-01 +1.868406E-02 +4.460301E-02 +4.132113E-03 +-2.190630E-02 +1.023889E-02 +-3.265764E-02 +2.060374E-03 +3.491521E-02 +4.785957E-04 +-3.623623E-02 +5.929111E-04 +-4.962268E-02 +1.814245E-03 +1.406439E-01 +1.174445E-02 +-9.433277E-02 +5.036897E-03 +9.058176E-02 +3.871598E-03 +-1.409089E-01 +6.665385E-03 +-1.062337E-01 +4.771650E-03 +1.155280E-01 +8.020320E-03 +8.348336E-02 +1.633941E-03 +1.475434E-02 +3.411046E-03 +4.474425E-03 +6.049348E-03 +6.716359E-03 +2.898000E-03 +-3.674047E-02 +2.971797E-03 +-2.368070E-02 +9.474965E-04 +-6.109826E-02 +4.846201E-03 +-5.076118E-02 +8.354393E-03 +-1.763594E-02 +1.017310E-03 +-2.941064E-02 +1.044916E-03 +-5.631429E-03 +3.915186E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.104000E+01 +3.668254E+02 +-7.832373E-01 +3.913941E-01 +2.281642E-01 +2.669856E-01 +-3.731272E-01 +6.152809E-01 +-3.232973E-01 +7.526283E-02 +3.686513E-01 +9.047618E-02 +-6.018185E-01 +9.140623E-02 +3.848843E-01 +3.431711E-01 +3.397425E-03 +8.879103E-02 +-2.471531E-02 +5.561795E-02 +1.373897E-01 +7.288680E-02 +1.816888E-01 +5.419638E-02 +-3.504404E-01 +1.461853E-01 +1.225356E-01 +3.443595E-02 +-3.109887E-01 +5.492397E-02 +-3.542105E-01 +6.530224E-02 +2.104218E-01 +4.093872E-02 +2.661467E-02 +3.058847E-02 +-3.744331E-01 +6.755739E-02 +1.391218E-01 +4.432842E-02 +1.622041E-01 +6.843992E-03 +4.149973E-02 +1.782398E-02 +2.551752E-01 +2.626972E-02 +-4.706697E-01 +9.193926E-02 +-1.287882E-01 +3.489982E-02 +tally 4: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.652157E-01 +1.242826E-01 +-1.008373E-02 +5.281691E-04 +-1.014715E-02 +2.749212E-04 +-2.506414E-02 +2.613512E-04 +4.320187E-03 +4.316562E-04 +1.439246E-02 +9.138575E-05 +-1.532539E-02 +2.360878E-04 +9.963404E-03 +1.511695E-04 +-6.314554E-03 +2.742799E-05 +7.969329E-03 +1.380329E-04 +-1.298431E-03 +3.287236E-04 +1.441639E-02 +1.409552E-04 +6.516689E-03 +2.511011E-04 +1.294596E-02 +2.249729E-04 +6.983038E-03 +6.334969E-05 +-1.086161E-02 +1.140033E-04 +2.217006E-02 +4.221807E-04 +-6.503276E-03 +2.028281E-04 +2.915180E-02 +3.659182E-04 +-9.080091E-03 +1.503808E-04 +-6.476980E-04 +1.927326E-04 +-1.549603E-02 +3.445843E-04 +2.957508E-02 +1.835035E-04 +6.982790E-03 +1.237342E-04 +-2.653281E-02 +2.606704E-04 +1.372000E+01 +4.018980E+01 +-2.015212E-01 +1.072884E-01 +-2.606953E-01 +4.894468E-02 +7.537153E-02 +2.216346E-02 +-3.818524E-02 +6.301675E-02 +2.386335E-01 +1.931104E-02 +-1.872805E-02 +1.265896E-02 +3.732943E-02 +2.347696E-02 +-8.857050E-02 +1.636275E-02 +-1.718450E-01 +1.043488E-02 +1.526226E-01 +2.435399E-02 +7.344765E-02 +1.541644E-02 +-9.819186E-03 +1.473467E-02 +-8.215914E-03 +1.463085E-02 +2.197504E-01 +2.244815E-02 +2.521002E-02 +8.206540E-03 +3.677974E-01 +3.982027E-02 +-1.934606E-01 +3.440019E-02 +1.050141E-01 +2.346980E-02 +2.458487E-01 +1.861429E-02 +4.226131E-02 +2.690841E-03 +3.174234E-02 +1.867018E-02 +2.284995E-01 +1.190246E-02 +-7.894573E-03 +3.715471E-03 +-1.593928E-01 +1.391828E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.200000E+00 +2.342600E+00 +-2.991985E-01 +1.868406E-02 +4.460301E-02 +4.132113E-03 +-2.190630E-02 +1.023889E-02 +-3.265764E-02 +2.060374E-03 +3.491521E-02 +4.785957E-04 +-3.623623E-02 +5.929111E-04 +-4.962268E-02 +1.814245E-03 +1.406439E-01 +1.174445E-02 +-9.433277E-02 +5.036897E-03 +9.058176E-02 +3.871598E-03 +-1.409089E-01 +6.665385E-03 +-1.062337E-01 +4.771650E-03 +1.155280E-01 +8.020320E-03 +8.348336E-02 +1.633941E-03 +1.475434E-02 +3.411046E-03 +4.474425E-03 +6.049348E-03 +6.716359E-03 +2.898000E-03 +-3.674047E-02 +2.971797E-03 +-2.368070E-02 +9.474965E-04 +-6.109826E-02 +4.846201E-03 +-5.076118E-02 +8.354393E-03 +-1.763594E-02 +1.017310E-03 +-2.941064E-02 +1.044916E-03 +-5.631429E-03 +3.915186E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.104000E+01 +3.668254E+02 +-7.832373E-01 +3.913941E-01 +2.281642E-01 +2.669856E-01 +-3.731272E-01 +6.152809E-01 +-3.232973E-01 +7.526283E-02 +3.686513E-01 +9.047618E-02 +-6.018185E-01 +9.140623E-02 +3.848843E-01 +3.431711E-01 +3.397425E-03 +8.879103E-02 +-2.471531E-02 +5.561795E-02 +1.373897E-01 +7.288680E-02 +1.816888E-01 +5.419638E-02 +-3.504404E-01 +1.461853E-01 +1.225356E-01 +3.443595E-02 +-3.109887E-01 +5.492397E-02 +-3.542105E-01 +6.530224E-02 +2.104218E-01 +4.093872E-02 +2.661467E-02 +3.058847E-02 +-3.744331E-01 +6.755739E-02 +1.391218E-01 +4.432842E-02 +1.622041E-01 +6.843992E-03 +4.149973E-02 +1.782398E-02 +2.551752E-01 +2.626972E-02 +-4.706697E-01 +9.193926E-02 +-1.287882E-01 +3.489982E-02 diff --git a/tests/test_score_total_yn/tallies.xml b/tests/test_score_total_yn/tallies.xml index ca5dcd2dc..51cb79c39 100644 --- a/tests/test_score_total_yn/tallies.xml +++ b/tests/test_score_total_yn/tallies.xml @@ -11,5 +11,19 @@ total-y4 U-235 total + + + + total-y4 + U-235 total + analog + + + + + total-y4 + U-235 total + collision + From 4ce7a5b615caded1e10d1b49aaf73dbf38d736f1 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 17 Sep 2015 20:41:33 -0400 Subject: [PATCH 57/95] Explain analog = collision for flux score in docs --- docs/source/usersguide/input.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 34d3f7df4..a80c01d14 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1298,7 +1298,9 @@ The ```` element accepts the following sub-elements: physical quantities: :flux: - Total flux in particle-cm per source particle. + Total flux in particle-cm per source particle. Note: The ``analog`` + estimator is actually identical to the ``collision`` estimator for the + flux score. :total: Total reaction rate in reactions per source particle. From c57b2c22d906fd657b26830293405d3f94832f44 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 18 Sep 2015 22:05:50 +0700 Subject: [PATCH 58/95] Minor fix in StatePoint.std_dev property and plot-mesh-tally script --- openmc/statepoint.py | 1 - openmc/tallies.py | 5 ++++- scripts/openmc-plot-mesh-tally | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 9583563d5..8d6eb67e1 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -2,7 +2,6 @@ import copy import sys import numpy as np -import scipy.stats import openmc from openmc.constants import * diff --git a/openmc/tallies.py b/openmc/tallies.py index 25cc554ee..7452626be 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -322,7 +322,10 @@ class Tally(object): return None n = self.num_realizations - self._std_dev = np.sqrt((self.sum_sq/n - self.mean**2)/(n - 1)) + nonzero = self.mean > 0 + self._std_dev = np.zeros_like(self.mean) + self._std_dev[nonzero] = np.sqrt((self.sum_sq[nonzero]/n - + self.mean[nonzero]**2)/(n - 1)) self.with_batch_statistics = True return self._std_dev diff --git a/scripts/openmc-plot-mesh-tally b/scripts/openmc-plot-mesh-tally index 1559ea328..04f1f06c6 100755 --- a/scripts/openmc-plot-mesh-tally +++ b/scripts/openmc-plot-mesh-tally @@ -273,8 +273,6 @@ class MeshPlotter(tk.Frame): def get_file_data(self, filename): # Create StatePoint object and read in data self.datafile = StatePoint(filename) - self.datafile.read_results() - self.datafile.compute_stdev() # Find which tallies are mesh tallies self.meshTallies = [] From 04caeb99ba04f92cba484884f8223446c2bc9bee Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Fri, 18 Sep 2015 17:55:52 -0400 Subject: [PATCH 59/95] Minor fixes for #455 --- src/input_xml.F90 | 7 +++---- src/tally.F90 | 24 ++++++++---------------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index d5a932ff6..15a08148d 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3132,7 +3132,7 @@ contains ! tally needs post-collision information if (t % estimator == ESTIMATOR_ANALOG) then call fatal_error("Cannot use track-length estimator for tally " & - &// to_str(t % id)) + // to_str(t % id)) end if ! Set estimator to track-length estimator @@ -3143,16 +3143,15 @@ contains ! tally needs post-collision information if (t % estimator == ESTIMATOR_ANALOG) then call fatal_error("Cannot use collision estimator for tally " & - &// to_str(t % id)) + // to_str(t % id)) end if ! Set estimator to collision estimator t % estimator = ESTIMATOR_COLLISION - write(*, *) t % estimator case default call fatal_error("Invalid estimator '" // trim(temp_str) & - &// "' on tally " // to_str(t % id)) + // "' on tally " // to_str(t % id)) end select end if diff --git a/src/tally.F90 b/src/tally.F90 index 9f9ae7765..12085b5d2 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -92,8 +92,7 @@ contains end if score = score / material_xs % total - else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & - t % estimator == ESTIMATOR_COLLISION) then + else ! For flux, we need no cross section score = flux end if @@ -112,8 +111,7 @@ contains score = p % last_wgt end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & - t % estimator == ESTIMATOR_COLLISION) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % total * atom_density * flux else @@ -131,8 +129,7 @@ contains ! reaction rate score = p % last_wgt - else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & - t % estimator == ESTIMATOR_COLLISION) then + else ! Note SCORE_SCATTER_N not available for tracklength/collision. if (i_nuclide > 0) then score = (micro_xs(i_nuclide) % total & @@ -243,8 +240,7 @@ contains score = p % last_wgt end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & - t % estimator == ESTIMATOR_COLLISION) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % absorption * atom_density * flux else @@ -275,8 +271,7 @@ contains / micro_xs(p % event_nuclide) % absorption end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & - t % estimator == ESTIMATOR_COLLISION) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % fission * atom_density * flux else @@ -319,8 +314,7 @@ contains score = keff * p % wgt_bank end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & - t % estimator == ESTIMATOR_COLLISION) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % nu_fission * atom_density * flux else @@ -353,8 +347,7 @@ contains micro_xs(p % event_nuclide) % absorption end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & - t % estimator == ESTIMATOR_COLLISION) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % kappa_fission * atom_density * flux else @@ -375,8 +368,7 @@ contains if (p % event_MT /= score_bin) cycle SCORE_LOOP score = p % last_wgt - else if (t % estimator == ESTIMATOR_TRACKLENGTH .or. & - t % estimator == ESTIMATOR_COLLISION) then + else ! Any other cross section has to be calculated on-the-fly. For ! cross sections that are used often (e.g. n2n, ngamma, etc. for ! depletion), it might make sense to optimize this section or From 42032210fb618724ab912e79217803bf2686adb3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 19 Sep 2015 07:38:33 +0700 Subject: [PATCH 60/95] Added IPython notebook with post-processing examples. Since the notebook shows an example of how to histogram relative errors from a statepoint, we don't really need the openmc-statepoint-histogram utility, so it's been deleted. The user's guide section on post processing has been updated as well. --- docs/source/devguide/index.rst | 1 - docs/source/devguide/voxel.rst | 52 - .../pythonapi/examples/post-processing.ipynb | 1121 +++++++++++++++++ .../pythonapi/examples/post-processing.rst | 13 + docs/source/pythonapi/index.rst | 1 + docs/source/usersguide/output/voxel.rst | 6 +- docs/source/usersguide/processing.rst | 286 +---- scripts/openmc-statepoint-histogram | 43 - setup.py | 2 +- 9 files changed, 1207 insertions(+), 318 deletions(-) delete mode 100644 docs/source/devguide/voxel.rst create mode 100644 docs/source/pythonapi/examples/post-processing.ipynb create mode 100644 docs/source/pythonapi/examples/post-processing.rst delete mode 100755 scripts/openmc-statepoint-histogram diff --git a/docs/source/devguide/index.rst b/docs/source/devguide/index.rst index e73d8ba70..37b17bc0f 100644 --- a/docs/source/devguide/index.rst +++ b/docs/source/devguide/index.rst @@ -16,5 +16,4 @@ as debugging. styleguide workflow xml-parsing - voxel docbuild diff --git a/docs/source/devguide/voxel.rst b/docs/source/devguide/voxel.rst deleted file mode 100644 index 98f5cb73b..000000000 --- a/docs/source/devguide/voxel.rst +++ /dev/null @@ -1,52 +0,0 @@ -.. _devguide_voxel: - -===================================== -Voxel Plot Binary File Specifications -===================================== - -The current revision of the voxel plot binary file is 1. - -**integer(4) n_voxels_x** - - Number of voxels in the x direction - -**integer(4) n_voxels_y** - - Number of voxels in the y direction - -**integer(4) n_voxels_z** - - Number of voxels in the z direction - -**real(8) width_voxel_x** - - Width of voxels in the x direction - -**real(8) width_voxel_y** - - Width of voxels in the y direction - -**real(8) width_voxel_z** - - Width of voxels in the z direction - -**real(8) lower_left_x** - - Lower left x point of the voxel grid - -**real(8) lower_left_y** - - Lower left y point of the voxel grid - -**real(8) lower_left_z** - - Lower left z point of the voxel grid - -*do x = 1, n_voxels_x* - *do y = 1, n_voxels_y* - *do z = 1, n_voxels_z* - - **integer(4) id** - - Cell or material id number at this voxel center. Set to -1 when - cell not_found. diff --git a/docs/source/pythonapi/examples/post-processing.ipynb b/docs/source/pythonapi/examples/post-processing.ipynb new file mode 100644 index 000000000..1bd7ee49a --- /dev/null +++ b/docs/source/pythonapi/examples/post-processing.ipynb @@ -0,0 +1,1121 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook demonstrates some basic post-processing tasks that can be performed with the Python API, such as plotting a 2D mesh tally and plotting neutron source sites from an eigenvalue calculation. The problem we will use is a simple reflected pin-cell." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import Image\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "import openmc\n", + "from openmc.statepoint import StatePoint\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate Input Files" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate some Nuclides\n", + "h1 = openmc.Nuclide('H-1')\n", + "b10 = openmc.Nuclide('B-10')\n", + "o16 = openmc.Nuclide('O-16')\n", + "u235 = openmc.Nuclide('U-235')\n", + "u238 = openmc.Nuclide('U-238')\n", + "zr90 = openmc.Nuclide('Zr-90')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the nuclides we defined, we will now create three materials for the fuel, water, and cladding of the fuel pin." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 1.6 enriched fuel\n", + "fuel = openmc.Material(name='1.6% Fuel')\n", + "fuel.set_density('g/cm3', 10.31341)\n", + "fuel.add_nuclide(u235, 3.7503e-4)\n", + "fuel.add_nuclide(u238, 2.2625e-2)\n", + "fuel.add_nuclide(o16, 4.6007e-2)\n", + "\n", + "# borated water\n", + "water = openmc.Material(name='Borated Water')\n", + "water.set_density('g/cm3', 0.740582)\n", + "water.add_nuclide(h1, 4.9457e-2)\n", + "water.add_nuclide(o16, 2.4732e-2)\n", + "water.add_nuclide(b10, 8.0042e-6)\n", + "\n", + "# zircaloy\n", + "zircaloy = openmc.Material(name='Zircaloy')\n", + "zircaloy.set_density('g/cm3', 6.55)\n", + "zircaloy.add_nuclide(zr90, 7.2758e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With our three materials, we can now create a materials file object that can be exported to an actual XML file." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a MaterialsFile, add Materials\n", + "materials_file = openmc.MaterialsFile()\n", + "materials_file.add_material(fuel)\n", + "materials_file.add_material(water)\n", + "materials_file.add_material(zircaloy)\n", + "materials_file.default_xs = '71c'\n", + "\n", + "# Export to \"materials.xml\"\n", + "materials_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's move on to the geometry. Our problem will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces -- in this case two cylinders and six reflective planes." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create cylinders for the fuel and clad\n", + "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218)\n", + "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720)\n", + "\n", + "# Create boundary planes to surround the geometry\n", + "# Use both reflective and vacuum boundaries to make life interesting\n", + "min_x = openmc.XPlane(x0=-0.63, boundary_type='reflective')\n", + "max_x = openmc.XPlane(x0=+0.63, boundary_type='reflective')\n", + "min_y = openmc.YPlane(y0=-0.63, boundary_type='reflective')\n", + "max_y = openmc.YPlane(y0=+0.63, boundary_type='reflective')\n", + "min_z = openmc.ZPlane(z0=-0.63, boundary_type='reflective')\n", + "max_z = openmc.ZPlane(z0=+0.63, boundary_type='reflective')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create a Universe to encapsulate a fuel pin\n", + "pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin')\n", + "\n", + "# Create fuel Cell\n", + "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", + "fuel_cell.fill = fuel\n", + "fuel_cell.add_surface(fuel_outer_radius, halfspace=-1)\n", + "pin_cell_universe.add_cell(fuel_cell)\n", + "\n", + "# Create a clad Cell\n", + "clad_cell = openmc.Cell(name='1.6% Clad')\n", + "clad_cell.fill = zircaloy\n", + "clad_cell.add_surface(fuel_outer_radius, halfspace=+1)\n", + "clad_cell.add_surface(clad_outer_radius, halfspace=-1)\n", + "pin_cell_universe.add_cell(clad_cell)\n", + "\n", + "# Create a moderator Cell\n", + "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", + "moderator_cell.fill = water\n", + "moderator_cell.add_surface(clad_outer_radius, halfspace=+1)\n", + "pin_cell_universe.add_cell(moderator_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create root Cell\n", + "root_cell = openmc.Cell(name='root cell')\n", + "root_cell.fill = pin_cell_universe\n", + "\n", + "# Add boundary planes\n", + "root_cell.add_surface(min_x, halfspace=+1)\n", + "root_cell.add_surface(max_x, halfspace=-1)\n", + "root_cell.add_surface(min_y, halfspace=+1)\n", + "root_cell.add_surface(max_y, halfspace=-1)\n", + "root_cell.add_surface(min_z, halfspace=+1)\n", + "root_cell.add_surface(max_z, halfspace=-1)\n", + "\n", + "# Create root Universe\n", + "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", + "root_universe.add_cell(root_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now must create a geometry that is assigned a root universe, put the geometry into a geometry file, and export it to XML." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create Geometry and set root Universe\n", + "geometry = openmc.Geometry()\n", + "geometry.root_universe = root_universe" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a GeometryFile\n", + "geometry_file = openmc.GeometryFile()\n", + "geometry_file.geometry = geometry\n", + "\n", + "# Export to \"geometry.xml\"\n", + "geometry_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 10 inactive batches and 90 active batches each with 5000 particles." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# OpenMC simulation parameters\n", + "batches = 100\n", + "inactive = 10\n", + "particles = 5000\n", + "\n", + "# Instantiate a SettingsFile\n", + "settings_file = openmc.SettingsFile()\n", + "settings_file.batches = batches\n", + "settings_file.inactive = inactive\n", + "settings_file.particles = particles\n", + "source_bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n", + "settings_file.set_source_space('box', source_bounds)\n", + "\n", + "# Export to \"settings.xml\"\n", + "settings_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us also create a plot file that we can use to verify that our pin cell geometry was created successfully." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a Plot\n", + "plot = openmc.Plot(plot_id=1)\n", + "plot.filename = 'materials-xy'\n", + "plot.origin = [0, 0, 0]\n", + "plot.width = [1.26, 1.26]\n", + "plot.pixels = [250, 250]\n", + "plot.color = 'mat'\n", + "\n", + "# Instantiate a PlotsFile, add Plot, and export to \"plots.xml\"\n", + "plot_file = openmc.PlotsFile()\n", + "plot_file.add_plot(plot)\n", + "plot_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the plots.xml file, we can now generate and view the plot. OpenMC outputs plots in .ppm format, which can be converted into a compressed format like .png with the convert utility." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Run openmc in plotting mode\n", + "executor = openmc.Executor()\n", + "executor.plot_geometry(output=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JEwAiCb5uYN4AAALKSURBVGje7dpLcqQwDAbgHHE2\nYeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\nnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\nvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\ndwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\nACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\nvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\nQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTUtMDktMThUMjE6MTc6\nMDErMDc6MDA/DItCAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA5LTE4VDIxOjE3OjAxKzA3OjAw\nTlEz/gAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Convert OpenMC's funky ppm to png\n", + "!convert materials-xy.ppm materials-xy.png\n", + "\n", + "# Display the materials plot inline\n", + "Image(filename='materials-xy.png')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see from the plot, we have a nice pin cell with fuel, cladding, and water! Before we run our simulation, we need to tell the code what we want to tally. The following code shows how to create a 2D mesh tally." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate an empty TalliesFile\n", + "tallies_file = openmc.TalliesFile()\n", + "tallies_file.tallies = []" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create mesh which will be used for tally\n", + "mesh = openmc.Mesh()\n", + "mesh.dimension = [100, 100]\n", + "mesh.lower_left = [-0.63, -0.63]\n", + "mesh.upper_right = [0.63, 0.63]\n", + "tallies_file.add_mesh(mesh)\n", + "\n", + "# Create mesh filter for tally\n", + "mesh_filter = openmc.Filter(type='mesh', bins=[1])\n", + "mesh_filter.mesh = mesh\n", + "\n", + "# Create mesh tally to score flux and fission rate\n", + "tally = openmc.Tally(name='flux')\n", + "tally.add_filter(mesh_filter)\n", + "tally.add_score('flux')\n", + "tally.add_score('fission')\n", + "tallies_file.add_tally(tally)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Export to \"tallies.xml\"\n", + "tallies_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we a have a complete set of inputs, so we can go ahead and run our simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " .d88888b. 888b d888 .d8888b.\n", + " d88P\" \"Y88b 8888b d8888 d88P Y88b\n", + " 888 888 88888b.d88888 888 888\n", + " 888 888 88888b. .d88b. 88888b. 888Y88888P888 888 \n", + " 888 888 888 \"88b d8P Y8b 888 \"88b 888 Y888P 888 888 \n", + " 888 888 888 888 88888888 888 888 888 Y8P 888 888 888\n", + " Y88b. .d88P 888 d88P Y8b. 888 888 888 \" 888 Y88b d88P\n", + " \"Y88888P\" 88888P\" \"Y8888 888 888 888 888 \"Y8888P\"\n", + "__________________888______________________________________________________\n", + " 888\n", + " 888\n", + "\n", + " Copyright: 2011-2015 Massachusetts Institute of Technology\n", + " License: http://mit-crpg.github.io/openmc/license.html\n", + " Version: 0.7.0\n", + " Git SHA1: 3df61825cc8c93656ed1458c34fca14000884e73\n", + " Date/Time: 2015-09-19 07:34:09\n", + " OpenMP Threads: 4\n", + "\n", + " ===========================================================================\n", + " ========================> INITIALIZATION <=========================\n", + " ===========================================================================\n", + "\n", + " Reading settings XML file...\n", + " Reading cross sections XML file...\n", + " Reading geometry XML file...\n", + " Reading materials XML file...\n", + " Reading tallies XML file...\n", + " Building neighboring cells lists for each surface...\n", + " Loading ACE cross section table: 92238.71c\n", + " Loading ACE cross section table: 8016.71c\n", + " Loading ACE cross section table: 92235.71c\n", + " Loading ACE cross section table: 5010.71c\n", + " Loading ACE cross section table: 1001.71c\n", + " Loading ACE cross section table: 40090.71c\n", + " Initializing source particles...\n", + "\n", + " ===========================================================================\n", + " ====================> K EIGENVALUE SIMULATION <====================\n", + " ===========================================================================\n", + "\n", + " Bat./Gen. k Average k \n", + " ========= ======== ==================== \n", + " 1/1 1.01593 \n", + " 2/1 1.05332 \n", + " 3/1 1.03858 \n", + " 4/1 1.03420 \n", + " 5/1 1.03004 \n", + " 6/1 1.03899 \n", + " 7/1 1.04639 \n", + " 8/1 1.03921 \n", + " 9/1 1.00410 \n", + " 10/1 1.06702 \n", + " 11/1 1.03401 \n", + " 12/1 1.05518 1.04460 +/- 0.01059\n", + " 13/1 1.03358 1.04092 +/- 0.00713\n", + " 14/1 1.00991 1.03317 +/- 0.00925\n", + " 15/1 1.04884 1.03631 +/- 0.00782\n", + " 16/1 1.03449 1.03600 +/- 0.00639\n", + " 17/1 1.04612 1.03745 +/- 0.00559\n", + " 18/1 1.07511 1.04216 +/- 0.00675\n", + " 19/1 1.01774 1.03944 +/- 0.00655\n", + " 20/1 1.04054 1.03955 +/- 0.00586\n", + " 21/1 1.01202 1.03705 +/- 0.00586\n", + " 22/1 1.04460 1.03768 +/- 0.00538\n", + " 23/1 1.04415 1.03818 +/- 0.00498\n", + " 24/1 1.04222 1.03846 +/- 0.00462\n", + " 25/1 1.04045 1.03860 +/- 0.00430\n", + " 26/1 1.04133 1.03877 +/- 0.00403\n", + " 27/1 1.03166 1.03835 +/- 0.00381\n", + " 28/1 1.00701 1.03661 +/- 0.00399\n", + " 29/1 1.04111 1.03685 +/- 0.00378\n", + " 30/1 1.05130 1.03757 +/- 0.00366\n", + " 31/1 1.02685 1.03706 +/- 0.00352\n", + " 32/1 1.03458 1.03695 +/- 0.00335\n", + " 33/1 1.05243 1.03762 +/- 0.00328\n", + " 34/1 1.05717 1.03843 +/- 0.00324\n", + " 35/1 1.07396 1.03985 +/- 0.00342\n", + " 36/1 1.01690 1.03897 +/- 0.00340\n", + " 37/1 1.03340 1.03877 +/- 0.00328\n", + " 38/1 1.04153 1.03886 +/- 0.00316\n", + " 39/1 1.01971 1.03820 +/- 0.00312\n", + " 40/1 1.01491 1.03743 +/- 0.00311\n", + " 41/1 1.02779 1.03712 +/- 0.00303\n", + " 42/1 1.03047 1.03691 +/- 0.00294\n", + " 43/1 1.02305 1.03649 +/- 0.00288\n", + " 44/1 1.07854 1.03773 +/- 0.00305\n", + " 45/1 1.04412 1.03791 +/- 0.00297\n", + " 46/1 1.05139 1.03828 +/- 0.00291\n", + " 47/1 1.05357 1.03870 +/- 0.00286\n", + " 48/1 1.06435 1.03937 +/- 0.00287\n", + " 49/1 1.02632 1.03904 +/- 0.00281\n", + " 50/1 1.05201 1.03936 +/- 0.00276\n", + " 51/1 1.04582 1.03952 +/- 0.00270\n", + " 52/1 1.02056 1.03907 +/- 0.00267\n", + " 53/1 1.06448 1.03966 +/- 0.00267\n", + " 54/1 1.03609 1.03958 +/- 0.00261\n", + " 55/1 1.02701 1.03930 +/- 0.00257\n", + " 56/1 1.04865 1.03950 +/- 0.00252\n", + " 57/1 1.06310 1.04000 +/- 0.00252\n", + " 58/1 1.02975 1.03979 +/- 0.00247\n", + " 59/1 1.03922 1.03978 +/- 0.00242\n", + " 60/1 1.07259 1.04043 +/- 0.00246\n", + " 61/1 1.04555 1.04053 +/- 0.00242\n", + " 62/1 1.01950 1.04013 +/- 0.00240\n", + " 63/1 1.04618 1.04024 +/- 0.00236\n", + " 64/1 1.02489 1.03996 +/- 0.00233\n", + " 65/1 1.06850 1.04048 +/- 0.00235\n", + " 66/1 1.03623 1.04040 +/- 0.00231\n", + " 67/1 0.99892 1.03967 +/- 0.00238\n", + " 68/1 1.05557 1.03995 +/- 0.00236\n", + " 69/1 1.01211 1.03948 +/- 0.00236\n", + " 70/1 1.04679 1.03960 +/- 0.00233\n", + " 71/1 1.03461 1.03952 +/- 0.00229\n", + " 72/1 1.01993 1.03920 +/- 0.00227\n", + " 73/1 1.04742 1.03933 +/- 0.00224\n", + " 74/1 1.05269 1.03954 +/- 0.00222\n", + " 75/1 1.05696 1.03981 +/- 0.00220\n", + " 76/1 1.05904 1.04010 +/- 0.00218\n", + " 77/1 1.05930 1.04039 +/- 0.00217\n", + " 78/1 1.03375 1.04029 +/- 0.00214\n", + " 79/1 1.07044 1.04073 +/- 0.00215\n", + " 80/1 1.04144 1.04074 +/- 0.00212\n", + " 81/1 1.06296 1.04105 +/- 0.00212\n", + " 82/1 1.04630 1.04112 +/- 0.00209\n", + " 83/1 1.03772 1.04108 +/- 0.00206\n", + " 84/1 1.03774 1.04103 +/- 0.00203\n", + " 85/1 1.03984 1.04101 +/- 0.00200\n", + " 86/1 1.03040 1.04087 +/- 0.00198\n", + " 87/1 1.03484 1.04080 +/- 0.00196\n", + " 88/1 1.03820 1.04076 +/- 0.00193\n", + " 89/1 1.04654 1.04084 +/- 0.00191\n", + " 90/1 1.03377 1.04075 +/- 0.00189\n", + " 91/1 1.03370 1.04066 +/- 0.00187\n", + " 92/1 1.04172 1.04067 +/- 0.00184\n", + " 93/1 1.04945 1.04078 +/- 0.00182\n", + " 94/1 1.03360 1.04069 +/- 0.00181\n", + " 95/1 1.06547 1.04099 +/- 0.00181\n", + " 96/1 1.04340 1.04101 +/- 0.00179\n", + " 97/1 1.07502 1.04140 +/- 0.00181\n", + " 98/1 1.05391 1.04155 +/- 0.00179\n", + " 99/1 1.05622 1.04171 +/- 0.00178\n", + " 100/1 1.01519 1.04142 +/- 0.00179\n", + " Creating state point statepoint.100.h5...\n", + "\n", + " ===========================================================================\n", + " ======================> SIMULATION FINISHED <======================\n", + " ===========================================================================\n", + "\n", + "\n", + " =======================> TIMING STATISTICS <=======================\n", + "\n", + " Total time for initialization = 3.6600E-01 seconds\n", + " Reading cross sections = 1.1500E-01 seconds\n", + " Total time in simulation = 8.1308E+01 seconds\n", + " Time in transport only = 8.1157E+01 seconds\n", + " Time in inactive batches = 2.1600E+00 seconds\n", + " Time in active batches = 7.9148E+01 seconds\n", + " Time synchronizing fission bank = 1.6000E-02 seconds\n", + " Sampling source sites = 9.0000E-03 seconds\n", + " SEND/RECV source sites = 7.0000E-03 seconds\n", + " Time accumulating tallies = 1.0000E-02 seconds\n", + " Total time for finalization = 1.6400E-01 seconds\n", + " Total time elapsed = 8.1856E+01 seconds\n", + " Calculation Rate (inactive) = 23148.1 neutrons/second\n", + " Calculation Rate (active) = 5685.55 neutrons/second\n", + "\n", + " ============================> RESULTS <============================\n", + "\n", + " k-effective (Collision) = 1.04100 +/- 0.00169\n", + " k-effective (Track-length) = 1.04142 +/- 0.00179\n", + " k-effective (Absorption) = 1.04380 +/- 0.00147\n", + " Combined k-effective = 1.04287 +/- 0.00130\n", + " Leakage Fraction = 0.00000 +/- 0.00000\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Run OpenMC!\n", + "executor.run_simulation()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tally Data Processing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our simulation ran successfully and created a statepoint file with all the tally data in it. We begin our analysis here loading the statepoint file and 'reading' the results. By default, data from the statepoint file is only read into memory when it is requested. This helps keep the memory use to a minimum even when a statepoint file may be huge." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "# Load the statepoint file\n", + "sp = StatePoint('statepoint.100.h5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we need to get the tally, which can be done with the ``StatePoint.get_tally(...)`` method." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tally\n", + "\tID =\t10000\n", + "\tName =\t\n", + "\tFilters =\t\n", + " \t\tmesh\t[10000]\n", + "\tNuclides =\t-1 \n", + "\tScores =\t['flux', 'fission']\n", + "\tEstimator =\ttracklength\n", + "\n" + ] + } + ], + "source": [ + "tally = sp.get_tally(scores=['flux'])\n", + "print(tally)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The statepoint file actually stores the sum and sum-of-squares for each tally bin from which the mean and variance can be calculated as described [here](http://mit-crpg.github.io/openmc/methods/tallies.html#variance). The sum and sum-of-squares can be accessed using the ``sum`` and ``sum_sq`` properties:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0.41271426, 0. ]],\n", + "\n", + " [[ 0.40846766, 0. ]],\n", + "\n", + " [[ 0.4112029 , 0. ]],\n", + "\n", + " ..., \n", + " [[ 0.41437289, 0. ]],\n", + "\n", + " [[ 0.41376468, 0. ]],\n", + "\n", + " [[ 0.41312074, 0. ]]])" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tally.sum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, the mean and standard deviation of the mean are usually what you are more interested in. The Tally class also has properties ``mean`` and ``std_dev`` which automatically calculate these statistics on-the-fly." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(10000, 1, 2)\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([[[ 0.00458571, 0. ]],\n", + " \n", + " [[ 0.00453853, 0. ]],\n", + " \n", + " [[ 0.00456892, 0. ]],\n", + " \n", + " ..., \n", + " [[ 0.00460414, 0. ]],\n", + " \n", + " [[ 0.00459739, 0. ]],\n", + " \n", + " [[ 0.00459023, 0. ]]]),\n", + " array([[[ 2.02702426e-05, 0.00000000e+00]],\n", + " \n", + " [[ 1.77108625e-05, 0.00000000e+00]],\n", + " \n", + " [[ 1.79568064e-05, 0.00000000e+00]],\n", + " \n", + " ..., \n", + " [[ 1.83114148e-05, 0.00000000e+00]],\n", + " \n", + " [[ 1.69970626e-05, 0.00000000e+00]],\n", + " \n", + " [[ 1.92143217e-05, 0.00000000e+00]]]))" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(tally.mean.shape)\n", + "(tally.mean, tally.std_dev)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The tally data has three dimensions: one for filter combinations, one for nuclides, and one for scores. We see that there are 10000 filter combinations (corresponding to the 100 x 100 mesh bins), a single nuclide (since none was specified), and two scores. If we only want to look at a single score, we can use the ``get_slice(...)`` method as follows." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tally\n", + "\tID =\t10000\n", + "\tName =\t\n", + "\tFilters =\t\n", + " \t\tmesh\t[10000]\n", + "\tNuclides =\t-1 \n", + "\tScores =\t['flux']\n", + "\tEstimator =\ttracklength\n", + "\n" + ] + } + ], + "source": [ + "flux = tally.get_slice(scores=['flux'])\n", + "fission = tally.get_slice(scores=['fission'])\n", + "print(flux)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To get the bins into a form that we can plot, we can simply change the shape of the array since it is a numpy array." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "flux.std_dev.shape = (100, 100)\n", + "flux.mean.shape = (100, 100)\n", + "fission.std_dev.shape = (100, 100)\n", + "fission.mean.shape = (100, 100)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig = plt.subplot(121)\n", + "fig.imshow(flux.mean)\n", + "fig2 = plt.subplot(122)\n", + "fig2.imshow(fission.mean)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's say we want to look at the distribution of relative errors of our tally bins for flux. First we create a new variable called ``relative_error`` and set it to the ratio of the standard deviation and the mean, being careful not to divide by zero in case some bins were never scored to." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Determine relative error\n", + "relative_error = np.zeros_like(flux.std_dev)\n", + "nonzero = flux.mean > 0\n", + "relative_error[nonzero] = flux.std_dev[nonzero] / flux.mean[nonzero]\n", + "\n", + "# distribution of relative errors\n", + "ret = plt.hist(relative_error[nonzero], bins=50)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Source Sites" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Source sites can be accessed from the ``source`` property. As shown below, the source sites are represented as a numpy array with a structured datatype." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ (1.0, [0.08159183470384083, 0.37187405724079425, -0.4569273259677805], [-0.5991379733562734, 0.6213299732428319, -0.5049581697849825], 1.4308796774550836),\n", + " (1.0, [0.08159183470384083, 0.37187405724079425, -0.4569273259677805], [0.6943502674814661, -0.18996972225593808, 0.694110373553384], 1.8499326750790277),\n", + " (1.0, [-0.2283457014858208, -0.3149356437736135, -0.6287339985223156], [0.22841158666373973, -0.9428738529578353, 0.24252225565130936], 2.8993105331976654),\n", + " ...,\n", + " (1.0, [-0.20844939420957254, 0.043779246455180054, -0.22209004880139005], [0.871391386295745, 0.3866181159860615, 0.30199914615933615], 2.2329770939373517),\n", + " (1.0, [-0.20844939420957254, 0.043779246455180054, -0.22209004880139005], [-0.4649777417907873, 0.38973845929247963, 0.7949211489119309], 1.6836109244016622),\n", + " (1.0, [-0.20844939420957254, 0.043779246455180054, -0.22209004880139005], [-0.4649777417907873, 0.38973845929247963, 0.7949211489119309], 1.6836109244016622)], \n", + " dtype=[('wgt', '" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAY4AAAEUCAYAAAA8+dFZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAGeRJREFUeJzt3X20ZFV55/Hvz8YXUBL6Jo4O0IojELtdOgENsGJmxBdc\npFVQOhFoEpUZBY0dXyaZMK6oMOOsTHSiImHJ4BIVDQ0qEAdHEF9BaR0UQVT6grAcMrysIcRu3yAq\nL8/8UXWhKG7VrXO7zq26t7+ftWp1nX32OfXUprof9tn77JOqQpKkUT1i0gFIkpYXE4ckqREThySp\nEROHJKkRE4ckqREThySpkVYTR5LDk1yf5MYkJ82z/2lJvpHkF0n+rMmxkqTJSFv3cSRZBdwAvBC4\nDfgWcGxVzfbUeTzwZOBlwPaqes+ox0qSJqPNHsdBwE1VdXNV3QOcBxzZW6Gq7qyqq4B7mh4rSZqM\nNhPHXsAtPdu3dsvaPlaS1KI2E8eOXANzHRRJmlK7tHju24A1Pdtr6PQcxnZsEhOMJC1CVWWxx7bZ\n47gK2C/JPkkeBRwNXDSgbv8XGPnYqmr9dfLJJ7d+3EJ1B+1vUt5f1r991FFHTW1bNjl2lHq25/ja\nc9j+UdptlLKlaMsdac+l+Lu+I+3Zv72jWutxVNW9STYBlwKrgLOqajbJid39ZyZ5Ip0ZU78G3J/k\nTcC6qvr5fMe2FetCDj300NaPW6juoP1NyvvLFvu9dsSOfOaox45Sz/YcX3sO2z9KuzUpa9s0/10f\ntG8Sv83WpuMuhSS1nOOfNhs2bOCCCy6YdBgrhu05PrbleCWhpvRSlZaZtWvXTjqEFcX2HB/bcrqY\nOPSAdevWTTqEFcX2HB/bcrqYOCRJjZg4JEmNmDgkSY2YOCRJjZg4JEmNmDgkSY2YOCRJjZg4JEmN\nmDgkSY2YOCRJjZg4JK14MzOQzP+amZl0dMtPmw9ykqSpsH07DFpIO4teI3bnZY9DktSIiUOS1IiJ\nQ5LUiIlDktSIiUPSsuHsqOngrCpJy4azo6aDPQ5JUiMmDklSIyYOSVIjJg5JUiMmDklSIyYOSZqH\nU38HczquJM3Dqb+D2eOQJDVi4pAkNWLikCQ1YuKQJDVi4pAkNWLikCQ1YuKQJDVi4pAkNWLikCQ1\n0mriSHJ4kuuT3JjkpAF1TuvuvzbJAT3lb01yXZLvJdmc5NFtxipJGk1riSPJKuB04HBgHXBskrV9\n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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create log-spaced energy bins from 1 keV to 100 MeV\n", + "energy_bins = np.logspace(-3,1)\n", + "\n", + "# Calculate pdf for source energies\n", + "probability, bin_edges = np.histogram(sp.source['E'], energy_bins, density=True)\n", + "\n", + "# Make sure integrating the PDF gives us unity\n", + "print(sum(probability*np.diff(energy_bins)))\n", + "\n", + "# Plot source energy PDF\n", + "plt.semilogx(energy_bins[:-1], probability*np.diff(energy_bins), linestyle='steps')\n", + "plt.xlabel('Energy (MeV)')\n", + "plt.ylabel('Probability/MeV')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's also look at the spatial distribution of the sites. To make the plot a little more interesting, we can also include the direction of the particle emitted from the source and color each source by the logarithm of its energy." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(-0.5, 0.5)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.quiver(sp.source['xyz'][:,0], sp.source['xyz'][:,1],\n", + " sp.source['uvw'][:,0], sp.source['uvw'][:,1],\n", + " np.log(sp.source['E']), cmap='jet', scale=20.0)\n", + "plt.colorbar()\n", + "plt.xlim((-0.5,0.5))\n", + "plt.ylim((-0.5,0.5))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.9" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/source/pythonapi/examples/post-processing.rst b/docs/source/pythonapi/examples/post-processing.rst new file mode 100644 index 000000000..b488d15ff --- /dev/null +++ b/docs/source/pythonapi/examples/post-processing.rst @@ -0,0 +1,13 @@ +.. _notebook_post_processing: + +=============== +Post Processing +=============== + +.. only:: html + + .. notebook:: post-processing.ipynb + +.. only:: latex + + IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/pythonapi/index.rst b/docs/source/pythonapi/index.rst index 8c42f2d7e..12baf937d 100644 --- a/docs/source/pythonapi/index.rst +++ b/docs/source/pythonapi/index.rst @@ -62,6 +62,7 @@ on a given module or class. .. toctree:: :maxdepth: 1 + examples/post-processing examples/pandas-dataframes examples/tally-arithmetic diff --git a/docs/source/usersguide/output/voxel.rst b/docs/source/usersguide/output/voxel.rst index bcdcd8eb1..1da501fb5 100644 --- a/docs/source/usersguide/output/voxel.rst +++ b/docs/source/usersguide/output/voxel.rst @@ -1,8 +1,8 @@ .. _usersguide_voxel: -================= -Voxel File Format -================= +====================== +Voxel Plot File Format +====================== **/filetype** (*char[]*) diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst index a6e9875ce..3a6766a2d 100644 --- a/docs/source/usersguide/processing.rst +++ b/docs/source/usersguide/processing.rst @@ -6,31 +6,33 @@ Data Processing and Visualization This section is intended to explain in detail the recommended procedures for carrying out common post-processing tasks with OpenMC. While several utilities -of varying complexity are provided to help automate the process, in many cases -it will be extremely beneficial to do some coding in Python to quickly obtain -results. In these cases, and for many of the provided utilities, it is necessary -for your Python installation to contain: +of varying complexity are provided to help automate the process, the most +powerful capabilities for post-processing derive from use of the :ref:`Python +API `. Both the provided scripts and the Python API rely on a number +third-party Python packages, including: -* [1]_ `Numpy `_ -* [1]_ `Scipy `_ -* [2]_ `h5py `_ -* [3]_ `Matplotlib `_ +* [1]_ `NumPy `_ +* [2]_ `h5py `_ +* [3]_ `pandas `_ +* [3]_ `matplotlib `_ * [3]_ `Silomesh `_ * [3]_ `VTK `_ +* [3]_ `lxml `_ -Most of these are easily obtainable in Ubuntu through the package manager, or -are easily installed with distutils. +Most of these are can easily be installed with `pip `_ +or alternatively obtaining through a package manager. -.. [1] Required for tally data extraction from statepoints with statepoint.py -.. [2] Required only if reading HDF5 statepoint files. -.. [3] Optional for plotting utilities +.. [1] Required for most post-processing tasks +.. [2] Required for reading HDF5 output files +.. [3] Not used directly by the Python API, but are optional dependencies for a + number of scripts. ---------------------- Geometry Visualization ---------------------- Geometry plotting is carried out by creating a plots.xml, specifying plots, and -running OpenMC with the -plot or -p command-line option (See +running OpenMC with the --plot or -p command-line option (See :ref:`usersguide_plotting`). Plotting in 2D @@ -128,27 +130,26 @@ capabilities of 3D voxel plots. Voxel plots are built the same way 2D slice plots are, by determining the cell or material id of a particle at the center of each voxel. In this example, the space covered is the cube between the points (-5,-5,-5) and (5,5,5), with voxel -centers 10/500 = 0.02 cm apart. The binary VOXEL files that are produced do not +centers 10/500 = 0.02 cm apart. The HDF5 voxel files that are produced do not specify any color - instead containing only material or cell ids (material id in this example) - and thus the ``background``, ``col_spec``, and ``mask`` elements are not used. If no cell is found at a voxel center, an id of -1 is stored. -The binary VOXEL files output by OpenMC can not be viewed directly by any -existing viewers. In order to view them, they must be converted into a standard -mesh format that can be viewed in ParaView, Visit, etc. This typically will -compress the size of the file significantly. The provided utility voxel.py -accomplishes this for SILO: +The voxel plot data is written to an HDF5 file. The voxel file can subsequently +be converted into a standard mesh format that can be viewed in ParaView, Visit, +etc. This typically will compress the size of the file significantly. The +provided utility openmc-voxel-to-silovtk accomplishes this for SILO: .. code-block:: sh - /src/utils/voxel.py myplot.voxel -o output.silo + openmc-voxel-to-silovtk myplot.voxel -o output.silo and VTK file formats: .. code-block:: sh - /src/utils/voxel.py myplot.voxel --vtk -o output.vti + openmc-voxel-to-silovtk myplot.voxel --vtk -o output.vti To use this utility you need either @@ -156,11 +157,10 @@ To use this utility you need either or -* `VTK `_ with python bindings - On Ubuntu, these are - easily obtained with ``sudo apt-get install python-vtk`` +* `VTK `_ with python bindings. On debian derivatives, + these are easily obtained with ``sudo apt-get install python-vtk`` -Users can process the binary into any other format if desired by following the -example of voxel.py. For the binary file structure, see :ref:`devguide_voxel`. +For the HDF5 file structure, see :ref:`usersguide_voxel`. Once processed into a standard 3D file format, colors and masks can be defined using the stored id numbers to better explore the geometry. The process for @@ -183,150 +183,38 @@ doing this will depend on the 3D viewer, but should be straightforward. Tally Visualization ------------------- -Tally results are saved in both a text file (tallies.out) as well as a binary +Tally results are saved in both a text file (tallies.out) as well as an HDF5 statepoint file. While the tallies.out file may be fine for simple tallies, in -many cases the user requires more information about the tally or the run, or -has to deal with a large number of result values (e.g. for mesh tallies). In -these cases, extracting data from the statepoint file via Python scripting is -the preferred method of data analysis and visualization. +many cases the user requires more information about the tally or the run, or has +to deal with a large number of result values (e.g. for mesh tallies). In these +cases, extracting data from the statepoint file via the Python API is the +preferred method of data analysis and visualization. Data Extraction --------------- A great deal of information is available in statepoint files (See -:ref:`usersguide_statepoint`), most of which is easily extracted by the provided -utility statepoint.py. This utility provides a Python class to load statepoints -and extract data - it is used in many of the provided plotting utilities, and -can be used in user-created scripts to carry out manipulations of the data. To -read tallies using this utility, make sure statepoint.py is in your PYTHONPATH, -and then import the class, instantiate it, and call read_results: +:ref:`usersguide_statepoint`), all of which is accessible through the Python +API. The ``openmc.statepoint`` module (see :ref:`pythonapi_statepoint`) provides +a class to load statepoints and access data as requested; it is used in many of +the provided plotting utilities, OpenMC's regression test suite, and can be used +in user-created scripts to carry out manipulations of the data. -.. code-block:: python - - from statepoint import StatePoint - sp = StatePoint('statepoint.100.binary') - sp.read_results() - -At this point the user can extract entire scores from tallies into a data -dictionary containing numpy arrays: - -.. code-block:: python - - tallyid = 1 - score = 'flux' - data = sp.extract_results(tallyid, score) - means = data['means'] - print data.keys() - -The results from this function contain all filter bins (all mesh points, all -energy groups, etc.), which can be reshaped with the bin ordering also contained -in the output dictionary. This is the best choice of output for easily -integrating ranges of data. - -Alternatively the user can extract specific values for a single score/filter -combination: - -.. code-block:: python - - tallyid = 1 - score = 'flux' - filters = [('mesh', (1, 1, 5)), ('energyin', 0)] - value, error = sp.get_value(tallyid, filters, score) - -In the future more documentation may become available here for statepoint.py and -the data extraction functions of StatePoint objects. However, for now it is up -to the user to explore the classes in statepoint.py to discover what data is -available in StatePoint objects (we highly recommend interactively exploring -with `IPython `_). Many examples can be found by looking -through the other utilities that use statepoint.py, and a few common -visualization tasks will be described here in the following sections. +An :ref:`example IPython notebook ` demonstrates how +to extract data from a statepoint using the Python API. Plotting in 2D -------------- +The :ref:`IPython notebook example ` also demonstrates +how to plot a mesh tally in two dimensions using the Python API. Note, however, +that there is also a script distributed with OpenMC, ``openmc-plot-mesh-tally``, +that interactive GUI to explore and plot mesh tallies for any scores and filter +bins. + .. image:: ../_images/plotmeshtally.png :height: 200px -For simple viewing of 2D slices of a mesh plot, the utility plot_mesh_tally.py -is provided. This utility provides an interactive GUI to explore and plot -mesh tallies for any scores and filter bins. It requires statepoint.py. - -.. image:: ../_images/fluxplot.png - :height: 200px - -Alternatively, the user can write their own Python script to manipulate the data -appropriately. Consider a run where the first tally contains a 105x105x20 mesh -over a small core, with a flux score and two energyin filter bins. To explicitly -extract the data and create a plot with gnuplot, the following script can be -used. The script operates in several steps for clarity, and is not necessarily -the most efficient way to extract data from large mesh tallies. This creates the -two heatmaps in the previous figure. - -.. code-block:: python - - #!/usr/bin/env python - - import os - - import statepoint - - # load and parse the statepoint file - sp = statepoint.StatePoint('statepoint.300.binary') - sp.read_results() - - tallyid = 0 # This is tally 1 - score = 0 # This corresponds to flux (see tally.scores) - - # get mesh dimensions - meshid = sp.tallies[tallyid].filters['mesh'].bins[0] - for i,m in enumerate(sp.meshes): - if m.id == meshid: - mesh = m - break - nx,ny,nz = mesh.dimension - - # loop through mesh and extract values to python dictionaries - thermal = {} - fast = {} - for x in range(1,nx+1): - for y in range(1,ny+1): - for z in range(1,nz+1): - val,err = sp.get_value(tallyid, - [('mesh',(x,y,z)),('energyin',0)], - score) - thermal[(x,y,z)] = val - val,err = sp.get_value(tallyid, - [('mesh',(x,y,z)),('energyin',1)], - score) - fast[(x,y,z)] = val - - # sum up the axial values and write datafile for gnuplot - with open('meshdata.dat','w') as fh: - for x in range(1,nx+1): - for y in range(1,ny+1): - thermalval = 0. - fastval = 0. - for z in range(1,nz+1): - thermalval += thermal[(x,y,z)] - fastval += fast[(x,y,z)] - fh.write("{} {} {} {}\n".format(x,y,thermalval,fastval)) - - # write gnuplot file - with open('tmp.gnuplot','w') as fh: - fh.write(r"""set terminal png size 1000 400 - set output 'fluxplot.png' - set nokey - set autoscale fix - set multiplot layout 1,2 title "Pin Mesh Flux Tally" - set title "Thermal" - plot 'meshdata.dat' using 1:2:3 with image - set title "Fast" - plot 'meshdata.dat' using 1:2:4 with image - """) - - # make plot - os.system("gnuplot < tmp.gnuplot") - Plotting in 3D -------------- @@ -334,22 +222,23 @@ Plotting in 3D :height: 200px As with 3D plots of the geometry, meshtally data needs to be put into a standard -format for viewing. The utility statepoint_3d.py is provided to accomplish this -for both VTK and SILO. By default statepoint_3d.py processes a statepoint into a -3D file with all mesh tallies and filter/score combinations, +format for viewing. The utility ``openmc-statepoint-3d`` is provided to +accomplish this for both VTK and SILO. By default ``openmc-statepoint-3d`` +processes a statepoint into a 3D file with all mesh tallies and filter/score +combinations, .. code-block:: sh - /src/utils/statepoint_3d.py -o output.silo - /src/utils/statepoint_3d.py --vtk -o output.vtm + openmc-statepoint-3d -o output.silo + openmc-statepoint-3d --vtk -o output.vtm but it also provides several command-line options to selectively process only certain data arrays in order to keep file sizes down. .. code-block:: sh - statepoint_3d.py --tallies 2,4 --scores 4.1,4.3 -o output.silo - statepoint_3d.py --filters 2.energyin.1 --vtk -o output.vtm + openmc-statepoint-3d --tallies 2,4 --scores 4.1,4.3 -o output.silo + openmc-statepoint-3d --filters 2.energyin.1 --vtk -o output.vtm All available options for specifying a subset of tallies, scores, and filters can be listed with the ``--list`` or ``-l`` command line options. @@ -426,13 +315,11 @@ Getting Data into MATLAB ------------------------ There is currently no front-end utility to dump tally data to MATLAB files, but -the process is straightforward. First extract the data using a custom Python -script with statepoint.py, put the data into appropriately-shaped numpy arrays, -and then use the `Scipy MATLAB IO routines +the process is straightforward. First extract the data using the Python API via +``openmc.statepoint`` and then use the `Scipy MATLAB IO routines `_ to save to a MAT -file. Note that the data contained in the output from -``StatePoint.extract_result`` is already in a Numpy array that can be reshaped -and dumped to MATLAB in one step. +file. Note that all arrays that are accessible in a statepoint are already in +NumPy arrays that can be reshaped and dumped to MATLAB in one step. ---------------------------- Particle Track Visualization @@ -463,15 +350,15 @@ particle numbers, respectively. For example, to output the tracks for particles After running OpenMC, the directory should contain a file of the form -"track_(batch #)_(generation #)_(particle #).(binary or h5)" for each particle -tracked. These track files can be converted into VTK poly data files with the -"track.py" utility. The usage of track.py is of the form "track.py [-o OUT] IN" -where OUT is the optional output filename and IN is one or more filenames -describing track files. The default output name is "track.pvtp". A common -usage of track.py is "track.py track*.binary" which will use the data from all -binary track files in the directory to write a "track.pvtp" VTK output file. -The .pvtp file can then be read and plotted by 3d visualization programs such as -ParaView. +"track_(batch #)_(generation #)_(particle #).h5" for each particle tracked. +These track files can be converted into VTK poly data files with the +``openmc-track-to-vtk`` utility. The usage of ``openmc-track-to-vtk`` is of the +form "openmc-track-to-vtk [-o OUT] IN" where OUT is the optional output filename +and IN is one or more filenames describing track files. The default output name +is "track.pvtp". A common usage of track.py is "openmc-track-to-vtk track*.h5" +which will use the data from all binary track files in the directory to write a +"track.pvtp" VTK output file. The .pvtp file can then be read and plotted by 3d +visualization programs such as ParaView. ---------------------- Source Site Processing @@ -480,43 +367,6 @@ Source Site Processing For eigenvalue problems, OpenMC will store information on the fission source sites in the statepoint file by default. For each source site, the weight, position, sampled direction, and sampled energy are stored. To extract this data -from a statepoint file, the statepoint.py Python module can be used. Below is an -example of an interactive ipython session using the statepoint.py Python module: - -.. code-block:: python - - In [1]: import statepoint - - In [2]: sp = statepoint.StatePoint('statepoint.100.h5') - - In [3]: sp.read_source() - - In [4]: len(sp.source) - Out[4]: 1000 - - In [5]: sp.source[0:10] - Out[5]: - [, - , - , - , - , - , - , - , - , - ] - - In [6]: site = sp.source[0] - - In [7]: site.weight - Out[7]: 1.0 - - In [8]: site.xyz - Out[8]: array([ 2.21980946, -8.92686048, 87.93720485]) - - In [9]: site.uvw - Out[9]: array([ 0.06740523, 0.50612814, 0.85982024]) - - In [10]: site.E - Out[10]: 0.93292326356564159 +from a statepoint file, the ``openmc.statepoint`` module can be used. An +:ref:`example IPython notebook ` demontrates how to +analyze and plot source information. diff --git a/scripts/openmc-statepoint-histogram b/scripts/openmc-statepoint-histogram deleted file mode 100755 index 26e8bdae6..000000000 --- a/scripts/openmc-statepoint-histogram +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python - -from __future__ import print_function -from sys import argv -from math import sqrt - -import numpy as np -import scipy.stats -import matplotlib.pyplot as plt - -from openmc.statepoint import StatePoint - -# Get filename -filename = argv[1] - -# Create StatePoint object -sp = StatePoint(filename) -sp.read_results() -sp.compute_ci() - -# Check if tallies are present -if not sp.tallies_present: - raise Exception("No tally data in state point!") - -# Loop over all tallies -for i, t in sp.tallies.items(): - # Determine relative error and fraction of bins with less than 1% half-width - # of CI - n_bins = t.mean.size - relative_error = t.std_dev[t.mean > 0.] / t.mean[t.mean > 0.] - fraction = float(sum(relative_error < 0.01))/n_bins - - # Display results - print("Tally " + str(i)) - print(" Fraction under 1% = {0}".format(fraction)) - print(" Min relative error = {0}".format(min(relative_error))) - print(" Max relative error = {0}".format(max(relative_error))) - print(" Non-scoring bins = {0}".format( - 1.0 - float(relative_error.size)/n_bins)) - - # Plot histogram - plt.hist(relative_error, 100) - plt.show() diff --git a/setup.py b/setup.py index 655e38e3a..3273f1db7 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ kwargs = {'name': 'openmc', if have_setuptools: kwargs.update({ # Required dependencies - 'install_requires': ['numpy', 'scipy', 'h5py', 'matplotlib'], + 'install_requires': ['numpy', 'h5py', 'matplotlib'], # Optional dependencies 'extras_require': { From ce46f8b918cb802267d9c529043583c40b197395 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 19 Sep 2015 07:42:36 +0700 Subject: [PATCH 61/95] Fix documentation for openmc-validate-xml --- docs/source/usersguide/input.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 93e8236ec..346922d1d 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -79,14 +79,13 @@ Message Description [VALID] XML file matches RelaxNG. ======================== =================================== -As an example, if OpenMC is installed in the directory -``/opt/openmc/0.6.2`` and the current working directory is where -OpenMC XML input files are located, they can be validated using -the following command: +As an example, if OpenMC is installed in the directory ``/opt/openmc/`` and the +current working directory is where OpenMC XML input files are located, they can +be validated using the following command: .. code-block:: bash - /opt/openmc/0.6.2/bin/xml_validate + /opt/openmc/bin/openmc-validate-xml -------------------------------------- Settings Specification -- settings.xml From 609c8c28aed946a4ccc9b854efa8addd0e2e4af3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 19 Sep 2015 07:47:03 +0700 Subject: [PATCH 62/95] Updated troubleshooting guide. --- docs/source/usersguide/troubleshoot.rst | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/docs/source/usersguide/troubleshoot.rst b/docs/source/usersguide/troubleshoot.rst index 10ac12184..c5e4e7c1e 100644 --- a/docs/source/usersguide/troubleshoot.rst +++ b/docs/source/usersguide/troubleshoot.rst @@ -31,21 +31,6 @@ f951: error: unrecognized command line option "-fbacktrace" You are probably using a version of the gfortran compiler that is too old. Download and install the latest version of gfortran_. - -make[1]: ifort: Command not found -********************************* - -You tried compiling with the Intel Fortran compiler and it was not found on your -:envvar:`PATH`. If you have the Intel compiler installed, make sure the shell -can locate it (this can be tested with :program:`which ifort`). - -make[1]: pgf90: Command not found -********************************* - -You tried compiling with the PGI Fortran compiler and it was not found on your -:envvar:`PATH`. If you have the PGI compiler installed, make sure the shell can -locate it (this can be tested with :program:`which pgf90`). - ------------------------- Problems with Simulations ------------------------- @@ -56,13 +41,13 @@ Segmentation Fault A segmentation fault occurs when the program tries to access a variable in memory that was outside the memory allocated for the program. The best way to debug a segmentation fault is to re-compile OpenMC with debug options turned -on. First go to your ``openmc/src`` directory where OpenMC was compiled and type -the following commands: +on. Create a new build directory and type the following commands: .. code-block:: sh - make distclean - make DEBUG=yes + mkdir build-debug && cd build-debug + cmake -Ddebug=on /path/to/openmc + make Now when you re-run your problem, it should report exactly where the program failed. If after reading the debug output, you are still unsure why the program From cb3d79a1af9f96f1717d6f3b79dd7c53319c0356 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 19 Sep 2015 10:10:19 +0700 Subject: [PATCH 63/95] Added summary file format in documentation. sab_names now array of strings. --- docs/source/usersguide/input.rst | 20 +- docs/source/usersguide/output/index.rst | 1 + docs/source/usersguide/output/summary.rst | 298 ++++++++++++++++++++++ openmc/summary.py | 18 +- src/constants.F90 | 1 + src/summary.F90 | 22 +- 6 files changed, 330 insertions(+), 30 deletions(-) create mode 100644 docs/source/usersguide/output/summary.rst diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 346922d1d..d69800659 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1525,16 +1525,16 @@ sub-elements: *Default*: None - Required entry :type: - Keyword for type of plot to be produced. Currently only "slice" and - "voxel" plots are implemented. The "slice" plot type creates 2D pixel - maps saved in the PPM file format. PPM files can be displayed in most - viewers (e.g. the default Gnome viewer, IrfanView, etc.). The "voxel" - plot type produces a binary datafile containing voxel grid positioning and - the cell or material (specified by the ``color`` tag) at the center of each - voxel. These datafiles can be processed into 3D SILO files using the - ``voxel.py`` utility provided with the OpenMC source, and subsequently - viewed with a 3D viewer such as VISIT or Paraview. See the - :ref:`devguide_voxel` for information about the datafile structure. + Keyword for type of plot to be produced. Currently only "slice" and "voxel" + plots are implemented. The "slice" plot type creates 2D pixel maps saved in + the PPM file format. PPM files can be displayed in most viewers (e.g. the + default Gnome viewer, IrfanView, etc.). The "voxel" plot type produces a + binary datafile containing voxel grid positioning and the cell or material + (specified by the ``color`` tag) at the center of each voxel. These + datafiles can be processed into 3D SILO files using the + ``openmc-voxel-to-silovtk`` utility provided with the OpenMC source, and + subsequently viewed with a 3D viewer such as VISIT or Paraview. See the + :ref:`usersguide_voxel` for information about the datafile structure. .. note:: Since the PPM format is saved without any kind of compression, the resulting file sizes can be quite large. Saving the image in diff --git a/docs/source/usersguide/output/index.rst b/docs/source/usersguide/output/index.rst index 161a8de2d..31bd1da91 100644 --- a/docs/source/usersguide/output/index.rst +++ b/docs/source/usersguide/output/index.rst @@ -10,6 +10,7 @@ Output File Formats statepoint source + summary particle_restart track voxel diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst new file mode 100644 index 000000000..f924cb1d6 --- /dev/null +++ b/docs/source/usersguide/output/summary.rst @@ -0,0 +1,298 @@ +.. _usersguide_summary: + +=================== +Summary File Format +=================== + +The current revision of the summary file format is 1. + +**/filetype** (*char[]*) + + String indicating the type of file. + +**/revision** (*int*) + + Revision of the summary file format. Any time a change is made in the + format, this integer is incremented. + +**/version_major** (*int*) + + Major version number for OpenMC + +**/version_minor** (*int*) + + Minor version number for OpenMC + +**/version_release** (*int*) + + Release version number for OpenMC + +**/date_and_time** (*char[]*) + + Date and time the state point was written. + +**/n_procs** (*int*) + + Number of MPI processes used. + +**/n_particles** (*int8_t*) + + Number of particles used per generation. + +**/n_batches** (*int*) + + Number of batches to simulate. + +if (run_mode == MODE_EIGENVALUE) + + **/n_inactive** (*int*) + + Number of inactive batches. + + **/n_active** (*int*) + + Number of active batches. + + **/gen_per_batch** (*int*) + + Number of generations per batch. + +end if + +**/geometry/n_cells** (*int*) + +**/geometry/n_surfaces** (*int*) + +**/geometry/n_universes** (*int*) + +**/geometry/n_lattices** (*int*) + +do i = 1, n_cells + + **/geometry/cells/cell /index** (*int*) + + **/geometry/cells/cell /name** (*char[]*) + + **/geometry/cells/cell /universe** (*int*) + + **/geometry/cells/cell /fill_type** (*int*) + + **/geometry/cells/cell /material** (*int*) + + **/geometry/cells/cell /fill** (*int*) + + **/geometry/cells/cell /maps** (*int*) + + **/geometry/cells/cell /offset** (*int[]*) + + **/geometry/cells/cell /translated** (*int*) + + **/geometry/cells/cell /translation** (*double[]*) + + **/geometry/cells/cell /rotated** (*int*) + + **/geometry/cells/cell /rotation** (*double[]*) + + **/geometry/cells/cell /lattice** (*int*) + + **/geometry/cells/cell /surfaces** (*int[]*) + +end do + +do i = 1, n_surfaces + + **/geometry/surfaces/surface /index** (*int*) + + **/geometry/surfaces/surface /name** (*char[]*) + + **/geometry/surfaces/surface /type** (*char[]*) + + **/geometry/surfaces/surface /coefficients** (*double[]*) + + **/geometry/surfaces/surface /neighbors_positive** (*int[]*) + + **/geometry/surfaces/surface /neighbors_negative** (*int[]*) + + **/geometry/surfaces/surface /boundary_condition** (*char[]*) + +end do + +do i = 1, n_universes + + **/geometry/universes/universe /index** (*int*) + + **/geometry/universes/universe /cells** (*int[]*) + +end do + +do i = 1, n_lattices + + **/geometry/lattices/lattice /index** (*int*) + + **/geometry/lattices/lattice /name** (*char[]*) + + **/geometry/lattices/lattice /type** (*char[]*) + + **/geometry/lattices/lattice /pitch** (*double[]*) + + **/geometry/lattices/lattice /outer** (*int*) + + **/geometry/lattices/lattice /offset_size** (*int[]*) + + **/geometry/lattices/lattice /maps** (*int*) + + **/geometry/lattices/lattice /offsets** (*int[]*) + + **/geometry/lattices/lattice /universes** (*int[]*) + + if (rectangular lattice) + + **/geometry/lattices/lattice /dimension** (*int[]*) + + **/geometry/lattices/lattice /lower_left** (*double[]*) + + elseif (hexagonal lattice) + + **/geometry/lattices/lattice /n_rings** (*int*) + + **/geometry/lattices/lattice /n_axial** (*int*) + + **/geometry/lattices/lattice /center** (*double[]*) + + end if + +end do + +**/n_materials** (*int*) + +do i = 1, n_materials + + **/materials/material /index** (*int*) + + **/materials/material /name** (*char[]*) + + **/materials/material /atom_density** (*double[]*) + + **/materials/material /nuclides** (*int[]*) + + **/materials/material /nuclide_densities** (*double[]*) + + **/materials/material /n_sab** (*int*) + + **/materials/material /i_sab_nuclides** (*int*) + + **/materials/material /i_sab_tables** (*int*) + + **/materials/material /sab_names** (*char[][]*) + +end do + +**/tallies/n_tallies** (*int*) + +**/tallies/n_meshes** (*int*) + +do i = 1, n_meshes + + **/tallies/mesh /index** (*int*) + + **/tallies/mesh /type** (*int*) + + **/tallies/mesh /n_dimension** (*int*) + + **/tallies/mesh /dimension** (*int[]*) + + **/tallies/mesh /lower_left** (*double[]*) + + **/tallies/mesh /upper_right** (*double[]*) + + **/tallies/mesh /width** (*double[]*) + +end do + +do i = 1, n_tallies + + **/tallies/tally /index** (*int*) + + **/tallies/tally /name** (*char[]*) + + **/tallies/tally /total_score_bins** (*int*) + + **/tallies/tally /total_filter_bins** (*int*) + + **/tallies/tally /n_filters** (*int*) + + do j = 1, n_filters + + **/tallies/tally /filter j/type** (*int*) + + **/tallies/tally /filter j/n_bins** (*int*) + + **/tallies/tally /filter j/bins** (*int[]* or *double[]*) + + **/tallies/tally /filter j/type_name** (*char[]*) + + end do + + **/tallies/tally /n_nuclide_bins** (*int*) + + **/tallies/tally /nuclide_bins** (*int[]*) + + **/tallies/tally /n_score_bins** (*int*) + + **/tallies/tally /score_bins** (*int[]*) + +end do + +**/nuclides/n_nuclides** (*int*) + +do i = 1, n_nuclides + + **/nuclides//index** (*int*) + + **/nuclides//zaid** (*int*) + + **/nuclides//alias** (*char[]*) + + **/nuclides//awr** (*double*) + + **/nuclides//kT** (*double*) + + **/nuclides//n_grid** (*int*) + + **/nuclides//n_reactions** (*int*) + + **/nuclides//n_fission** (*int*) + + **/nuclides//size_xs** (*int*) + + do j = 1, n_reactions + + **/nuclides//reactions//Q_value** (*double*) + + **/nuclides//reactions//multiplicity** (*int*) + + **/nuclides//reactions//threshold** (*double*) + + **/nuclides//reactions//size_angle** (*int*) + + **/nuclides//reactions//size_energy** (*int*) + + end do + + **/nuclides//urr_n_energy** (*int*) + + **/nuclides//urr_n_prob** (*int*) + + **/nuclides//urr_interp** (*int*) + + **/nuclides//urr_inelastic** (*int*) + + **/nuclides//urr_absorption** (*int*) + + **/nuclides//urr_min_E** (*double*) + + **/nuclides//urr_max_E** (*double*) + + **/nuclides//size_total** (*int*) + +end do diff --git a/openmc/summary.py b/openmc/summary.py index 8b5e5710a..aeba2f94b 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -103,17 +103,15 @@ class Summary(object): nuclides = self._f['materials'][key]['nuclides'][...] n_sab = self._f['materials'][key]['n_sab'].value - sab_names = [] - sab_xs = [] - # Read the names of the S(a,b) tables for this Material - for i in range(1, n_sab+1): - sab_table = \ - self._f['materials'][key]['sab_tables'][str(i)].value - - # Read the cross-section identifiers for each S(a,b) table - sab_names.append(sab_table.split('.')[0]) - sab_xs.append(sab_table.split('.')[1]) + if n_sab > 0: + sab_tables = self._f['materials'][key]['sab_names'].value + sab_names = [] + sab_xs = [] + for sab_table in sab_tables: + name, xs = sab_table.decode().split('.') + sab_names.append(name) + sab_xs.append(xs) # Create the Material material = openmc.Material(material_id=material_id, name=name) diff --git a/src/constants.F90 b/src/constants.F90 index 01dd6148a..9c011a838 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -14,6 +14,7 @@ module constants integer, parameter :: REVISION_STATEPOINT = 14 integer, parameter :: REVISION_PARTICLE_RESTART = 1 integer, parameter :: REVISION_TRACK = 1 + integer, parameter :: REVISION_SUMMARY = 1 ! ============================================================================ ! ADJUSTABLE PARAMETERS diff --git a/src/summary.F90 b/src/summary.F90 index 0147230a0..5fcdbf81c 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -79,6 +79,10 @@ contains subroutine write_header(file_id) integer(HID_T), intent(in) :: file_id + ! Write filetype and revision + call write_dataset(file_id, "filetype", "summary") + call write_dataset(file_id, "revision", REVISION_SUMMARY) + ! Write version information call write_dataset(file_id, "version_major", VERSION_MAJOR) call write_dataset(file_id, "version_minor", VERSION_MINOR) @@ -442,12 +446,7 @@ contains if (m%n_sab > 0) then call write_dataset(material_group, "i_sab_nuclides", m%i_sab_nuclides) call write_dataset(material_group, "i_sab_tables", m%i_sab_tables) - - sab_group = create_group(material_group, "sab_tables") - do j = 1, m%n_sab - call write_dataset(sab_group, to_str(j), m%sab_names(j)) - end do - call close_group(sab_group) + call write_dataset(material_group, "sab_names", m%sab_names) end if call close_group(material_group) @@ -483,6 +482,9 @@ contains m => meshes(i) mesh_group = create_group(tallies_group, "mesh " // trim(to_str(m%id))) + ! Write internal OpenMC index for this mesh + call write_dataset(mesh_group, "index", i) + ! Write type and number of dimensions call write_dataset(mesh_group, "type", m%type) call write_dataset(mesh_group, "n_dimension", m%n_dimension) @@ -504,11 +506,11 @@ contains t => tallies(i) tally_group = create_group(tallies_group, "tally " // trim(to_str(t%id))) + ! Write internal OpenMC index for this tally + call write_dataset(tally_group, "index", i) + ! Write the name for this tally - call write_dataset(tally_group, "name_size", len(t%name)) - if (len(t%name) > 0) then - call write_dataset(tally_group, "name", t%name) - endif + call write_dataset(tally_group, "name", t%name) ! Write size of each tally call write_dataset(tally_group, "total_score_bins", t%total_score_bins) From 40d38df2449509801874a8e2085269042e11659f Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 19 Sep 2015 00:20:27 -0400 Subject: [PATCH 64/95] Assume unspecified surface coeffs = 0 in PyAPI --- openmc/surface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/surface.py b/openmc/surface.py index d5d258fa7..9502002ff 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -134,7 +134,7 @@ class Surface(object): element.set("type", self._type) element.set("boundary", self._boundary_type) - element.set("coeffs", ' '.join([str(self._coeffs[key]) + element.set("coeffs", ' '.join([str(self._coeffs.setdefault(key, 0.0)) for key in self._coeff_keys])) return element From 0f1cbdfd1484d1d12d795e8b68e3edb09707824e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 19 Sep 2015 13:44:18 +0700 Subject: [PATCH 65/95] Get rid of unused variable sab_group --- src/summary.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/summary.F90 b/src/summary.F90 index 5fcdbf81c..68f967a74 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -400,7 +400,6 @@ contains integer, allocatable :: zaids(:) integer(HID_T) :: materials_group integer(HID_T) :: material_group - integer(HID_T) :: sab_group type(Material), pointer :: m materials_group = create_group(file_id, "materials") From 4462db19f3c0c23e40aba02beb26f473935f687b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 20 Sep 2015 08:13:33 +0700 Subject: [PATCH 66/95] Update RELAX NG schema for geometry.xml (outside -> outer) --- src/relaxng/geometry.rnc | 8 ++++---- src/relaxng/geometry.rng | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/relaxng/geometry.rnc b/src/relaxng/geometry.rnc index cebbc5b6a..82f1f15b3 100644 --- a/src/relaxng/geometry.rnc +++ b/src/relaxng/geometry.rnc @@ -6,7 +6,7 @@ element geometry { (element universe { xsd:int } | attribute universe { xsd:int })? & ( (element fill { xsd:int } | attribute fill { xsd:int }) | - (element material { ( xsd:int | "void" ) } | + (element material { ( xsd:int | "void" ) } | attribute material { ( xsd:int | "void" ) }) ) & (element surfaces { list { xsd:int* } } | attribute surfaces { list { xsd:int* } })? & @@ -18,7 +18,7 @@ element geometry { (element id { xsd:int } | attribute id { xsd:int }) & (element name { xsd:string { maxLength="52" } } | attribute name { xsd:string { maxLength="52" } })? & - (element type { xsd:string { maxLength = "15" } } | + (element type { xsd:string { maxLength = "15" } } | attribute type { xsd:string { maxLength = "15" } }) & (element coeffs { list { xsd:double+ } } | attribute coeffs { list { xsd:double+ } }) & (element boundary { ( "transmit" | "reflective" | "vacuum" ) } | @@ -29,12 +29,12 @@ element geometry { (element id { xsd:int } | attribute id { xsd:int }) & (element name { xsd:string { maxLength="52" } } | attribute name { xsd:string { maxLength="52" } })? & - (element dimension { list { xsd:positiveInteger+ } } | + (element dimension { list { xsd:positiveInteger+ } } | attribute dimension { list { xsd:positiveInteger+ } }) & (element lower_left { list { xsd:double+ } } | attribute lower_left { list { xsd:double+ } }) & (element pitch { list { xsd:double+ } } | attribute pitch { list { xsd:double+ } }) & (element universes { list { xsd:int+ } } | attribute universes { list { xsd:int+ } }) & - (element outside { xsd:int } | attribute outside { xsd:int })? + (element outer { xsd:int } | attribute outer { xsd:int })? }* & element hex_lattice { diff --git a/src/relaxng/geometry.rng b/src/relaxng/geometry.rng index fdbf74cbd..9bd573b34 100644 --- a/src/relaxng/geometry.rng +++ b/src/relaxng/geometry.rng @@ -282,10 +282,10 @@ - + - + From 9a0acdebc35477cd06ed0329de68bacd6b68f5fb Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 20 Sep 2015 08:39:33 +0700 Subject: [PATCH 67/95] Write constant values as strings in HDF5 formats. This includes things like the run mode, tally estimator, filter type, tally scores, etc. Also do not write nuclides in summary file. --- openmc/constants.py | 129 ----------------- openmc/filter.py | 6 +- openmc/particle_restart.py | 4 +- openmc/statepoint.py | 25 ++-- openmc/summary.py | 93 +++--------- openmc/surface.py | 5 +- src/particle_restart.F90 | 9 +- src/particle_restart_write.F90 | 11 +- src/state_point.F90 | 255 ++++++++++++++------------------- src/summary.F90 | 216 +++++++++------------------- 10 files changed, 232 insertions(+), 521 deletions(-) delete mode 100644 openmc/constants.py diff --git a/openmc/constants.py b/openmc/constants.py deleted file mode 100644 index 797c99091..000000000 --- a/openmc/constants.py +++ /dev/null @@ -1,129 +0,0 @@ -"""Dictionaries of integer-to-string mappings from openmc/src/constants.F90""" - -RUN_TYPES = {1: 'fixed source', - 2: 'k-eigenvalue', - 3: 'plot', - 4: 'particle restart'} - -SURFACE_TYPES = {1: 'x-plane', - 2: 'y-plane', - 3: 'z-plane', - 4: 'plane', - 5: 'x-cylinder', - 6: 'y-cylinder', - 7: 'z-cylinder', - 8: 'sphere', - 9: 'x-cone', - 10: 'y-cone', - 11: 'z-cone'} - -BC_TYPES = {0: 'transmission', - 1: 'vacuum', - 2: 'reflective', - 3: 'periodic'} - -FILL_TYPES = {1: 'normal', - 2: 'fill', - 3: 'lattice'} - -LATTICE_TYPES = {1: 'rectangular', - 2: 'hexagonal'} - -ESTIMATOR_TYPES = {1: 'analog', - 2: 'tracklength', - 3: 'collision'} - -FILTER_TYPES = {1: 'universe', - 2: 'material', - 3: 'cell', - 4: 'cellborn', - 5: 'surface', - 6: 'mesh', - 7: 'energy', - 8: 'energyout', - 9: 'distribcell'} - -SCORE_TYPES = {-1: 'flux', - -2: 'total', - -3: 'scatter', - -4: 'nu-scatter', - -5: 'scatter-n', - -6: 'scatter-pn', - -7: 'nu-scatter-n', - -8: 'nu-scatter-pn', - -9: 'transport', - -10: 'n1n', - -11: 'absorption', - -12: 'fission', - -13: 'nu-fission', - -14: 'kappa-fission', - -15: 'current', - -16: 'flux-yn', - -17: 'total-yn', - -18: 'scatter-yn', - -19: 'nu-scatter-yn', - -20: 'events', - 1: '(n,total)', - 2: '(n,elastic)', - 4: '(n,level)', - 11: '(n,2nd)', - 16: '(n,2n)', - 17: '(n,3n)', - 18: '(n,fission)', - 19: '(n,f)', - 20: '(n,nf)', - 21: '(n,2nf)', - 22: '(n,na)', - 23: '(n,n3a)', - 24: '(n,2na)', - 25: '(n,3na)', - 28: '(n,np)', - 29: '(n,n2a)', - 30: '(n,2n2a)', - 32: '(n,nd)', - 33: '(n,nt)', - 34: '(n,nHe-3)', - 35: '(n,nd2a)', - 36: '(n,nt2a)', - 37: '(n,4n)', - 38: '(n,3nf)', - 41: '(n,2np)', - 42: '(n,3np)', - 44: '(n,n2p)', - 45: '(n,npa)', - 91: '(n,nc)', - 101: '(n,disappear)', - 102: '(n,gamma)', - 103: '(n,p)', - 104: '(n,d)', - 105: '(n,t)', - 106: '(n,3He)', - 107: '(n,a)', - 108: '(n,2a)', - 109: '(n,3a)', - 111: '(n,2p)', - 112: '(n,pa)', - 113: '(n,t2a)', - 114: '(n,d2a)', - 115: '(n,pd)', - 116: '(n,pt)', - 117: '(n,da)', - 201: '(n,Xn)', - 202: '(n,Xgamma)', - 203: '(n,Xp)', - 204: '(n,Xd)', - 205: '(n,Xt)', - 206: '(n,X3He)', - 207: '(n,Xa)', - 444: '(damage)', - 649: '(n,pc)', - 699: '(n,dc)', - 749: '(n,tc)', - 799: '(n,3Hec)', - 849: '(n,tc)'} -SCORE_TYPES.update({MT: '(n,n' + str(MT-50) + ')' for MT in range(51,91)}) -SCORE_TYPES.update({MT: '(n,p' + str(MT-600) + ')' for MT in range(600,649)}) -SCORE_TYPES.update({MT: '(n,d' + str(MT-650) + ')' for MT in range(650,699)}) -SCORE_TYPES.update({MT: '(n,t' + str(MT-700) + ')' for MT in range(700,749)}) -SCORE_TYPES.update({MT: '(n,3He' + str(MT-750) + ')' for MT in range(750,649)}) -SCORE_TYPES.update({MT: '(n,a' + str(MT-800) + ')' for MT in range(800,849)}) diff --git a/openmc/filter.py b/openmc/filter.py index b9b6df36b..6dd4bdaff 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -5,10 +5,12 @@ from numbers import Real, Integral import numpy as np from openmc import Mesh -from openmc.constants import * from openmc.checkvalue import check_type, check_iterable_type, \ check_greater_than, _isinstance +_FILTER_TYPES = ['universe', 'material', 'cell', 'cellborn', 'surface', + 'mesh', 'energy', 'energyout', 'distribcell'] + class Filter(object): """A filter used to constrain a tally to a specific criterion, e.g. only tally events when the particle is in a certain cell and energy range. @@ -109,7 +111,7 @@ class Filter(object): def type(self, type): if type is None: self._type = type - elif type not in FILTER_TYPES.values(): + elif type not in _FILTER_TYPES: msg = 'Unable to set Filter type to "{0}" since it is not one ' \ 'of the supported types'.format(type) raise ValueError(msg) diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py index 3ab294585..ff47ef474 100644 --- a/openmc/particle_restart.py +++ b/openmc/particle_restart.py @@ -1,7 +1,5 @@ import struct -from openmc.constants import RUN_TYPES - class Particle(object): """Information used to restart a specific particle that caused a simulation to @@ -74,7 +72,7 @@ class Particle(object): @property def run_mode(self): - return RUN_TYPES[self._f['run_mode'].value] + return self._f['run_mode'].value.decode() @property def uvw(self): diff --git a/openmc/statepoint.py b/openmc/statepoint.py index d5f220a9c..7d5e96b81 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -4,7 +4,6 @@ import sys import numpy as np import openmc -from openmc.constants import * if sys.version > '3': long = int @@ -317,7 +316,7 @@ class StatePoint(object): @property def run_mode(self): - return RUN_TYPES[self._f['run_mode'].value] + return self._f['run_mode'].value.decode() @property def seed(self): @@ -355,16 +354,14 @@ class StatePoint(object): # Iterate over all Tallies for tally_key in tally_keys: - # Read integer Tally estimator type code (analog, tracklength, or collision) - estimator_type = self._f['{0}{1}/estimator'.format(base, tally_key)].value - # Read the Tally size specifications n_realizations = self._f['{0}{1}/n_realizations'.format(base, tally_key)].value # Create Tally object and assign basic properties tally = openmc.Tally(tally_key) tally._statepoint = self - tally.estimator = ESTIMATOR_TYPES[estimator_type] + tally.estimator = self._f['{0}{1}/estimator'.format( + base, tally_key)].value.decode() tally.num_realizations = n_realizations # Read the number of Filters @@ -375,8 +372,8 @@ class StatePoint(object): # Initialize all Filters for j in range(1, n_filters+1): - # Read the integer Filter type code - filter_type = self._f['{0}{1}/type'.format(subbase, j)].value + # Read the Filter type + filter_type = self._f['{0}{1}/type'.format(subbase, j)].value.decode() # Read the Filter offset offset = self._f['{0}{1}/offset'.format(subbase, j)].value @@ -389,21 +386,21 @@ class StatePoint(object): raise ValueError(msg) # Read the bin values - if FILTER_TYPES[filter_type] in ['energy', 'energyout']: + if filter_type in ['energy', 'energyout']: bins = self._f['{0}{1}/bins'.format(subbase, j)].value - elif FILTER_TYPES[filter_type] in ['mesh', 'distribcell']: + elif filter_type in ['mesh', 'distribcell']: bins = self._f['{0}{1}/bins'.format(subbase, j)].value else: bins = self._f['{0}{1}/bins'.format(subbase, j)].value # Create Filter object - filter = openmc.Filter(FILTER_TYPES[filter_type], bins) + filter = openmc.Filter(filter_type, bins) filter.offset = offset filter.num_bins = n_bins - if FILTER_TYPES[filter_type] == 'mesh': + if filter_type == 'mesh': mesh_ids = self._f['tallies/meshes/ids'].value mesh_keys = self._f['tallies/meshes/keys'].value @@ -427,9 +424,8 @@ class StatePoint(object): tally.num_score_bins = n_score_bins - score_bins = self._f['{0}{1}/score_bins'.format( + scores = self._f['{0}{1}/scores'.format( base, tally_key)].value - scores = [SCORE_TYPES[score] for score in score_bins] n_user_scores = self._f['{0}{1}/n_user_score_bins' .format(base, tally_key)].value @@ -447,6 +443,7 @@ class StatePoint(object): # Add the scores to the Tally for j, score in enumerate(scores): + score = score.decode() # If this is a scattering moment, insert the scattering order if '-n' in score: score = score.replace('-n', '-' + moments[j].decode()) diff --git a/openmc/summary.py b/openmc/summary.py index aeba2f94b..34c6e102d 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -46,7 +46,6 @@ class Summary(object): def _read_geometry(self): # Read in and initialize the Materials and Geometry - self._read_nuclides() self._read_materials() self._read_surfaces() self._read_cells() @@ -54,35 +53,6 @@ class Summary(object): self._read_lattices() self._finalize_geometry() - def _read_nuclides(self): - self.n_nuclides = self._f['nuclides/n_nuclides'] - - # Initialize dictionary for each Nuclide - # Keys - Nuclide ZAIDs - # Values - Nuclide objects - self.nuclides = {} - - for key in self._f['nuclides'].keys(): - if key == 'n_nuclides': - continue - - index = self._f['nuclides'][key]['index'].value - alias = self._f['nuclides'][key]['alias'].value.decode() - zaid = self._f['nuclides'][key]['zaid'].value - - # Read the Nuclide's name (e.g., 'H-1' or 'U-235') - name = alias.split('.')[0] - - # Read the Nuclide's cross-section identifier (e.g., '70c') - xs = alias.split('.')[1] - - # Initialize this Nuclide and add to global dictionary of Nuclides - if 'nat' in name: - self.nuclides[zaid] = openmc.Element(name=name, xs=xs) - else: - self.nuclides[zaid] = openmc.Nuclide(name=name, xs=xs) - self.nuclides[zaid].zaid = zaid - def _read_materials(self): self.n_materials = self._f['n_materials'].value @@ -100,18 +70,14 @@ class Summary(object): name = self._f['materials'][key]['name'].value.decode() density = self._f['materials'][key]['atom_density'].value nuc_densities = self._f['materials'][key]['nuclide_densities'][...] - nuclides = self._f['materials'][key]['nuclides'][...] - n_sab = self._f['materials'][key]['n_sab'].value + nuclides = self._f['materials'][key]['nuclides'].value - # Read the names of the S(a,b) tables for this Material - if n_sab > 0: + # Read the names of the S(a,b) tables for this Material and add them + if 'sab_names' in self._f['materials'][key]: sab_tables = self._f['materials'][key]['sab_names'].value - sab_names = [] - sab_xs = [] for sab_table in sab_tables: name, xs = sab_table.decode().split('.') - sab_names.append(name) - sab_xs.append(xs) + material.add_s_alpha_beta(name, xs) # Create the Material material = openmc.Material(material_id=material_id, name=name) @@ -119,22 +85,21 @@ class Summary(object): # Set the Material's density to g/cm3 - this is what is used in OpenMC material.set_density(density=density, units='g/cm3') - # Add all Nuclides to the Material - for i, zaid in enumerate(nuclides): - nuclide = self.get_nuclide_by_zaid(zaid) - density = nuc_densities[i] + # Add all nuclides to the Material + for fullname, density in zip(nuclides, nuc_densities): + fullname = fullname.decode().strip() + name, xs = fullname.split('.') + + if 'nat' in name: + nuclide = openmc.Element(name=name, xs=xs) + else: + nuclide = openmc.Nuclide(name=name, xs=xs) if isinstance(nuclide, openmc.Nuclide): material.add_nuclide(nuclide, percent=density, percent_type='ao') elif isinstance(nuclide, openmc.Element): material.add_element(nuclide, percent=density, percent_type='ao') - # Add S(a,b) table(s?) to the Material - for i in range(n_sab): - name = sab_names[i] - xs = sab_xs[i] - material.add_s_alpha_beta(name, xs) - # Add the Material to the global dictionary of all Materials self.materials[index] = material @@ -540,9 +505,9 @@ class Summary(object): tally = openmc.Tally(tally_id, tally_name) # Read score metadata - score_bins = self._f['{0}/score_bins'.format(subbase)][...] - for score_bin in score_bins: - tally.add_score(openmc.SCORE_TYPES[score_bin]) + scores = self._f['{0}/scores'.format(subbase)].value + for score in scores: + tally.add_score(score.decode()) num_score_bins = self._f['{0}/n_score_bins'.format(subbase)][...] tally.num_score_bins = num_score_bins @@ -554,8 +519,7 @@ class Summary(object): subsubbase = '{0}/filter {1}'.format(subbase, j) # Read filter type (e.g., "cell", "energy", etc.) - filter_type_code = self._f['{0}/type'.format(subsubbase)].value - filter_type = openmc.FILTER_TYPES[filter_type_code] + filter_type = self._f['{0}/type'.format(subsubbase)].value.decode() # Read the filter bins num_bins = self._f['{0}/n_bins'.format(subsubbase)].value @@ -587,29 +551,6 @@ class Summary(object): if self.opencg_geometry is None: self.opencg_geometry = get_opencg_geometry(self.openmc_geometry) - def get_nuclide_by_zaid(self, zaid): - """Return a Nuclide object given the 'zaid' identifier for the nuclide. - - Parameters - ---------- - zaid : int - 1000*Z + A, where Z is the atomic number of the nuclide and A is the - mass number. For example, the zaid for U-235 is 92235. - - Returns - ------- - nuclide : openmc.nuclide.Nuclide or None - Nuclide matching the specified zaid, or None if no matching object - is found. - - """ - - for index, nuclide in self.nuclides.items(): - if nuclide._zaid == zaid: - return nuclide - - return None - def get_material_by_id(self, material_id): """Return a Material object given the material id diff --git a/openmc/surface.py b/openmc/surface.py index d5d258fa7..203e7e1e0 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -4,7 +4,6 @@ from xml.etree import ElementTree as ET import sys from openmc.checkvalue import check_type, check_value, check_greater_than -from openmc.constants import BC_TYPES if sys.version_info[0] >= 3: basestring = str @@ -12,6 +11,8 @@ if sys.version_info[0] >= 3: # A static variable for auto-generated Surface IDs AUTO_SURFACE_ID = 10000 +_BC_TYPES = ['transmission', 'vacuum', 'reflective', 'periodic'] + def reset_auto_surface_id(): global AUTO_SURFACE_ID @@ -106,7 +107,7 @@ class Surface(object): @boundary_type.setter def boundary_type(self, boundary_type): check_type('boundary type', boundary_type, basestring) - check_value('boundary type', boundary_type, BC_TYPES.values()) + check_value('boundary type', boundary_type, _BC_TYPES) self._boundary_type = boundary_type def __repr__(self): diff --git a/src/particle_restart.F90 b/src/particle_restart.F90 index c8874b071..2e0523d48 100644 --- a/src/particle_restart.F90 +++ b/src/particle_restart.F90 @@ -71,6 +71,7 @@ contains integer :: int_scalar integer(HID_T) :: file_id + character(MAX_WORD_LEN) :: mode ! Write meessage call write_message("Loading particle restart file " & @@ -86,7 +87,13 @@ contains call read_dataset(file_id, 'gen_per_batch', gen_per_batch) call read_dataset(file_id, 'current_gen', current_gen) call read_dataset(file_id, 'n_particles', n_particles) - call read_dataset(file_id, 'run_mode', previous_run_mode) + call read_dataset(file_id, 'run_mode', mode) + select case (mode) + case ('k-eigenvalue') + previous_run_mode = MODE_EIGENVALUE + case ('fixed source') + previous_run_mode = MODE_FIXEDSOURCE + end select call read_dataset(file_id, 'id', p%id) call read_dataset(file_id, 'weight', p%wgt) call read_dataset(file_id, 'energy', p%E) diff --git a/src/particle_restart_write.F90 b/src/particle_restart_write.F90 index 8b19bb879..77de7f669 100644 --- a/src/particle_restart_write.F90 +++ b/src/particle_restart_write.F90 @@ -46,7 +46,16 @@ contains call write_dataset(file_id, 'gen_per_batch', gen_per_batch) call write_dataset(file_id, 'current_gen', current_gen) call write_dataset(file_id, 'n_particles', n_particles) - call write_dataset(file_id, 'run_mode', run_mode) + select case(run_mode) + case (MODE_FIXEDSOURCE) + call write_dataset(file_id, 'run_mode', 'fixed source') + case (MODE_EIGENVALUE) + call write_dataset(file_id, 'run_mode', 'k-eigenvalue') + case (MODE_PLOTTING) + call write_dataset(file_id, 'run_mode', 'plot') + case (MODE_PARTICLE) + call write_dataset(file_id, 'run_mode', 'particle restart') + end select call write_dataset(file_id, 'id', p%id) call write_dataset(file_id, 'weight', src%wgt) call write_dataset(file_id, 'energy', src%E) diff --git a/src/state_point.F90 b/src/state_point.F90 index 97375c89c..60057a2c9 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -13,6 +13,7 @@ module state_point use constants + use endf, only: reaction_name use error, only: fatal_error, warning use global use hdf5_interface @@ -50,6 +51,7 @@ contains integer(HID_T) :: tallies_group, tally_group integer(HID_T) :: meshes_group, mesh_group integer(HID_T) :: filter_group + character(20), allocatable :: scores(:) character(8), allocatable :: moment_names(:) ! names of moments (e.g, P3) character(MAX_FILE_LEN) :: filename type(StructuredMesh), pointer :: meshp @@ -90,7 +92,16 @@ contains call write_dataset(file_id, "seed", seed) ! Write run information - call write_dataset(file_id, "run_mode", run_mode) + select case(run_mode) + case (MODE_FIXEDSOURCE) + call write_dataset(file_id, "run_mode", "fixed source") + case (MODE_EIGENVALUE) + call write_dataset(file_id, "run_mode", "k-eigenvalue") + case (MODE_PLOTTING) + call write_dataset(file_id, "run_mode", "plot") + case (MODE_PARTICLE) + call write_dataset(file_id, "run_mode", "particle restart") + end select call write_dataset(file_id, "n_particles", n_particles) call write_dataset(file_id, "n_batches", n_batches) @@ -214,7 +225,14 @@ contains tally_group = create_group(tallies_group, "tally " // & trim(to_str(tally%id))) - call write_dataset(tally_group, "estimator", tally%estimator) + select case(tally%estimator) + case (ESTIMATOR_ANALOG) + call write_dataset(tally_group, "estimator", "analog") + case (ESTIMATOR_TRACKLENGTH) + call write_dataset(tally_group, "estimator", "tracklength") + case (ESTIMATOR_COLLISION) + call write_dataset(tally_group, "estimator", "collision") + end select call write_dataset(tally_group, "n_realizations", tally%n_realizations) call write_dataset(tally_group, "n_filters", tally%n_filters) @@ -223,7 +241,28 @@ contains filter_group = create_group(tally_group, "filter " // & trim(to_str(j))) - call write_dataset(filter_group, "type", tally%filters(j)%type) + ! Write name of type + select case (tally%filters(j)%type) + case(FILTER_UNIVERSE) + call write_dataset(filter_group, "type", "universe") + case(FILTER_MATERIAL) + call write_dataset(filter_group, "type", "material") + case(FILTER_CELL) + call write_dataset(filter_group, "type", "cell") + case(FILTER_CELLBORN) + call write_dataset(filter_group, "type", "cellborn") + case(FILTER_SURFACE) + call write_dataset(filter_group, "type", "surface") + case(FILTER_MESH) + call write_dataset(filter_group, "type", "mesh") + case(FILTER_ENERGYIN) + call write_dataset(filter_group, "type", "energy") + case(FILTER_ENERGYOUT) + call write_dataset(filter_group, "type", "energyout") + case(FILTER_DISTRIBCELL) + call write_dataset(filter_group, "type", "distribcell") + end select + call write_dataset(filter_group, "offset", tally%filters(j)%offset) call write_dataset(filter_group, "n_bins", tally%filters(j)%n_bins) if (tally%filters(j)%type == FILTER_ENERGYIN .or. & @@ -253,9 +292,59 @@ contains deallocate(key_array) call write_dataset(tally_group, "n_score_bins", tally%n_score_bins) + allocate(scores(size(tally%score_bins))) + do j = 1, size(tally%score_bins) + select case(tally%score_bins(j)) + case (SCORE_FLUX) + scores(j) = "flux" + case (SCORE_TOTAL) + scores(j) = "total" + case (SCORE_SCATTER) + scores(j) = "scatter" + case (SCORE_NU_SCATTER) + scores(j) = "nu-scatter" + case (SCORE_SCATTER_N) + scores(j) = "scatter-n" + case (SCORE_SCATTER_PN) + scores(j) = "scatter-pn" + case (SCORE_NU_SCATTER_N) + scores(j) = "nu-scatter-n" + case (SCORE_NU_SCATTER_PN) + scores(j) = "nu-scatter-pn" + case (SCORE_TRANSPORT) + scores(j) = "transport" + case (SCORE_N_1N) + scores(j) = "n1n" + case (SCORE_ABSORPTION) + scores(j) = "absorption" + case (SCORE_FISSION) + scores(j) = "fission" + case (SCORE_NU_FISSION) + scores(j) = "nu-fission" + case (SCORE_KAPPA_FISSION) + scores(j) = "kappa-fission" + case (SCORE_CURRENT) + scores(j) = "current" + case (SCORE_FLUX_YN) + scores(j) = "flux-yn" + case (SCORE_TOTAL_YN) + scores(j) = "total-yn" + case (SCORE_SCATTER_YN) + scores(j) = "scatter-yn" + case (SCORE_NU_SCATTER_YN) + scores(j) = "nu-scatter-yn" + case (SCORE_EVENTS) + scores(j) = "events" + case default + scores(j) = reaction_name(tally%score_bins(j)) + end select + end do + call write_dataset(tally_group, "scores", scores) call write_dataset(tally_group, "score_bins", tally%score_bins) call write_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) + deallocate(scores) + ! Write explicit moment order strings for each score bin k = 1 allocate(moment_names(tally%n_score_bins)) @@ -578,22 +667,15 @@ contains subroutine load_state_point() - integer :: i, j - integer :: int_array(3) - integer :: curr_key - integer, allocatable :: id_array(:) - integer, allocatable :: key_array(:) - integer, allocatable :: temp_array(:) + integer :: i + integer :: int_array(3) integer(HID_T) :: file_id integer(HID_T) :: cmfd_group - integer(HID_T) :: tallies_group, tally_group - integer(HID_T) :: meshes_group, mesh_group - integer(HID_T) :: filter_group - real(8) :: real_array(3) - logical :: source_present - character(MAX_FILE_LEN) :: path_temp - character(19) :: current_time - type(StructuredMesh), pointer :: meshp + integer(HID_T) :: tallies_group + integer(HID_T) :: tally_group + real(8) :: real_array(3) + logical :: source_present + character(MAX_WORD_LEN) :: word type(TallyObject), pointer :: tally ! Write message @@ -614,27 +696,17 @@ contains &in OpenMC.") end if - ! Read OpenMC version - call read_dataset(file_id, "version_major", int_array(1)) - call read_dataset(file_id, "version_minor", int_array(2)) - call read_dataset(file_id, "version_release", int_array(3)) - if (int_array(1) /= VERSION_MAJOR .or. int_array(2) /= VERSION_MINOR & - .or. int_array(3) /= VERSION_RELEASE) then - if (master) call warning("State point file was created with a different & - &version of OpenMC.") - end if - - ! Read date and time - call read_dataset(file_id, "date_and_time", current_time) - - ! Read path to input - call read_dataset(file_id, "path", path_temp) - ! Read and overwrite random number seed call read_dataset(file_id, "seed", seed) ! Read and overwrite run information except number of batches - call read_dataset(file_id, "run_mode", run_mode) + call read_dataset(file_id, "run_mode", word) + select case(word) + case ('fixed source') + run_mode = MODE_FIXEDSOURCE + case ('k-eigenvalue') + run_mode = MODE_EIGENVALUE + end select call read_dataset(file_id, "n_particles", n_particles) call read_dataset(file_id, "n_batches", int_array(1)) @@ -694,108 +766,6 @@ contains end if end if - ! Read number of meshes - tallies_group = open_group(file_id, "tallies") - meshes_group = open_group(tallies_group, "meshes") - call read_dataset(meshes_group, "n_meshes", n_meshes) - - if (n_meshes > 0) then - - ! Read list of mesh keys-> IDs - allocate(id_array(n_meshes)) - allocate(key_array(n_meshes)) - - call read_dataset(meshes_group, "ids", id_array) - call read_dataset(meshes_group, "keys", key_array) - - ! Read and overwrite mesh information - MESH_LOOP: do i = 1, n_meshes - - meshp => meshes(id_array(i)) - curr_key = key_array(id_array(i)) - - mesh_group = open_group(meshes_group, "mesh " // & - trim(to_str(curr_key))) - call read_dataset(mesh_group, "id", meshp%id) - call read_dataset(mesh_group, "type", meshp%type) - call read_dataset(mesh_group, "n_dimension", meshp%n_dimension) - call read_dataset(mesh_group, "dimension", meshp%dimension) - call read_dataset(mesh_group, "lower_left", meshp%lower_left) - call read_dataset(mesh_group, "upper_right", meshp%upper_right) - call read_dataset(mesh_group, "width", meshp%width) - call close_group(mesh_group) - end do MESH_LOOP - - deallocate(id_array) - deallocate(key_array) - - end if - - call close_group(meshes_group) - - ! Read and overwrite number of tallies - call read_dataset(tallies_group, "n_tallies", n_tallies) - - ! Read list of tally keys-> IDs - allocate(id_array(n_tallies)) - allocate(key_array(n_tallies)) - - call read_dataset(tallies_group, "ids", id_array) - call read_dataset(tallies_group, "keys", key_array) - - ! Read in tally metadata - TALLY_METADATA: do i = 1, n_tallies - - ! Get pointer to tally - tally => tallies(i) - curr_key = key_array(id_array(i)) - tally_group = open_group(tallies_group, "tally " // & - trim(to_str(curr_key))) - - call read_dataset(tally_group, "estimator", tally%estimator) - call read_dataset(tally_group, "n_realizations", tally%n_realizations) - call read_dataset(tally_group, "n_filters", tally%n_filters) - - FILTER_LOOP: do j = 1, tally%n_filters - filter_group = open_group(tally_group, "filter " // trim(to_str(j))) - - call read_dataset(filter_group, "type", tally%filters(j)%type) - call read_dataset(filter_group, "offset", tally%filters(j)%offset) - call read_dataset(filter_group, "n_bins", tally%filters(j)%n_bins) - if (tally%filters(j)%type == FILTER_ENERGYIN .or. & - tally%filters(j)%type == FILTER_ENERGYOUT) then - call read_dataset(filter_group, "bins", tally%filters(j)%real_bins) - else - call read_dataset(filter_group, "bins", tally%filters(j)%int_bins) - end if - - call close_group(filter_group) - end do FILTER_LOOP - - call read_dataset(tally_group, "n_nuclides", tally%n_nuclide_bins) - - ! Set up nuclide bin array and then read - allocate(temp_array(tally%n_nuclide_bins)) - call read_dataset(tally_group, "nuclides", temp_array) - - NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins - if (temp_array(j) > 0) then - tally%nuclide_bins(j) = temp_array(j) - else - tally%nuclide_bins(j) = temp_array(j) - end if - end do NUCLIDE_LOOP - - deallocate(temp_array) - - ! Write number of score bins, score bins, user score bins - call read_dataset(tally_group, "n_score_bins", tally%n_score_bins) - call read_dataset(tally_group, "score_bins", tally%score_bins) - call read_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) - - call close_group(tally_group) - end do TALLY_METADATA - ! Check to make sure source bank is present if (path_source_point == path_state_point .and. .not. source_present) then call fatal_error("Source bank must be contained in statepoint restart & @@ -808,13 +778,6 @@ contains ! Read number of realizations for global tallies call read_dataset(file_id, "n_realizations", n_realizations, indep=.true.) - ! Read number of global tallies - call read_dataset(file_id, "n_global_tallies", int_array(1), indep=.false.) - if (int_array(1) /= N_GLOBAL_TALLIES) then - call fatal_error("Number of global tallies does not match in state & - &point.") - end if - ! Read global tally data call read_dataset(file_id, "global_tallies", global_tallies) @@ -825,14 +788,12 @@ contains ! Read in sum and sum squared if (int_array(1) == 1) then TALLY_RESULTS: do i = 1, n_tallies - ! Set pointer to tally tally => tallies(i) - curr_key = key_array(id_array(i)) ! Read sum and sum_sq for each bin tally_group = open_group(tallies_group, "tally " // & - trim(to_str(curr_key))) + trim(to_str(tally%id))) call read_dataset(tally_group, "results", tally%results) call close_group(tally_group) end do TALLY_RESULTS @@ -841,8 +802,6 @@ contains call close_group(tallies_group) end if - deallocate(id_array) - deallocate(key_array) ! Read source if in eigenvalue mode if (run_mode == MODE_EIGENVALUE) then diff --git a/src/summary.F90 b/src/summary.F90 index 68f967a74..e9717bc09 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -62,7 +62,6 @@ contains call write_geometry(file_id) call write_materials(file_id) - call write_nuclides(file_id) if (n_tallies > 0) then call write_tallies(file_id) end if @@ -238,16 +237,6 @@ contains ! Write coefficients for surface call write_dataset(surface_group, "coefficients", s%coeffs) - ! Write positive neighbors - if (allocated(s%neighbor_pos)) then - call write_dataset(surface_group, "neighbors_positive", s%neighbor_pos) - end if - - ! Write negative neighbors - if (allocated(s%neighbor_neg)) then - call write_dataset(surface_group, "neighbors_negative", s%neighbor_neg) - end if - ! Write boundary condition select case (s%bc) case (BC_TRANSMIT) @@ -395,9 +384,10 @@ contains subroutine write_materials(file_id) integer(HID_T), intent(in) :: file_id - integer :: i - integer :: j - integer, allocatable :: zaids(:) + integer :: i + integer :: j + integer :: i_list + character(12), allocatable :: nucnames(:) integer(HID_T) :: materials_group integer(HID_T) :: material_group type(Material), pointer :: m @@ -425,26 +415,22 @@ contains "atom/b-cm") ! Copy ZAID for each nuclide to temporary array - allocate(zaids(m%n_nuclides)) + allocate(nucnames(m%n_nuclides)) do j = 1, m%n_nuclides - zaids(j) = nuclides(m%nuclide(j))%zaid + i_list = nuclides(m%nuclide(j))%listing + nucnames(j) = xs_listings(i_list)%alias end do ! Write temporary array to 'nuclides' - call write_dataset(material_group, "nuclides", zaids) + call write_dataset(material_group, "nuclides", nucnames) ! Deallocate temporary array - deallocate(zaids) + deallocate(nucnames) ! Write atom densities call write_dataset(material_group, "nuclide_densities", m%atom_density) - ! Write S(a,b) information if present - call write_dataset(material_group, "n_sab", m%n_sab) - if (m%n_sab > 0) then - call write_dataset(material_group, "i_sab_nuclides", m%i_sab_nuclides) - call write_dataset(material_group, "i_sab_tables", m%i_sab_tables) call write_dataset(material_group, "sab_names", m%sab_names) end if @@ -462,12 +448,13 @@ contains subroutine write_tallies(file_id) integer(HID_T), intent(in) :: file_id - integer :: i, j + integer :: i, j integer, allocatable :: temp_array(:) ! nuclide bin array integer(HID_T) :: tallies_group integer(HID_T) :: mesh_group integer(HID_T) :: tally_group integer(HID_T) :: filter_group + character(20), allocatable :: scores(:) type(StructuredMesh), pointer :: m type(TallyObject), pointer :: t @@ -486,7 +473,6 @@ contains ! Write type and number of dimensions call write_dataset(mesh_group, "type", m%type) - call write_dataset(mesh_group, "n_dimension", m%n_dimension) ! Write mesh information call write_dataset(mesh_group, "dimension", m%dimension) @@ -521,9 +507,6 @@ contains FILTER_LOOP: do j = 1, t%n_filters filter_group = create_group(tally_group, "filter " // trim(to_str(j))) - ! Write type of filter - call write_dataset(filter_group, "type", t%filters(j)%type) - ! Write number of bins for this filter call write_dataset(filter_group, "n_bins", t%filters(j)%n_bins) @@ -538,21 +521,23 @@ contains ! Write name of type select case (t%filters(j)%type) case(FILTER_UNIVERSE) - call write_dataset(filter_group, "type_name", "universe") + call write_dataset(filter_group, "type", "universe") case(FILTER_MATERIAL) - call write_dataset(filter_group, "type_name", "material") + call write_dataset(filter_group, "type", "material") case(FILTER_CELL) - call write_dataset(filter_group, "type_name", "cell") + call write_dataset(filter_group, "type", "cell") case(FILTER_CELLBORN) - call write_dataset(filter_group, "type_name", "cellborn") + call write_dataset(filter_group, "type", "cellborn") case(FILTER_SURFACE) - call write_dataset(filter_group, "type_name", "surface") + call write_dataset(filter_group, "type", "surface") case(FILTER_MESH) - call write_dataset(filter_group, "type_name", "mesh") + call write_dataset(filter_group, "type", "mesh") case(FILTER_ENERGYIN) - call write_dataset(filter_group, "type_name", "energy") + call write_dataset(filter_group, "type", "energy") case(FILTER_ENERGYOUT) - call write_dataset(filter_group, "type_name", "energyout") + call write_dataset(filter_group, "type", "energyout") + case(FILTER_DISTRIBCELL) + call write_dataset(filter_group, "type", "distribcell") end select call close_group(filter_group) @@ -577,8 +562,58 @@ contains ! Write number of score bins call write_dataset(tally_group, "n_score_bins", t%n_score_bins) + allocate(scores(size(t%score_bins))) + do j = 1, size(t%score_bins) + select case(t%score_bins(j)) + case (SCORE_FLUX) + scores(j) = "flux" + case (SCORE_TOTAL) + scores(j) = "total" + case (SCORE_SCATTER) + scores(j) = "scatter" + case (SCORE_NU_SCATTER) + scores(j) = "nu-scatter" + case (SCORE_SCATTER_N) + scores(j) = "scatter-n" + case (SCORE_SCATTER_PN) + scores(j) = "scatter-pn" + case (SCORE_NU_SCATTER_N) + scores(j) = "nu-scatter-n" + case (SCORE_NU_SCATTER_PN) + scores(j) = "nu-scatter-pn" + case (SCORE_TRANSPORT) + scores(j) = "transport" + case (SCORE_N_1N) + scores(j) = "n1n" + case (SCORE_ABSORPTION) + scores(j) = "absorption" + case (SCORE_FISSION) + scores(j) = "fission" + case (SCORE_NU_FISSION) + scores(j) = "nu-fission" + case (SCORE_KAPPA_FISSION) + scores(j) = "kappa-fission" + case (SCORE_CURRENT) + scores(j) = "current" + case (SCORE_FLUX_YN) + scores(j) = "flux-yn" + case (SCORE_TOTAL_YN) + scores(j) = "total-yn" + case (SCORE_SCATTER_YN) + scores(j) = "scatter-yn" + case (SCORE_NU_SCATTER_YN) + scores(j) = "nu-scatter-yn" + case (SCORE_EVENTS) + scores(j) = "events" + case default + scores(j) = reaction_name(t%score_bins(j)) + end select + end do + call write_dataset(tally_group, "scores", scores) call write_dataset(tally_group, "score_bins", t%score_bins) + deallocate(scores) + call close_group(tally_group) end do TALLY_METADATA @@ -586,115 +621,6 @@ contains end subroutine write_tallies -!=============================================================================== -! WRITE_NUCLIDES -!=============================================================================== - - subroutine write_nuclides(file_id) - integer(HID_T), intent(in) :: file_id - - integer :: i, j - integer :: size_total - integer :: size_xs - integer :: size_angle - integer :: size_energy - integer(HID_T) :: nuclides_group, nuclide_group - integer(HID_T) :: reactions_group, rxn_group - type(Nuclide), pointer :: nuc - type(Reaction), pointer :: rxn - type(UrrData), pointer :: urr - - nuclides_group = create_group(file_id, "nuclides") - - ! write number of nuclides - call write_dataset(nuclides_group, "n_nuclides", n_nuclides_total) - - ! Write information on each nuclide - NUCLIDE_LOOP: do i = 1, n_nuclides_total - nuc => nuclides(i) - nuclide_group = create_group(nuclides_group, nuc%name) - - ! Write internal OpenMC index for this nuclide - call write_dataset(nuclide_group, "index", i) - - ! Determine size of cross-sections - size_xs = (5 + nuc%n_reaction) * nuc%n_grid * 8 - size_total = size_xs - - ! Write some basic attributes - call write_dataset(nuclide_group, "zaid", nuc%zaid) - call write_dataset(nuclide_group, "alias", xs_listings(nuc%listing)%alias) - call write_dataset(nuclide_group, "awr", nuc%awr) - call write_dataset(nuclide_group, "kT", nuc%kT) - call write_dataset(nuclide_group, "n_grid", nuc%n_grid) - call write_dataset(nuclide_group, "n_reactions", nuc%n_reaction) - call write_dataset(nuclide_group, "n_fission", nuc%n_fission) - call write_dataset(nuclide_group, "size_xs", size_xs) - - ! ======================================================================= - ! WRITE INFORMATION ON EACH REACTION - - ! Create overall group for reactions and close it - reactions_group = create_group(nuclide_group, "reactions") - - RXN_LOOP: do j = 1, nuc%n_reaction - ! Information on each reaction - rxn => nuc%reactions(j) - rxn_group = create_group(reactions_group, trim(reaction_name(rxn%MT))) - - ! Determine size of angle distribution - if (rxn%has_angle_dist) then - size_angle = rxn%adist%n_energy * 16 + size(rxn%adist%data) * 8 - else - size_angle = 0 - end if - - ! Determine size of energy distribution - if (rxn%has_energy_dist) then - size_energy = size(rxn%edist%data) * 8 - else - size_energy = 0 - end if - - ! Write information on reaction - call write_dataset(rxn_group, "Q_value", rxn%Q_value) - call write_dataset(rxn_group, "multiplicity", rxn%multiplicity) - call write_dataset(rxn_group, "threshold", rxn%threshold) - call write_dataset(rxn_group, "size_angle", size_angle) - call write_dataset(rxn_group, "size_energy", size_energy) - - ! Accumulate data size - size_total = size_total + size_angle + size_energy - - call close_group(rxn_group) - end do RXN_LOOP - - call close_group(reactions_group) - - ! ======================================================================= - ! WRITE INFORMATION ON URR PROBABILITY TABLES - - if (nuc%urr_present) then - urr => nuc%urr_data - call write_dataset(nuclide_group, "urr_n_energy", urr%n_energy) - call write_dataset(nuclide_group, "urr_n_prob", urr%n_prob) - call write_dataset(nuclide_group, "urr_interp", urr%interp) - call write_dataset(nuclide_group, "urr_inelastic", urr%inelastic_flag) - call write_dataset(nuclide_group, "urr_absorption", urr%absorption_flag) - call write_dataset(nuclide_group, "urr_min_E", urr%energy(1)) - call write_dataset(nuclide_group, "urr_max_E", urr%energy(urr%n_energy)) - end if - - ! Write total memory used - call write_dataset(nuclide_group, "size_total", size_total) - - call close_group(nuclide_group) - end do NUCLIDE_LOOP - - call close_group(nuclides_group) - - end subroutine write_nuclides - !=============================================================================== ! WRITE_TIMING !=============================================================================== From 36a22174872403c7084e27ad37b0aa5609347ea9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 20 Sep 2015 09:03:38 +0700 Subject: [PATCH 68/95] Write cell surface specification with user ids in summary.h5 --- openmc/summary.py | 4 ++-- src/summary.F90 | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/openmc/summary.py b/openmc/summary.py index 34c6e102d..f599289af 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -251,8 +251,8 @@ class Summary(object): for surface_halfspace in surfaces: halfspace = np.sign(surface_halfspace) - surface_id = np.abs(surface_halfspace) - surface = self.surfaces[surface_id] + surface_id = abs(surface_halfspace) + surface = self.get_surface_by_id(surface_id) cell.add_surface(surface, halfspace) # Add the Cell to the global dictionary of all Cells diff --git a/src/summary.F90 b/src/summary.F90 index e9717bc09..90a4e726f 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -106,6 +106,7 @@ contains integer :: i, j, k, m integer, allocatable :: lattice_universes(:,:,:) + integer, allocatable :: surface_ids(:) integer(HID_T) :: geom_group integer(HID_T) :: cells_group, cell_group integer(HID_T) :: surfaces_group, surface_group @@ -182,7 +183,13 @@ contains ! Write list of bounding surfaces if (c%n_surfaces > 0) then - call write_dataset(cell_group, "surfaces", c%surfaces) + allocate(surface_ids(c%n_surfaces)) + do j = 1, c%n_surfaces + k = c%surfaces(j) + surface_ids(j) = sign(surfaces(abs(k))%id, k) + end do + call write_dataset(cell_group, "surfaces", surface_ids) + deallocate(surface_ids) end if call close_group(cell_group) From 8753f2305954d2cac7b9efd0fda04e18abaa8bb3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 20 Sep 2015 09:44:31 +0700 Subject: [PATCH 69/95] Change StructuredMesh to RegularMesh. Write type as 'regular'. --- openmc/mesh.py | 4 ++-- openmc/statepoint.py | 7 ++----- src/cmfd_data.F90 | 6 +++--- src/cmfd_execute.F90 | 5 ++--- src/cmfd_input.F90 | 8 ++++---- src/constants.F90 | 2 +- src/eigenvalue.F90 | 4 ++-- src/global.F90 | 8 ++++---- src/input_xml.F90 | 8 ++++---- src/mesh.F90 | 14 +++++++------- src/mesh_header.F90 | 4 ++-- src/output.F90 | 8 ++++---- src/plot.F90 | 3 ++- src/plot_header.F90 | 4 ++-- src/state_point.F90 | 6 +++--- src/summary.F90 | 6 +++--- src/tally.F90 | 8 ++++---- src/trigger.F90 | 3 ++- 18 files changed, 53 insertions(+), 55 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 7e907aaa5..fefc6d707 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -54,7 +54,7 @@ class Mesh(object): # Initialize Mesh class attributes self.id = mesh_id self.name = name - self._type = 'rectangular' + self._type = 'regular' self._dimension = None self._lower_left = None self._upper_right = None @@ -156,7 +156,7 @@ class Mesh(object): check_type('type for mesh ID="{0}"'.format(self._id), meshtype, basestring) check_value('type for mesh ID="{0}"'.format(self._id), - meshtype, ['rectangular', 'hexagonal']) + meshtype, ['regular', 'hexagonal']) self._type = meshtype @dimension.setter diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 7d5e96b81..72c85d27e 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -264,7 +264,7 @@ class StatePoint(object): for mesh_key in mesh_keys: # Read the user-specified Mesh ID and type mesh_id = self._f['{0}{1}/id'.format(base, mesh_key)].value - mesh_type = self._f['{0}{1}/type'.format(base, mesh_key)].value + mesh_type = self._f['{0}{1}/type'.format(base, mesh_key)].value.decode() # Read the mesh dimensions, lower-left coordinates, # upper-right coordinates, and width of each mesh cell @@ -275,14 +275,11 @@ class StatePoint(object): # Create the Mesh and assign properties to it mesh = openmc.Mesh(mesh_id) - mesh.dimension = dimension mesh.width = width mesh.lower_left = lower_left mesh.upper_right = upper_right - - #FIXME: Set the mesh type to 'rectangular' by default - mesh.type = 'rectangular' + mesh.type = mesh_type # Add mesh to the global dictionary of all Meshes self._meshes[mesh_id] = mesh diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index 2b1778419..19fe39572 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -57,7 +57,7 @@ contains use global, only: cmfd, n_cmfd_tallies, cmfd_tallies, meshes,& matching_bins use mesh, only: mesh_indices_to_bin - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use string, only: to_str use tally_header, only: TallyObject @@ -79,8 +79,8 @@ contains integer :: i_filter_eout ! index for outgoing energy filter integer :: i_filter_surf ! index for surface filter real(8) :: flux ! temp variable for flux - type(TallyObject), pointer :: t => null() ! pointer for tally object - type(StructuredMesh), pointer :: m => null() ! pointer for mesh object + type(TallyObject), pointer :: t ! pointer for tally object + type(RegularMesh), pointer :: m ! pointer for mesh object ! Extract spatial and energy indices from object nx = cmfd % indices(1) diff --git a/src/cmfd_execute.F90 b/src/cmfd_execute.F90 index c55d206cb..4dfe99d77 100644 --- a/src/cmfd_execute.F90 +++ b/src/cmfd_execute.F90 @@ -217,7 +217,7 @@ contains use error, only: warning, fatal_error use global, only: meshes, source_bank, work, n_user_meshes, cmfd, & master - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use mesh, only: count_bank_sites, get_mesh_indices use search, only: binary_search use string, only: to_str @@ -239,8 +239,7 @@ contains integer :: n_groups ! number of energy groups logical :: outside ! any source sites outside mesh logical :: in_mesh ! source site is inside mesh - - type(StructuredMesh), pointer :: m ! point to mesh + type(RegularMesh), pointer :: m ! point to mesh ! Associate pointer m => meshes(n_user_meshes + 1) diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 2d44d3e9b..dac74c9c3 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -247,7 +247,7 @@ contains use constants, only: MAX_LINE_LEN use error, only: fatal_error, warning - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use string use tally, only: setup_active_cmfdtallies use tally_header, only: TallyObject, TallyFilter @@ -264,10 +264,10 @@ contains integer :: i_filter_mesh ! index for mesh filter integer :: iarray3(3) ! temp integer array real(8) :: rarray3(3) ! temp double array - type(TallyObject), pointer :: t => null() - type(StructuredMesh), pointer :: m => null() + type(TallyObject), pointer :: t + type(RegularMesh), pointer :: m type(TallyFilter) :: filters(N_FILTER_TYPES) ! temporary filters - type(Node), pointer :: node_mesh => null() + type(Node), pointer :: node_mesh ! Set global variables if they are 0 (this can happen if there is no tally ! file) diff --git a/src/constants.F90 b/src/constants.F90 index 7d71c0f28..962c4a6a2 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -327,7 +327,7 @@ module constants RELATIVE_ERROR = 2, & STANDARD_DEVIATION = 3 - ! Global tallY parameters + ! Global tally parameters integer, parameter :: N_GLOBAL_TALLIES = 4 integer, parameter :: & K_COLLISION = 1, & diff --git a/src/eigenvalue.F90 b/src/eigenvalue.F90 index 33d63b7cc..403347caa 100644 --- a/src/eigenvalue.F90 +++ b/src/eigenvalue.F90 @@ -9,7 +9,7 @@ module eigenvalue use global use math, only: t_percentile use mesh, only: count_bank_sites - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use particle_header, only: Particle use random_lcg, only: prn, set_particle_seed, prn_skip use search, only: binary_search @@ -304,7 +304,7 @@ contains integer :: i, j, k ! index for bank sites integer :: n ! # of boxes in each dimension logical :: sites_outside ! were there sites outside entropy box? - type(StructuredMesh), pointer :: m => null() + type(RegularMesh), pointer :: m ! Get pointer to entropy mesh m => entropy_mesh diff --git a/src/global.F90 b/src/global.F90 index adc8f17da..398b72e14 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -8,7 +8,7 @@ module global use dict_header, only: DictCharInt, DictIntInt use geometry_header, only: Cell, Universe, Lattice, LatticeContainer, Surface use material_header, only: Material - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use plot_header, only: ObjectPlot use set_header, only: SetInt use source_header, only: ExtSource @@ -90,7 +90,7 @@ module global ! ============================================================================ ! TALLY-RELATED VARIABLES - type(StructuredMesh), allocatable, target :: meshes(:) + type(RegularMesh), allocatable, target :: meshes(:) type(TallyObject), allocatable, target :: tallies(:) integer, allocatable :: matching_bins(:) @@ -203,11 +203,11 @@ module global logical :: entropy_on = .false. real(8), allocatable :: entropy(:) ! shannon entropy at each generation real(8), allocatable :: entropy_p(:,:,:,:) ! % of source sites in each cell - type(StructuredMesh), pointer :: entropy_mesh + type(RegularMesh), pointer :: entropy_mesh ! Uniform fission source weighting logical :: ufs = .false. - type(StructuredMesh), pointer :: ufs_mesh => null() + type(RegularMesh), pointer :: ufs_mesh => null() real(8), allocatable :: source_frac(:,:,:,:) ! Write source at end of simulation diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 15a08148d..4abc83f6a 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -8,7 +8,7 @@ module input_xml use geometry_header, only: Cell, Surface, Lattice, RectLattice, HexLattice use global use list_header, only: ListChar, ListReal - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use output, only: write_message use plot_header use random_lcg, only: prn @@ -2091,9 +2091,9 @@ contains character(MAX_WORD_LEN) :: temp_str character(MAX_WORD_LEN), allocatable :: sarray(:) type(DictCharInt) :: trigger_scores - type(ElemKeyValueCI), pointer :: pair_list => null() - type(TallyObject), pointer :: t => null() - type(StructuredMesh), pointer :: m => null() + type(ElemKeyValueCI), pointer :: pair_list + type(TallyObject), pointer :: t + type(RegularMesh), pointer :: m type(TallyFilter), allocatable :: filters(:) ! temporary filters type(Node), pointer :: doc => null() type(Node), pointer :: node_mesh => null() diff --git a/src/mesh.F90 b/src/mesh.F90 index b9d85f439..3d0235d18 100644 --- a/src/mesh.F90 +++ b/src/mesh.F90 @@ -20,7 +20,7 @@ contains subroutine get_mesh_bin(m, xyz, bin) - type(StructuredMesh), pointer :: m ! mesh pointer + type(RegularMesh), pointer :: m ! mesh pointer real(8), intent(in) :: xyz(:) ! coordinates integer, intent(out) :: bin ! tally bin @@ -73,7 +73,7 @@ contains subroutine get_mesh_indices(m, xyz, ijk, in_mesh) - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m real(8), intent(in) :: xyz(:) ! coordinates to check integer, intent(out) :: ijk(:) ! indices in mesh logical, intent(out) :: in_mesh ! were given coords in mesh? @@ -98,7 +98,7 @@ contains function mesh_indices_to_bin(m, ijk, surface_current) result(bin) - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m integer, intent(in) :: ijk(:) logical, optional :: surface_current integer :: bin @@ -132,7 +132,7 @@ contains subroutine bin_to_mesh_indices(m, bin, ijk) - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m integer, intent(in) :: bin integer, intent(out) :: ijk(:) @@ -163,7 +163,7 @@ contains subroutine count_bank_sites(m, bank_array, cnt, energies, size_bank, & sites_outside) - type(StructuredMesh), pointer :: m ! mesh to count sites + type(RegularMesh), pointer :: m ! mesh to count sites type(Bank), intent(in) :: bank_array(:) ! fission or source bank real(8), intent(out) :: cnt(:,:,:,:) ! weight of sites in each ! cell and energy group @@ -264,7 +264,7 @@ contains function mesh_intersects_2d(m, xyz0, xyz1) result(intersects) - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m real(8), intent(in) :: xyz0(2) real(8), intent(in) :: xyz1(2) logical :: intersects @@ -330,7 +330,7 @@ contains function mesh_intersects_3d(m, xyz0, xyz1) result(intersects) - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m real(8), intent(in) :: xyz0(3) real(8), intent(in) :: xyz1(3) logical :: intersects diff --git a/src/mesh_header.F90 b/src/mesh_header.F90 index 9aa57df90..9da06f813 100644 --- a/src/mesh_header.F90 +++ b/src/mesh_header.F90 @@ -7,7 +7,7 @@ module mesh_header ! congruent squares or cubes !=============================================================================== - type StructuredMesh + type RegularMesh integer :: id ! user-specified id integer :: type ! rectangular, hexagonal integer :: n_dimension ! rank of mesh @@ -16,6 +16,6 @@ module mesh_header real(8), allocatable :: lower_left(:) ! lower-left corner of mesh real(8), allocatable :: upper_right(:) ! upper-right corner of mesh real(8), allocatable :: width(:) ! width of each mesh cell - end type StructuredMesh + end type RegularMesh end module mesh_header diff --git a/src/output.F90 b/src/output.F90 index 73b8e595d..1a841a777 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -10,7 +10,7 @@ module output HexLattice, BASE_UNIVERSE use global use math, only: t_percentile - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use mesh, only: mesh_indices_to_bin, bin_to_mesh_indices use particle_header, only: LocalCoord, Particle use plot_header @@ -1194,7 +1194,7 @@ contains integer :: filter_index ! index in results array for filters logical :: print_ebin ! should incoming energy bin be displayed? character(MAX_LINE_LEN) :: string - type(StructuredMesh), pointer :: m => null() + type(RegularMesh), pointer :: m ! Get pointer to mesh i_filter_mesh = t % find_filter(FILTER_MESH) @@ -1361,8 +1361,8 @@ contains integer, allocatable :: ijk(:) ! indices in mesh real(8) :: E0 ! lower bound for energy bin real(8) :: E1 ! upper bound for energy bin - type(StructuredMesh), pointer :: m => null() - type(Universe), pointer :: univ => null() + type(RegularMesh), pointer :: m + type(Universe), pointer :: univ bin = matching_bins(i_filter) diff --git a/src/plot.F90 b/src/plot.F90 index d8c255c34..a5497bc20 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -7,6 +7,7 @@ module plot use global use hdf5_interface use mesh, only: get_mesh_indices + use mesh_header, only: RegularMesh use output, only: write_message use particle_header, only: Particle, LocalCoord use plot_header @@ -215,7 +216,7 @@ contains real(8) :: xyz_ur_plot(3) ! upper right xyz of plot image real(8) :: xyz_ll(3) ! lower left xyz real(8) :: xyz_ur(3) ! upper right xyz - type(StructuredMesh), pointer :: m => null() + type(RegularMesh), pointer :: m m => pl % meshlines_mesh diff --git a/src/plot_header.F90 b/src/plot_header.F90 index 8dc725d9d..a6ea9a580 100644 --- a/src/plot_header.F90 +++ b/src/plot_header.F90 @@ -1,7 +1,7 @@ module plot_header use constants - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh implicit none @@ -28,7 +28,7 @@ module plot_header integer :: pixels(3) ! pixel width/height of plot slice integer :: meshlines_width ! pixel width of meshlines integer :: level ! universe depth to plot the cells of - type(StructuredMesh), pointer :: meshlines_mesh => null() ! mesh to plot + type(RegularMesh), pointer :: meshlines_mesh => null() ! mesh to plot type(ObjectColor) :: meshlines_color ! Color for meshlines type(ObjectColor) :: not_found ! color for positions where no cell found type(ObjectColor), allocatable :: colors(:) ! colors of cells/mats diff --git a/src/state_point.F90 b/src/state_point.F90 index 60057a2c9..1115647c4 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -20,7 +20,7 @@ module state_point use output, only: write_message, time_stamp use string, only: to_str, zero_padded, count_digits use tally_header, only: TallyObject - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use dict_header, only: ElemKeyValueII, ElemKeyValueCI #ifdef MPI @@ -54,7 +54,7 @@ contains character(20), allocatable :: scores(:) character(8), allocatable :: moment_names(:) ! names of moments (e.g, P3) character(MAX_FILE_LEN) :: filename - type(StructuredMesh), pointer :: meshp + type(RegularMesh), pointer :: meshp type(TallyObject), pointer :: tally type(ElemKeyValueII), pointer :: current type(ElemKeyValueII), pointer :: next @@ -181,7 +181,7 @@ contains mesh_group = create_group(meshes_group, "mesh " // trim(to_str(meshp%id))) call write_dataset(mesh_group, "id", meshp%id) - call write_dataset(mesh_group, "type", meshp%type) + call write_dataset(mesh_group, "type", "regular") call write_dataset(mesh_group, "n_dimension", meshp%n_dimension) call write_dataset(mesh_group, "dimension", meshp%dimension) call write_dataset(mesh_group, "lower_left", meshp%lower_left) diff --git a/src/summary.F90 b/src/summary.F90 index 90a4e726f..4159a209d 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -8,7 +8,7 @@ module summary use global use hdf5_interface use material_header, only: Material - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use output, only: time_stamp use string, only: to_str use tally_header, only: TallyObject @@ -462,7 +462,7 @@ contains integer(HID_T) :: tally_group integer(HID_T) :: filter_group character(20), allocatable :: scores(:) - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m type(TallyObject), pointer :: t tallies_group = create_group(file_id, "tallies") @@ -479,7 +479,7 @@ contains call write_dataset(mesh_group, "index", i) ! Write type and number of dimensions - call write_dataset(mesh_group, "type", m%type) + call write_dataset(mesh_group, "type", "regular") ! Write mesh information call write_dataset(mesh_group, "dimension", m%dimension) diff --git a/src/tally.F90 b/src/tally.F90 index 12085b5d2..69615314f 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -9,7 +9,7 @@ module tally use mesh, only: get_mesh_bin, bin_to_mesh_indices, & get_mesh_indices, mesh_indices_to_bin, & mesh_intersects_2d, mesh_intersects_3d - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use output, only: header use particle_header, only: LocalCoord, Particle use search, only: binary_search @@ -908,7 +908,7 @@ contains logical :: start_in_mesh ! starting coordinates inside mesh? logical :: end_in_mesh ! ending coordinates inside mesh? type(TallyObject), pointer :: t - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m type(Material), pointer :: mat t => tallies(i_tally) @@ -1249,7 +1249,7 @@ contains integer :: offset ! offset for distribcell real(8) :: E ! particle energy type(TallyObject), pointer :: t - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m found_bin = .true. t => tallies(i_tally) @@ -1402,7 +1402,7 @@ contains logical :: y_same ! same starting/ending y index (j) logical :: z_same ! same starting/ending z index (k) type(TallyObject), pointer :: t - type(StructuredMesh), pointer :: m + type(RegularMesh), pointer :: m TALLY_LOOP: do i = 1, active_current_tallies % size() ! Copy starting and ending location of particle diff --git a/src/trigger.F90 b/src/trigger.F90 index 4a16cd5ca..a74a64be0 100644 --- a/src/trigger.F90 +++ b/src/trigger.F90 @@ -9,6 +9,7 @@ module trigger use string, only: to_str use output, only: warning, write_message use mesh, only: mesh_indices_to_bin + use mesh_header, only: RegularMesh use trigger_header, only: TriggerObject use tally, only: TallyObject @@ -315,7 +316,7 @@ contains real(8) :: std_dev = ZERO ! temporary standard deviration of result type(TallyObject), pointer :: t ! surface current tally type(TriggerObject) :: trigger ! surface current tally trigger - type(StructuredMesh), pointer :: m ! surface current mesh + type(RegularMesh), pointer :: m ! surface current mesh ! Get pointer to mesh i_filter_mesh = t % find_filter(FILTER_MESH) From da2bc6b6fe4f5b9491adde2178d64710187d32ea Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 20 Sep 2015 10:10:48 +0700 Subject: [PATCH 70/95] Write tally nuclides as array of strings for HDF5 files --- openmc/statepoint.py | 6 +-- src/state_point.F90 | 89 ++++++++++++++++++++++---------------------- src/summary.F90 | 64 ++++++++++++++++--------------- 3 files changed, 81 insertions(+), 78 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 72c85d27e..fbe8fecd8 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -410,11 +410,11 @@ class StatePoint(object): # Read Nuclide bins n_nuclides = self._f['{0}{1}/n_nuclides'.format(base, tally_key)].value - nuclide_zaids = self._f['{0}{1}/nuclides'.format(base, tally_key)].value + nuclide_names = self._f['{0}{1}/nuclides'.format(base, tally_key)].value # Add all Nuclides to the Tally - for nuclide_zaid in nuclide_zaids: - tally.add_nuclide(nuclide_zaid) + for name in nuclide_names: + tally.add_nuclide(name.decode()) # Read score bins n_score_bins = self._f['{0}{1}/n_score_bins'.format(base, tally_key)].value diff --git a/src/state_point.F90 b/src/state_point.F90 index 1115647c4..18bedcd4f 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -41,19 +41,19 @@ contains subroutine write_state_point() - integer :: i, j, k - integer :: n_order ! loop index for moment orders - integer :: nm_order ! loop index for Ynm moment orders - integer, allocatable :: id_array(:) - integer, allocatable :: key_array(:) + integer :: i, j, k + integer :: i_list + integer :: n_order ! loop index for moment orders + integer :: nm_order ! loop index for Ynm moment orders + integer, allocatable :: id_array(:) + integer, allocatable :: key_array(:) integer(HID_T) :: file_id integer(HID_T) :: cmfd_group integer(HID_T) :: tallies_group, tally_group integer(HID_T) :: meshes_group, mesh_group integer(HID_T) :: filter_group - character(20), allocatable :: scores(:) - character(8), allocatable :: moment_names(:) ! names of moments (e.g, P3) - character(MAX_FILE_LEN) :: filename + character(20), allocatable :: str_array(:) + character(MAX_FILE_LEN) :: filename type(RegularMesh), pointer :: meshp type(TallyObject), pointer :: tally type(ElemKeyValueII), pointer :: current @@ -280,101 +280,102 @@ contains call write_dataset(tally_group, "n_nuclides", tally%n_nuclide_bins) ! Set up nuclide bin array and then write - allocate(key_array(tally%n_nuclide_bins)) + allocate(str_array(tally%n_nuclide_bins)) NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins if (tally%nuclide_bins(j) > 0) then - key_array(j) = nuclides(tally%nuclide_bins(j))%zaid + i_list = nuclides(tally%nuclide_bins(j))%listing + str_array(j) = xs_listings(i_list)%alias else - key_array(j) = tally%nuclide_bins(j) + str_array(j) = 'total' end if end do NUCLIDE_LOOP - call write_dataset(tally_group, "nuclides", key_array) - deallocate(key_array) + call write_dataset(tally_group, "nuclides", str_array) + deallocate(str_array) call write_dataset(tally_group, "n_score_bins", tally%n_score_bins) - allocate(scores(size(tally%score_bins))) + allocate(str_array(size(tally%score_bins))) do j = 1, size(tally%score_bins) select case(tally%score_bins(j)) case (SCORE_FLUX) - scores(j) = "flux" + str_array(j) = "flux" case (SCORE_TOTAL) - scores(j) = "total" + str_array(j) = "total" case (SCORE_SCATTER) - scores(j) = "scatter" + str_array(j) = "scatter" case (SCORE_NU_SCATTER) - scores(j) = "nu-scatter" + str_array(j) = "nu-scatter" case (SCORE_SCATTER_N) - scores(j) = "scatter-n" + str_array(j) = "scatter-n" case (SCORE_SCATTER_PN) - scores(j) = "scatter-pn" + str_array(j) = "scatter-pn" case (SCORE_NU_SCATTER_N) - scores(j) = "nu-scatter-n" + str_array(j) = "nu-scatter-n" case (SCORE_NU_SCATTER_PN) - scores(j) = "nu-scatter-pn" + str_array(j) = "nu-scatter-pn" case (SCORE_TRANSPORT) - scores(j) = "transport" + str_array(j) = "transport" case (SCORE_N_1N) - scores(j) = "n1n" + str_array(j) = "n1n" case (SCORE_ABSORPTION) - scores(j) = "absorption" + str_array(j) = "absorption" case (SCORE_FISSION) - scores(j) = "fission" + str_array(j) = "fission" case (SCORE_NU_FISSION) - scores(j) = "nu-fission" + str_array(j) = "nu-fission" case (SCORE_KAPPA_FISSION) - scores(j) = "kappa-fission" + str_array(j) = "kappa-fission" case (SCORE_CURRENT) - scores(j) = "current" + str_array(j) = "current" case (SCORE_FLUX_YN) - scores(j) = "flux-yn" + str_array(j) = "flux-yn" case (SCORE_TOTAL_YN) - scores(j) = "total-yn" + str_array(j) = "total-yn" case (SCORE_SCATTER_YN) - scores(j) = "scatter-yn" + str_array(j) = "scatter-yn" case (SCORE_NU_SCATTER_YN) - scores(j) = "nu-scatter-yn" + str_array(j) = "nu-scatter-yn" case (SCORE_EVENTS) - scores(j) = "events" + str_array(j) = "events" case default - scores(j) = reaction_name(tally%score_bins(j)) + str_array(j) = reaction_name(tally%score_bins(j)) end select end do - call write_dataset(tally_group, "scores", scores) + call write_dataset(tally_group, "scores", str_array) call write_dataset(tally_group, "score_bins", tally%score_bins) call write_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) - deallocate(scores) + deallocate(str_array) ! Write explicit moment order strings for each score bin k = 1 - allocate(moment_names(tally%n_score_bins)) + allocate(str_array(tally%n_score_bins)) MOMENT_LOOP: do j = 1, tally%n_user_score_bins select case(tally%score_bins(k)) case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - moment_names(k) = 'P' // trim(to_str(tally%moment_order(k))) + str_array(k) = 'P' // trim(to_str(tally%moment_order(k))) k = k + 1 case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) do n_order = 0, tally%moment_order(k) - moment_names(k) = 'P' // trim(to_str(n_order)) + str_array(k) = 'P' // trim(to_str(n_order)) k = k + 1 end do case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & SCORE_TOTAL_YN) do n_order = 0, tally%moment_order(k) do nm_order = -n_order, n_order - moment_names(k) = 'Y' // trim(to_str(n_order)) // ',' // & + str_array(k) = 'Y' // trim(to_str(n_order)) // ',' // & trim(to_str(nm_order)) k = k + 1 end do end do case default - moment_names(k) = '' + str_array(k) = '' k = k + 1 end select end do MOMENT_LOOP - call write_dataset(tally_group, "moment_orders", moment_names) - deallocate(moment_names) + call write_dataset(tally_group, "moment_orders", str_array) + deallocate(str_array) call close_group(tally_group) end do TALLY_METADATA diff --git a/src/summary.F90 b/src/summary.F90 index 4159a209d..aa1ee3509 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -456,12 +456,13 @@ contains integer(HID_T), intent(in) :: file_id integer :: i, j + integer :: i_list integer, allocatable :: temp_array(:) ! nuclide bin array integer(HID_T) :: tallies_group integer(HID_T) :: mesh_group integer(HID_T) :: tally_group integer(HID_T) :: filter_group - character(20), allocatable :: scores(:) + character(20), allocatable :: str_array(:) type(RegularMesh), pointer :: m type(TallyObject), pointer :: t @@ -551,75 +552,76 @@ contains end do FILTER_LOOP ! Write number of nuclide bins - call write_dataset(tally_group, "n_nuclide_bins", t%n_nuclide_bins) + call write_dataset(tally_group, "n_nuclides", t%n_nuclide_bins) ! Create temporary array for nuclide bins - allocate(temp_array(t%n_nuclide_bins)) + allocate(str_array(t%n_nuclide_bins)) NUCLIDE_LOOP: do j = 1, t%n_nuclide_bins if (t%nuclide_bins(j) > 0) then - temp_array(j) = nuclides(t%nuclide_bins(j))%zaid + i_list = nuclides(t%nuclide_bins(j))%listing + str_array(j) = xs_listings(i_list)%alias else - temp_array(j) = t%nuclide_bins(j) + str_array(j) = 'total' end if end do NUCLIDE_LOOP ! Write and deallocate nuclide bins - call write_dataset(tally_group, "nuclide_bins", temp_array) - deallocate(temp_array) + call write_dataset(tally_group, "nuclides", str_array) + deallocate(str_array) ! Write number of score bins call write_dataset(tally_group, "n_score_bins", t%n_score_bins) - allocate(scores(size(t%score_bins))) + allocate(str_array(size(t%score_bins))) do j = 1, size(t%score_bins) select case(t%score_bins(j)) case (SCORE_FLUX) - scores(j) = "flux" + str_array(j) = "flux" case (SCORE_TOTAL) - scores(j) = "total" + str_array(j) = "total" case (SCORE_SCATTER) - scores(j) = "scatter" + str_array(j) = "scatter" case (SCORE_NU_SCATTER) - scores(j) = "nu-scatter" + str_array(j) = "nu-scatter" case (SCORE_SCATTER_N) - scores(j) = "scatter-n" + str_array(j) = "scatter-n" case (SCORE_SCATTER_PN) - scores(j) = "scatter-pn" + str_array(j) = "scatter-pn" case (SCORE_NU_SCATTER_N) - scores(j) = "nu-scatter-n" + str_array(j) = "nu-scatter-n" case (SCORE_NU_SCATTER_PN) - scores(j) = "nu-scatter-pn" + str_array(j) = "nu-scatter-pn" case (SCORE_TRANSPORT) - scores(j) = "transport" + str_array(j) = "transport" case (SCORE_N_1N) - scores(j) = "n1n" + str_array(j) = "n1n" case (SCORE_ABSORPTION) - scores(j) = "absorption" + str_array(j) = "absorption" case (SCORE_FISSION) - scores(j) = "fission" + str_array(j) = "fission" case (SCORE_NU_FISSION) - scores(j) = "nu-fission" + str_array(j) = "nu-fission" case (SCORE_KAPPA_FISSION) - scores(j) = "kappa-fission" + str_array(j) = "kappa-fission" case (SCORE_CURRENT) - scores(j) = "current" + str_array(j) = "current" case (SCORE_FLUX_YN) - scores(j) = "flux-yn" + str_array(j) = "flux-yn" case (SCORE_TOTAL_YN) - scores(j) = "total-yn" + str_array(j) = "total-yn" case (SCORE_SCATTER_YN) - scores(j) = "scatter-yn" + str_array(j) = "scatter-yn" case (SCORE_NU_SCATTER_YN) - scores(j) = "nu-scatter-yn" + str_array(j) = "nu-scatter-yn" case (SCORE_EVENTS) - scores(j) = "events" + str_array(j) = "events" case default - scores(j) = reaction_name(t%score_bins(j)) + str_array(j) = reaction_name(t%score_bins(j)) end select end do - call write_dataset(tally_group, "scores", scores) + call write_dataset(tally_group, "scores", str_array) call write_dataset(tally_group, "score_bins", t%score_bins) - deallocate(scores) + deallocate(str_array) call close_group(tally_group) end do TALLY_METADATA From 843aff3ce75a37f05b7f487918f5d97e2f92caf7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 20 Sep 2015 10:23:20 +0700 Subject: [PATCH 71/95] Don't write mesh%n_dimension in statepoint --- src/state_point.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/state_point.F90 b/src/state_point.F90 index 18bedcd4f..24d2fac1b 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -182,7 +182,6 @@ contains call write_dataset(mesh_group, "id", meshp%id) call write_dataset(mesh_group, "type", "regular") - call write_dataset(mesh_group, "n_dimension", meshp%n_dimension) 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) From b167d70c877c516deca785801b9fa6f53fb0985b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 20 Sep 2015 14:36:25 +0700 Subject: [PATCH 72/95] Allow ENDF reaction names to be used on tallies, e.g. (n,2n), (n,gamma), etc. The only score that needed more work was elastic scattering, so a block in score_general has been added. --- src/input_xml.F90 | 81 ++++++++++++++++++++++++++++++++++++++++++++--- src/tally.F90 | 13 ++++++++ 2 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 4abc83f6a..e6e644459 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2730,7 +2730,7 @@ contains t % moment_order(j : j + n_bins - 1) = n_order j = j + n_bins - 1 - case ('total') + case ('total', '(n,total)') t % score_bins(j) = SCORE_TOTAL if (t % find_filter(FILTER_ENERGYOUT) > 0) then call fatal_error("Cannot tally total reaction rate with an & @@ -2816,13 +2816,13 @@ contains ! Set tally estimator to analog t % estimator = ESTIMATOR_ANALOG - case ('n2n') + case ('n2n', '(n,2n)') t % score_bins(j) = N_2N - case ('n3n') + case ('n3n', '(n,3n)') t % score_bins(j) = N_3N - case ('n4n') + case ('n4n', '(n,4n)') t % score_bins(j) = N_4N case ('absorption') @@ -2903,6 +2903,79 @@ contains case ('events') t % score_bins(j) = SCORE_EVENTS + case ('elastic', '(n,elastic)') + t % score_bins(j) = ELASTIC + case ('(n,2nd)') + t % score_bins(j) = N_2ND + case ('(n,na)') + t % score_bins(j) = N_2NA + case ('(n,n3a)') + t % score_bins(j) = N_N3A + case ('(n,2na)') + t % score_bins(j) = N_2NA + case ('(n,3na)') + t % score_bins(j) = N_3NA + case ('(n,np)') + t % score_bins(j) = N_NP + case ('(n,n2a)') + t % score_bins(j) = N_N2A + case ('(n,2n2a)') + t % score_bins(j) = N_2N2A + case ('(n,nd)') + t % score_bins(j) = N_ND + case ('(n,nt)') + t % score_bins(j) = N_NT + case ('(n,nHe-3)') + t % score_bins(j) = N_N3HE + case ('(n,nd2a)') + t % score_bins(j) = N_ND2A + case ('(n,nt2a)') + t % score_bins(j) = N_NT2A + case ('(n,3nf)') + t % score_bins(j) = N_3NF + case ('(n,2np)') + t % score_bins(j) = N_2NP + case ('(n,3np)') + t % score_bins(j) = N_3NP + case ('(n,n2p)') + t % score_bins(j) = N_N2P + case ('(n,npa)') + t % score_bins(j) = N_NPA + case ('(n,n1)') + t % score_bins(j) = N_N1 + case ('(n,nc)') + t % score_bins(j) = N_NC + case ('(n,gamma)') + t % score_bins(j) = N_GAMMA + case ('(n,p)') + t % score_bins(j) = N_P + case ('(n,d)') + t % score_bins(j) = N_D + case ('(n,t)') + t % score_bins(j) = N_T + case ('(n,3He)') + t % score_bins(j) = N_3HE + case ('(n,a)') + t % score_bins(j) = N_A + case ('(n,2a)') + t % score_bins(j) = N_2A + case ('(n,3a)') + t % score_bins(j) = N_3A + case ('(n,2p)') + t % score_bins(j) = N_2P + case ('(n,pa)') + t % score_bins(j) = N_PA + case ('(n,t2a)') + t % score_bins(j) = N_T2A + case ('(n,d2a)') + t % score_bins(j) = N_D2A + case ('(n,pd)') + t % score_bins(j) = N_PD + case ('(n,pt)') + t % score_bins(j) = N_PT + case ('(n,da)') + t % score_bins(j) = N_DA + case default ! Assume that user has specified an MT number MT = int(str_to_int(score_name)) diff --git a/src/tally.F90 b/src/tally.F90 index 69615314f..33e452a4c 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -360,6 +360,19 @@ contains ! Simply count number of scoring events score = ONE + case (ELASTIC) + if (t % estimator == ESTIMATOR_ANALOG) then + ! Check if event MT matches + if (p % event_MT /= ELASTIC) cycle SCORE_LOOP + score = p % last_wgt + + else + if (i_nuclide > 0) then + score = micro_xs(i_nuclide) % elastic * atom_density * flux + else + score = material_xs % elastic * flux + end if + end if case default if (t % estimator == ESTIMATOR_ANALOG) then From b0ea5b8ae045fc1f22eda293e31ce0d7e36f5503 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Sep 2015 10:00:51 +0700 Subject: [PATCH 73/95] Fix handling of mesh type --- openmc/mesh.py | 2 +- src/constants.F90 | 4 ++++ src/input_xml.F90 | 8 +++++--- src/relaxng/tallies.rnc | 6 +++--- src/relaxng/tallies.rng | 10 ++-------- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index fefc6d707..2fe873d2b 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -156,7 +156,7 @@ class Mesh(object): check_type('type for mesh ID="{0}"'.format(self._id), meshtype, basestring) check_value('type for mesh ID="{0}"'.format(self._id), - meshtype, ['regular', 'hexagonal']) + meshtype, ['regular']) self._type = meshtype @dimension.setter diff --git a/src/constants.F90 b/src/constants.F90 index 962c4a6a2..53891cdaa 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -312,6 +312,10 @@ module constants FILTER_ENERGYOUT = 8, & FILTER_DISTRIBCELL = 9 + ! Mesh types + integer, parameter :: & + MESH_REGULAR = 1 + ! Tally surface current directions integer, parameter :: & IN_RIGHT = 1, & diff --git a/src/input_xml.F90 b/src/input_xml.F90 index e6e644459..3899d43f0 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2188,9 +2188,11 @@ contains call get_node_value(node_mesh, "type", temp_str) select case (to_lower(temp_str)) case ('rect', 'rectangle', 'rectangular') - m % type = LATTICE_RECT - case ('hex', 'hexagon', 'hexagonal') - m % type = LATTICE_HEX + call warning("Mesh type '" // trim(temp_str) // "' is deprecated. & + &Please use 'regular' instead.") + m % type = MESH_REGULAR + case ('regular') + m % type = MESH_REGULAR case default call fatal_error("Invalid mesh type: " // trim(temp_str)) end select diff --git a/src/relaxng/tallies.rnc b/src/relaxng/tallies.rnc index c2e0860b8..ee93d273c 100644 --- a/src/relaxng/tallies.rnc +++ b/src/relaxng/tallies.rnc @@ -1,8 +1,8 @@ element tallies { element mesh { (element id { xsd:int } | attribute id { xsd:int }) & - (element type { ( "rectangular" | "hexagonal" ) } | - attribute type { ( "rectangular" | "hexagonal" ) }) & + (element type { ( "regular" ) } | + attribute type { ( "regular" ) }) & (element dimension { list { xsd:positiveInteger+ } } | attribute dimension { list { xsd:positiveInteger+ } }) & (element lower_left { list { xsd:double+ } } | @@ -32,7 +32,7 @@ element tallies { element nuclides { list { xsd:string { maxLength = "12" }+ } }? & - element scores { + element scores { list { xsd:string { maxLength = "20" }+ } } & element trigger { diff --git a/src/relaxng/tallies.rng b/src/relaxng/tallies.rng index 9ea941fea..76973e855 100644 --- a/src/relaxng/tallies.rng +++ b/src/relaxng/tallies.rng @@ -14,16 +14,10 @@ - - rectangular - hexagonal - + regular - - rectangular - hexagonal - + regular From 43fdeb41a1dea449c064c30e9de487ff4a154308 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Sep 2015 10:01:26 +0700 Subject: [PATCH 74/95] Make sure std_dev is calculated if mean is negative. Don't set nuclides in link_with_summary. Update pandas-dataframe notebook. --- .../examples/pandas-dataframes.ipynb | 132 +++++++++--------- openmc/statepoint.py | 9 -- openmc/tallies.py | 2 +- 3 files changed, 67 insertions(+), 76 deletions(-) diff --git a/docs/source/pythonapi/examples/pandas-dataframes.ipynb b/docs/source/pythonapi/examples/pandas-dataframes.ipynb index 384fa7620..565e6c73a 100644 --- a/docs/source/pythonapi/examples/pandas-dataframes.ipynb +++ b/docs/source/pythonapi/examples/pandas-dataframes.ipynb @@ -374,7 +374,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JEAsWB/wc/iEAAAPZSURBVGje7Zs7buMwEIZ9iey5\n0gyNjQpXKTYudIScgkdQYTfut1idwkdQkQNsYQO2Qj0sPiVK+mlQDmwgwIcgg8Cc4fCTSK5W4OeF\nkM8rHv+2I/rgxPZEPZgR7XtQxKdXYuUXJSUnBQ/9WCgo4vOSJ+WFUvF7E08mlia+rn7VcKXP8sRs\nzFX8b2MdX2y6v1Tw6MZUw4H4ojfIjD8mvn/qRL5p4+vvlMqvp2EhR8WBzfiz20hXORmP9fi/bM9E\neUFvV5H/0yRkeSbiGRfFJErxD9ENdz7Mbhig/h89fvtFdMiI/ePUIXV4lXju8K3DKv9NThOZ3q2K\nmUy6grxFES8rjeyic+FFQav+ncg3fXjH+Ts+/iibztFqOiZuZP/Z3OafPX40NGgST2r+uvQkXXp6\ncKvmr+r0e1Eef5um3+JHP3IFF1D/seNZJgaDmvY0Gav1s+2f1fqpIcublfKGt6apotG/NVx3SInW\ntLX+7Vg/Pv1YqOsnun6JSVdOXT/X7vk75f938QP+8OmSBs0fXtymMhJbf8qlPynYmpKCh7OB1fzN\nalOj1sl0ZAruHLiA+RM73pDe/VjMVP89+aTXwjyc/x5n+u991895/utrJTy8/06TXh0r/5JOa2Jm\nYmqi4r/vUm/H4wLmT+z4anhr05X+q6KUXhtzr/9qSff5L5uMT//V/NdU4YuBTPa/8P67l/6r44ds\n+hYuoP5jx9ciy6XTWlibBrmx8V/TdMfjkP+6pOsu/lvM9N90sf7r+f6m/65n+S8p/itN15v0UkW3\n/+48+PRfJX6S9Joo4g+G/1qYG9KroqP/WypcuvyXPf13wH89/hHef7MB6R3Cqn55U4rv4kfH3zaS\ngQuYP7HjVf89tXrbO+hfLdr+Ozv/SP1dgtQ/Ov8C+i/3+q/Zf2D/HWi6bjT6rym9I/v/03/b+LHS\n4cTg/utTsV7/net/Afzz4f0XGX84/2j9xZ4/sePR/of2X7D/o+vPo/sv6h9B/Bfxr9j1Hz2eN/hO\n8/wfff4A848+f/1A/530/I0+/8PvH9D3H9HnT+R49P0b+v4PfP/4E/wXfP8Mvf9G37/D/ovuP8Se\nP7Hj0f0vdP8tqP9O339cyv7p3P1fdP8Z3v9G999j13/seMax8x/o+ZN7+O+E8zdP/8XOf8Hnz9Dz\nb7HnT+x49PxlCp7/BM+fOv13wvnXBfivt2lMvD8TyH/Hnb+Gz3+j589jz5/Y8ej9h4D+W7qQmf57\nefqv239n3T+C7z+h969i13/seMax+3/o/cMcu/8Y2H9n3p+J6r98pv8m4fwXuH+M3n+OO3++AX9c\nlR+4PhbRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA5LTE2VDE4OjE5OjQ5KzA3OjAwTRYi9AAA\nACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wOS0xNlQxODoxOTo0OSswNzowMDxLmkgAAAAASUVORK5C\nYII=\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JFQI2Mgck1R0AAAPZSURBVGje7Zs7buMwEIZ9iey5\n0gyNjQpXKTYudIScgkdQYTfut1idwkdQkQNsYQO2Qj0sPiVK+mlQDmwgwIcgg8Cc4fCTSK5W4OeF\nkM8rHv+2I/rgxPZEPZgR7XtQxKdXYuUXJSUnBQ/9WCgo4vOSJ+WFUvF7E08mlia+rn7VcKXP8sRs\nzFX8b2MdX2y6v1Tw6MZUw4H4ojfIjD8mvn/qRL5p4+vvlMqvp2EhR8WBzfiz20hXORmP9fi/bM9E\neUFvV5H/0yRkeSbiGRfFJErxD9ENdz7Mbhig/h89fvtFdMiI/ePUIXV4lXju8K3DKv9NThOZ3q2K\nmUy6grxFES8rjeyic+FFQav+ncg3fXjH+Ts+/iibztFqOiZuZP/Z3OafPX40NGgST2r+uvQkXXp6\ncKvmr+r0e1Eef5um3+JHP3IFF1D/seNZJgaDmvY0Gav1s+2f1fqpIcublfKGt6apotG/NVx3SInW\ntLX+7Vg/Pv1YqOsnun6JSVdOXT/X7vk75f938QP+8OmSBs0fXtymMhJbf8qlPynYmpKCh7OB1fzN\nalOj1sl0ZAruHLiA+RM73pDe/VjMVP89+aTXwjyc/x5n+u991895/utrJTy8/06TXh0r/5JOa2Jm\nYmqi4r/vUm/H4wLmT+z4anhr05X+q6KUXhtzr/9qSff5L5uMT//V/NdU4YuBTPa/8P67l/6r44ds\n+hYuoP5jx9ciy6XTWlibBrmx8V/TdMfjkP+6pOsu/lvM9N90sf7r+f6m/65n+S8p/itN15v0UkW3\n/+48+PRfJX6S9Joo4g+G/1qYG9KroqP/WypcuvyXPf13wH89/hHef7MB6R3Cqn55U4rv4kfH3zaS\ngQuYP7HjVf89tXrbO+hfLdr+Ozv/SP1dgtQ/Ov8C+i/3+q/Zf2D/HWi6bjT6rym9I/v/03/b+LHS\n4cTg/utTsV7/net/Afzz4f0XGX84/2j9xZ4/sePR/of2X7D/o+vPo/sv6h9B/Bfxr9j1Hz2eN/hO\n8/wfff4A848+f/1A/530/I0+/8PvH9D3H9HnT+R49P0b+v4PfP/4E/wXfP8Mvf9G37/D/ovuP8Se\nP7Hj0f0vdP8tqP9O339cyv7p3P1fdP8Z3v9G999j13/seMax8x/o+ZN7+O+E8zdP/8XOf8Hnz9Dz\nb7HnT+x49PxlCp7/BM+fOv13wvnXBfivt2lMvD8TyH/Hnb+Gz3+j589jz5/Y8ej9h4D+W7qQmf57\nefqv239n3T+C7z+h969i13/seMax+3/o/cMcu/8Y2H9n3p+J6r98pv8m4fwXuH+M3n+OO3++AX9c\nlR+4PhbRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA5LTIxVDA5OjQ2OjQyKzA3OjAwIbcawwAA\nACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wOS0yMVQwOTo0Njo0MiswNzowMFDqon8AAAAASUVORK5C\nYII=\n", "text/plain": [ "" ] @@ -429,7 +429,7 @@ "source": [ "# Instantiate a tally Mesh\n", "mesh = openmc.Mesh(mesh_id=1)\n", - "mesh.type = 'rectangular'\n", + "mesh.type = 'regular'\n", "mesh.dimension = [17, 17]\n", "mesh.lower_left = [-10.71, -10.71]\n", "mesh.width = [1.26, 1.26]\n", @@ -563,8 +563,8 @@ " Copyright: 2011-2015 Massachusetts Institute of Technology\n", " License: http://mit-crpg.github.io/openmc/license.html\n", " Version: 0.7.0\n", - " Git SHA1: 36a516ed8125ab8a86d8c9b3aee4bd4bc2db859c\n", - " Date/Time: 2015-09-16 18:22:08\n", + " Git SHA1: b167d70c877c516deca785801b9fa6f53fb0985b\n", + " Date/Time: 2015-09-21 09:54:51\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -631,20 +631,20 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 5.5700E-01 seconds\n", - " Reading cross sections = 1.8900E-01 seconds\n", - " Total time in simulation = 1.1416E+01 seconds\n", - " Time in transport only = 1.1395E+01 seconds\n", - " Time in inactive batches = 1.4590E+00 seconds\n", - " Time in active batches = 9.9570E+00 seconds\n", + " Total time for initialization = 4.0200E-01 seconds\n", + " Reading cross sections = 1.3900E-01 seconds\n", + " Total time in simulation = 1.3557E+01 seconds\n", + " Time in transport only = 1.3542E+01 seconds\n", + " Time in inactive batches = 1.4020E+00 seconds\n", + " Time in active batches = 1.2155E+01 seconds\n", " Time synchronizing fission bank = 4.0000E-03 seconds\n", - " Sampling source sites = 4.0000E-03 seconds\n", - " SEND/RECV source sites = 0.0000E+00 seconds\n", - " Time accumulating tallies = 1.0000E-03 seconds\n", - " Total time for finalization = 0.0000E+00 seconds\n", - " Total time elapsed = 1.1985E+01 seconds\n", - " Calculation Rate (inactive) = 8567.51 neutrons/second\n", - " Calculation Rate (active) = 3766.19 neutrons/second\n", + " Sampling source sites = 3.0000E-03 seconds\n", + " SEND/RECV source sites = 1.0000E-03 seconds\n", + " Time accumulating tallies = 0.0000E+00 seconds\n", + " Total time for finalization = 1.0000E-03 seconds\n", + " Total time elapsed = 1.3972E+01 seconds\n", + " Calculation Rate (inactive) = 8915.83 neutrons/second\n", + " Calculation Rate (active) = 3085.15 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", @@ -737,7 +737,7 @@ " \t\tmesh\t[1]\n", " \t\tenergy\t[ 0.00000000e+00 6.25000000e-07 2.00000000e+01]\n", "\tNuclides =\ttotal \n", - "\tScores =\t['fission', 'nu-fission']\n", + "\tScores =\t[u'fission', u'nu-fission']\n", "\tEstimator =\ttracklength\n", "\n" ] @@ -1085,7 +1085,7 @@ "data": { "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1108,7 +1108,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 27, @@ -1119,7 +1119,7 @@ "data": { "image/png": "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\nEvx/rHWCrxSlro8AAAAASUVORK5CYII=\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1164,7 +1164,7 @@ "\tName =\tcell tally\n", "\tFilters =\t\n", " \t\tcell\t[10000]\n", - "\tNuclides =\tU-235 U-238 \n", + "\tNuclides =\tU-235.71c U-238.71c \n", "\tScores =\t[u'scatter-Y0,0', u'scatter-Y1,-1', u'scatter-Y1,0', u'scatter-Y1,1', u'scatter-Y2,-2', u'scatter-Y2,-1', u'scatter-Y2,0', u'scatter-Y2,1', u'scatter-Y2,2']\n", "\tEstimator =\tanalog\n", "\n" @@ -1213,7 +1213,7 @@ " \n", " 0\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y0,0\n", " 0.036453\n", " 0.001219\n", @@ -1221,7 +1221,7 @@ " \n", " 1\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y1,-1\n", " 0.000302\n", " 0.000314\n", @@ -1229,7 +1229,7 @@ " \n", " 2\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y1,0\n", " -0.000006\n", " 0.000347\n", @@ -1237,7 +1237,7 @@ " \n", " 3\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y1,1\n", " 0.000244\n", " 0.000286\n", @@ -1245,7 +1245,7 @@ " \n", " 4\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y2,-2\n", " 0.000184\n", " 0.000211\n", @@ -1253,7 +1253,7 @@ " \n", " 5\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y2,-1\n", " 0.000067\n", " 0.000173\n", @@ -1261,7 +1261,7 @@ " \n", " 6\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y2,0\n", " 0.000353\n", " 0.000210\n", @@ -1269,7 +1269,7 @@ " \n", " 7\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y2,1\n", " -0.000266\n", " 0.000263\n", @@ -1277,7 +1277,7 @@ " \n", " 8\n", " 10000\n", - " U-235\n", + " U-235.71c\n", " scatter-Y2,2\n", " -0.000246\n", " 0.000153\n", @@ -1285,7 +1285,7 @@ " \n", " 9\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y0,0\n", " 2.315893\n", " 0.008243\n", @@ -1293,7 +1293,7 @@ " \n", " 10\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y1,-1\n", " -0.022028\n", " 0.002316\n", @@ -1301,7 +1301,7 @@ " \n", " 11\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y1,0\n", " -0.003426\n", " 0.002651\n", @@ -1309,7 +1309,7 @@ " \n", " 12\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y1,1\n", " 0.026620\n", " 0.002084\n", @@ -1317,7 +1317,7 @@ " \n", " 13\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y2,-2\n", " -0.001295\n", " 0.001627\n", @@ -1325,7 +1325,7 @@ " \n", " 14\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y2,-1\n", " 0.000759\n", " 0.001426\n", @@ -1333,7 +1333,7 @@ " \n", " 15\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y2,0\n", " 0.005513\n", " 0.001983\n", @@ -1341,7 +1341,7 @@ " \n", " 16\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y2,1\n", " 0.000431\n", " 0.001862\n", @@ -1349,7 +1349,7 @@ " \n", " 17\n", " 10000\n", - " U-238\n", + " U-238.71c\n", " scatter-Y2,2\n", " -0.001962\n", " 0.001222\n", @@ -1359,26 +1359,26 @@ "" ], "text/plain": [ - " cell nuclide score mean std. dev.\n", - "bin \n", - "0 10000 U-235 scatter-Y0,0 0.036453 0.001219\n", - "1 10000 U-235 scatter-Y1,-1 0.000302 0.000314\n", - "2 10000 U-235 scatter-Y1,0 -0.000006 0.000347\n", - "3 10000 U-235 scatter-Y1,1 0.000244 0.000286\n", - "4 10000 U-235 scatter-Y2,-2 0.000184 0.000211\n", - "5 10000 U-235 scatter-Y2,-1 0.000067 0.000173\n", - "6 10000 U-235 scatter-Y2,0 0.000353 0.000210\n", - "7 10000 U-235 scatter-Y2,1 -0.000266 0.000263\n", - "8 10000 U-235 scatter-Y2,2 -0.000246 0.000153\n", - "9 10000 U-238 scatter-Y0,0 2.315893 0.008243\n", - "10 10000 U-238 scatter-Y1,-1 -0.022028 0.002316\n", - "11 10000 U-238 scatter-Y1,0 -0.003426 0.002651\n", - "12 10000 U-238 scatter-Y1,1 0.026620 0.002084\n", - "13 10000 U-238 scatter-Y2,-2 -0.001295 0.001627\n", - "14 10000 U-238 scatter-Y2,-1 0.000759 0.001426\n", - "15 10000 U-238 scatter-Y2,0 0.005513 0.001983\n", - "16 10000 U-238 scatter-Y2,1 0.000431 0.001862\n", - "17 10000 U-238 scatter-Y2,2 -0.001962 0.001222" + " cell nuclide score mean std. dev.\n", + "bin \n", + "0 10000 U-235.71c scatter-Y0,0 0.036453 0.001219\n", + "1 10000 U-235.71c scatter-Y1,-1 0.000302 0.000314\n", + "2 10000 U-235.71c scatter-Y1,0 -0.000006 0.000347\n", + "3 10000 U-235.71c scatter-Y1,1 0.000244 0.000286\n", + "4 10000 U-235.71c scatter-Y2,-2 0.000184 0.000211\n", + "5 10000 U-235.71c scatter-Y2,-1 0.000067 0.000173\n", + "6 10000 U-235.71c scatter-Y2,0 0.000353 0.000210\n", + "7 10000 U-235.71c scatter-Y2,1 -0.000266 0.000263\n", + "8 10000 U-235.71c scatter-Y2,2 -0.000246 0.000153\n", + "9 10000 U-238.71c scatter-Y0,0 2.315893 0.008243\n", + "10 10000 U-238.71c scatter-Y1,-1 -0.022028 0.002316\n", + "11 10000 U-238.71c scatter-Y1,0 -0.003426 0.002651\n", + "12 10000 U-238.71c scatter-Y1,1 0.026620 0.002084\n", + "13 10000 U-238.71c scatter-Y2,-2 -0.001295 0.001627\n", + "14 10000 U-238.71c scatter-Y2,-1 0.000759 0.001426\n", + "15 10000 U-238.71c scatter-Y2,0 0.005513 0.001983\n", + "16 10000 U-238.71c scatter-Y2,1 0.000431 0.001862\n", + "17 10000 U-238.71c scatter-Y2,2 -0.001962 0.001222" ] }, "execution_count": 29, @@ -1421,7 +1421,7 @@ "# Get the standard deviations for two of the spherical harmonic\n", "# scattering reaction rates \n", "data = tally.get_values(scores=['scatter-Y2,2', 'scatter-Y0,0'], \n", - " nuclides=['U-238', 'U-235'], value='std_dev')\n", + " nuclides=['U-238.71c', 'U-235.71c'], value='std_dev')\n", "print(data)" ] }, @@ -1449,7 +1449,7 @@ "\tFilters =\t\n", " \t\tdistribcell\t[10002]\n", "\tNuclides =\ttotal \n", - "\tScores =\t['absorption', 'scatter']\n", + "\tScores =\t[u'absorption', u'scatter']\n", "\tEstimator =\ttracklength\n", "\n" ] @@ -2376,7 +2376,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 38, @@ -2387,7 +2387,7 @@ "data": { "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -2414,7 +2414,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 39, @@ -2425,7 +2425,7 @@ "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAEZCAYAAAB4hzlwAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XeYVPXZ//H3vUuRsjSBBaSsSkSKqIAFMYgkoiaCIhZK\nECP2lkfDozH+ErHFJI8plqgRUUEFEiVGUKMgRkQCEgUEBEQ60kFdWZC2e//+mLPjArvLbJk5M7Of\n13Wdi5nT5jOH2bnnfM8532PujoiICEBG2AFERCR5qCiIiEiUioKIiESpKIiISJSKgoiIRKkoiIhI\nlIqCSAnM7C4zGxV2DpFEUlGQhDKzM83sP2b2tZltN7MPzKxbBdd5pZnNOGjc82Z2f0XW6+4Pufs1\nFVlHScyswMzyzGyHma03s0fNrFqMy440sxfikUtERUESxszqAa8DjwANgaOAe4E9YeYqjpllJuBl\nOrt7FtATuBi4NgGvKVIqFQVJpOMAd/e/ecRud5/q7gsLZzCza8xssZl9Y2afmtnJwfhfmNnyIuMv\nCsa3B54Euge/ur8ys2uAwcAdwbjXgnlbmNlEM9tiZivN7JYirzvSzF4xsxfMLBe4sugvcjPLCX7d\nX2Fma8xsq5n9ssjytcxsjJl9GeS/w8zWxbJR3H0FMBPoUGR9j5jZWjPLNbOPzOzMYPx5wF3A5cF7\nmxeMr29mo81sg5l9YWb3m1lGMK2tmU0P9s62mtmEsv7HSdWhoiCJ9BmQHzTtnGdmDYtONLNLgXuA\noe5eD+gHbA8mLwfODMbfC7xoZtnuvgS4Hpjl7lnu3tDdRwEvAb8Lxl0YfEFOBuYBLYAfAP9jZn2K\nROgHvOzu9YPli+sDpgeR4vYD4Ndm1i4Yfw/QGjgaOAf4SQnLH/CWg/d9PPB9YE6RaXOAE4nsUY0D\nXjazGu7+FvAbYELw3k4O5n8e2AscC5wM9AGuDqbdD7zl7g2I7J09ephcUoWpKEjCuPsO4EwiX5aj\ngC1m9pqZNQ1muZrIF/nHwfwr3H1t8PgVd98UPP478DlwWrCclfCSRcefAjR29wfcfb+7rwKeAQYW\nmec/7j4peI3dJaz3Xnff4+4LgE+IfHEDXAr8xt1z3X09kSayknIVmmtmecBi4BV3H1s4wd1fcvev\n3L3A3f8I1AQKC5AVXbeZZQPnA7e5+7fuvhX4c5H3thfIMbOj3H2vu//nMLmkClNRkIRy96Xu/lN3\nbwV0IvKr/c/B5JbAiuKWC5pt5gXNQ18Fyx5ZhpduA7QoXD5Yx11A0yLzfBHDejYVebwLqBs8bgEU\nbS6KZV0nu3td4HLgCjNrUzjBzEYEzVBfB1nrA41LWE8boDqwsch7ewpoEky/g0gRmWNmi8zspzFk\nkyoqprMdROLB3T8zszF8d4B1HdD24PmCL8ungd5Emok8aEsv/LVcXDPNwePWAqvc/biS4hSzTFm6\nEN4ItAKWBs9bxbqgu79sZhcCI4Gfmtn3gf8Ferv7pwBm9iUlv991RA7WH+nuBcWsfzPBNjazHsA7\nZjbd3VfGmlGqDu0pSMKYWTszu93MjgqetwIGAbOCWZ4BRphZF4toa2atgTpEvgi3ARnBL91ORVa9\nGWhpZtUPGndMkedzgB3BAeBaZpZpZp3su9Nhi2vqOVzzT1F/B+4yswbB+7uZshWV3wKDzKwlkAXs\nB7aZWQ0z+zVQr8i8m4g0BxmAu28EpgB/NLMsM8sws2PNrCdEjtUE6wX4Osh1SPEQARUFSawdRI4D\nfBi0pc8CFgA/h8hxA+BBIgdWvwH+ATR098XAH4L5NxEpCB8UWe804FNgk5ltCcaNBjoEzSn/CH5B\nXwCcBKwEthLZ+yj8si1pT8EPel6S+4g0Ga0i8gX9MpG2/JIcsC53XwS8C9wOvBUMy4DVwLdE9nQK\nvRz8u93MPgoeXwHUIHJ84stgnmbBtG7AbDPbAbwG3Oruq0vJJlWYxesmO8GvwLFE2mwdeNrdHzWz\nRsDfiLSDrgYuc/ev4xJCJCRmdgORz/bZYWcRKYt47insI3I2REfgdOAmi5xT/gtgatC2Oy14LpLS\nzKyZmfUImm7aEfnF/2rYuUTKKm5Fwd03ufv84HEesITIOdL9gDHBbGOAi+KVQSSBahA54+cbIj92\n/gk8EWoikXKIW/PRAS9ilgNMJ9IWvNbdGwbjDfiy8LmIiIQr7geazawuMBH4WXDxUpRHKlL8q5KI\niMQkrtcpBKcITgRecPd/BqM3m1kzd99kZs2BLcUsp0IhIlIO7l6WU6kPEbc9haBpaDSw2N3/XGTS\nJGBY8HgYkbbXQ7i7BncuvvjiuKw32MrFDMm77eO1LVJx0LbQtihuqAzx3FPoQaRTsAWFPTkS6Vbg\nt8DfzWw4wSmpccwgIiJlELei4O4fUPKeyA/j9boiIlJ+uqI5ybVv3z7sCElD2+I72hbf0baoXCoK\nSa5Dhw6Hn6mK0Lb4jrbFd7QtKpd6SRWRYgX97aWEIUOGhB0h4SrrwPLBVBREpETx+uKRiolnwVbz\nkYiIRKkoiIhIlIqCiIhEqSiIiEiUioKIpJScnBymTZsWfT5hwgQaNWrE+++/T0ZGBllZWWRlZdGs\nWTP69u3LO++8c8jytWvXjs6XlZXFrbfemui3kbRUFEQkpZhZ9OybMWPGcPPNN/Pmm2/SunVrAHJz\nc9mxYwcLFizgnHPOoX///owZM+aA5V9//XV27NgRHR599NFQ3ksyUlEQkZTj7vz1r39lxIgRTJky\nhdNPP/2QeZo2bcqtt97KyJEjufPOO0NImZpUFEQk5TzxxBPcc889vPvuu3Tp0qXUefv378+WLVv4\n7LPPouN0/UXJdPGaiJSL3Vs5F1D5PWX7gnZ33nnnHXr37k2nTp0OO3+LFi0A+PLLL6PLX3TRRVSr\n9t3X38MPP8zw4cPLlCNdqSiISLmU9cu8spgZTz31FPfffz9XX301o0ePLnX+9evXA9CoUaPo8q+9\n9hq9e/eOe9ZUpOYjEUk52dnZTJs2jRkzZnDjjTeWOu+rr75KdnY27dq1S1C61KaiICIpqXnz5kyb\nNo233nqL22+/PTq+8HjB5s2befzxx7nvvvt46KGHDlhWxxRKpuYjEUlZrVq14t1336Vnz55s2rQJ\ngAYNGuDu1KlTh1NOOYVXXnmFPn36HLBc3759yczMjD7v06cPEydOTGj2ZKWiICIpZdWqVQc8z8nJ\nYe3atQCMGzeuzMvLgdR8JCIiUSoKIiISpaIgIiJRKgoiIhKloiAiIlEqCiIiEqWiICIiUSoKIiIS\npaIgImmlU6dOvP/++2HHSFkqCiISk8I7nsVziMXBt+MEeP755/n+978PwKJFi+jZs2ep61i9ejUZ\nGRkUFBSUb2OkMXVzISJlEM+O5GIrCmUpIIcTr47x8vPzD+hbKZVoT0FCVZFfjCLFycnJ4d133wVg\nzpw5dOvWjfr169OsWTNGjBgBEN2TaNCgAVlZWXz44Ye4Ow888AA5OTlkZ2czbNgwvvnmm+h6x44d\nS5s2bWjcuHF0vsLXGTlyJJdccglDhw6lfv36jBkzhv/+9790796dhg0b0qJFC2655Rb27dsXXV9G\nRgZPPvkk3/ve96hXrx6//vWvWbFiBd27d6dBgwYMHDjwgPkTRUVBkoAfNIiUrrRf+EV/VPzsZz/j\ntttuIzc3l5UrV3LppZcCMGPGDAByc3PZsWMHp512Gs899xxjxozhvffeY+XKleTl5XHzzTcDsHjx\nYm666SbGjx/Pxo0byc3NZcOGDQe87qRJk7j00kvJzc1l8ODBZGZm8sgjj7B9+3ZmzZrFtGnTeOKJ\nJw5YZsqUKcybN4/Zs2fzu9/9jmuuuYbx48ezdu1aFi5cyPjx4ytle5WFioKIpJTC22k2bNgwOtx0\n003F7mHWqFGDzz//nG3btlG7dm1OO+206DoO9tJLL/Hzn/+cnJwc6tSpw0MPPcSECRPIz8/nlVde\noV+/fpxxxhlUr16d++6775DXO+OMM+jXrx8ARxxxBF26dOHUU08lIyODNm3acO211zJ9+vQDlrnj\njjuoW7cuHTp04IQTTuD8888nJyeHevXqcf755zNv3rzK2mwxU1EQkZRSeDvNr776Kjo88cQTxX7R\njx49mmXLltG+fXtOPfVU3njjjRLXu3HjRtq0aRN93rp1a/bv38/mzZvZuHEjLVu2jE6rVasWRx55\n5AHLF50OsGzZMi644AKaN29O/fr1ufvuu9m+ffsB82RnZx+wzoOf5+XlHWZrVD4VBRFJeSU1J7Vt\n25Zx48axdetW7rzzTi655BK+/fbbYvcqWrRowerVq6PP165dS7Vq1WjWrBnNmzfniy++iE779ttv\nD/mCP3idN9xwAx06dGD58uXk5uby4IMPpsTZTioKIpK2XnzxRbZu3QpA/fr1MTMyMjJo0qQJGRkZ\nrFixIjrvoEGD+NOf/sTq1avJy8vjl7/8JQMHDiQjI4MBAwYwefJkZs2axd69exk5cuRhz1zKy8sj\nKyuL2rVrs3TpUp588snD5i26zrBuGaqiICJlYHEcKpCqhLPW3n77bTp16kRWVha33XYbEyZMoGbN\nmtSuXZu7776bHj160LBhQ+bMmcNVV13F0KFD6dmzJ8cccwy1a9fmscceA6Bjx4489thjDBw4kBYt\nWpCVlUXTpk2pWbNmia//8MMPM27cOOrVq8e1117LwIEDD5inuLwHTw/jTDxLxhtYm5knY64wjBs3\njsGDB1f6eiMftuK2sSX0F0rxOYrPEK9tkYoSsS3MEvtZSCV5eXk0bNiQ5cuXH3AcIlFK+r8Jxleo\nkmhPQUQkBpMnT2bXrl3s3LmTESNG0Llz51AKQrypKIiIxGDSpEkcddRRHHXUUaxYsYIJEyaEHSku\n1M2FiEgMRo0axahRo8KOEXfaUxARkSgVBRERiVJREBGRKB1TEJESqcfaqkdFQUSKlSrXKOj6lcql\n5iMREYlSURARkai4FgUze9bMNpvZwiLjRprZF2Y2LxjOi2cGERGJXbz3FJ4DDv7Sd+CP7n5yMLwV\n5wwiIhKjuBYFd58BfFXMJJ3SICKShMI6pnCLmX1iZqPNrEFIGURE5CBhnJL6JHBf8Ph+4A/A8INn\nGjBgQPRx+/bt6dChQ0LCJZuZM2cm/DXHjRt3wPMhQ4aUOO9LL72UkAxQOduipPcSr/cRL2F8LpJV\nVd4WixcvZsmSJZW6zrjfT8HMcoDJ7n5CrNN0P4XvJMP9FOJ574VE30+hLK+XzHRu/ne0Lb6TkvdT\nMLPmRZ72BxaWNK+IiCRWXJuPzGw8cBbQ2MzWAfcAvczsJCI/11YB18Uzg4iIxC6uRcHdBxUz+tl4\nvqaIiJSfrmgWEZEoFQUREYlSURARkSgVBRERiVJREBGRKBUFERGJUlEQEZEo3Y6zCojnfXbLsu5k\n7kqipPcRa+bStkMyv2+Rg6koVBmH9vcTn/UWrjterxcvJb2PRK9DJFxqPhIRkSgVBRERiVJREBGR\nKBUFERGJUlEQEZEoFQUREYlSURARkSgVBRERiVJREBGRKBUFERGJUlEQEZEoFQUREYlSURARkSgV\nBRERiVJREBGRKBUFERGJUlEQEZEoFQUREYlSURARkSgVBRERiaoWdgBJPma62XxlKm57untM85U0\nr0i8qChIMQ7+ElKRqJiybE9tewmXmo9ERCRKRUFERKJUFEREJOqwxxTM7B/AaOBf7l4Q/0iSdOoD\nrcZDw5WQuQ/ysmFLJ9gA7A87nIhUplj2FJ4EhgDLzey3ZtYuzpkkWTT/GH5yLlwHdHgFauSBFUCz\n+XDuz+F/gUsvheMmg+WHnVZEKsFh9xTcfSow1cwaAAOBaWa2FhgFvOju++KcURLOoddI6PYUvPsA\nTJgC+yceOtsRBh3PgZ4PRIrEB3fCgqGg+iCSsmI6pmBmRwJXAlcDc4FHga7A1Lglk3AY0P8KOHYK\nPLkQ5l5TchPRbuDja+GZ2TD5aej4d7i5HXSEQ0+tFJFUEMsxhVeB44EXgL7uvjGYNMHMPo5nOEk0\nh/OArA0w5l3YXyvG5QxW94oMOe9Bn7Ph9DPg7T/CF93jllZEKl8sF6+Ncvc3i44ws5ruvsfdu8Yp\nl4ShyzNwNPDsxDIUhIOs7hVpWOx8A1x2KazoA1N/D7sqMaeIxE0szUcPFjNuVmUHkZA1+hx+8Ev4\nO7C7QcXW5cAnV8DjS2B3fbixI5wMBWU4ec3MDhmGDBlS7PiShnhJ5GuJJFqJRcHMmptZV6CWmXUx\ns67Bv72A2glLKAngcOFV8P6vYFslrnZvFrz9J3jxLegKZz1/Fou2LIo90yFDWcbHW6JfTyQxSttT\nOBd4GDgK+EPw+A/A7cAv4x9NEqbjy1BjJ8y5KT7r33QyjIYhJwzh7DFnc+fUO9m5d2d8XktEKqTE\nouDuz7v72cCV7n52kaGfu/8jgRklnqrthnPugLf+BJ4Zv9dxuL7b9Sy6YREb8jbQ4YkOvLrk1fi9\nnoiUS4kHms1sqLu/AOSY2e1FJwHu7n+MezqJv5Oeg80nwJqzEvJy2XWzeaH/C7y3+j1ufONGGAz8\nayV8dUxCXl9ESlda81HhcYOsEgZJdRn7ocfvYUbiWwN75fRi/vXzYQ1wzalw1n2RvRYRCVWJewru\n/tfg35EJSyOJ1WkC5LYJ7VqCGpk1YCawaC6c9z9wwwnw5uOwIpQ4IkIMp6Sa2e/NrJ6ZVTezaWa2\nzcyGxrJyM3vWzDab2cIi4xqZ2VQzW2ZmU4LuMyQMPX4PH/wi7BSQ2xr+9g946xH4cdCk1DTWs5RE\npDLFcp3Cue7+DXABsBo4lkhXaLF4jsg1skX9Apjq7scB04LnkmitiDTXLD837CTf+fxH8JfFsBIY\n1hv6XQ1Z68NOJVKlxFIUCpuYLgBecfdcYjwx291nAF8dNLofMCZ4PAa4KJZ1SSXrSqTfomS73WN+\nTZgNPLYMdjWGG0+A82+B+mvCTiZSJcRSFCab2VIiXyPTzKwpka7Qyivb3TcHjzcD2RVYl5THEV9F\nerOaPyzsJCXb3QDe+S385dNIlxvXdYn8fGg2P+xkImktlq6zf2Fm/wd87e75ZrYTuLAyXtzd3cyK\n3esYMGBA9HH79u3p0KFDZbxkypk5c2blr7TzS7Ac2NWk8tddinJ1B5HXPNJ30oy74JRGMPDCyB7E\n3Kvh08vh20YlLjpu3LgKpK28dVR0vcXNO2TIEIYMGVLs/C+99FK5c6WiuPyNpIjFixezZMmSSl2n\nuR++JcjMegBtgOrBKHf3sTG9gFkOMNndTwieLwV6ufsmM2sO/Nvdjz9oGY8lV1Uwbtw4Bg8eXKF1\nRL6Mi2zP4d1h+mxYXtw2PmjeEseVdXwlzWv74Zh3oMtoaPsWbOgKn70HKxfC1g7gGdF5i/sMHbIt\nDvN6lbGO4uYty3pjn7fk+dNZZfyNpAszw90r1CYcS9fZLwLHAPM58PYpMRWFYkwChgG/C/79ZznX\nI+XRYBU0Wh45mJuKPBNWnBsZqu+Co6dBu/fglP5QexusOwM2dIMtsHTbUto2aku1jFg6AxYRiK3r\n7K5Ah/L8dDez8cBZQGMzWwf8Gvgt8HczG07kbKbLyrpeqYBOE2DxJVDwVNhJKm5fbVjWF5YBfA51\nNkPrmdBsHpwAF4y7gA07NnDckcfRqWknOjbpCMcBW1ZFrs/wmO4xJVKlxFIUFgHNidymvUzcfVAJ\nk35Y1nVJJTlhfOQCMdKgKBxsZzYsuTgy8ADLJyxn596dLNm2hEVbFvHplk/hFKBpT6j1VaS5aUsn\nWA+sXQhbO6pQSJUXS1FoAiw2sznAnmCcu3u/+MWSuGi8BGpth7Vnhp0kYerUqEO3Ft3o1qIbAA+f\n+zCwDo74GposhuwF0PI5OKN/ZNt8cTqs6Rm5OdCmcLOLhCGWojAy+Nf57qT2qnUkK10c/xos7a9f\nwxA55XXdGZHhoxuA5ZHmp1b/idxS9OKfQG0YNHEQfY7pwznHnkPLei3DTi0Sd7GckvpecAZRW3d/\nx8xqx7KcJKF2k+C9kWGnSF47syNFc2n/yPP6xg8H/pC3V7zN/079X5pnNefCdhdCC2BjgYqrpKVY\nzj66FrgGaESki4uWwJPAD+IbTSpVnc2R5pLViekiOy3kwvAuwxneZTj5Bfl8uP5DXlv6GlwM1GgF\nn/WLHL9Y1Vv7zpI2YvmpcxNwJvANgLsvA5rGM5TEwXGvR9rJ82uGnSQlZWZkckarM/jdOb+Dx4Ex\n78LXR8MP74Lb2kR+IjVeGnZMkQqLpSjscffCA8yYWTX0uyj1tJsESyvlQnQB2N4OZt4BT38UuQd1\nBjDsbPjJuZFrJ/QnIikqlqIw3czuBmqb2TnAy8Dk+MaSSlUdOPrfsPz8sJMklJkdMsTFlk4wFfjz\nalg0EM6/Fa45Ddq8H5/XE4mjWIrCL4CtwELgOuBN4P/FM5RUsjbAppNK7ScoPXkxQxzl14T5P4Un\nF8Ks26D/FXA56v5bUsphi4K75xPpiuJGd7/E3UepY6IUcyzJdd+EdOcZsGgQPL400g/w9SfDSc+j\nJiVJBSUWBYsYaWbbgM+Az4K7rt1jcdsPl7g4Flh5Ttgpqp79R8B7wNipcPqfItc+VN8VdiqRUpW2\np3Ab0AM4xd0buntD4NRg3G2JCCcVt/6b9VCXSG+iEo7NJ8LoWZE9iOHdQTeglSRWWlG4Ahjs7qsK\nR7j7SmBIME1SwNSVU2EVkd5FJTz7asOrYyPHHK4i0g+TSBIqrShUc/etB48MxumK5hQxdeVUWBF2\nCokwmP0/MBV+MPYHzFk/J+xAIocorSjsK+c0SRIFXsDUFSoKSWchjOo7ir7j+7Jg84Kw04gcoLSi\n0NnMdhQ3ACckKqCU3yebPqFhrYaQG3YSOVjfdn159LxHOf+l81nxpaq2JI8Sm4Hc1Qid6t5Z+Q7n\nHHMOyyJ3oZEkc3mny/l699f0ebEPc65WU5IkB3XzmMamr5lOr5xeYceQUlzX7TouPv5iBk4cqL9G\nSQr6GKap/QX7+WDtB/Rs0zPsKHIYD/3wIQzT/QglKagopJGiffxUb1Wd3HW5ZNfNDjuWHEa1jGpM\nuGQCtAeO/2eF15ewPp8kLakopJ2gj582D8PqG1HXCqmhUa1G8A/gguuh7sYKri2B/T1J2lFRSFc5\n78Ea3VAnpawDProOLrwKfZlLWFQU0pHlQ+sPdJe1VPT+/4NaX0LXp8NOIlWUikI6avYJ5DWP3HNY\nUktBdXjtWej9K6i7Kew0UgWpKKSjnPe0l5DKtnaEucPh3NvDTiJVkIpCOmozHVb3CjuFVMT7v4KW\nsyPdnoskkIpCurH8yG0gdZA5te2rDW8+BudFrjkRSRQVhXSTvTByLCGvWdhJpKI+/xHsgGfmPhN2\nEqlCVBTSjY4npBGDKXDv9Hv5Zs83YYeRKkJFId20ngFr1LVF2tgEfY7tw+9n/j7sJFJFqCikmzYz\nYO33w06RNuLVZURZ1jt22FgenPIgVlfdVkj8qSikkyOJ3Cw+t3XYSdLIwV1GVNaVxmVY7zcOi26A\n7ndUcgaRQ6kopJPWwBrtJaSlD34BXUdB7W1hJ5E0p6KQTtqgpqN0ldsaPr0Muv8h7CSS5lQU0on2\nFNLbjLsifSLV+jLsJJLGVBTSxMYdG+EIYFv7sKNIvOS2gWV91VmexJWKQpqYsXZGpOtl139pWpt1\nG5z6GOgO6hIn+gZJEzPWzIA1YaeQuNt8YmRvsGPYQSRdqSikiQ/WfQBrw04hCTHrdugOOjVV4kFF\nIQ3k7s7l8+2fQ0Xv4iipYfl5UA04+t9hJ5E0VC3sAFI2ubm5XHHFtezd+924rQ02UrN5bXbm7wwv\nmCSOZ8Bs4LRHYFXvsNNImlFRSDF79uzhX//6F/v2jfpuZO8JsPlIYGtouSTBFgI/nAH11sE3rcJO\nI2lEzUcpKDPzCODy74Y222HtKSGnkoTaCywcDF3UrbZULhWFVJe5B5rPhXX6tVjlfHQddBkNGboJ\nj1QeFYVUd9R/YdvxsLdm2Ekk0bacAF+3geNeDzuJpBEVhVTX+gNYe2bYKSQsH10P3Z4KO4WkERWF\nVNd6hvo7qsoWXwLNP4aGK8NOImlCRSGVWT60+o/2FKqy/bVgwVAdcJZKE1pRMLPVZrbAzOaZ2Zyw\ncqS0pp/CriawMzvsJBKm+VdC5xciPxJEKijM6xQc6OXu6ge4vNR0JACbO8POpnD0u6BWJKmgsJuP\ndLPZitD9mKXQ/CvhpOfDTiFpIMyi4MA7ZvaRmV0TYo4U5dpTkO8sGgTHvQE6M1kqKMzmox7uvtHM\nmgBTzWypu88onDhgwIDojO3bt6dDhw5hZAzdzJkzD3iem5tLfn4+NFwF5vDVMSElk6SyqzGs/AF0\n/AfMPXTyuHHjEp8pQQ7+G6lKFi9ezJIlSyp1naEVBXffGPy71cxeBU4FokVh4sSJYUVLOoMHD44+\n3rJlC7fffg/7cv4Nq3uhFjiJmv9TOLP4olD0M5SO0v39xcqs4t8HoTQfmVltM8sKHtcB+hDp4kti\nlfMerDo77BSSTJafC42AIz8LO4mksLCOKWQDM8xsPvAh8Lq7TwkpS8pxPFIUVvcKO4okk4LqsAA4\naUzYSSSFhVIU3H2Vu58UDJ3c/aEwcqQqb1AAVgBftg07iiSb+cCJY3XNgpRb2KekSjkUtN4Lq89G\nxxPkEFsIrlnQXdmkfFQUUlBB631qOpKSzR8GJ6oJScpHRSHFuDsFbfbpILOUbNEgaDcZauwIO4mk\nIBWFFLMqd1Xksj9dnyAl2dkU1vSEDjqtW8pORSHFzNwwk4y11dHxBCmVmpCknFQUUszM9YVFQaQU\nyy6A7IVQf03YSSTFqCikEHeP7CmsqRF2FEl2+TXh08vgxBfCTiIpRkUhhSzcspDa1WqTkZsZdhRJ\nBfOHRa5ZECkDFYUUMmXFFM5upbOOJEbrTwU3aBl2EEklKgop5O0Vb3NWq7PCjiEpw+CTYXBS2Dkk\nlagopIhd+3Yx+4vZnHmU7scsZbDgJ9ABdu/fHXYSSREqCilixpoZnNzsZLJqZIUdRVJJbmvYBJM/\nmxx2EklLx8GIAAALz0lEQVQRKgop4u0Vb9Pn2D5hx5BU9AmMXaADzhIbFYUUMWXFFBUFKZ8lkT3N\nzXmbw04iKUBFIQWsy13HxryNdG3eNewokor2woXHX8i4hel7S06pPCoKKeD1Za/zo+/9iMwMXZ8g\n5TPsxGFqQpKYqCikgEnLJtHvuH5hx5AU1iunF9t3bWfB5gVhR5Ekp6KQ5L4t+JYP1n7AuW3PDTuK\npLAMy2Bo56GM/UR7C1I6FYUkt3DnQs5odQb1atYLO4qkuCtOvIKXFr7E/oL9YUeRJKaikOTm7pyr\npiOpFO0atyOnQQ5TVkwJO4okMRWFJLa/YD/zd82nb7u+YUeRNHFF5yvUhCSlUlFIYtNXT6dxtca0\nrt867CiSJgZ2GsjbK95m686tYUeRJKWikMQmLJpA96zuYceQNNKwVkP6H9+f0fNGhx1FkpSKQpLa\nm7+XV5e+yul1Tw87iqSZm065iac+eor8gvywo0gSUlFIUlNXTKV9k/YcWf3IsKNImunaoivN6jbj\nzc/fDDuKJCEVhSQ14dMJDOw4MOwYkqZuPOVG/vLfv4QdQ5KQikIS2rVvF68ve51LOlwSdhRJU5d1\nvIy5G+fy+fbPw44iSUZFIQm9/OnL9GjVg+y62WFHkTR1RLUjuLrL1Tzy4SNhR5Eko6KQhJ6Z9wxX\nd7k67BiS5m497VbGLRzHlp1bwo4iSURFIcks3baU5V8u58ff+3HYUSTNNavbjMs6XsZjHz4WdhRJ\nIioKSeaZuc9w5YlXUj2zethRpAoYccYInvr4KXbs2RF2FEkSKgpJJG9vHs/Pf55rul4TdhSpIto2\nakvvo3vz9MdPhx1FkoSKQhJ5dt6z9MrpxTENjwk7ilQhvzzzlzw862Hy9uaFHUWSgIpCksgvyOfP\ns//MiDNGhB1FqpgTm51I76N786dZfwo7iiQBFYUkMXHJRJpnNef0lurWQhLvvl738ciHj7Bt17aw\no0jIVBSSwP6C/dzz3j38uuevw44iVdSxjY7l8o6X88D7D4QdRUKmopAEXvjkBZrWaUqfY/uEHUWq\nsJG9RjJ+0Xg+2fRJ2FEkRCoKIdu9fzf3Tr+XB3s/iJmFHUeqsCZ1mvDA2Q9w/RvXU+AFYceRkKgo\nhOw3M35D1xZdObP1mWFHEWF4l+EYplNUq7BqYQeoypZuW8oT/32C+dfPDzuKCAAZlsGovqM46/mz\n6H10b4478riwI0mCaU8hJPsL9nPt5Gv5Vc9f0bJey7DjiER1bNqRe3vdy+CJg9mbvzfsOJJgKgoh\neeD9B6ieWZ2bT7057Cgih7jxlBtpVb8VN71xE+4edhxJIBWFELz5+Zs8/fHTvNj/RTIzMsOOI3II\nM2PsRWOZs2EOf5z1x7DjSALpmEKCzd04lyv/eSWTBk2ieVbzsOOIlCirZhaTB02mx7M9yKqZxbVd\nrw07kiSAikICzf5iNhdOuJCn+z6tK5clJbSu35p/D/s3vcf0Zvf+3dxy6i06dTrNqfkoQV5b+hr9\nxvfjuQuf46LjLwo7jkjM2jZqy/Qrp/PXj//Kda9fx579e8KOJHEUSlEws/PMbKmZfW5md4aRIVHy\n9uZx21u38bO3fsakQZP40fd+FHYkkTI7uuHRzB4+m+3fbqfr012Zs35O2JEkThJeFMwsE3gcOA/o\nAAwys/aJzhFve/bv4bl5z9H+L+3Z9u025l43t1xNRosXL45DOpGyy6qZxSuXvsLd37+bfuP7MWji\nIJZuWxp2LP2NVLIwjimcCix399UAZjYBuBBYEkKWSlXgBXy04SP+ufSfPDf/OTpnd2b8gPEVulp5\nyZKU3yySRsyMQScMom+7vjz24WP0fK4nHZt2ZGjnoZzf9vxQTp7Q30jlCqMoHAWsK/L8C+C0EHKU\ni7uzJ38P23ZtY23uWtZ8vYZl25fx3w3/Zc76OTSu3ZgL213I1KFT6dS0U9hxReKibo263PX9u7i9\n++28vux1xi8az4gpI2ie1ZxuLbrRuWln2jVux1FZR9EiqwVN6jQhw3QIMxWEURRiuhKmwAvoN74f\njuPu0X8jKzj8OA9eJpZxh1tvfkE+O/bu4Js930TvZXtk7SNpU78Nreu3pm2jtlx18lU88eMnaF2/\ndSVuquLt2/c19er1PWDcnj3L2KPjf5JgNavVZECHAQzoMID8gnzmbZrH/E3zWbh5IdNWTWPDjg2s\n37GeL7/9klrValG3Rl3q1qhLnRp1qJ5RncyMTKplVCPTMsnMyIz+m2EZGKWf5VR4FtTHOR/z43E/\nLn6eUtbRvWV37u55d/nffJqyRF+taGanAyPd/bzg+V1Agbv/rsg8uoRSRKQc3L1C5wyHURSqAZ8B\nPwA2AHOAQe6uhkERkZAlvPnI3feb2c3A20AmMFoFQUQkOSR8T0FERJJXaKcDmFkjM5tqZsvMbIqZ\nNShhvmIvdDOzkWb2hZnNC4bzEpe+csRyEZ+ZPRpM/8TMTi7LsqmkgttitZktCD4HKX9V1eG2hZkd\nb2azzGy3mf28LMummgpui6r2uRgS/G0sMLOZZtY51mUP4O6hDMDvgTuCx3cCvy1mnkxgOZADVAfm\nA+2DafcAt4eVvxLef4nvrcg8PwLeDB6fBsyOddlUGiqyLYLnq4BGYb+PBG6LJkA34AHg52VZNpWG\nimyLKvq56A7UDx6fV97vizBPHO4HjAkejwGK6xAoeqGbu+8DCi90K5TKPXMd7r1BkW3k7h8CDcys\nWYzLppLybovsItNT+bNQ1GG3hbtvdfePgH1lXTbFVGRbFKpKn4tZ7p4bPP0QaBnrskWFWRSy3X1z\n8HgzkF3MPMVd6HZUkee3BLtLo0tqfkpih3tvpc3TIoZlU0lFtgVErn15x8w+MrNr4pYyMWLZFvFY\nNhlV9P1U5c/FcODN8iwb17OPzGwq0KyYSQdcMeLuXsK1CaUdBX8SuC94fD/wByIbIlXEeoQ/XX7p\nlKai2+JMd99gZk2AqWa21N1nVFK2RKvImR/pdtZIRd9PD3ffWNU+F2Z2NnAV0KOsy0Kci4K7n1PS\nNDPbbGbN3H2TmTUHthQz23qgVZHnrYhUOdw9Or+ZPQNMrpzUCVPieytlnpbBPNVjWDaVlHdbrAdw\n9w3Bv1vN7FUiu8up+scfy7aIx7LJqELvx903Bv9Wmc9FcHB5FHCeu39VlmULhdl8NAkYFjweBvyz\nmHk+Ar5nZjlmVgO4PFiOoJAU6g8sjGPWeCjxvRUxCbgColeCfx00ucWybCop97Yws9pmlhWMrwP0\nIfU+C0WV5f/24D2nqvi5KHTAtqiKnwszaw38A/iJuy8vy7IHCPFoeiPgHWAZMAVoEIxvAbxRZL7z\niVwBvRy4q8j4scAC4BMiBSU77DMEyrENDnlvwHXAdUXmeTyY/gnQ5XDbJVWH8m4L4BgiZ1PMBxZV\nhW1BpEl2HZALfAWsBepWxc9FSduiin4ungG2A/OCYU5py5Y06OI1ERGJUl+2IiISpaIgIiJRKgoi\nIhKloiAiIlEqCiIiEqWiICIiUSoKUqWZWYGZvVDkeTUz22pmqXaFvEilUFGQqm4n0NHMjgien0Ok\nCwBdwCNVkoqCSKQ3yR8HjwcB4wm6TTCzOmb2rJl9aGZzzaxfMD7HzN43s4+DoXswvpeZvWdmL5vZ\nEjN7MYw3JFJeKgoi8DdgoJnVBE4g0hd9obuBae5+GtAb+D8zq02ku/dz3L0rMBB4tMgyJwE/AzoA\nx5hZD0RSRFx7SRVJBe6+0MxyiOwlvHHQ5D5AXzMbETyvSaSXyU3A42Z2IpAPfK/IMnM86LnVzOYT\nuePVzHjlF6lMKgoiEZOAh4GziNzisaiL3f3zoiPMbCSw0d2HmlkmsLvI5D1FHuejvzNJIWo+Eol4\nFhjp7p8eNP5t4NbCJ2Z2cvCwHpG9BYh06Z0Z94QiCaCiIFWdA7j7end/vMi4wrOP7geqm9kCM1sE\n3BuMfwIYFjQPtQPyDl5nKc9Fkpa6zhYRkSjtKYiISJSKgoiIRKkoiIhIlIqCiIhEqSiIiEiUioKI\niESpKIiISJSKgoiIRP1/aoYdn8j4yjkAAAAASUVORK5CYII=\n", "text/plain": [ - "" + "" ] }, "metadata": {}, diff --git a/openmc/statepoint.py b/openmc/statepoint.py index fbe8fecd8..0e4a277f8 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -608,15 +608,6 @@ class StatePoint(object): tally.name = summary.tallies[tally_id].name tally.with_summary = True - nuclide_zaids = copy.deepcopy(tally.nuclides) - - for nuclide_zaid in nuclide_zaids: - tally.remove_nuclide(nuclide_zaid) - if nuclide_zaid == -1: - tally.add_nuclide(openmc.Nuclide('total')) - else: - tally.add_nuclide(summary.nuclides[nuclide_zaid]) - for filter in tally.filters: if filter.type == 'surface': surface_ids = [] diff --git a/openmc/tallies.py b/openmc/tallies.py index cfbe613c2..20a6af3f2 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -322,7 +322,7 @@ class Tally(object): return None n = self.num_realizations - nonzero = self.mean > 0 + nonzero = np.abs(self.mean) > 0 self._std_dev = np.zeros_like(self.mean) self._std_dev[nonzero] = np.sqrt((self.sum_sq[nonzero]/n - self.mean[nonzero]**2)/(n - 1)) From bc36dad0280a0dd6d6d82f9fde3c117cc11d8c5d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Sep 2015 10:24:22 +0700 Subject: [PATCH 75/95] Don't write cross section identifier for tally 'nuclides' dataset --- openmc/statepoint.py | 3 ++- src/state_point.F90 | 9 +++++++-- src/summary.F90 | 9 +++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 0e4a277f8..ca4fc02ab 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -414,7 +414,8 @@ class StatePoint(object): # Add all Nuclides to the Tally for name in nuclide_names: - tally.add_nuclide(name.decode()) + nuclide = openmc.Nuclide(name.decode().strip()) + tally.add_nuclide(nuclide) # Read score bins n_score_bins = self._f['{0}{1}/n_score_bins'.format(base, tally_key)].value diff --git a/src/state_point.F90 b/src/state_point.F90 index 24d2fac1b..bfbbadb57 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -42,7 +42,7 @@ contains subroutine write_state_point() integer :: i, j, k - integer :: i_list + integer :: i_list, i_xs integer :: n_order ! loop index for moment orders integer :: nm_order ! loop index for Ynm moment orders integer, allocatable :: id_array(:) @@ -283,7 +283,12 @@ contains NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins if (tally%nuclide_bins(j) > 0) then i_list = nuclides(tally%nuclide_bins(j))%listing - str_array(j) = xs_listings(i_list)%alias + i_xs = index(xs_listings(i_list)%alias, '.') + if (i_xs > 0) then + str_array(j) = xs_listings(i_list)%alias(1:i_xs - 1) + else + str_array(j) = xs_listings(i_list)%alias + end if else str_array(j) = 'total' end if diff --git a/src/summary.F90 b/src/summary.F90 index aa1ee3509..5fcf0c64e 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -456,7 +456,7 @@ contains integer(HID_T), intent(in) :: file_id integer :: i, j - integer :: i_list + integer :: i_list, i_xs integer, allocatable :: temp_array(:) ! nuclide bin array integer(HID_T) :: tallies_group integer(HID_T) :: mesh_group @@ -559,7 +559,12 @@ contains NUCLIDE_LOOP: do j = 1, t%n_nuclide_bins if (t%nuclide_bins(j) > 0) then i_list = nuclides(t%nuclide_bins(j))%listing - str_array(j) = xs_listings(i_list)%alias + i_xs = index(xs_listings(i_list)%alias, '.') + if (i_xs > 0) then + str_array(j) = xs_listings(i_list)%alias(1:i_xs - 1) + else + str_array(j) = xs_listings(i_list)%alias + end if else str_array(j) = 'total' end if From 75e37efac3d7c0b1ee1880ad89cd180a949bdea1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Sep 2015 10:29:36 +0700 Subject: [PATCH 76/95] Update Jupyter notebooks again. --- .../examples/pandas-dataframes.ipynb | 118 +++++++++--------- .../pythonapi/examples/tally-arithmetic.ipynb | 28 ++--- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/docs/source/pythonapi/examples/pandas-dataframes.ipynb b/docs/source/pythonapi/examples/pandas-dataframes.ipynb index 565e6c73a..cb63e2ac3 100644 --- a/docs/source/pythonapi/examples/pandas-dataframes.ipynb +++ b/docs/source/pythonapi/examples/pandas-dataframes.ipynb @@ -374,7 +374,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JFQI2Mgck1R0AAAPZSURBVGje7Zs7buMwEIZ9iey5\n0gyNjQpXKTYudIScgkdQYTfut1idwkdQkQNsYQO2Qj0sPiVK+mlQDmwgwIcgg8Cc4fCTSK5W4OeF\nkM8rHv+2I/rgxPZEPZgR7XtQxKdXYuUXJSUnBQ/9WCgo4vOSJ+WFUvF7E08mlia+rn7VcKXP8sRs\nzFX8b2MdX2y6v1Tw6MZUw4H4ojfIjD8mvn/qRL5p4+vvlMqvp2EhR8WBzfiz20hXORmP9fi/bM9E\neUFvV5H/0yRkeSbiGRfFJErxD9ENdz7Mbhig/h89fvtFdMiI/ePUIXV4lXju8K3DKv9NThOZ3q2K\nmUy6grxFES8rjeyic+FFQav+ncg3fXjH+Ts+/iibztFqOiZuZP/Z3OafPX40NGgST2r+uvQkXXp6\ncKvmr+r0e1Eef5um3+JHP3IFF1D/seNZJgaDmvY0Gav1s+2f1fqpIcublfKGt6apotG/NVx3SInW\ntLX+7Vg/Pv1YqOsnun6JSVdOXT/X7vk75f938QP+8OmSBs0fXtymMhJbf8qlPynYmpKCh7OB1fzN\nalOj1sl0ZAruHLiA+RM73pDe/VjMVP89+aTXwjyc/x5n+u991895/utrJTy8/06TXh0r/5JOa2Jm\nYmqi4r/vUm/H4wLmT+z4anhr05X+q6KUXhtzr/9qSff5L5uMT//V/NdU4YuBTPa/8P67l/6r44ds\n+hYuoP5jx9ciy6XTWlibBrmx8V/TdMfjkP+6pOsu/lvM9N90sf7r+f6m/65n+S8p/itN15v0UkW3\n/+48+PRfJX6S9Joo4g+G/1qYG9KroqP/WypcuvyXPf13wH89/hHef7MB6R3Cqn55U4rv4kfH3zaS\ngQuYP7HjVf89tXrbO+hfLdr+Ozv/SP1dgtQ/Ov8C+i/3+q/Zf2D/HWi6bjT6rym9I/v/03/b+LHS\n4cTg/utTsV7/net/Afzz4f0XGX84/2j9xZ4/sePR/of2X7D/o+vPo/sv6h9B/Bfxr9j1Hz2eN/hO\n8/wfff4A848+f/1A/530/I0+/8PvH9D3H9HnT+R49P0b+v4PfP/4E/wXfP8Mvf9G37/D/ovuP8Se\nP7Hj0f0vdP8tqP9O339cyv7p3P1fdP8Z3v9G999j13/seMax8x/o+ZN7+O+E8zdP/8XOf8Hnz9Dz\nb7HnT+x49PxlCp7/BM+fOv13wvnXBfivt2lMvD8TyH/Hnb+Gz3+j589jz5/Y8ej9h4D+W7qQmf57\nefqv239n3T+C7z+h969i13/seMax+3/o/cMcu/8Y2H9n3p+J6r98pv8m4fwXuH+M3n+OO3++AX9c\nlR+4PhbRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA5LTIxVDA5OjQ2OjQyKzA3OjAwIbcawwAA\nACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wOS0yMVQwOTo0Njo0MiswNzowMFDqon8AAAAASUVORK5C\nYII=\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JFQMbBgd4EXAAAALKSURBVGje7dpLcqQwDAbgHHE2\nYeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\nnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\nvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\ndwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\nACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\nvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\nQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTUtMDktMjFUMTA6MjU6\nMjYrMDc6MDAKj62JAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA5LTIxVDEwOjI1OjI2KzA3OjAw\ne9IVNQAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] @@ -564,7 +564,7 @@ " License: http://mit-crpg.github.io/openmc/license.html\n", " Version: 0.7.0\n", " Git SHA1: b167d70c877c516deca785801b9fa6f53fb0985b\n", - " Date/Time: 2015-09-21 09:54:51\n", + " Date/Time: 2015-09-21 10:27:06\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -631,20 +631,20 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 4.0200E-01 seconds\n", - " Reading cross sections = 1.3900E-01 seconds\n", - " Total time in simulation = 1.3557E+01 seconds\n", - " Time in transport only = 1.3542E+01 seconds\n", - " Time in inactive batches = 1.4020E+00 seconds\n", - " Time in active batches = 1.2155E+01 seconds\n", + " Total time for initialization = 4.4100E-01 seconds\n", + " Reading cross sections = 1.7900E-01 seconds\n", + " Total time in simulation = 1.2656E+01 seconds\n", + " Time in transport only = 1.2642E+01 seconds\n", + " Time in inactive batches = 2.0300E+00 seconds\n", + " Time in active batches = 1.0626E+01 seconds\n", " Time synchronizing fission bank = 4.0000E-03 seconds\n", " Sampling source sites = 3.0000E-03 seconds\n", " SEND/RECV source sites = 1.0000E-03 seconds\n", " Time accumulating tallies = 0.0000E+00 seconds\n", - " Total time for finalization = 1.0000E-03 seconds\n", - " Total time elapsed = 1.3972E+01 seconds\n", - " Calculation Rate (inactive) = 8915.83 neutrons/second\n", - " Calculation Rate (active) = 3085.15 neutrons/second\n", + " Total time for finalization = 0.0000E+00 seconds\n", + " Total time elapsed = 1.3110E+01 seconds\n", + " Calculation Rate (inactive) = 6157.64 neutrons/second\n", + " Calculation Rate (active) = 3529.08 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", @@ -1085,7 +1085,7 @@ "data": { "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1108,7 +1108,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 27, @@ -1119,7 +1119,7 @@ "data": { "image/png": "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\nEvx/rHWCrxSlro8AAAAASUVORK5CYII=\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1164,7 +1164,7 @@ "\tName =\tcell tally\n", "\tFilters =\t\n", " \t\tcell\t[10000]\n", - "\tNuclides =\tU-235.71c U-238.71c \n", + "\tNuclides =\tU-235 U-238 \n", "\tScores =\t[u'scatter-Y0,0', u'scatter-Y1,-1', u'scatter-Y1,0', u'scatter-Y1,1', u'scatter-Y2,-2', u'scatter-Y2,-1', u'scatter-Y2,0', u'scatter-Y2,1', u'scatter-Y2,2']\n", "\tEstimator =\tanalog\n", "\n" @@ -1213,7 +1213,7 @@ " \n", " 0\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y0,0\n", " 0.036453\n", " 0.001219\n", @@ -1221,7 +1221,7 @@ " \n", " 1\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y1,-1\n", " 0.000302\n", " 0.000314\n", @@ -1229,7 +1229,7 @@ " \n", " 2\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y1,0\n", " -0.000006\n", " 0.000347\n", @@ -1237,7 +1237,7 @@ " \n", " 3\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y1,1\n", " 0.000244\n", " 0.000286\n", @@ -1245,7 +1245,7 @@ " \n", " 4\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y2,-2\n", " 0.000184\n", " 0.000211\n", @@ -1253,7 +1253,7 @@ " \n", " 5\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y2,-1\n", " 0.000067\n", " 0.000173\n", @@ -1261,7 +1261,7 @@ " \n", " 6\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y2,0\n", " 0.000353\n", " 0.000210\n", @@ -1269,7 +1269,7 @@ " \n", " 7\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y2,1\n", " -0.000266\n", " 0.000263\n", @@ -1277,7 +1277,7 @@ " \n", " 8\n", " 10000\n", - " U-235.71c\n", + " U-235\n", " scatter-Y2,2\n", " -0.000246\n", " 0.000153\n", @@ -1285,7 +1285,7 @@ " \n", " 9\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y0,0\n", " 2.315893\n", " 0.008243\n", @@ -1293,7 +1293,7 @@ " \n", " 10\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y1,-1\n", " -0.022028\n", " 0.002316\n", @@ -1301,7 +1301,7 @@ " \n", " 11\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y1,0\n", " -0.003426\n", " 0.002651\n", @@ -1309,7 +1309,7 @@ " \n", " 12\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y1,1\n", " 0.026620\n", " 0.002084\n", @@ -1317,7 +1317,7 @@ " \n", " 13\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y2,-2\n", " -0.001295\n", " 0.001627\n", @@ -1325,7 +1325,7 @@ " \n", " 14\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y2,-1\n", " 0.000759\n", " 0.001426\n", @@ -1333,7 +1333,7 @@ " \n", " 15\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y2,0\n", " 0.005513\n", " 0.001983\n", @@ -1341,7 +1341,7 @@ " \n", " 16\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y2,1\n", " 0.000431\n", " 0.001862\n", @@ -1349,7 +1349,7 @@ " \n", " 17\n", " 10000\n", - " U-238.71c\n", + " U-238\n", " scatter-Y2,2\n", " -0.001962\n", " 0.001222\n", @@ -1359,26 +1359,26 @@ "" ], "text/plain": [ - " cell nuclide score mean std. dev.\n", - "bin \n", - "0 10000 U-235.71c scatter-Y0,0 0.036453 0.001219\n", - "1 10000 U-235.71c scatter-Y1,-1 0.000302 0.000314\n", - "2 10000 U-235.71c scatter-Y1,0 -0.000006 0.000347\n", - "3 10000 U-235.71c scatter-Y1,1 0.000244 0.000286\n", - "4 10000 U-235.71c scatter-Y2,-2 0.000184 0.000211\n", - "5 10000 U-235.71c scatter-Y2,-1 0.000067 0.000173\n", - "6 10000 U-235.71c scatter-Y2,0 0.000353 0.000210\n", - "7 10000 U-235.71c scatter-Y2,1 -0.000266 0.000263\n", - "8 10000 U-235.71c scatter-Y2,2 -0.000246 0.000153\n", - "9 10000 U-238.71c scatter-Y0,0 2.315893 0.008243\n", - "10 10000 U-238.71c scatter-Y1,-1 -0.022028 0.002316\n", - "11 10000 U-238.71c scatter-Y1,0 -0.003426 0.002651\n", - "12 10000 U-238.71c scatter-Y1,1 0.026620 0.002084\n", - "13 10000 U-238.71c scatter-Y2,-2 -0.001295 0.001627\n", - "14 10000 U-238.71c scatter-Y2,-1 0.000759 0.001426\n", - "15 10000 U-238.71c scatter-Y2,0 0.005513 0.001983\n", - "16 10000 U-238.71c scatter-Y2,1 0.000431 0.001862\n", - "17 10000 U-238.71c scatter-Y2,2 -0.001962 0.001222" + " cell nuclide score mean std. dev.\n", + "bin \n", + "0 10000 U-235 scatter-Y0,0 0.036453 0.001219\n", + "1 10000 U-235 scatter-Y1,-1 0.000302 0.000314\n", + "2 10000 U-235 scatter-Y1,0 -0.000006 0.000347\n", + "3 10000 U-235 scatter-Y1,1 0.000244 0.000286\n", + "4 10000 U-235 scatter-Y2,-2 0.000184 0.000211\n", + "5 10000 U-235 scatter-Y2,-1 0.000067 0.000173\n", + "6 10000 U-235 scatter-Y2,0 0.000353 0.000210\n", + "7 10000 U-235 scatter-Y2,1 -0.000266 0.000263\n", + "8 10000 U-235 scatter-Y2,2 -0.000246 0.000153\n", + "9 10000 U-238 scatter-Y0,0 2.315893 0.008243\n", + "10 10000 U-238 scatter-Y1,-1 -0.022028 0.002316\n", + "11 10000 U-238 scatter-Y1,0 -0.003426 0.002651\n", + "12 10000 U-238 scatter-Y1,1 0.026620 0.002084\n", + "13 10000 U-238 scatter-Y2,-2 -0.001295 0.001627\n", + "14 10000 U-238 scatter-Y2,-1 0.000759 0.001426\n", + "15 10000 U-238 scatter-Y2,0 0.005513 0.001983\n", + "16 10000 U-238 scatter-Y2,1 0.000431 0.001862\n", + "17 10000 U-238 scatter-Y2,2 -0.001962 0.001222" ] }, "execution_count": 29, @@ -1421,7 +1421,7 @@ "# Get the standard deviations for two of the spherical harmonic\n", "# scattering reaction rates \n", "data = tally.get_values(scores=['scatter-Y2,2', 'scatter-Y0,0'], \n", - " nuclides=['U-238.71c', 'U-235.71c'], value='std_dev')\n", + " nuclides=['U-238', 'U-235'], value='std_dev')\n", "print(data)" ] }, @@ -2376,7 +2376,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 38, @@ -2387,7 +2387,7 @@ "data": { "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -2414,7 +2414,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 39, @@ -2425,7 +2425,7 @@ "data": { "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, diff --git a/docs/source/pythonapi/examples/tally-arithmetic.ipynb b/docs/source/pythonapi/examples/tally-arithmetic.ipynb index 0ff2e5f58..2f32f3d9a 100644 --- a/docs/source/pythonapi/examples/tally-arithmetic.ipynb +++ b/docs/source/pythonapi/examples/tally-arithmetic.ipynb @@ -358,7 +358,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JEAsiA0Bbyc8AAALKSURBVGje7dpLcqQwDAbgHHE2\nYeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\nnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\nvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\ndwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\nACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\nvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\nQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTUtMDktMTZUMTg6MzE6\nMzUrMDc6MDDLyLisAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA5LTE2VDE4OjMxOjM1KzA3OjAw\nupUAEAAAAABJRU5ErkJggg==\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JFQMZGiFPL70AAALKSURBVGje7dpLcqQwDAbgHHE2\nYeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\nnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\nvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\ndwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\nACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\nvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\nQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTUtMDktMjFUMTA6MDg6\nNTcrMDc6MDALr51VAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA5LTIxVDEwOjA4OjU3KzA3OjAw\nevIl6QAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] @@ -569,8 +569,8 @@ " Copyright: 2011-2015 Massachusetts Institute of Technology\n", " License: http://mit-crpg.github.io/openmc/license.html\n", " Version: 0.7.0\n", - " Git SHA1: 36a516ed8125ab8a86d8c9b3aee4bd4bc2db859c\n", - " Date/Time: 2015-09-16 18:34:04\n", + " Git SHA1: b167d70c877c516deca785801b9fa6f53fb0985b\n", + " Date/Time: 2015-09-21 10:25:26\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -625,20 +625,20 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 5.2100E-01 seconds\n", - " Reading cross sections = 1.7200E-01 seconds\n", - " Total time in simulation = 1.5669E+01 seconds\n", - " Time in transport only = 1.5663E+01 seconds\n", - " Time in inactive batches = 2.1160E+00 seconds\n", - " Time in active batches = 1.3553E+01 seconds\n", - " Time synchronizing fission bank = 0.0000E+00 seconds\n", - " Sampling source sites = 0.0000E+00 seconds\n", + " Total time for initialization = 9.1800E-01 seconds\n", + " Reading cross sections = 6.5800E-01 seconds\n", + " Total time in simulation = 1.7037E+01 seconds\n", + " Time in transport only = 1.7024E+01 seconds\n", + " Time in inactive batches = 2.8600E+00 seconds\n", + " Time in active batches = 1.4177E+01 seconds\n", + " Time synchronizing fission bank = 4.0000E-03 seconds\n", + " Sampling source sites = 4.0000E-03 seconds\n", " SEND/RECV source sites = 0.0000E+00 seconds\n", " Time accumulating tallies = 0.0000E+00 seconds\n", " Total time for finalization = 1.0000E-03 seconds\n", - " Total time elapsed = 1.6203E+01 seconds\n", - " Calculation Rate (inactive) = 5907.37 neutrons/second\n", - " Calculation Rate (active) = 2766.91 neutrons/second\n", + " Total time elapsed = 1.7971E+01 seconds\n", + " Calculation Rate (inactive) = 4370.63 neutrons/second\n", + " Calculation Rate (active) = 2645.13 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", From 1453ec18bd9ada26c7b246d069f48450d19598fa Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Sep 2015 10:48:25 +0700 Subject: [PATCH 77/95] Added short section on DBRC in documentation. Closes #433. --- docs/source/methods/physics.rst | 38 +++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/docs/source/methods/physics.rst b/docs/source/methods/physics.rst index d0a6a2c99..7eedc4e6e 100644 --- a/docs/source/methods/physics.rst +++ b/docs/source/methods/physics.rst @@ -1027,14 +1027,19 @@ probability distribution function can be found by integrating equation Let us call the normalization factor in the denominator of equation :eq:`target-pdf-1` :math:`C`. -It is normally assumed that :math:`\sigma (v_r)` is constant over the range of + +Contant Cross Section Model +--------------------------- + +It is often assumed that :math:`\sigma (v_r)` is constant over the range of relative velocities of interest. This is a good assumption for almost all cases since the elastic scattering cross section varies slowly with velocity for light nuclei, and for heavy nuclei where large variations can occur due to resonance scattering, the moderating effect is rather small. Nonetheless, this assumption may cause incorrect answers in systems with low-lying resonances that can cause a significant amount of up-scatter that would be ignored by this assumption -(e.g. U-238 in commercial light-water reactors). Nevertheless, with this +(e.g. U-238 in commercial light-water reactors). We will revisit this assumption +later in :ref:`energy_dependent_xs_model`. For now, continuing with the assumption, we write :math:`\sigma (v_r) = \sigma_s` which simplifies :eq:`target-pdf-1` to @@ -1232,6 +1237,35 @@ If is not accepted, then we repeat the process and resample a target speed and cosine until a combination is found that satisfies equation :eq:`freegas-accept-2`. +.. _energy_dependent_xs_model: + +Energy-Dependent Cross Section Model +------------------------------------ + +As was noted earlier, assuming that the elastic scattering cross section is +constant in :eq:`reaction-rate` is not strictly correct, especially when +low-lying resonances are present in the cross sections for heavy nuclides. To +correctly account for energy dependence of the scattering cross section entails +performing another rejection step. The most common method is to sample +:math:`\mu` and :math:`v_T` as in the constant cross section approximation and +then perform a rejection on the ratio of the 0 K elastic scattering cross +section at the relative velocity to the maximum 0 K elastic scattering cross +section over the range of velocities considered: + +.. math:: + :label: dbrc + + p_{dbrc} = \frac{\sigma_s(v_r)}{\sigma_{s,max}} + +where it should be noted that the maximum is taken over the range :math:`[v_n - +4/\beta, 4_n + 4\beta]`. This method is known as Doppler broadening rejection +correction (DBRC) and was first introduced by `Becker et al.`_. OpenMC has an +implementation of DBRC as well as an accelerated sampling method that are +described fully in `Walsh et al.`_ + +.. _Becker et al.: http://dx.doi.org/10.1016/j.anucene.2008.12.001 +.. _Walsh et al.: http://dx.doi.org/10.1016/j.anucene.2014.01.017 + .. _sab_tables: ------------ From 7d7f9463b2e5fc67456f61ef174ec643f6b0cebd Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Sep 2015 10:57:19 +0700 Subject: [PATCH 78/95] Fix typo in documentation --- docs/source/methods/physics.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/methods/physics.rst b/docs/source/methods/physics.rst index 7eedc4e6e..e25057488 100644 --- a/docs/source/methods/physics.rst +++ b/docs/source/methods/physics.rst @@ -1028,8 +1028,8 @@ Let us call the normalization factor in the denominator of equation :eq:`target-pdf-1` :math:`C`. -Contant Cross Section Model ---------------------------- +Constant Cross Section Model +---------------------------- It is often assumed that :math:`\sigma (v_r)` is constant over the range of relative velocities of interest. This is a good assumption for almost all cases From 397d5fe269eecc2fe9acef5b70f202b3b4ac3c82 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Sep 2015 11:34:03 +0700 Subject: [PATCH 79/95] Update file format documentation. Use score_bins instead of scores. --- docs/source/usersguide/output/statepoint.rst | 42 +++++----- docs/source/usersguide/output/summary.rst | 80 ++------------------ openmc/statepoint.py | 2 +- openmc/summary.py | 2 +- src/state_point.F90 | 3 +- src/summary.F90 | 3 +- 6 files changed, 28 insertions(+), 104 deletions(-) diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index 66fcce27f..42d923351 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -39,7 +39,7 @@ The current revision of the statepoint file format is 13. Pseudo-random number generator seed. -**/run_mode** (*int*) +**/run_mode** (*char[]*) Run mode used. A value of 1 indicates a fixed-source run and a value of 2 indicates an eigenvalue run. @@ -142,14 +142,10 @@ if (run_mode == MODE_EIGENVALUE) Unique identifier of the mesh. - **/tallies/meshes/mesh i/type** (*int*) + **/tallies/meshes/mesh i/type** (*char[]*) Type of mesh. - **/tallies/meshes/mesh i/n_dimension** (*int*) - - Number of dimensions for mesh (2 or 3). - **/tallies/meshes/mesh i/dimension** (*int*) Number of mesh cells in each dimension. @@ -180,9 +176,9 @@ if (run_mode == MODE_EIGENVALUE) *do i = 1, n_tallies* - **/tallies/tally i/estimator** (*int*) + **/tallies/tally i/estimator** (*char[]*) - Type of tally estimator: analog (1) or tracklength (2). + Type of tally estimator. **/tallies/tally i/n_realizations** (*int*) @@ -194,7 +190,7 @@ if (run_mode == MODE_EIGENVALUE) *do j = 1, tallies(i) % n_filters* - **/tallies/tally i/filter j/type** (*int*) + **/tallies/tally i/filter j/type** (*char[]*) Type of tally filter. @@ -214,28 +210,32 @@ if (run_mode == MODE_EIGENVALUE) Number of nuclide bins. If none are specified, this is just one. - **/tallies/tally i/nuclides** (*int[]*) + **/tallies/tally i/nuclides** (*char[][]*) - Values of specified nuclide bins (ZAID identifiers) + Values of specified nuclide bins. **/tallies/tally i/n_score_bins** (*int*) - Number of scoring bins. + Number of scores. - **/tallies/tally i/score_bins** (*int*) + **/tallies/tally i/score_bins** (*char[][]*) - Values of specified scoring bins (e.g. SCORE_FLUX). + Values of specified scores. - **/tallies/tally i/n_user_score_bins** (*int*) + **/tallies/tally i/n_user_scores** (*int*) - Number of scoring bins without accounting for those added by - expansions, e.g. scatter-PN. + Number of scores without accounting for those added by expansions, + e.g. scatter-PN. **/tallies/tally i/moment_orders** (*char[][]*) Tallying moment orders for Legendre and spherical harmonic tally expansions (*e.g.*, 'P2', 'Y1,2', etc.). + **/tallies/tally i/results** (Compound type) + + Accumulated sum and sum-of-squares for each bin of the i-th tally. + **/source_present** (*int*) Flag indicated if source bank is present in the file @@ -257,13 +257,7 @@ if (run_mode == MODE_EIGENVALUE) Flag indicated if tallies are present in the file. -*do i = 1, n_tallies* - -**/tallies/tally i/results** (Compound type) - - Accumulated sum and sum-of-squares for each bin of the tally i-th tally - -if (run_mode == MODE_EIGENVALUE and source_present) +if (run_mode == 'k-eigenvalue' and source_present > 0) **/source_bank** (Compound type) diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst index f924cb1d6..78cf9fbd5 100644 --- a/docs/source/usersguide/output/summary.rst +++ b/docs/source/usersguide/output/summary.rst @@ -75,12 +75,10 @@ do i = 1, n_cells **/geometry/cells/cell /universe** (*int*) - **/geometry/cells/cell /fill_type** (*int*) + **/geometry/cells/cell /fill_type** (*char[]*) **/geometry/cells/cell /material** (*int*) - **/geometry/cells/cell /fill** (*int*) - **/geometry/cells/cell /maps** (*int*) **/geometry/cells/cell /offset** (*int[]*) @@ -109,10 +107,6 @@ do i = 1, n_surfaces **/geometry/surfaces/surface /coefficients** (*double[]*) - **/geometry/surfaces/surface /neighbors_positive** (*int[]*) - - **/geometry/surfaces/surface /neighbors_negative** (*int[]*) - **/geometry/surfaces/surface /boundary_condition** (*char[]*) end do @@ -177,12 +171,6 @@ do i = 1, n_materials **/materials/material /nuclide_densities** (*double[]*) - **/materials/material /n_sab** (*int*) - - **/materials/material /i_sab_nuclides** (*int*) - - **/materials/material /i_sab_tables** (*int*) - **/materials/material /sab_names** (*char[][]*) end do @@ -195,9 +183,7 @@ do i = 1, n_meshes **/tallies/mesh /index** (*int*) - **/tallies/mesh /type** (*int*) - - **/tallies/mesh /n_dimension** (*int*) + **/tallies/mesh /type** (*char[]*) **/tallies/mesh /dimension** (*int[]*) @@ -223,7 +209,7 @@ do i = 1, n_tallies do j = 1, n_filters - **/tallies/tally /filter j/type** (*int*) + **/tallies/tally /filter j/type** (*char[]*) **/tallies/tally /filter j/n_bins** (*int*) @@ -233,66 +219,12 @@ do i = 1, n_tallies end do - **/tallies/tally /n_nuclide_bins** (*int*) + **/tallies/tally /n_nuclides** (*int*) - **/tallies/tally /nuclide_bins** (*int[]*) + **/tallies/tally /nuclides** (*char[][]*) **/tallies/tally /n_score_bins** (*int*) - **/tallies/tally /score_bins** (*int[]*) - -end do - -**/nuclides/n_nuclides** (*int*) - -do i = 1, n_nuclides - - **/nuclides//index** (*int*) - - **/nuclides//zaid** (*int*) - - **/nuclides//alias** (*char[]*) - - **/nuclides//awr** (*double*) - - **/nuclides//kT** (*double*) - - **/nuclides//n_grid** (*int*) - - **/nuclides//n_reactions** (*int*) - - **/nuclides//n_fission** (*int*) - - **/nuclides//size_xs** (*int*) - - do j = 1, n_reactions - - **/nuclides//reactions//Q_value** (*double*) - - **/nuclides//reactions//multiplicity** (*int*) - - **/nuclides//reactions//threshold** (*double*) - - **/nuclides//reactions//size_angle** (*int*) - - **/nuclides//reactions//size_energy** (*int*) - - end do - - **/nuclides//urr_n_energy** (*int*) - - **/nuclides//urr_n_prob** (*int*) - - **/nuclides//urr_interp** (*int*) - - **/nuclides//urr_inelastic** (*int*) - - **/nuclides//urr_absorption** (*int*) - - **/nuclides//urr_min_E** (*double*) - - **/nuclides//urr_max_E** (*double*) - - **/nuclides//size_total** (*int*) + **/tallies/tally /score_bins** (*char[][]*) end do diff --git a/openmc/statepoint.py b/openmc/statepoint.py index ca4fc02ab..f848fe1e7 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -422,7 +422,7 @@ class StatePoint(object): tally.num_score_bins = n_score_bins - scores = self._f['{0}{1}/scores'.format( + scores = self._f['{0}{1}/score_bins'.format( base, tally_key)].value n_user_scores = self._f['{0}{1}/n_user_score_bins' .format(base, tally_key)].value diff --git a/openmc/summary.py b/openmc/summary.py index f599289af..10470bb8e 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -505,7 +505,7 @@ class Summary(object): tally = openmc.Tally(tally_id, tally_name) # Read score metadata - scores = self._f['{0}/scores'.format(subbase)].value + scores = self._f['{0}/score_bins'.format(subbase)].value for score in scores: tally.add_score(score.decode()) num_score_bins = self._f['{0}/n_score_bins'.format(subbase)][...] diff --git a/src/state_point.F90 b/src/state_point.F90 index bfbbadb57..700d51b1b 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -344,8 +344,7 @@ contains str_array(j) = reaction_name(tally%score_bins(j)) end select end do - call write_dataset(tally_group, "scores", str_array) - call write_dataset(tally_group, "score_bins", tally%score_bins) + call write_dataset(tally_group, "score_bins", str_array) call write_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) deallocate(str_array) diff --git a/src/summary.F90 b/src/summary.F90 index 5fcf0c64e..229fda535 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -623,8 +623,7 @@ contains str_array(j) = reaction_name(t%score_bins(j)) end select end do - call write_dataset(tally_group, "scores", str_array) - call write_dataset(tally_group, "score_bins", t%score_bins) + call write_dataset(tally_group, "score_bins", str_array) deallocate(str_array) From 23427ceccdf906f2bd28e9e3a5761beb9db19cf4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Sep 2015 11:43:29 +0700 Subject: [PATCH 80/95] Get rid of n_nuclides dataset in summary/statepoint --- docs/source/usersguide/output/statepoint.rst | 4 ---- docs/source/usersguide/output/summary.rst | 2 -- openmc/statepoint.py | 4 +--- src/state_point.F90 | 2 -- src/summary.F90 | 3 --- 5 files changed, 1 insertion(+), 14 deletions(-) diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index 42d923351..b9898ea5d 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -206,10 +206,6 @@ if (run_mode == MODE_EIGENVALUE) Value for each filter bin of this type. - **/tallies/tally i/n_nuclides** (*int*) - - Number of nuclide bins. If none are specified, this is just one. - **/tallies/tally i/nuclides** (*char[][]*) Values of specified nuclide bins. diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst index 78cf9fbd5..453a48d98 100644 --- a/docs/source/usersguide/output/summary.rst +++ b/docs/source/usersguide/output/summary.rst @@ -219,8 +219,6 @@ do i = 1, n_tallies end do - **/tallies/tally /n_nuclides** (*int*) - **/tallies/tally /nuclides** (*char[][]*) **/tallies/tally /n_score_bins** (*int*) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index f848fe1e7..c1be20126 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -408,8 +408,6 @@ class StatePoint(object): tally.add_filter(filter) # Read Nuclide bins - n_nuclides = self._f['{0}{1}/n_nuclides'.format(base, tally_key)].value - nuclide_names = self._f['{0}{1}/nuclides'.format(base, tally_key)].value # Add all Nuclides to the Tally @@ -430,7 +428,7 @@ class StatePoint(object): # Compute and set the filter strides for i in range(n_filters): filter = tally.filters[i] - filter.stride = n_score_bins * n_nuclides + filter.stride = n_score_bins * len(nuclide_names) for j in range(i+1, n_filters): filter.stride *= tally.filters[j].num_bins diff --git a/src/state_point.F90 b/src/state_point.F90 index 700d51b1b..fbdbdbeba 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -276,8 +276,6 @@ contains call close_group(filter_group) end do FILTER_LOOP - call write_dataset(tally_group, "n_nuclides", tally%n_nuclide_bins) - ! Set up nuclide bin array and then write allocate(str_array(tally%n_nuclide_bins)) NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins diff --git a/src/summary.F90 b/src/summary.F90 index 229fda535..d01d1b4da 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -551,9 +551,6 @@ contains call close_group(filter_group) end do FILTER_LOOP - ! Write number of nuclide bins - call write_dataset(tally_group, "n_nuclides", t%n_nuclide_bins) - ! Create temporary array for nuclide bins allocate(str_array(t%n_nuclide_bins)) NUCLIDE_LOOP: do j = 1, t%n_nuclide_bins From dd5b288b030e7d1c90ee3a32f727a4629a1a27d1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 23 Sep 2015 10:17:30 +0700 Subject: [PATCH 81/95] Remove unused variable temp_array --- src/summary.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/summary.F90 b/src/summary.F90 index d01d1b4da..d80f35748 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -457,7 +457,6 @@ contains integer :: i, j integer :: i_list, i_xs - integer, allocatable :: temp_array(:) ! nuclide bin array integer(HID_T) :: tallies_group integer(HID_T) :: mesh_group integer(HID_T) :: tally_group From 759f96c9e05f6bcc8ab588b93c1ddbda2edb6e9e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 25 Sep 2015 10:40:50 +0700 Subject: [PATCH 82/95] Complete documentation of summary file format, including suggestions from @wbinventor. --- docs/source/usersguide/input.rst | 3 +- docs/source/usersguide/output/statepoint.rst | 95 +++--- docs/source/usersguide/output/summary.rst | 292 +++++++++++++------ src/summary.F90 | 1 + 4 files changed, 254 insertions(+), 137 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 833cd99b2..b4d153f18 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1426,8 +1426,7 @@ a separate element with the tag name ````. This element has the following attributes/sub-elements: :type: - The type of structured mesh. Valid options include "rectangular" and - "hexagonal". + The type of structured mesh. The only valid option is "regular". :dimension: The number of mesh cells in each direction. diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index b9898ea5d..02f4fdcf3 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -56,7 +56,7 @@ The current revision of the statepoint file format is 13. The number of batches already simulated. -if (run_mode == MODE_EIGENVALUE) +if run_mode == 'k-eigenvalue': **/n_inactive** (*int*) @@ -136,31 +136,29 @@ if (run_mode == MODE_EIGENVALUE) User-identified unique ID of each mesh -*do i = 1, n_meshes* +**/tallies/meshes/mesh /id** (*int*) - **/tallies/meshes/mesh i/id** (*int*) + Unique identifier of the mesh. - Unique identifier of the mesh. +**/tallies/meshes/mesh /type** (*char[]*) - **/tallies/meshes/mesh i/type** (*char[]*) + Type of mesh. - Type of mesh. +**/tallies/meshes/mesh /dimension** (*int*) - **/tallies/meshes/mesh i/dimension** (*int*) + Number of mesh cells in each dimension. - Number of mesh cells in each dimension. +**/tallies/meshes/mesh /lower_left** (*double[]*) - **/tallies/meshes/mesh i/lower_left** (*double[]*) + Coordinates of lower-left corner of mesh. - Coordinates of lower-left corner of mesh. +**/tallies/meshes/mesh /upper_right** (*double[]*) - **/tallies/meshes/mesh i/upper_right** (*double[]*) + Coordinates of upper-right corner of mesh. - Coordinates of upper-right corner of mesh. +**/tallies/meshes/mesh /width** (*double[]*) - **/tallies/meshes/mesh i/width** (*double[]*) - - Width of each mesh cell in each dimension. + Width of each mesh cell in each dimension. **/tallies/n_tallies** (*int*) @@ -174,63 +172,66 @@ if (run_mode == MODE_EIGENVALUE) User-identified unique ID of each tally. -*do i = 1, n_tallies* +**/tallies/tally /estimator** (*char[]*) - **/tallies/tally i/estimator** (*char[]*) + Type of tally estimator, either 'analog', 'tracklength', or 'collision'. - Type of tally estimator. +**/tallies/tally /n_realizations** (*int*) - **/tallies/tally i/n_realizations** (*int*) + Number of realizations. - Number of realizations. +**/tallies/tally /n_filters** (*int*) - **/tallies/tally i/n_filters** (*int*) + Number of filters used. - Number of filters used. +**/tallies/tally /filter /type** (*char[]*) - *do j = 1, tallies(i) % n_filters* + Type of the j-th filter. Can be 'universe', 'material', 'cell', 'cellborn', + 'surface', 'mesh', 'energy', 'energyout', or 'distribcell'. - **/tallies/tally i/filter j/type** (*char[]*) +**/tallies/tally /filter /offset** (*int*) - Type of tally filter. + Filter offset (used for distribcell filter). - **/tallies/tally i/filter j/offset** (*int*) +**/tallies/tally /filter /n_bins** (*int*) - Filter offset (used for distribcell). + Number of bins for the j-th filter. - **/tallies/tally i/filter j/n_bins** (*int*) +**/tallies/tally /filter /bins** (*int[]* or *double[]*) - Number of bins for filter. + Value for each filter bin of this type. - **/tallies/tally i/filter j/bins** (*int[]* or *double[]*) +**/tallies/tally /nuclides** (*char[][]*) - Value for each filter bin of this type. + Array of nuclides to tally. Note that if no nuclide is specified in the user + input, a single 'total' nuclide appears here. - **/tallies/tally i/nuclides** (*char[][]*) +**/tallies/tally /n_score_bins** (*int*) - Values of specified nuclide bins. + Number of scoring bins for a single nuclide. In general, this can be greater + than the number of user-specified scores since each score might have + multiple scoring bins, e.g., scatter-PN. - **/tallies/tally i/n_score_bins** (*int*) +**/tallies/tally /score_bins** (*char[][]*) - Number of scores. + Values of specified scores. - **/tallies/tally i/score_bins** (*char[][]*) +**/tallies/tally /n_user_scores** (*int*) - Values of specified scores. + Number of scores without accounting for those added by expansions, + e.g. scatter-PN. - **/tallies/tally i/n_user_scores** (*int*) +**/tallies/tally /moment_orders** (*char[][]*) - Number of scores without accounting for those added by expansions, - e.g. scatter-PN. + Tallying moment orders for Legendre and spherical harmonic tally expansions + (*e.g.*, 'P2', 'Y1,2', etc.). - **/tallies/tally i/moment_orders** (*char[][]*) +**/tallies/tally /results** (Compound type) - Tallying moment orders for Legendre and spherical harmonic tally - expansions (*e.g.*, 'P2', 'Y1,2', etc.). - - **/tallies/tally i/results** (Compound type) - - Accumulated sum and sum-of-squares for each bin of the i-th tally. + Accumulated sum and sum-of-squares for each bin of the i-th tally. This is a + two-dimensional array, the first dimension of which represents combinations + of filter bins and the second dimensions of which represents scoring + bins. Each element of the array has fields 'sum' and 'sum_sq'. **/source_present** (*int*) diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst index 453a48d98..f7e026998 100644 --- a/docs/source/usersguide/output/summary.rst +++ b/docs/source/usersguide/output/summary.rst @@ -29,7 +29,7 @@ The current revision of the summary file format is 1. **/date_and_time** (*char[]*) - Date and time the state point was written. + Date and time the summary was written. **/n_procs** (*int*) @@ -43,186 +43,302 @@ The current revision of the summary file format is 1. Number of batches to simulate. -if (run_mode == MODE_EIGENVALUE) +**/n_inactive** (*int*) - **/n_inactive** (*int*) + Number of inactive batches. Only present if /run_mode is set to + 'k-eigenvalue'. - Number of inactive batches. +**/n_active** (*int*) - **/n_active** (*int*) + Number of active batches. Only present if /run_mode is set to + 'k-eigenvalue'. - Number of active batches. +**/gen_per_batch** (*int*) - **/gen_per_batch** (*int*) - - Number of generations per batch. - -end if + Number of generations per batch. Only present if /run_mode is set to + 'k-eigenvalue'. **/geometry/n_cells** (*int*) + Number of cells in the problem. + **/geometry/n_surfaces** (*int*) + Number of surfaces in the problem. + **/geometry/n_universes** (*int*) + Number of unique universes in the problem. + **/geometry/n_lattices** (*int*) -do i = 1, n_cells + Number of lattices in the problem. - **/geometry/cells/cell /index** (*int*) +**/geometry/cells/cell /index** (*int*) - **/geometry/cells/cell /name** (*char[]*) + Index in cells array used internally in OpenMC. - **/geometry/cells/cell /universe** (*int*) +**/geometry/cells/cell /name** (*char[]*) - **/geometry/cells/cell /fill_type** (*char[]*) + Name of the cell. - **/geometry/cells/cell /material** (*int*) +**/geometry/cells/cell /universe** (*int*) - **/geometry/cells/cell /maps** (*int*) + Universe assigned to the cell. If none is specified, the default + universe (0) is assigned. - **/geometry/cells/cell /offset** (*int[]*) +**/geometry/cells/cell /fill_type** (*char[]*) - **/geometry/cells/cell /translated** (*int*) + Type of fill for the cell. Can be 'normal', 'universe', or 'lattice'. - **/geometry/cells/cell /translation** (*double[]*) +**/geometry/cells/cell /material** (*int*) - **/geometry/cells/cell /rotated** (*int*) + Unique ID of the material assigned to the cell. This dataset is present only + if fill_type is set to 'normal'. - **/geometry/cells/cell /rotation** (*double[]*) +**/geometry/cells/cell /maps** (*int*) - **/geometry/cells/cell /lattice** (*int*) + TODO: Add description. - **/geometry/cells/cell /surfaces** (*int[]*) +**/geometry/cells/cell /offset** (*int[]*) -end do + Offset used for distribcell tally filter. This dataset is present only if + fill_type is set to 'universe'. -do i = 1, n_surfaces +**/geometry/cells/cell /translated** (*int*) - **/geometry/surfaces/surface /index** (*int*) + Indicates if a translation is to be applied to the fill universe if one is + present. Note that this dataset assumes values of 0 or 1. This dataset is + present only if fill_type is set to 'universe'. - **/geometry/surfaces/surface /name** (*char[]*) +**/geometry/cells/cell /translation** (*double[3]*) - **/geometry/surfaces/surface /type** (*char[]*) + Translation applied to the fill universe. This dataset is present only if + fill_type is set to 'universe'. - **/geometry/surfaces/surface /coefficients** (*double[]*) +**/geometry/cells/cell /rotated** (*int*) - **/geometry/surfaces/surface /boundary_condition** (*char[]*) + Indicates if a rotation is to be applied to the fill universe if one is + present. Note that this dataset assumes values of 0 or 1. This dataset is + present only if fill_type is set to 'universe'. -end do +**/geometry/cells/cell /rotation** (*double[3]*) -do i = 1, n_universes + Angles in degrees about the x-, y-, and z-axes for which the fill universe + should be rotated. This dataset is present only if fill_type is set to + 'universe'. - **/geometry/universes/universe /index** (*int*) +**/geometry/cells/cell /lattice** (*int*) - **/geometry/universes/universe /cells** (*int[]*) + Unique ID of the lattice which fills the cell. Only present if fill_type is + set to 'lattice'. -end do +**/geometry/cells/cell /surfaces** (*int[]*) -do i = 1, n_lattices + Surface specification for the cell. - **/geometry/lattices/lattice /index** (*int*) +**/geometry/surfaces/surface /index** (*int*) - **/geometry/lattices/lattice /name** (*char[]*) + Index in surfaces array used internally in OpenMC. - **/geometry/lattices/lattice /type** (*char[]*) +**/geometry/surfaces/surface /name** (*char[]*) - **/geometry/lattices/lattice /pitch** (*double[]*) + Name of the surface. - **/geometry/lattices/lattice /outer** (*int*) +**/geometry/surfaces/surface /type** (*char[]*) - **/geometry/lattices/lattice /offset_size** (*int[]*) + Type of the surface. Can be 'X Plane', 'Y Plane', 'Z Plane', 'Plane', 'X + Cylinder', 'Y Cylinder', 'Sphere', 'X Cone', 'Y Cone', or 'Z Cone'. - **/geometry/lattices/lattice /maps** (*int*) +**/geometry/surfaces/surface /coefficients** (*double[]*) - **/geometry/lattices/lattice /offsets** (*int[]*) + Array of coefficients that define the surface. See :ref:`surface_element` + for what coefficients are defined for each surface type. - **/geometry/lattices/lattice /universes** (*int[]*) +**/geometry/surfaces/surface /boundary_condition** (*char[]*) - if (rectangular lattice) + Boundary condition applied to the surface. Can be 'transmission', 'vacuum', + 'reflective', or 'periodic'. - **/geometry/lattices/lattice /dimension** (*int[]*) +**/geometry/universes/universe /index** (*int*) - **/geometry/lattices/lattice /lower_left** (*double[]*) + Index in the universes array used internally in OpenMC. - elseif (hexagonal lattice) +**/geometry/universes/universe /cells** (*int[]*) - **/geometry/lattices/lattice /n_rings** (*int*) + Array of unique IDs of cells that appear in the universe. - **/geometry/lattices/lattice /n_axial** (*int*) +**/geometry/lattices/lattice /index** (*int*) - **/geometry/lattices/lattice /center** (*double[]*) + Index in the lattices array used internally in OpenMC. - end if +**/geometry/lattices/lattice /name** (*char[]*) -end do + Name of the lattice. + +**/geometry/lattices/lattice /type** (*char[]*) + + Type of the lattice, either 'rectangular' or 'hexagonal'. + +**/geometry/lattices/lattice /pitch** (*double[]*) + + Pitch of the lattice. + +**/geometry/lattices/lattice /outer** (*int*) + + Outer universe assigned to lattice cells outside the defined range. + +**/geometry/lattices/lattice /offset_size** (*int[]*) + + TODO: Explain offset_size + +**/geometry/lattices/lattice /maps** (*int*) + + TODO: Explain maps + +**/geometry/lattices/lattice /offsets** (*int[]*) + + Offsets used for distribcell tally filter. + +**/geometry/lattices/lattice /universes** (*int[]*) + + Three-dimensional array of universes assigned to each cell of the lattice. + +**/geometry/lattices/lattice /dimension** (*int[]*) + + The number of lattice cells in each direction. This dataset is present only + when the 'type' dataset is set to 'rectangular'. + +**/geometry/lattices/lattice /lower_left** (*double[]*) + + The coordinates of the lower-left corner of the lattice. This dataset is + present only when the 'type' dataset is set to 'rectangular'. + +**/geometry/lattices/lattice /n_rings** (*int*) + + Number of radial ring positions in the xy-plane. This dataset is present + only when the 'type' dataset is set to 'hexagonal'. + +**/geometry/lattices/lattice /n_axial** (*int*) + + Number of lattice positions along the z-axis. This dataset is present only + when the 'type' dataset is set to 'hexagonal'. + +**/geometry/lattices/lattice /center** (*double[]*) + + Coordinates of the center of the lattice. This dataset is present only when + the 'type' dataset is set to 'hexagonal'. **/n_materials** (*int*) -do i = 1, n_materials + Number of materials in the problem. - **/materials/material /index** (*int*) +**/materials/material /index** (*int*) - **/materials/material /name** (*char[]*) + Index in materials array used internally in OpenMC. - **/materials/material /atom_density** (*double[]*) +**/materials/material /name** (*char[]*) - **/materials/material /nuclides** (*int[]*) + Name of the material. - **/materials/material /nuclide_densities** (*double[]*) +**/materials/material /atom_density** (*double[]*) - **/materials/material /sab_names** (*char[][]*) + Total atom density of the material in atom/b-cm. -end do +**/materials/material /nuclides** (*char[][]*) + + Array of nuclides present in the material, e.g., 'U-235.71c'. + +**/materials/material /nuclide_densities** (*double[]*) + + Atom density of each nuclide. + +**/materials/material /sab_names** (*char[][]*) + + Names of S(:math:`\alpha`,:math:`\beta`) tables assigned to the material. **/tallies/n_tallies** (*int*) + Number of tallies in the problem. + **/tallies/n_meshes** (*int*) -do i = 1, n_meshes + Number of meshes in the problem. - **/tallies/mesh /index** (*int*) +**/tallies/mesh /index** (*int*) - **/tallies/mesh /type** (*char[]*) + Index in the meshes array used internally in OpenMC - **/tallies/mesh /dimension** (*int[]*) +**/tallies/mesh /type** (*char[]*) - **/tallies/mesh /lower_left** (*double[]*) + Type of the mesh. The only valid option is currently 'regular'. - **/tallies/mesh /upper_right** (*double[]*) +**/tallies/mesh /dimension** (*int[]*) - **/tallies/mesh /width** (*double[]*) + Number of mesh cells in each direction. -end do +**/tallies/mesh /lower_left** (*double[]*) -do i = 1, n_tallies + Coordinates of the lower-left corner of the mesh. - **/tallies/tally /index** (*int*) +**/tallies/mesh /upper_right** (*double[]*) - **/tallies/tally /name** (*char[]*) + Coordinates of the upper-right corner of the mesh. - **/tallies/tally /total_score_bins** (*int*) +**/tallies/mesh /width** (*double[]*) - **/tallies/tally /total_filter_bins** (*int*) + Width of a single mesh cell in each direction. - **/tallies/tally /n_filters** (*int*) +**/tallies/tally /index** (*int*) - do j = 1, n_filters + Index in tallies array used internally in OpenMC. - **/tallies/tally /filter j/type** (*char[]*) +**/tallies/tally /name** (*char[]*) - **/tallies/tally /filter j/n_bins** (*int*) + Name of the tally. - **/tallies/tally /filter j/bins** (*int[]* or *double[]*) +**/tallies/tally /total_score_bins** (*int*) - **/tallies/tally /filter j/type_name** (*char[]*) + Total number of scoring bins for all nuclides. This is used as the size of + second dimension of the tally results array. - end do +**/tallies/tally /total_filter_bins** (*int*) - **/tallies/tally /nuclides** (*char[][]*) + Total number of filter bins accounting for all filters. This is used as the + size of first dimension of the tally results array. - **/tallies/tally /n_score_bins** (*int*) +**/tallies/tally /n_filters** (*int*) - **/tallies/tally /score_bins** (*char[][]*) + Number of filters applied to the tally. -end do +**/tallies/tally /filter /type** (*char[]*) + + Type of the j-th filter. Can be 'universe', 'material', 'cell', 'cellborn', + 'surface', 'mesh', 'energy', 'energyout', or 'distribcell'. + +**/tallies/tally /filter /offset** (*int*) + + Filter offset (used for distribcell filter). + +**/tallies/tally /filter /n_bins** (*int*) + + Number of bins for the j-th filter. + +**/tallies/tally /filter /bins** (*int[]* or *double[]*) + + Value for each filter bin of this type. + +**/tallies/tally /nuclides** (*char[][]*) + + Array of nuclides to tally. Note that if no nuclide is specified in the user + input, a single 'total' nuclide appears here. + +**/tallies/tally /n_score_bins** (*int*) + + Number of scoring bins for a single nuclide. In general, this can be greater + than the number of user-specified scores since each score might have + multiple scoring bins, e.g., scatter-PN. + +**/tallies/tally /score_bins** (*char[][]*) + + Scoring bins for the tally. diff --git a/src/summary.F90 b/src/summary.F90 index d80f35748..7c6a3a29a 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -515,6 +515,7 @@ contains filter_group = create_group(tally_group, "filter " // trim(to_str(j))) ! Write number of bins for this filter + call write_dataset(filter_group, "offset", t%filters(j)%offset) call write_dataset(filter_group, "n_bins", t%filters(j)%n_bins) ! Write filter bins From 9bc3b3358c6630f5756fb4eab0648c71bbffd213 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 25 Sep 2015 10:53:36 +0700 Subject: [PATCH 83/95] Got rid of maps, offset_size, translated, and rotated datasets. --- docs/source/usersguide/output/summary.rst | 26 +------------ openmc/summary.py | 20 ++++------ src/summary.F90 | 46 +++++++---------------- 3 files changed, 22 insertions(+), 70 deletions(-) diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst index f7e026998..81400c936 100644 --- a/docs/source/usersguide/output/summary.rst +++ b/docs/source/usersguide/output/summary.rst @@ -96,32 +96,16 @@ The current revision of the summary file format is 1. Unique ID of the material assigned to the cell. This dataset is present only if fill_type is set to 'normal'. -**/geometry/cells/cell /maps** (*int*) - - TODO: Add description. - **/geometry/cells/cell /offset** (*int[]*) - Offset used for distribcell tally filter. This dataset is present only if + Offsets used for distribcell tally filter. This dataset is present only if fill_type is set to 'universe'. -**/geometry/cells/cell /translated** (*int*) - - Indicates if a translation is to be applied to the fill universe if one is - present. Note that this dataset assumes values of 0 or 1. This dataset is - present only if fill_type is set to 'universe'. - **/geometry/cells/cell /translation** (*double[3]*) Translation applied to the fill universe. This dataset is present only if fill_type is set to 'universe'. -**/geometry/cells/cell /rotated** (*int*) - - Indicates if a rotation is to be applied to the fill universe if one is - present. Note that this dataset assumes values of 0 or 1. This dataset is - present only if fill_type is set to 'universe'. - **/geometry/cells/cell /rotation** (*double[3]*) Angles in degrees about the x-, y-, and z-axes for which the fill universe @@ -188,14 +172,6 @@ The current revision of the summary file format is 1. Outer universe assigned to lattice cells outside the defined range. -**/geometry/lattices/lattice /offset_size** (*int[]*) - - TODO: Explain offset_size - -**/geometry/lattices/lattice /maps** (*int*) - - TODO: Explain maps - **/geometry/lattices/lattice /offsets** (*int[]*) Offsets used for distribcell tally filter. diff --git a/openmc/summary.py b/openmc/summary.py index 10470bb8e..fa9ed6575 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -224,21 +224,17 @@ class Summary(object): cell = openmc.Cell(cell_id=cell_id, name=name) if fill_type == 'universe': - maps = self._f['geometry/cells'][key]['maps'].value - - if maps > 0: + if 'offset' in self._f['geometry/cells'][key]: offset = self._f['geometry/cells'][key]['offset'][...] cell.offsets = offset - translated = self._f['geometry/cells'][key]['translated'].value - if translated: + if 'translation' in self._f['geometry/cells'][key]: translation = \ self._f['geometry/cells'][key]['translation'][...] translation = np.asarray(translation, dtype=np.float64) cell.translation = translation - rotated = self._f['geometry/cells'][key]['rotated'].value - if rotated: + if 'rotation' in self._f['geometry/cells'][key]: rotation = \ self._f['geometry/cells'][key]['rotation'][...] rotation = np.asarray(rotation, dtype=np.int) @@ -301,11 +297,11 @@ class Summary(object): index = self._f['geometry/lattices'][key]['index'].value name = self._f['geometry/lattices'][key]['name'].value.decode() lattice_type = self._f['geometry/lattices'][key]['type'].value.decode() - maps = self._f['geometry/lattices'][key]['maps'].value - offset_size = self._f['geometry/lattices'][key]['offset_size'].value - if offset_size > 0: + if 'offsets' in self._f['geometry/lattices'][key]: offsets = self._f['geometry/lattices'][key]['offsets'][...] + else: + offsets = None if lattice_type == 'rectangular': dimension = self._f['geometry/lattices'][key]['dimension'][...] @@ -346,7 +342,7 @@ class Summary(object): universes = universes[:, ::-1, :] lattice.universes = universes - if offset_size > 0: + if offsets: offsets = np.swapaxes(offsets, 0, 1) offsets = np.swapaxes(offsets, 1, 2) lattice.offsets = offsets @@ -440,7 +436,7 @@ class Summary(object): # Lattice is 2D; extract the only axial level lattice.universes = universes[0] - if offset_size > 0: + if offsets: lattice.offsets = offsets # Add the Lattice to the global dictionary of all Lattices diff --git a/src/summary.F90 b/src/summary.F90 index 7c6a3a29a..3d3a47a75 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -157,23 +157,15 @@ contains case (CELL_FILL) call write_dataset(cell_group, "fill_type", "universe") call write_dataset(cell_group, "fill", universes(c%fill)%id) - call write_dataset(cell_group, "maps", size(c%offset)) if (size(c%offset) > 0) then call write_dataset(cell_group, "offset", c%offset) end if if (allocated(c%translation)) then - call write_dataset(cell_group, "translated", 1) call write_dataset(cell_group, "translation", c%translation) - else - call write_dataset(cell_group, "translated", 0) end if - if (allocated(c%rotation)) then - call write_dataset(cell_group, "rotated", 1) call write_dataset(cell_group, "rotation", c%rotation) - else - call write_dataset(cell_group, "rotated", 0) end if case (CELL_LATTICE) @@ -298,10 +290,16 @@ contains ! Write internal OpenMC index for this lattice call write_dataset(lattice_group, "index", i) - ! Write name for this lattice + ! Write name, pitch, and outer universe call write_dataset(lattice_group, "name", lat%name) + call write_dataset(lattice_group, "pitch", lat%pitch) + call write_dataset(lattice_group, "outer", lat%outer) + + ! Write distribcell offsets if present + if (size(lat%offset) > 0) then + call write_dataset(lattice_group, "offsets", lat%offset) + end if - ! Write lattice type select type (lat) type is (RectLattice) ! Write lattice type. @@ -310,15 +308,6 @@ contains ! Write lattice dimensions, lower left corner, and pitch call write_dataset(lattice_group, "dimension", lat%n_cells) call write_dataset(lattice_group, "lower_left", lat%lower_left) - call write_dataset(lattice_group, "pitch", lat%pitch) - - call write_dataset(lattice_group, "outer", lat%outer) - call write_dataset(lattice_group, "offset_size", size(lat%offset)) - call write_dataset(lattice_group, "maps", size(lat%offset,1)) - - if (size(lat%offset) > 0) then - call write_dataset(lattice_group, "offsets", lat%offset) - end if ! Write lattice universes. allocate(lattice_universes(lat%n_cells(1), lat%n_cells(2), & @@ -330,8 +319,6 @@ contains end do end do end do - call write_dataset(lattice_group, "universes", lattice_universes) - deallocate(lattice_universes) type is (HexLattice) ! Write lattice type. @@ -341,17 +328,8 @@ contains call write_dataset(lattice_group, "n_rings", lat%n_rings) call write_dataset(lattice_group, "n_axial", lat%n_axial) - ! Write lattice center, pitch and outer universe. + ! Write lattice center call write_dataset(lattice_group, "center", lat%center) - call write_dataset(lattice_group, "pitch", lat%pitch) - - call write_dataset(lattice_group, "outer", lat%outer) - call write_dataset(lattice_group, "offset_size", size(lat%offset)) - call write_dataset(lattice_group, "maps", size(lat%offset,1)) - - if (size(lat%offset) > 0) then - call write_dataset(lattice_group, "offsets", lat%offset) - end if ! Write lattice universes. allocate(lattice_universes(2*lat%n_rings - 1, 2*lat%n_rings - 1, & @@ -372,10 +350,12 @@ contains end do end do end do - call write_dataset(lattice_group, "universes", lattice_universes) - deallocate(lattice_universes) end select + ! Write lattice universes + call write_dataset(lattice_group, "universes", lattice_universes) + deallocate(lattice_universes) + call close_group(lattice_group) end do LATTICE_LOOP From 81fa63886babd8fec48284fbd801534ca86db2dd Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 25 Sep 2015 10:59:58 +0700 Subject: [PATCH 84/95] Get rid of total_score_bins and total_filter_bins datasets in summary. --- docs/source/usersguide/output/summary.rst | 10 ---------- src/summary.F90 | 4 ---- 2 files changed, 14 deletions(-) diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst index 81400c936..0623693c5 100644 --- a/docs/source/usersguide/output/summary.rst +++ b/docs/source/usersguide/output/summary.rst @@ -273,16 +273,6 @@ The current revision of the summary file format is 1. Name of the tally. -**/tallies/tally /total_score_bins** (*int*) - - Total number of scoring bins for all nuclides. This is used as the size of - second dimension of the tally results array. - -**/tallies/tally /total_filter_bins** (*int*) - - Total number of filter bins accounting for all filters. This is used as the - size of first dimension of the tally results array. - **/tallies/tally /n_filters** (*int*) Number of filters applied to the tally. diff --git a/src/summary.F90 b/src/summary.F90 index 3d3a47a75..cc04599b0 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -484,10 +484,6 @@ contains ! Write the name for this tally call write_dataset(tally_group, "name", t%name) - ! Write size of each tally - call write_dataset(tally_group, "total_score_bins", t%total_score_bins) - call write_dataset(tally_group, "total_filter_bins", t%total_filter_bins) - ! Write number of filters call write_dataset(tally_group, "n_filters", t%n_filters) From f3f6753820f40c343853eb9bdc2184b0101c0ef9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 25 Sep 2015 14:43:32 +0700 Subject: [PATCH 85/95] Respond to remaining comments from @wbinventor on #454 --- docs/source/usersguide/processing.rst | 17 ++++++++------- examples/python/lattice/nested/build-xml.py | 2 +- examples/python/lattice/simple/build-xml.py | 2 +- examples/python/pincell/build-xml.py | 2 +- examples/xml/lattice/nested/tallies.xml | 2 +- examples/xml/lattice/simple/tallies.xml | 2 +- examples/xml/pincell/tallies.xml | 4 ++-- openmc/particle_restart.py | 5 ++++- openmc/statepoint.py | 23 +++++++-------------- openmc/summary.py | 15 ++++++-------- src/particle_restart_write.F90 | 2 -- src/state_point.F90 | 13 +++++++----- tests/test_cmfd_feed/tallies.xml | 2 +- tests/test_cmfd_nofeed/tallies.xml | 2 +- tests/test_filter_mesh_2d/tallies.xml | 4 ++-- tests/test_filter_mesh_3d/tallies.xml | 4 ++-- tests/test_score_current/tallies.xml | 4 ++-- tests/test_sourcepoint_restart/tallies.xml | 4 ++-- tests/test_statepoint_restart/tallies.xml | 4 ++-- 19 files changed, 53 insertions(+), 60 deletions(-) diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst index 3a6766a2d..b18569ec6 100644 --- a/docs/source/usersguide/processing.rst +++ b/docs/source/usersguide/processing.rst @@ -14,17 +14,18 @@ third-party Python packages, including: * [1]_ `NumPy `_ * [2]_ `h5py `_ * [3]_ `pandas `_ -* [3]_ `matplotlib `_ -* [3]_ `Silomesh `_ -* [3]_ `VTK `_ -* [3]_ `lxml `_ +* [4]_ `matplotlib `_ +* [4]_ `Silomesh `_ +* [4]_ `VTK `_ +* [4]_ `lxml `_ Most of these are can easily be installed with `pip `_ or alternatively obtaining through a package manager. .. [1] Required for most post-processing tasks .. [2] Required for reading HDF5 output files -.. [3] Not used directly by the Python API, but are optional dependencies for a +.. [3] Optional dependency for advanced features in Python API +.. [4] Not used directly by the Python API, but are optional dependencies for a number of scripts. ---------------------- @@ -187,7 +188,7 @@ Tally results are saved in both a text file (tallies.out) as well as an HDF5 statepoint file. While the tallies.out file may be fine for simple tallies, in many cases the user requires more information about the tally or the run, or has to deal with a large number of result values (e.g. for mesh tallies). In these -cases, extracting data from the statepoint file via the Python API is the +cases, extracting data from the statepoint file via the :ref:`pythonapi` is the preferred method of data analysis and visualization. Data Extraction @@ -209,8 +210,8 @@ Plotting in 2D The :ref:`IPython notebook example ` also demonstrates how to plot a mesh tally in two dimensions using the Python API. Note, however, that there is also a script distributed with OpenMC, ``openmc-plot-mesh-tally``, -that interactive GUI to explore and plot mesh tallies for any scores and filter -bins. +that provides an interactive GUI to explore and plot mesh tallies for any scores +and filter bins. .. image:: ../_images/plotmeshtally.png :height: 200px diff --git a/examples/python/lattice/nested/build-xml.py b/examples/python/lattice/nested/build-xml.py index ce6766542..24b5554c0 100644 --- a/examples/python/lattice/nested/build-xml.py +++ b/examples/python/lattice/nested/build-xml.py @@ -168,7 +168,7 @@ plot_file.export_to_xml() # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) -mesh.type = 'rectangular' +mesh.type = 'regular' mesh.dimension = [4, 4] mesh.lower_left = [-2, -2] mesh.width = [1, 1] diff --git a/examples/python/lattice/simple/build-xml.py b/examples/python/lattice/simple/build-xml.py index 675c7e08b..57e1f1729 100644 --- a/examples/python/lattice/simple/build-xml.py +++ b/examples/python/lattice/simple/build-xml.py @@ -157,7 +157,7 @@ plot_file.export_to_xml() # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) -mesh.type = 'rectangular' +mesh.type = 'regular' mesh.dimension = [4, 4] mesh.lower_left = [-2, -2] mesh.width = [1, 1] diff --git a/examples/python/pincell/build-xml.py b/examples/python/pincell/build-xml.py index 9338aff0e..fc9663b90 100644 --- a/examples/python/pincell/build-xml.py +++ b/examples/python/pincell/build-xml.py @@ -189,7 +189,7 @@ settings_file.export_to_xml() # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) -mesh.type = 'rectangular' +mesh.type = 'regular' mesh.dimension = [100, 100, 1] mesh.lower_left = [-0.62992, -0.62992, -1.e50] mesh.upper_right = [0.62992, 0.62992, 1.e50] diff --git a/examples/xml/lattice/nested/tallies.xml b/examples/xml/lattice/nested/tallies.xml index 5730e6b12..89c0774f1 100644 --- a/examples/xml/lattice/nested/tallies.xml +++ b/examples/xml/lattice/nested/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular 4 4 -2.0 -2.0 1.0 1.0 diff --git a/examples/xml/lattice/simple/tallies.xml b/examples/xml/lattice/simple/tallies.xml index 5730e6b12..89c0774f1 100644 --- a/examples/xml/lattice/simple/tallies.xml +++ b/examples/xml/lattice/simple/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular 4 4 -2.0 -2.0 1.0 1.0 diff --git a/examples/xml/pincell/tallies.xml b/examples/xml/pincell/tallies.xml index bbfd58836..73242b913 100644 --- a/examples/xml/pincell/tallies.xml +++ b/examples/xml/pincell/tallies.xml @@ -1,7 +1,7 @@ - + 100 100 1 -0.62992 -0.62992 -1.e50 0.62992 0.62992 1.e50 @@ -13,4 +13,4 @@ flux fission nu-fission - \ No newline at end of file + diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py index ff47ef474..72bf3ac3d 100644 --- a/openmc/particle_restart.py +++ b/openmc/particle_restart.py @@ -44,7 +44,10 @@ class Particle(object): 'filetype'].value.decode() != 'particle restart': raise IOError('{} is not a particle restart file.'.format(filename)) if self._f['revision'].value != 1: - raise IOError('Particle restart file revision is not consistent.') + raise IOError('Particle restart file has a file revision of {} ' + 'which is not consistent with the revision this ' + 'version of OpenMC expects ({}).'.format( + self._f['revision'].value, 1)) @property def current_batch(self): diff --git a/openmc/statepoint.py b/openmc/statepoint.py index c1be20126..cdb82d95e 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -96,7 +96,10 @@ class StatePoint(object): 'filetype'].value.decode() != 'statepoint': raise IOError('{} is not a statepoint file.'.format(filename)) if self._f['revision'].value != 14: - raise IOError('Statepoint revision is not consistent.') + raise IOError('Statepoint file has a file revision of {} ' + 'which is not consistent with the revision this ' + 'version of OpenMC expects ({}).'.format( + self._f['revision'].value, 14)) # Set flags for what data has been read self._meshes_read = False @@ -207,7 +210,7 @@ class StatePoint(object): @property def k_generation(self): if self.run_mode == 'k-eigenvalue': - return self._f['k_generation']/value + return self._f['k_generation'].value else: return None @@ -355,7 +358,7 @@ class StatePoint(object): n_realizations = self._f['{0}{1}/n_realizations'.format(base, tally_key)].value # Create Tally object and assign basic properties - tally = openmc.Tally(tally_key) + tally = openmc.Tally(tally_id=tally_key) tally._statepoint = self tally.estimator = self._f['{0}{1}/estimator'.format( base, tally_key)].value.decode() @@ -377,20 +380,8 @@ class StatePoint(object): n_bins = self._f['{0}{1}/n_bins'.format(subbase, j)].value - if n_bins <= 0: - msg = 'Unable to create Filter "{0}" for Tally ID="{1}" ' \ - 'since no bins were specified'.format(j, tally_key) - raise ValueError(msg) - # Read the bin values - if filter_type in ['energy', 'energyout']: - bins = self._f['{0}{1}/bins'.format(subbase, j)].value - - elif filter_type in ['mesh', 'distribcell']: - bins = self._f['{0}{1}/bins'.format(subbase, j)].value - - else: - bins = self._f['{0}{1}/bins'.format(subbase, j)].value + bins = self._f['{0}{1}/bins'.format(subbase, j)].value # Create Filter object filter = openmc.Filter(filter_type, bins) diff --git a/openmc/summary.py b/openmc/summary.py index fa9ed6575..3d7da115f 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -91,14 +91,11 @@ class Summary(object): name, xs = fullname.split('.') if 'nat' in name: - nuclide = openmc.Element(name=name, xs=xs) + material.add_element(openmc.Element(name=name, xs=xs), + percent=density, percent_type='ao') else: - nuclide = openmc.Nuclide(name=name, xs=xs) - - if isinstance(nuclide, openmc.Nuclide): - material.add_nuclide(nuclide, percent=density, percent_type='ao') - elif isinstance(nuclide, openmc.Element): - material.add_element(nuclide, percent=density, percent_type='ao') + material.add_nuclide(openmc.Nuclide(name=name, xs=xs), + percent=density, percent_type='ao') # Add the Material to the global dictionary of all Materials self.materials[index] = material @@ -342,7 +339,7 @@ class Summary(object): universes = universes[:, ::-1, :] lattice.universes = universes - if offsets: + if offsets is not None: offsets = np.swapaxes(offsets, 0, 1) offsets = np.swapaxes(offsets, 1, 2) lattice.offsets = offsets @@ -436,7 +433,7 @@ class Summary(object): # Lattice is 2D; extract the only axial level lattice.universes = universes[0] - if offsets: + if offsets is not None: lattice.offsets = offsets # Add the Lattice to the global dictionary of all Lattices diff --git a/src/particle_restart_write.F90 b/src/particle_restart_write.F90 index 77de7f669..edd779df0 100644 --- a/src/particle_restart_write.F90 +++ b/src/particle_restart_write.F90 @@ -51,8 +51,6 @@ contains call write_dataset(file_id, 'run_mode', 'fixed source') case (MODE_EIGENVALUE) call write_dataset(file_id, 'run_mode', 'k-eigenvalue') - case (MODE_PLOTTING) - call write_dataset(file_id, 'run_mode', 'plot') case (MODE_PARTICLE) call write_dataset(file_id, 'run_mode', 'particle restart') end select diff --git a/src/state_point.F90 b/src/state_point.F90 index fbdbdbeba..a5c89a8a2 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -97,10 +97,6 @@ contains call write_dataset(file_id, "run_mode", "fixed source") case (MODE_EIGENVALUE) call write_dataset(file_id, "run_mode", "k-eigenvalue") - case (MODE_PLOTTING) - call write_dataset(file_id, "run_mode", "plot") - case (MODE_PARTICLE) - call write_dataset(file_id, "run_mode", "particle restart") end select call write_dataset(file_id, "n_particles", n_particles) call write_dataset(file_id, "n_batches", n_batches) @@ -181,7 +177,10 @@ contains mesh_group = create_group(meshes_group, "mesh " // trim(to_str(meshp%id))) call write_dataset(mesh_group, "id", meshp%id) - call write_dataset(mesh_group, "type", "regular") + 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) @@ -280,7 +279,11 @@ contains allocate(str_array(tally%n_nuclide_bins)) NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins if (tally%nuclide_bins(j) > 0) then + ! Get index in cross section listings for this nuclide i_list = nuclides(tally%nuclide_bins(j))%listing + + ! Determine position of . in alias string (e.g. "U-235.71c"). If + ! no . is found, just use the entire string. i_xs = index(xs_listings(i_list)%alias, '.') if (i_xs > 0) then str_array(j) = xs_listings(i_list)%alias(1:i_xs - 1) diff --git a/tests/test_cmfd_feed/tallies.xml b/tests/test_cmfd_feed/tallies.xml index b20c0ad61..37edcecc2 100644 --- a/tests/test_cmfd_feed/tallies.xml +++ b/tests/test_cmfd_feed/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -10 -1 -1 10 1 1 10 1 1 diff --git a/tests/test_cmfd_nofeed/tallies.xml b/tests/test_cmfd_nofeed/tallies.xml index b20c0ad61..37edcecc2 100644 --- a/tests/test_cmfd_nofeed/tallies.xml +++ b/tests/test_cmfd_nofeed/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -10 -1 -1 10 1 1 10 1 1 diff --git a/tests/test_filter_mesh_2d/tallies.xml b/tests/test_filter_mesh_2d/tallies.xml index e046549de..de3fa6553 100644 --- a/tests/test_filter_mesh_2d/tallies.xml +++ b/tests/test_filter_mesh_2d/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -182.07 -182.07 182.07 182.07 17 17 @@ -13,4 +13,4 @@ total - \ No newline at end of file + diff --git a/tests/test_filter_mesh_3d/tallies.xml b/tests/test_filter_mesh_3d/tallies.xml index b2be27279..cd7f925e8 100644 --- a/tests/test_filter_mesh_3d/tallies.xml +++ b/tests/test_filter_mesh_3d/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -182.07 -182.07 -183.00 182.07 182.07 183.00 17 17 17 @@ -13,4 +13,4 @@ total - \ No newline at end of file + diff --git a/tests/test_score_current/tallies.xml b/tests/test_score_current/tallies.xml index a740949fa..3f496d43a 100644 --- a/tests/test_score_current/tallies.xml +++ b/tests/test_score_current/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -182.07 -182.07 -183.00 182.07 182.07 183.00 17 17 17 @@ -19,4 +19,4 @@ current - \ No newline at end of file + diff --git a/tests/test_sourcepoint_restart/tallies.xml b/tests/test_sourcepoint_restart/tallies.xml index 1704f56e1..67a1b50a9 100644 --- a/tests/test_sourcepoint_restart/tallies.xml +++ b/tests/test_sourcepoint_restart/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular 5 3 4 -10. -5. 0. 10. 4. 9. @@ -20,4 +20,4 @@ fission absorption total flux - \ No newline at end of file + diff --git a/tests/test_statepoint_restart/tallies.xml b/tests/test_statepoint_restart/tallies.xml index 1704f56e1..67a1b50a9 100644 --- a/tests/test_statepoint_restart/tallies.xml +++ b/tests/test_statepoint_restart/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular 5 3 4 -10. -5. 0. 10. 4. 9. @@ -20,4 +20,4 @@ fission absorption total flux - \ No newline at end of file + From 3d2fe2a0efd2bfce8be672ac00fcf6730e7e4836 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 25 Sep 2015 20:34:39 +0700 Subject: [PATCH 86/95] Few minor fixes for #454. Mesh ID is no longer written for statepoint. --- docs/source/usersguide/output/statepoint.rst | 6 +----- docs/source/usersguide/output/summary.rst | 2 +- openmc/statepoint.py | 7 +++---- src/state_point.F90 | 1 - 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index 02f4fdcf3..d1ebc7231 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -134,11 +134,7 @@ if run_mode == 'k-eigenvalue': **/tally/meshes/keys** (*int[]*) - User-identified unique ID of each mesh - -**/tallies/meshes/mesh /id** (*int*) - - Unique identifier of the mesh. + User-identified unique ID of each mesh. **/tallies/meshes/mesh /type** (*char[]*) diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst index 0623693c5..6bf0cf2ad 100644 --- a/docs/source/usersguide/output/summary.rst +++ b/docs/source/usersguide/output/summary.rst @@ -243,7 +243,7 @@ The current revision of the summary file format is 1. **/tallies/mesh /index** (*int*) - Index in the meshes array used internally in OpenMC + Index in the meshes array used internally in OpenMC. **/tallies/mesh /type** (*char[]*) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index cdb82d95e..133bd766c 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -265,8 +265,7 @@ class StatePoint(object): # Iterate over all Meshes for mesh_key in mesh_keys: - # Read the user-specified Mesh ID and type - mesh_id = self._f['{0}{1}/id'.format(base, mesh_key)].value + # Read the mesh type mesh_type = self._f['{0}{1}/type'.format(base, mesh_key)].value.decode() # Read the mesh dimensions, lower-left coordinates, @@ -277,7 +276,7 @@ class StatePoint(object): width = self._f['{0}{1}/width'.format(base, mesh_key)].value # Create the Mesh and assign properties to it - mesh = openmc.Mesh(mesh_id) + mesh = openmc.Mesh(mesh_key) mesh.dimension = dimension mesh.width = width mesh.lower_left = lower_left @@ -285,7 +284,7 @@ class StatePoint(object): mesh.type = mesh_type # Add mesh to the global dictionary of all Meshes - self._meshes[mesh_id] = mesh + self._meshes[mesh_key] = mesh self._meshes_read = True diff --git a/src/state_point.F90 b/src/state_point.F90 index a5c89a8a2..64ba7ef55 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -176,7 +176,6 @@ contains meshp => meshes(id_array(i)) mesh_group = create_group(meshes_group, "mesh " // trim(to_str(meshp%id))) - call write_dataset(mesh_group, "id", meshp%id) select case (meshp%type) case (MESH_REGULAR) call write_dataset(mesh_group, "type", "regular") From 47abbed14893da8f381163312850e352f6291195 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 25 Sep 2015 20:38:50 +0700 Subject: [PATCH 87/95] Use surface type names consistently in XML input and Python API. --- docs/source/usersguide/output/summary.rst | 4 ++-- openmc/summary.py | 24 +++++++++++------------ src/summary.F90 | 22 ++++++++++----------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst index 6bf0cf2ad..9ced8448a 100644 --- a/docs/source/usersguide/output/summary.rst +++ b/docs/source/usersguide/output/summary.rst @@ -131,8 +131,8 @@ The current revision of the summary file format is 1. **/geometry/surfaces/surface /type** (*char[]*) - Type of the surface. Can be 'X Plane', 'Y Plane', 'Z Plane', 'Plane', 'X - Cylinder', 'Y Cylinder', 'Sphere', 'X Cone', 'Y Cone', or 'Z Cone'. + Type of the surface. Can be 'x-plane', 'y-plane', 'z-plane', 'plane', + 'x-cylinder', 'y-cylinder', 'sphere', 'x-cone', 'y-cone', or 'z-cone'. **/geometry/surfaces/surface /coefficients** (*double[]*) diff --git a/openmc/summary.py b/openmc/summary.py index 3d7da115f..2ae746484 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -120,61 +120,61 @@ class Summary(object): coeffs = self._f['geometry/surfaces'][key]['coefficients'][...] # Create the Surface based on its type - if surf_type == 'X Plane': + if surf_type == 'x-plane': x0 = coeffs[0] surface = openmc.XPlane(surface_id, bc, x0, name) - elif surf_type == 'Y Plane': + elif surf_type == 'y-plane': y0 = coeffs[0] surface = openmc.YPlane(surface_id, bc, y0, name) - elif surf_type == 'Z Plane': + elif surf_type == 'z-plane': z0 = coeffs[0] surface = openmc.ZPlane(surface_id, bc, z0, name) - elif surf_type == 'Plane': + elif surf_type == 'plane': A = coeffs[0] B = coeffs[1] C = coeffs[2] D = coeffs[3] surface = openmc.Plane(surface_id, bc, A, B, C, D, name) - elif surf_type == 'X Cylinder': + elif surf_type == 'x-cylinder': y0 = coeffs[0] z0 = coeffs[1] R = coeffs[2] surface = openmc.XCylinder(surface_id, bc, y0, z0, R, name) - elif surf_type == 'Y Cylinder': + elif surf_type == 'y-cylinder': x0 = coeffs[0] z0 = coeffs[1] R = coeffs[2] surface = openmc.YCylinder(surface_id, bc, x0, z0, R, name) - elif surf_type == 'Z Cylinder': + elif surf_type == 'z-cylinder': x0 = coeffs[0] y0 = coeffs[1] R = coeffs[2] surface = openmc.ZCylinder(surface_id, bc, x0, y0, R, name) - elif surf_type == 'Sphere': + elif surf_type == 'sphere': x0 = coeffs[0] y0 = coeffs[1] z0 = coeffs[2] R = coeffs[3] surface = openmc.Sphere(surface_id, bc, x0, y0, z0, R, name) - elif surf_type in ['X Cone', 'Y Cone', 'Z Cone']: + elif surf_type in ['x-cone', 'y-cone', 'z-cone']: x0 = coeffs[0] y0 = coeffs[1] z0 = coeffs[2] R2 = coeffs[3] - if surf_type == 'X Cone': + if surf_type == 'x-cone': surface = openmc.XCone(surface_id, bc, x0, y0, z0, R2, name) - if surf_type == 'Y Cone': + if surf_type == 'y-cone': surface = openmc.YCone(surface_id, bc, x0, y0, z0, R2, name) - if surf_type == 'Z Cone': + if surf_type == 'z-cone': surface = openmc.ZCone(surface_id, bc, x0, y0, z0, R2, name) # Add Surface to global dictionary of all Surfaces diff --git a/src/summary.F90 b/src/summary.F90 index cc04599b0..b93bf120c 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -210,27 +210,27 @@ contains ! Write surface type select case (s%type) case (SURF_PX) - call write_dataset(surface_group, "type", "X Plane") + call write_dataset(surface_group, "type", "x-plane") case (SURF_PY) - call write_dataset(surface_group, "type", "Y Plane") + call write_dataset(surface_group, "type", "y-plane") case (SURF_PZ) - call write_dataset(surface_group, "type", "Z Plane") + call write_dataset(surface_group, "type", "z-plane") case (SURF_PLANE) - call write_dataset(surface_group, "type", "Plane") + call write_dataset(surface_group, "type", "plane") case (SURF_CYL_X) - call write_dataset(surface_group, "type", "X Cylinder") + call write_dataset(surface_group, "type", "x-cylinder") case (SURF_CYL_Y) - call write_dataset(surface_group, "type", "Y Cylinder") + call write_dataset(surface_group, "type", "y-cylinder") case (SURF_CYL_Z) - call write_dataset(surface_group, "type", "Z Cylinder") + call write_dataset(surface_group, "type", "z-cylinder") case (SURF_SPHERE) - call write_dataset(surface_group, "type", "Sphere") + call write_dataset(surface_group, "type", "sphere") case (SURF_CONE_X) - call write_dataset(surface_group, "type", "X Cone") + call write_dataset(surface_group, "type", "x-cone") case (SURF_CONE_Y) - call write_dataset(surface_group, "type", "Y Cone") + call write_dataset(surface_group, "type", "y-cone") case (SURF_CONE_Z) - call write_dataset(surface_group, "type", "Z Cone") + call write_dataset(surface_group, "type", "z-cone") end select ! Write coefficients for surface From da95a4403a544c4f8a38a5d96839ace7432ee99f Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Sat, 26 Sep 2015 13:28:31 -0400 Subject: [PATCH 88/95] Fixes for nu_scatter tallies --- src/ace_header.F90 | 6 ++-- src/tally.F90 | 80 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/ace_header.F90 b/src/ace_header.F90 index 209b752bf..467887c19 100644 --- a/src/ace_header.F90 +++ b/src/ace_header.F90 @@ -1,8 +1,8 @@ module ace_header - use constants, only: MAX_FILE_LEN, ZERO - use endf_header, only: Tab1 - use list_header, only: ListInt + use constants, only: MAX_FILE_LEN, ZERO + use endf_header, only: Tab1 + use list_header, only: ListInt implicit none diff --git a/src/tally.F90 b/src/tally.F90 index 33e452a4c..6eb68a15a 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -5,6 +5,7 @@ module tally use error, only: fatal_error use geometry_header use global + use interpolation use math, only: t_percentile, calc_pn, calc_rn use mesh, only: get_mesh_bin, bin_to_mesh_indices, & get_mesh_indices, mesh_indices_to_bin, & @@ -61,6 +62,7 @@ contains real(8) :: uvw(3) ! particle direction type(Material), pointer :: mat type(Reaction), pointer :: rxn + real(8) :: multiplicity i = 0 SCORE_LOOP: do q = 1, t % n_user_score_bins @@ -170,10 +172,28 @@ contains ! Only analog estimators are available. ! Skip any event where the particle didn't scatter if (p % event /= EVENT_SCATTER) cycle SCORE_LOOP - ! For scattering production, we need to use the post-collision - ! weight as the estimate for the number of neutrons exiting a - ! reaction with neutrons in the exit channel - score = p % wgt + ! For scattering production, we need to use the pre-collision + ! weight times the multiplicity as the estimate for the number of + ! neutrons exiting a reaction with neutrons in the exit channel + + do m = 1, nuclides(i_nuclide) % n_reaction + ! Check if this is the desired MT + if (p % event_MT == nuclides(i_nuclide) % reactions(m) % MT) then + ! Found the reaction, set our pointer and move on with life + rxn => nuclides(i_nuclide) % reactions(m) + exit + end if + end do + + ! Get multiplicity + if (rxn % multiplicity_with_E) then + multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + else + multiplicity = real(rxn % multiplicity,8) + end if + + ! Apply multiplicity to the last weight + score = p % last_wgt * multiplicity case (SCORE_NU_SCATTER_PN) @@ -183,10 +203,28 @@ contains i = i + t % moment_order(i) cycle SCORE_LOOP end if - ! For scattering production, we need to use the post-collision - ! weight as the estimate for the number of neutrons exiting a - ! reaction with neutrons in the exit channel - score = p % wgt + ! For scattering production, we need to use the pre-collision + ! weight times the multiplicity as the estimate for the number of + ! neutrons exiting a reaction with neutrons in the exit channel + + do m = 1, nuclides(i_nuclide) % n_reaction + ! Check if this is the desired MT + if (p % event_MT == nuclides(i_nuclide) % reactions(m) % MT) then + ! Found the reaction, set our pointer and move on with life + rxn => nuclides(i_nuclide) % reactions(m) + exit + end if + end do + + ! Get multiplicity + if (rxn % multiplicity_with_E) then + multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + else + multiplicity = real(rxn % multiplicity,8) + end if + + ! Apply multiplicity to the last weight + score = p % last_wgt * multiplicity case (SCORE_NU_SCATTER_YN) @@ -196,10 +234,28 @@ contains i = i + (t % moment_order(i) + 1)**2 - 1 cycle SCORE_LOOP end if - ! For scattering production, we need to use the post-collision - ! weight as the estimate for the number of neutrons exiting a - ! reaction with neutrons in the exit channel - score = p % wgt + ! For scattering production, we need to use the pre-collision + ! weight times the multiplicity as the estimate for the number of + ! neutrons exiting a reaction with neutrons in the exit channel + + do m = 1, nuclides(i_nuclide) % n_reaction + ! Check if this is the desired MT + if (p % event_MT == nuclides(i_nuclide) % reactions(m) % MT) then + ! Found the reaction, set our pointer and move on with life + rxn => nuclides(i_nuclide) % reactions(m) + exit + end if + end do + + ! Get multiplicity + if (rxn % multiplicity_with_E) then + multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + else + multiplicity = real(rxn % multiplicity,8) + end if + + ! Apply multiplicity to the last weight + score = p % last_wgt * multiplicity case (SCORE_TRANSPORT) From 5658cb0e665aa5b8070c1d2d208977abf9083c63 Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Sat, 26 Sep 2015 14:06:45 -0400 Subject: [PATCH 89/95] All tested and results updates --- src/tally.F90 | 96 +++-- tests/test_cmfd_feed/results_true.dat | 500 ++++++++++++------------ tests/test_cmfd_nofeed/results_true.dat | 216 +++++----- tests/test_many_scores/results_true.dat | 56 +-- 4 files changed, 440 insertions(+), 428 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 6eb68a15a..2b805b27d 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -175,21 +175,25 @@ contains ! For scattering production, we need to use the pre-collision ! weight times the multiplicity as the estimate for the number of ! neutrons exiting a reaction with neutrons in the exit channel - - do m = 1, nuclides(i_nuclide) % n_reaction - ! Check if this is the desired MT - if (p % event_MT == nuclides(i_nuclide) % reactions(m) % MT) then - ! Found the reaction, set our pointer and move on with life - rxn => nuclides(i_nuclide) % reactions(m) - exit - end if - end do - - ! Get multiplicity - if (rxn % multiplicity_with_E) then - multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + multiplicity = ONE else - multiplicity = real(rxn % multiplicity,8) + do m = 1, nuclides(p % event_nuclide) % n_reaction + ! Check if this is the desired MT + if (p % event_MT == nuclides(p % event_nuclide) % reactions(m) % MT) then + ! Found the reaction, set our pointer and move on with life + rxn => nuclides(p % event_nuclide) % reactions(m) + exit + end if + end do + + ! Get multiplicity + if (rxn % multiplicity_with_E) then + multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + else + multiplicity = real(rxn % multiplicity,8) + end if end if ! Apply multiplicity to the last weight @@ -206,21 +210,25 @@ contains ! For scattering production, we need to use the pre-collision ! weight times the multiplicity as the estimate for the number of ! neutrons exiting a reaction with neutrons in the exit channel - - do m = 1, nuclides(i_nuclide) % n_reaction - ! Check if this is the desired MT - if (p % event_MT == nuclides(i_nuclide) % reactions(m) % MT) then - ! Found the reaction, set our pointer and move on with life - rxn => nuclides(i_nuclide) % reactions(m) - exit - end if - end do - - ! Get multiplicity - if (rxn % multiplicity_with_E) then - multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + multiplicity = ONE else - multiplicity = real(rxn % multiplicity,8) + do m = 1, nuclides(p % event_nuclide) % n_reaction + ! Check if this is the desired MT + if (p % event_MT == nuclides(p % event_nuclide) % reactions(m) % MT) then + ! Found the reaction, set our pointer and move on with life + rxn => nuclides(p % event_nuclide) % reactions(m) + exit + end if + end do + + ! Get multiplicity + if (rxn % multiplicity_with_E) then + multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + else + multiplicity = real(rxn % multiplicity,8) + end if end if ! Apply multiplicity to the last weight @@ -237,21 +245,25 @@ contains ! For scattering production, we need to use the pre-collision ! weight times the multiplicity as the estimate for the number of ! neutrons exiting a reaction with neutrons in the exit channel - - do m = 1, nuclides(i_nuclide) % n_reaction - ! Check if this is the desired MT - if (p % event_MT == nuclides(i_nuclide) % reactions(m) % MT) then - ! Found the reaction, set our pointer and move on with life - rxn => nuclides(i_nuclide) % reactions(m) - exit - end if - end do - - ! Get multiplicity - if (rxn % multiplicity_with_E) then - multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + multiplicity = ONE else - multiplicity = real(rxn % multiplicity,8) + do m = 1, nuclides(p % event_nuclide) % n_reaction + ! Check if this is the desired MT + if (p % event_MT == nuclides(p % event_nuclide) % reactions(m) % MT) then + ! Found the reaction, set our pointer and move on with life + rxn => nuclides(p % event_nuclide) % reactions(m) + exit + end if + end do + + ! Get multiplicity + if (rxn % multiplicity_with_E) then + multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + else + multiplicity = real(rxn % multiplicity,8) + end if end if ! Apply multiplicity to the last weight diff --git a/tests/test_cmfd_feed/results_true.dat b/tests/test_cmfd_feed/results_true.dat index 26380d403..9c109db6a 100644 --- a/tests/test_cmfd_feed/results_true.dat +++ b/tests/test_cmfd_feed/results_true.dat @@ -1,128 +1,128 @@ k-combined: -1.172666E+00 8.502438E-03 +1.168349E+00 1.145333E-02 tally 1: -1.170812E+01 -1.376785E+01 -2.179886E+01 -4.765478E+01 -2.945614E+01 -8.709999E+01 -3.527293E+01 -1.245879E+02 -3.829349E+01 -1.470691E+02 -3.709040E+01 -1.379455E+02 -3.380335E+01 -1.145311E+02 -2.801351E+01 -7.871047E+01 -2.029625E+01 -4.131602E+01 -1.084302E+01 -1.180329E+01 +1.167844E+01 +1.366808E+01 +2.141846E+01 +4.598143E+01 +2.928738E+01 +8.615095E+01 +3.513015E+01 +1.241914E+02 +3.715164E+01 +1.384553E+02 +3.639309E+01 +1.327919E+02 +3.370872E+01 +1.138391E+02 +2.875251E+01 +8.292323E+01 +2.117740E+01 +4.512961E+01 +1.130554E+01 +1.289872E+01 tally 2: -2.270565E+01 -2.599927E+01 -1.590852E+01 -1.276260E+01 -2.252857E+00 -2.614120E-01 -4.313167E+01 -9.326539E+01 -3.044479E+01 -4.648169E+01 -4.023051E+00 -8.172006E-01 -5.859113E+01 -1.725665E+02 -4.171599E+01 -8.755981E+01 -5.512216E+00 -1.531207E+00 -6.892516E+01 -2.383198E+02 -4.904413E+01 -1.207096E+02 -6.542718E+00 -2.155749E+00 -7.421495E+01 -2.764539E+02 -5.288881E+01 -1.405388E+02 -6.811354E+00 -2.358827E+00 -7.278191E+01 -2.661597E+02 -5.169924E+01 -1.343999E+02 -6.516967E+00 -2.148745E+00 -6.655238E+01 -2.222812E+02 -4.729758E+01 -1.123214E+02 -6.102046E+00 -1.890147E+00 -5.708495E+01 -1.636585E+02 -4.068603E+01 -8.317681E+01 -5.394757E+00 -1.465413E+00 -4.136562E+01 -8.598520E+01 -2.958591E+01 -4.402226E+01 -3.765802E+00 -7.200302E-01 -2.275517E+01 -2.614738E+01 -1.589295E+01 -1.276624E+01 -2.232715E+00 -2.558645E-01 +2.339531E+01 +2.755922E+01 +1.646762E+01 +1.365289E+01 +2.146174E+00 +2.369613E-01 +4.309769E+01 +9.312913E+01 +3.054873E+01 +4.681242E+01 +4.076365E+00 +8.462370E-01 +5.840647E+01 +1.715260E+02 +4.161366E+01 +8.713062E+01 +5.382541E+00 +1.473814E+00 +6.927641E+01 +2.411359E+02 +4.943841E+01 +1.228850E+02 +6.282202E+00 +1.990021E+00 +7.308593E+01 +2.678848E+02 +5.202069E+01 +1.357621E+02 +6.826145E+00 +2.353974E+00 +7.117026E+01 +2.543546E+02 +5.068896E+01 +1.290261E+02 +6.342979E+00 +2.033850E+00 +6.615720E+01 +2.193712E+02 +4.725156E+01 +1.119514E+02 +6.024815E+00 +1.833752E+00 +5.738164E+01 +1.651944E+02 +4.081217E+01 +8.360122E+01 +5.326191E+00 +1.435896E+00 +4.208669E+01 +8.911740E+01 +2.994944E+01 +4.517409E+01 +3.905846E+00 +7.855247E-01 +2.273578E+01 +2.615080E+01 +1.603853E+01 +1.303560E+01 +2.160924E+00 +2.473278E-01 tally 3: -1.529144E+01 -1.179942E+01 -1.023883E+00 -5.386625E-02 -2.936854E+01 -4.326483E+01 -1.881629E+00 -1.788063E-01 -4.015056E+01 -8.114284E+01 -2.594958E+00 -3.407980E-01 -4.720593E+01 -1.118311E+02 -3.161769E+00 -5.053887E-01 -5.095790E+01 -1.304930E+02 -3.308202E+00 -5.528151E-01 -4.979520E+01 -1.246892E+02 -3.163884E+00 -5.062497E-01 -4.554330E+01 -1.041770E+02 -3.019145E+00 -4.618487E-01 -3.921119E+01 -7.727273E+01 -2.472070E+00 -3.099171E-01 -2.843166E+01 -4.067093E+01 -1.823607E+00 -1.688171E-01 -1.530477E+01 -1.184246E+01 -1.047996E+00 -5.549017E-02 +1.584939E+01 +1.265206E+01 +1.096930E+00 +6.173135E-02 +2.940258E+01 +4.337818E+01 +1.932931E+00 +1.884749E-01 +4.008186E+01 +8.086427E+01 +2.512704E+00 +3.189987E-01 +4.759648E+01 +1.139252E+02 +3.041630E+00 +4.683237E-01 +5.006181E+01 +1.257467E+02 +3.137042E+00 +4.981005E-01 +4.883211E+01 +1.197646E+02 +3.130686E+00 +4.987337E-01 +4.550029E+01 +1.038199E+02 +2.853740E+00 +4.127265E-01 +3.937822E+01 +7.785807E+01 +2.488983E+00 +3.156421E-01 +2.884912E+01 +4.192640E+01 +1.855316E+00 +1.745109E-01 +1.543635E+01 +1.208459E+01 +1.025635E+00 +5.351565E-02 tally 4: 0.000000E+00 0.000000E+00 @@ -160,8 +160,8 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.111592E+00 -4.883699E-01 +3.119914E+00 +4.908283E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -208,10 +208,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.536088E+00 -1.540676E+00 -2.727975E+00 -3.757452E-01 +5.567786E+00 +1.556825E+00 +2.766088E+00 +3.864023E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -256,10 +256,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.518115E+00 -2.840502E+00 -5.271874E+00 -1.398895E+00 +7.491891E+00 +2.819491E+00 +5.235154E+00 +1.377898E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -304,10 +304,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.764240E+00 -3.855378E+00 -7.176540E+00 -2.591613E+00 +8.810357E+00 +3.898704E+00 +7.233068E+00 +2.630659E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -352,10 +352,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.381092E+00 -4.414024E+00 -8.597689E+00 -3.710217E+00 +9.374583E+00 +4.414420E+00 +8.565683E+00 +3.687428E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -400,10 +400,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.158655E+00 -4.215178E+00 -9.188880E+00 -4.244766E+00 +9.001252E+00 +4.073267E+00 +8.974821E+00 +4.050120E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -448,10 +448,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.362511E+00 -3.509173E+00 -9.159213E+00 -4.209143E+00 +8.236452E+00 +3.401934E+00 +9.042286E+00 +4.102906E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -496,10 +496,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.029505E+00 -2.479106E+00 -8.613258E+00 -3.719199E+00 +7.028546E+00 +2.482380E+00 +8.577643E+00 +3.691947E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -544,10 +544,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.119892E+00 -1.320586E+00 -7.401001E+00 -2.749355E+00 +5.159585E+00 +1.342512E+00 +7.389236E+00 +2.745028E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -592,10 +592,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.765680E+00 -3.903229E-01 -5.461998E+00 -1.501206E+00 +2.762685E+00 +3.914181E-01 +5.471849E+00 +1.509910E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -642,8 +642,8 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.044921E+00 -4.656739E-01 +3.038522E+00 +4.643520E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -662,114 +662,114 @@ k cmfd 0.000000E+00 0.000000E+00 0.000000E+00 -1.177990E+00 -1.160010E+00 -1.155990E+00 -1.160167E+00 -1.162166E+00 -1.161566E+00 -1.164454E+00 -1.166269E+00 -1.168529E+00 -1.168622E+00 -1.170296E+00 -1.168644E+00 -1.172975E+00 -1.176543E+00 -1.173389E+00 -1.178422E+00 +1.180802E+00 +1.162698E+00 +1.162794E+00 +1.159752E+00 +1.152596E+00 +1.151652E+00 +1.148131E+00 +1.151875E+00 +1.151434E+00 +1.158833E+00 +1.160751E+00 +1.155305E+00 +1.155356E+00 +1.158866E+00 +1.161574E+00 +1.154691E+00 cmfd entropy 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.214145E+00 -3.225292E+00 -3.229509E+00 -3.228530E+00 -3.224203E+00 -3.225547E+00 -3.224720E+00 -3.224546E+00 -3.224527E+00 -3.223579E+00 -3.224380E+00 -3.223483E+00 -3.222819E+00 -3.223067E+00 -3.224007E+00 -3.220616E+00 +3.214195E+00 +3.225164E+00 +3.227316E+00 +3.225663E+00 +3.226390E+00 +3.225832E+00 +3.226707E+00 +3.227866E+00 +3.229948E+00 +3.229269E+00 +3.230044E+00 +3.231568E+00 +3.234694E+00 +3.234771E+00 +3.234915E+00 +3.235876E+00 cmfd balance 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.801684E-03 -2.802571E-03 -1.828029E-03 -2.220542E-03 -1.709900E-03 -2.008246E-03 -2.578373E-03 -2.000076E-03 -1.645365E-03 -1.462882E-03 -1.208273E-03 -1.146126E-03 -1.214196E-03 -1.082376E-03 -8.967163E-04 -1.154433E-03 +4.742525E-03 +2.646417E-03 +1.981783E-03 +1.856593E-03 +1.797685E-03 +2.122587E-03 +1.200823E-03 +2.177249E-03 +1.442840E-03 +1.477754E-03 +1.236325E-03 +1.048988E-03 +8.395164E-04 +7.380254E-04 +7.742837E-04 +8.235911E-04 cmfd dominance ratio 0.000E+00 0.000E+00 0.000E+00 0.000E+00 - 5.472E-01 - 5.521E-01 - 5.445E-01 - 5.527E-01 + 5.467E-01 + 5.518E-01 + 5.535E-01 + 5.500E-01 + 5.481E-01 + 5.478E-01 + 5.467E-01 + 5.465E-01 + 5.493E-01 5.488E-01 - 5.078E-01 - 5.474E-01 - 5.475E-01 - 5.473E-01 - 5.469E-01 - 5.461E-01 - 5.455E-01 - 5.454E-01 - 5.459E-01 - 5.460E-01 - 5.432E-01 + 5.491E-01 + 5.503E-01 + 5.529E-01 + 5.531E-01 + 5.534E-01 + 5.552E-01 cmfd openmc source comparison 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.186654E-03 -6.033650E-03 -3.920380E-03 -4.218939E-03 -4.591972E-03 -4.042772E-03 -4.100500E-03 -3.664495E-03 -3.266803E-03 -3.164213E-03 -3.310474E-03 -3.165822E-03 -3.849586E-03 -2.718170E-03 -2.431480E-03 -3.322902E-03 +9.168094E-03 +5.978693E-03 +4.369223E-03 +4.546309E-03 +4.222522E-03 +4.221686E-03 +4.604208E-03 +3.950286E-03 +2.939283E-03 +3.667020E-03 +2.592899E-03 +2.272158E-03 +1.229170E-03 +1.114150E-03 +1.060490E-03 +1.714222E-03 cmfd source -4.296288E-02 -7.964357E-02 -1.107722E-01 -1.359821E-01 -1.425321E-01 -1.356719E-01 -1.285829E-01 -1.040603E-01 -7.630230E-02 -4.348975E-02 +4.724285E-02 +8.305825E-02 +1.081058E-01 +1.314542E-01 +1.357299E-01 +1.359417E-01 +1.240918E-01 +1.087580E-01 +8.111239E-02 +4.450518E-02 diff --git a/tests/test_cmfd_nofeed/results_true.dat b/tests/test_cmfd_nofeed/results_true.dat index e70287bf7..308dd7d82 100644 --- a/tests/test_cmfd_nofeed/results_true.dat +++ b/tests/test_cmfd_nofeed/results_true.dat @@ -83,44 +83,44 @@ tally 2: 2.336090E+00 2.851840E-01 tally 3: -1.523800E+01 -1.170551E+01 +1.524100E+01 +1.171023E+01 1.071050E+00 5.839198E-02 -2.862100E+01 -4.111143E+01 +2.862800E+01 +4.113148E+01 1.892774E+00 1.812712E-01 -3.804200E+01 -7.314552E+01 +3.804600E+01 +7.316097E+01 2.423654E+00 2.968521E-01 -4.433500E+01 -9.878201E+01 +4.434600E+01 +9.882906E+01 2.823929E+00 4.033633E-01 -4.954300E+01 -1.229796E+02 +4.955300E+01 +1.230293E+02 3.226029E+00 5.265680E-01 -4.999000E+01 -1.256279E+02 +4.999400E+01 +1.256474E+02 3.232464E+00 5.286388E-01 -4.723500E+01 -1.120638E+02 +4.724300E+01 +1.121029E+02 3.015553E+00 4.606928E-01 -4.050800E+01 -8.237529E+01 +4.051300E+01 +8.239672E+01 2.592073E+00 3.412174E-01 -2.911800E+01 -4.263022E+01 +2.912700E+01 +4.265700E+01 1.875109E+00 1.785438E-01 -1.592800E+01 -1.279461E+01 +1.593500E+01 +1.280638E+01 1.038638E+00 5.538157E-02 tally 4: @@ -662,114 +662,114 @@ k cmfd 0.000000E+00 0.000000E+00 0.000000E+00 -1.177990E+00 -1.160491E+00 -1.145875E+00 -1.148719E+00 -1.140676E+00 -1.141509E+00 -1.143597E+00 -1.141954E+00 -1.150311E+00 -1.155088E+00 -1.155464E+00 -1.152786E+00 -1.156950E+00 -1.159040E+00 -1.160571E+00 -1.161251E+00 +1.180802E+00 +1.163440E+00 +1.148572E+00 +1.151423E+00 +1.143374E+00 +1.144091E+00 +1.146212E+00 +1.144900E+00 +1.153511E+00 +1.158766E+00 +1.159179E+00 +1.156627E+00 +1.160647E+00 +1.162860E+00 +1.164312E+00 +1.164928E+00 cmfd entropy 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.214145E+00 -3.222082E+00 -3.225870E+00 -3.230292E+00 -3.228784E+00 -3.228863E+00 -3.228331E+00 -3.230222E+00 -3.231212E+00 -3.230979E+00 -3.229831E+00 -3.229258E+00 -3.228559E+00 -3.227915E+00 -3.227427E+00 -3.229561E+00 +3.214195E+00 +3.222259E+00 +3.225989E+00 +3.230436E+00 +3.228875E+00 +3.229003E+00 +3.228502E+00 +3.230397E+00 +3.231417E+00 +3.231192E+00 +3.229995E+00 +3.229396E+00 +3.228730E+00 +3.228091E+00 +3.227600E+00 +3.229723E+00 cmfd balance 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.801684E-03 -3.228380E-03 -2.568997E-03 -2.195796E-03 -2.248884E-03 -3.405416E-03 -2.332198E-03 -2.576061E-03 -2.326651E-03 -2.324425E-03 -2.205364E-03 -2.112702E-03 -1.864656E-03 -1.804877E-03 -1.557106E-03 -1.312058E-03 +4.742525E-03 +3.110598E-03 +2.490108E-03 +2.114137E-03 +2.190200E-03 +3.281877E-03 +2.219193E-03 +2.458372E-03 +2.200863E-03 +2.181858E-03 +2.064212E-03 +1.961178E-03 +1.713250E-03 +1.665361E-03 +1.436016E-03 +1.193462E-03 cmfd dominance ratio 0.000E+00 0.000E+00 0.000E+00 0.000E+00 - 5.472E-01 - 5.510E-01 - 5.519E-01 - 5.535E-01 - 5.535E-01 + 5.467E-01 5.505E-01 - 5.488E-01 - 5.505E-01 - 5.510E-01 - 5.513E-01 - 5.510E-01 + 5.514E-01 + 5.531E-01 + 5.529E-01 + 5.501E-01 + 5.484E-01 + 5.500E-01 + 5.506E-01 5.508E-01 - 5.487E-01 - 5.489E-01 - 5.481E-01 - 5.499E-01 + 5.504E-01 + 5.500E-01 + 5.480E-01 + 5.482E-01 + 5.475E-01 + 5.493E-01 cmfd openmc source comparison 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.186654E-03 -5.964812E-03 -4.465905E-03 -4.119425E-03 -4.973577E-03 -4.092492E-03 -4.063342E-03 -2.804589E-03 -3.632667E-03 -5.005042E-03 -3.428575E-03 -3.007070E-03 -3.091465E-03 -3.030625E-03 -2.751739E-03 -1.762364E-03 +9.168094E-03 +5.976241E-03 +4.426550E-03 +4.107499E-03 +4.957716E-03 +4.026213E-03 +3.986000E-03 +2.702714E-03 +3.619345E-03 +4.909616E-03 +3.355042E-03 +2.945724E-03 +3.010811E-03 +2.965662E-03 +2.673073E-03 +1.669634E-03 cmfd source -4.538792E-02 -8.103354E-02 -1.045198E-01 -1.221411E-01 -1.398214E-01 -1.401011E-01 -1.305055E-01 -1.120110E-01 -8.032924E-02 -4.414939E-02 +4.539734E-02 +8.104913E-02 +1.045143E-01 +1.221516E-01 +1.398002E-01 +1.400323E-01 +1.304628E-01 +1.120006E-01 +8.038230E-02 +4.420934E-02 diff --git a/tests/test_many_scores/results_true.dat b/tests/test_many_scores/results_true.dat index ab1c43254..bb151ae0e 100644 --- a/tests/test_many_scores/results_true.dat +++ b/tests/test_many_scores/results_true.dat @@ -7,16 +7,8 @@ tally 1: 3.427342E+01 8.628000E+00 2.481430E+01 -8.628000E+00 -2.481430E+01 -5.102293E-01 -8.710841E-02 -8.628000E+00 -2.481430E+01 -9.329009E-01 -2.902534E-01 -5.102293E-01 -8.710841E-02 +8.632000E+00 +2.483728E+01 5.102293E-01 8.710841E-02 8.628000E+00 @@ -25,6 +17,14 @@ tally 1: 2.902534E-01 5.102293E-01 8.710841E-02 +5.087118E-01 +8.657086E-02 +8.632000E+00 +2.483728E+01 +9.328366E-01 +2.902108E-01 +5.087118E-01 +8.657086E-02 9.212024E+00 2.829472E+01 8.628000E+00 @@ -89,23 +89,23 @@ tally 1: 1.459209E-04 4.629047E-02 7.823267E-04 -8.628000E+00 -2.481430E+01 --4.712248E-02 -1.140942E-03 --6.431930E-02 -4.290580E-03 --9.251642E-02 -8.134201E-03 -1.020119E-04 -1.154184E-04 --2.994164E-02 -3.079076E-04 -2.128844E-02 -2.046549E-04 -1.637972E-02 -1.459209E-04 -4.629047E-02 -7.823267E-04 +8.632000E+00 +2.483728E+01 +-4.651997E-02 +1.133839E-03 +-6.416955E-02 +4.279418E-03 +-9.280565E-02 +8.095106E-03 +-2.078094E-04 +1.151292E-04 +-3.005568E-02 +3.104764E-04 +2.199519E-02 +2.179172E-04 +1.660645E-02 +1.451345E-04 +4.607553E-02 +7.673412E-04 1.014000E+01 3.427342E+01 From a3b87ad37224dbf11de6e3e1a75c67121b09fe3e Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Sat, 26 Sep 2015 14:16:04 -0400 Subject: [PATCH 90/95] Fixed source code standard issues that travis called me out on --- src/tally.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 2b805b27d..0b13dbeba 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -176,7 +176,7 @@ contains ! weight times the multiplicity as the estimate for the number of ! neutrons exiting a reaction with neutrons in the exit channel if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & - (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then multiplicity = ONE else do m = 1, nuclides(p % event_nuclide) % n_reaction @@ -211,7 +211,7 @@ contains ! weight times the multiplicity as the estimate for the number of ! neutrons exiting a reaction with neutrons in the exit channel if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & - (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then multiplicity = ONE else do m = 1, nuclides(p % event_nuclide) % n_reaction @@ -246,7 +246,7 @@ contains ! weight times the multiplicity as the estimate for the number of ! neutrons exiting a reaction with neutrons in the exit channel if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & - (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then multiplicity = ONE else do m = 1, nuclides(p % event_nuclide) % n_reaction From 378d4fc0904ff15aba206e7c7ffb7462a744fe55 Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Sat, 26 Sep 2015 14:36:23 -0400 Subject: [PATCH 91/95] Some remaining updats to make from merge... --- openmc/filter.py | 3 ++- openmc/tallies.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index 6dd4bdaff..b99fb121b 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -9,7 +9,8 @@ from openmc.checkvalue import check_type, check_iterable_type, \ check_greater_than, _isinstance _FILTER_TYPES = ['universe', 'material', 'cell', 'cellborn', 'surface', - 'mesh', 'energy', 'energyout', 'distribcell'] + 'mesh', 'energy', 'energyout', 'mu', 'polar', 'azimuthal', + 'distribcell'] class Filter(object): """A filter used to constrain a tally to a specific criterion, e.g. only tally diff --git a/openmc/tallies.py b/openmc/tallies.py index 20a6af3f2..2d2b248b3 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1278,6 +1278,23 @@ class Tally(object): filter_bins = np.tile(filter_bins, tile_factor) df[filter.type + ' [MeV]'] = filter_bins + # mu, polar, and azimuthal + elif filter.type in ['mu', 'polar', 'azimuthal']: + bins = filter.bins + num_bins = filter.num_bins + + # Create strings for + template = '{0:1.2f} - {1:1.2f}' + filter_bins = [] + for i in range(num_bins): + filter_bins.append(template.format(bins[i], bins[i+1])) + + # Tile the mu bins into a DataFrame column + filter_bins = np.repeat(filter_bins, filter.stride) + tile_factor = data_size / len(filter_bins) + filter_bins = np.tile(filter_bins, tile_factor) + df[filter.type] = filter_bins + # universe, material, surface, cell, and cellborn filters else: filter_bins = np.repeat(filter.bins, filter.stride) From e30c609b81a062ed60fa93281e16200daad79d29 Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Sat, 26 Sep 2015 14:42:19 -0400 Subject: [PATCH 92/95] Undoing commit i made to incorrect branch --- openmc/filter.py | 3 +-- openmc/tallies.py | 17 ----------------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index b99fb121b..6dd4bdaff 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -9,8 +9,7 @@ from openmc.checkvalue import check_type, check_iterable_type, \ check_greater_than, _isinstance _FILTER_TYPES = ['universe', 'material', 'cell', 'cellborn', 'surface', - 'mesh', 'energy', 'energyout', 'mu', 'polar', 'azimuthal', - 'distribcell'] + 'mesh', 'energy', 'energyout', 'distribcell'] class Filter(object): """A filter used to constrain a tally to a specific criterion, e.g. only tally diff --git a/openmc/tallies.py b/openmc/tallies.py index 2d2b248b3..20a6af3f2 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1278,23 +1278,6 @@ class Tally(object): filter_bins = np.tile(filter_bins, tile_factor) df[filter.type + ' [MeV]'] = filter_bins - # mu, polar, and azimuthal - elif filter.type in ['mu', 'polar', 'azimuthal']: - bins = filter.bins - num_bins = filter.num_bins - - # Create strings for - template = '{0:1.2f} - {1:1.2f}' - filter_bins = [] - for i in range(num_bins): - filter_bins.append(template.format(bins[i], bins[i+1])) - - # Tile the mu bins into a DataFrame column - filter_bins = np.repeat(filter_bins, filter.stride) - tile_factor = data_size / len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - df[filter.type] = filter_bins - # universe, material, surface, cell, and cellborn filters else: filter_bins = np.repeat(filter.bins, filter.stride) From bb155e2128ca74d5ef3d3818257f4f3fe4a4ba87 Mon Sep 17 00:00:00 2001 From: Kelly Rowland Date: Sat, 26 Sep 2015 22:02:07 -0700 Subject: [PATCH 93/95] fix Shannon Entropy PDF link --- docs/source/methods/eigenvalue.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/methods/eigenvalue.rst b/docs/source/methods/eigenvalue.rst index fe99ba22e..41bf86549 100644 --- a/docs/source/methods/eigenvalue.rst +++ b/docs/source/methods/eigenvalue.rst @@ -142,7 +142,7 @@ than unity. By ensuring that the expected number of fission sites in each mesh cell is constant, the collision density across all cells, and hence the variance of tallies, is more uniform than it would be otherwise. -.. _Shannon entropy: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-06-3737_entropy.pdf +.. _Shannon entropy: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-06-3737.pdf .. [Lieberoth] J. Lieberoth, "A Monte Carlo Technique to Solve the Static Eigenvalue Problem of the Boltzmann Transport Equation," *Nukleonik*, **11**, From 643f9aaccb74fe0adb73f136c9f3d816e049452c Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Sun, 27 Sep 2015 12:54:11 -0400 Subject: [PATCH 94/95] Took advantage of p % wgt already incorporating the multiplicity if the multiplicity is provided as a function of E by just using p % wgt for nu_scatter tallies instead of p % last_wgt * multiplicity --- src/tally.F90 | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 0b13dbeba..7034b6d83 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -62,7 +62,6 @@ contains real(8) :: uvw(3) ! particle direction type(Material), pointer :: mat type(Reaction), pointer :: rxn - real(8) :: multiplicity i = 0 SCORE_LOOP: do q = 1, t % n_user_score_bins @@ -177,7 +176,9 @@ contains ! neutrons exiting a reaction with neutrons in the exit channel if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then - multiplicity = ONE + ! Don't waste time on very common reactions we know have multiplicities + ! of one. + score = p % last_wgt else do m = 1, nuclides(p % event_nuclide) % n_reaction ! Check if this is the desired MT @@ -188,17 +189,17 @@ contains end if end do - ! Get multiplicity + ! Get multiplicity and apply to score if (rxn % multiplicity_with_E) then - multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + ! Then the multiplicity was already incorporated in to p % wgt + ! per the scattering routine, + score = p % wgt else - multiplicity = real(rxn % multiplicity,8) + ! Grab the multiplicity from the rxn + score = p % last_wgt * real(rxn % multiplicity,8) end if end if - ! Apply multiplicity to the last weight - score = p % last_wgt * multiplicity - case (SCORE_NU_SCATTER_PN) ! Only analog estimators are available. @@ -212,7 +213,9 @@ contains ! neutrons exiting a reaction with neutrons in the exit channel if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then - multiplicity = ONE + ! Don't waste time on very common reactions we know have multiplicities + ! of one. + score = p % last_wgt else do m = 1, nuclides(p % event_nuclide) % n_reaction ! Check if this is the desired MT @@ -223,17 +226,17 @@ contains end if end do - ! Get multiplicity + ! Get multiplicity and apply to score if (rxn % multiplicity_with_E) then - multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + ! Then the multiplicity was already incorporated in to p % wgt + ! per the scattering routine, + score = p % wgt else - multiplicity = real(rxn % multiplicity,8) + ! Grab the multiplicity from the rxn + score = p % last_wgt * real(rxn % multiplicity,8) end if end if - ! Apply multiplicity to the last weight - score = p % last_wgt * multiplicity - case (SCORE_NU_SCATTER_YN) ! Only analog estimators are available. @@ -247,7 +250,9 @@ contains ! neutrons exiting a reaction with neutrons in the exit channel if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then - multiplicity = ONE + ! Don't waste time on very common reactions we know have multiplicities + ! of one. + score = p % last_wgt else do m = 1, nuclides(p % event_nuclide) % n_reaction ! Check if this is the desired MT @@ -258,17 +263,17 @@ contains end if end do - ! Get multiplicity + ! Get multiplicity and apply to score if (rxn % multiplicity_with_E) then - multiplicity = interpolate_tab1(rxn % multiplicity_E, p % last_E) + ! Then the multiplicity was already incorporated in to p % wgt + ! per the scattering routine, + score = p % wgt else - multiplicity = real(rxn % multiplicity,8) + ! Grab the multiplicity from the rxn + score = p % last_wgt * real(rxn % multiplicity,8) end if end if - ! Apply multiplicity to the last weight - score = p % last_wgt * multiplicity - case (SCORE_TRANSPORT) ! Only analog estimators are available. From d719129a5618c21dd04bd059fcf1859c03556ab8 Mon Sep 17 00:00:00 2001 From: Adam Nelson Date: Mon, 28 Sep 2015 04:59:29 -0400 Subject: [PATCH 95/95] Removed explicit casting of multiplicity to real in tally.f90, removed tally module dependence on interpolation, and updated nuscatter tests to better capture nu-scattering --- src/tally.F90 | 7 +- tests/test_score_nuscatter/results_true.dat | 14 ++-- tests/test_score_nuscatter/settings.xml | 2 +- tests/test_score_nuscatter_n/results_true.dat | 62 ++++++++-------- tests/test_score_nuscatter_n/settings.xml | 2 +- .../test_score_nuscatter_pn/results_true.dat | 42 +++++------ tests/test_score_nuscatter_pn/settings.xml | 2 +- .../test_score_nuscatter_yn/results_true.dat | 70 +++++++++---------- tests/test_score_nuscatter_yn/settings.xml | 2 +- 9 files changed, 101 insertions(+), 102 deletions(-) diff --git a/src/tally.F90 b/src/tally.F90 index 7034b6d83..d8ecf4db5 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -5,7 +5,6 @@ module tally use error, only: fatal_error use geometry_header use global - use interpolation use math, only: t_percentile, calc_pn, calc_rn use mesh, only: get_mesh_bin, bin_to_mesh_indices, & get_mesh_indices, mesh_indices_to_bin, & @@ -196,7 +195,7 @@ contains score = p % wgt else ! Grab the multiplicity from the rxn - score = p % last_wgt * real(rxn % multiplicity,8) + score = p % last_wgt * rxn % multiplicity end if end if @@ -233,7 +232,7 @@ contains score = p % wgt else ! Grab the multiplicity from the rxn - score = p % last_wgt * real(rxn % multiplicity,8) + score = p % last_wgt * rxn % multiplicity end if end if @@ -270,7 +269,7 @@ contains score = p % wgt else ! Grab the multiplicity from the rxn - score = p % last_wgt * real(rxn % multiplicity,8) + score = p % last_wgt * rxn % multiplicity end if end if diff --git a/tests/test_score_nuscatter/results_true.dat b/tests/test_score_nuscatter/results_true.dat index df695d8a8..66e0c0a03 100644 --- a/tests/test_score_nuscatter/results_true.dat +++ b/tests/test_score_nuscatter/results_true.dat @@ -1,11 +1,11 @@ k-combined: -1.005983E+00 2.248579E-02 +9.870214E-01 2.095925E-02 tally 1: 0.000000E+00 0.000000E+00 -1.169000E+01 -2.915330E+01 -3.200000E+00 -2.342600E+00 -4.064000E+01 -3.595168E+02 +3.353000E+01 +1.133379E+02 +8.150000E+00 +6.793700E+00 +1.098500E+02 +1.221333E+03 diff --git a/tests/test_score_nuscatter/settings.xml b/tests/test_score_nuscatter/settings.xml index 517637a59..ce632aae3 100644 --- a/tests/test_score_nuscatter/settings.xml +++ b/tests/test_score_nuscatter/settings.xml @@ -3,7 +3,7 @@ 10 - 5 + 0 100 diff --git a/tests/test_score_nuscatter_n/results_true.dat b/tests/test_score_nuscatter_n/results_true.dat index b46a1e184..5dbc7f8ab 100644 --- a/tests/test_score_nuscatter_n/results_true.dat +++ b/tests/test_score_nuscatter_n/results_true.dat @@ -1,33 +1,33 @@ k-combined: -1.005983E+00 2.248579E-02 +9.870214E-01 2.095925E-02 tally 1: -1.169000E+01 -2.915330E+01 -1.247253E+00 -3.767436E-01 -5.330812E-01 -1.385083E-01 -2.987823E-01 -5.699361E-02 -2.645512E-01 -2.905381E-02 -3.200000E+00 -2.342600E+00 -3.809941E-01 -2.965326E-02 -4.319242E-01 -3.738822E-02 -9.261909E-02 -6.711328E-03 --6.052442E-02 -7.087230E-03 -4.064000E+01 -3.595168E+02 -2.096700E+01 -9.516606E+01 -7.560566E+00 -1.248694E+01 -2.093348E-01 -4.278510E-02 --1.449929E+00 -4.356371E-01 +3.353000E+01 +1.133379E+02 +3.491100E+00 +1.265776E+00 +1.948509E+00 +4.761101E-01 +9.177045E-01 +1.251750E-01 +5.654249E-01 +5.567043E-02 +8.150000E+00 +6.793700E+00 +1.223263E+00 +1.678053E-01 +7.833173E-01 +8.407682E-02 +1.350170E-01 +7.393546E-03 +2.164837E-01 +1.367122E-02 +1.098500E+02 +1.221333E+03 +5.598624E+01 +3.183267E+02 +2.048716E+01 +4.301097E+01 +1.399456E+00 +4.458904E-01 +-2.183180E+00 +6.628474E-01 diff --git a/tests/test_score_nuscatter_n/settings.xml b/tests/test_score_nuscatter_n/settings.xml index 517637a59..ce632aae3 100644 --- a/tests/test_score_nuscatter_n/settings.xml +++ b/tests/test_score_nuscatter_n/settings.xml @@ -3,7 +3,7 @@ 10 - 5 + 0 100 diff --git a/tests/test_score_nuscatter_pn/results_true.dat b/tests/test_score_nuscatter_pn/results_true.dat index 3c34895d9..41bc17f8b 100644 --- a/tests/test_score_nuscatter_pn/results_true.dat +++ b/tests/test_score_nuscatter_pn/results_true.dat @@ -1,24 +1,24 @@ k-combined: -1.005983E+00 2.248579E-02 +9.870214E-01 2.095925E-02 tally 1: -1.169000E+01 -2.915330E+01 -1.247253E+00 -3.767436E-01 -5.330812E-01 -1.385083E-01 -2.987823E-01 -5.699361E-02 -2.645512E-01 -2.905381E-02 +3.353000E+01 +1.133379E+02 +3.491100E+00 +1.265776E+00 +1.948509E+00 +4.761101E-01 +9.177045E-01 +1.251750E-01 +5.654249E-01 +5.567043E-02 tally 2: -1.169000E+01 -2.915330E+01 -1.247253E+00 -3.767436E-01 -5.330812E-01 -1.385083E-01 -2.987823E-01 -5.699361E-02 -2.645512E-01 -2.905381E-02 +3.353000E+01 +1.133379E+02 +3.491100E+00 +1.265776E+00 +1.948509E+00 +4.761101E-01 +9.177045E-01 +1.251750E-01 +5.654249E-01 +5.567043E-02 diff --git a/tests/test_score_nuscatter_pn/settings.xml b/tests/test_score_nuscatter_pn/settings.xml index 517637a59..ce632aae3 100644 --- a/tests/test_score_nuscatter_pn/settings.xml +++ b/tests/test_score_nuscatter_pn/settings.xml @@ -3,7 +3,7 @@ 10 - 5 + 0 100 diff --git a/tests/test_score_nuscatter_yn/results_true.dat b/tests/test_score_nuscatter_yn/results_true.dat index 1e8e143ef..cdf051ee7 100644 --- a/tests/test_score_nuscatter_yn/results_true.dat +++ b/tests/test_score_nuscatter_yn/results_true.dat @@ -1,38 +1,38 @@ k-combined: -1.005983E+00 2.248579E-02 +9.870214E-01 2.095925E-02 tally 1: -1.169000E+01 -2.915330E+01 +3.353000E+01 +1.133379E+02 tally 2: -1.169000E+01 -2.915330E+01 --2.198379E-01 -2.828670E-02 --1.317276E-01 -9.568596E-03 -8.309792E-02 -1.155410E-02 --2.288506E-02 -3.710542E-03 --2.720674E-02 -1.789163E-03 --1.323964E-02 -1.819112E-04 -8.941597E-02 -4.265616E-03 -1.516805E-01 -1.332526E-02 --1.832782E-02 -6.611171E-03 -1.311371E-02 -2.840648E-03 -3.728365E-02 -2.866806E-03 --5.100587E-02 -2.957146E-03 -3.388028E-02 -2.481570E-03 --7.766921E-02 -3.129377E-03 -1.666131E-02 -3.828290E-03 +3.353000E+01 +1.133379E+02 +4.293226E-01 +6.259462E-02 +-2.011041E-02 +5.388144E-02 +3.900136E-01 +5.873137E-02 +6.150213E-02 +9.043796E-03 +5.518583E-02 +1.739087E-02 +-2.047987E-01 +1.993679E-02 +6.710345E-02 +1.652573E-02 +-3.619254E-02 +1.598186E-02 +3.551558E-02 +9.077346E-03 +1.044669E-01 +2.082961E-03 +-3.782063E-02 +1.681459E-02 +1.752386E-01 +1.411429E-02 +-3.289649E-02 +9.534958E-03 +5.252770E-02 +7.518445E-03 +2.688056E-02 +3.397824E-03 diff --git a/tests/test_score_nuscatter_yn/settings.xml b/tests/test_score_nuscatter_yn/settings.xml index 517637a59..ce632aae3 100644 --- a/tests/test_score_nuscatter_yn/settings.xml +++ b/tests/test_score_nuscatter_yn/settings.xml @@ -3,7 +3,7 @@ 10 - 5 + 0 100