Merge pull request #447 from paulromano/new-hdf5-interface

Complete revamp of binary output featuring new HDF5 interface
This commit is contained in:
Sterling Harper 2015-09-14 16:46:30 -04:00
commit f8bfa401cb
46 changed files with 4404 additions and 7379 deletions

View file

@ -7,6 +7,12 @@ 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)
#===============================================================================
# Architecture specific definitions
#===============================================================================
@ -23,37 +29,23 @@ 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")
add_definitions(-DMAX_COORD=${maxcoord})
#===============================================================================
# MPI for distributed-memory parallelism / HDF5 for binary output
# MPI for distributed-memory parallelism
#===============================================================================
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$")
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)
set(MPI_ENABLED TRUE)
set(HDF5_ENABLED TRUE)
endif()
# Check for Fortran 2008 MPI interface
@ -62,11 +54,52 @@ 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
#===============================================================================
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)
@ -75,88 +108,93 @@ 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")
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()
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()
@ -204,10 +242,34 @@ 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_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
# 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()
# 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)
#===============================================================================
# Install executable, scripts, manpage, license
@ -306,38 +368,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}

View file

@ -0,0 +1,399 @@
#.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 <wdicharry@stellarscience.com>.
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()
# Determine whether to search for serial or parallel executable first
if(HDF5_PREFER_PARALLEL)
set(HDF5_C_COMPILER_NAMES h5pcc h5cc)
set(HDF5_CXX_COMPILER_NAMES h5pc++ h5c++)
set(HDF5_Fortran_COMPILER_NAMES h5pfc h5fc)
else()
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 )
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
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} )
# find the HDF5 libraries
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.
# 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} )
# 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})
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 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
)

View file

@ -16,6 +16,5 @@ as debugging.
styleguide
workflow
xml-parsing
statepoint
voxel
docbuild

View file

@ -1,291 +0,0 @@
.. _devguide_statepoint:
======================================
State Point Binary File Specifications
======================================
The current revision of the statepoint binary file is 13.
**integer(4) FILETYPE_STATEPOINT**
Flags whether this file is a statepoint file or a particle restart file.
**integer(4) REVISION_STATEPOINT**
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**
Major version number for OpenMC
**integer(4) VERSION_MINOR**
Minor version number for OpenMC
**integer(4) VERSION_RELEASE**
Release version number for OpenMC
**character(19) time_stamp**
Date and time the state point was written.
**character(255) path**
Absolute path to directory containing input files.
**integer(8) seed**
Pseudo-random number generator seed.
**integer(4) run_mode**
run mode used. The modes are described in constants.F90.
**integer(8) n_particles**
Number of particles used per generation.
**integer(4) current_batch**
The number of batches already simulated.
if (run_mode == MODE_EIGENVALUE)
**integer(4) n_inactive**
Number of inactive batches
**integer(4) gen_per_batch**
Number of generations per batch for criticality calculations
*do i = 1, current_batch \* gen_per_batch*
**real(8) k_generation(i)**
k-effective for the i-th total generation
*do i = 1, current_batch \* gen_per_batch*
**real(8) entropy(i)**
Shannon entropy for the i-th total generation
**real(8) k_col_abs**
Sum of product of collision/absorption estimates of k-effective
**real(8) k_col_tra**
Sum of product of collision/track-length estimates of k-effective
**real(8) k_abs_tra**
Sum of product of absorption/track-length estimates of k-effective
**real(8) k_combined(2)**
Mean and standard deviation of a combined estimate of k-effective
**integer(4) cmfd_on**
Flag that cmfd is on
if (cmfd_on)
**integer(4) cmfd % indices**
Indices for cmfd mesh (i,j,k,g)
**real(8) cmfd % k_cmfd(1:current_batch)**
CMFD eigenvalues
**real(8) cmfd % src(1:G,1:I,1:J,1:K)**
CMFD fission source
**real(8) cmfd % entropy(1:current_batch)**
CMFD estimate of Shannon entropy
**real(8) cmfd % balance(1:current_batch)**
RMS of the residual neutron balance equation on CMFD mesh
**real(8) cmfd % dom(1:current_batch)**
CMFD estimate of dominance ratio
**real(8) cmfd % scr_cmp(1:current_batch)**
RMS comparison of difference between OpenMC and CMFD fission source
**integer(4) n_meshes**
Number of meshes in tallies.xml file
*do i = 1, n_meshes*
**integer(4) meshes(i) % id**
Unique ID of mesh.
**integer(4) meshes(i) % type**
Type of mesh.
**integer(4) meshes(i) % n_dimension**
Number of dimensions for mesh (2 or 3).
**integer(4) meshes(i) % dimension(:)**
Number of mesh cells in each dimension.
**real(8) meshes(i) % lower_left(:)**
Coordinates of lower-left corner of mesh.
**real(8) meshes(i) % upper_right(:)**
Coordinates of upper-right corner of mesh.
**real(8) meshes(i) % width(:)**
Width of each mesh cell in each dimension.
**integer(4) n_tallies**
*do i = 1, n_tallies*
**integer(4) tallies(i) % id**
Unique ID of tally.
**integer(4) tallies(i) % n_realizations**
Number of realizations for the i-th tally.
**integer(4) size(tallies(i) % scores, 1)**
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**
*do j = 1, tallies(i) % n_filters*
**integer(4) tallies(i) % filter(j) % type**
Type of tally filter.
**integer(4) tallies(i) % filter(j) % n_bins**
Number of bins for filter.
**integer(4)/real(8) tallies(i) % filter(j) % bins(:)**
Value for each filter bin of this type.
**integer(4) tallies(i) % n_nuclide_bins**
Number of nuclide bins. If none are specified, this is just one.
*do j = 1, tallies(i) % n_nuclide_bins*
**integer(4) tallies(i) % nuclide_bins(j)**
Values of specified nuclide bins
**integer(4) tallies(i) % n_score_bins**
Number of scoring bins.
*do j = 1, tallies(i) % n_score_bins*
**integer(4) tallies(i) % score_bins(j)**
Values of specified scoring bins (e.g. SCORE_FLUX).
**integer(4) tallies(i) % n_score_bins**
Number of scoring bins without accounting for those added by
the scatter-pn command.
*do j = 1, tallies(i) % n_user_score_bins*
**character(8) tallies(i) % moment_order(j)**
Tallying moment order for Legendre and spherical
harmonic tally expansions (*e.g.*, 'P2', 'Y1,2', etc.).
**integer(4) source_present**
Flag indicated if source bank is present in the file
**integer(4) n_realizations**
Number of realizations for global tallies.
**integer(4) N_GLOBAL_TALLIES**
Number of global tally scores
*do i = 1, N_GLOBAL_TALLIES*
**real(8) global_tallies(i) % sum**
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**
Flag indicated if tallies are present in the file.
if (tallies_on > 0)
*do i = 1, n_tallies*
*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
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.

View file

@ -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 HDF5_ installed, you can download and install OpenMC be
entering the following commands in a terminal:
.. code-block:: sh

View file

@ -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

View file

@ -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
-------------------------------
@ -308,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
-------------

View file

@ -0,0 +1,14 @@
.. _usersguide_output:
===================
Output File Formats
===================
.. toctree::
:numbered:
:maxdepth: 3
statepoint
source
particle_restart
track

View file

@ -0,0 +1,59 @@
.. _usersguide_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, a value of -3 indicates a
source file, and a value of -4 indicates a track file.
**/revision** (*int*)
Revision of the particle restart file format. Any time a change is made in
the format, 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.

View file

@ -0,0 +1,21 @@
.. _usersguide_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.

View file

@ -0,0 +1,276 @@
.. _usersguide_statepoint:
=======================
State Point File Format
=======================
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, a value of -3 indicates a
source file, and a value of -4 indicates a track file.
**/revision** (*int*)
Revision of the state point 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
**/time_stamp** (*char[19]*)
Date and time the state point was written.
**/path** (*char[255]*)
Absolute path to directory containing input files.
**/seed** (*int8_t*)
Pseudo-random number generator seed.
**/run_mode** (*int*)
Run mode used. A value of 1 indicates a fixed-source run and a value of 2
indicates an eigenvalue run.
**/n_particles** (*int8_t*)
Number of particles used per generation.
**/n_batches** (*int*)
Number of batches to simulate.
**/current_batch** (*int*)
The number of batches already simulated.
if (run_mode == MODE_EIGENVALUE)
**/n_inactive** (*int*)
Number of inactive batches.
**/gen_per_batch** (*int*)
Number of generations per batch.
**/k_generation** (*double[]*)
k-effective for each generation simulated.
**/entropy** (*double[]*)
Shannon entropy for each generation simulated
**/k_col_abs** (*double*)
Sum of product of collision/absorption estimates of k-effective
**/k_col_tra** (*double*)
Sum of product of collision/track-length estimates of k-effective
**/k_abs_tra** (*double*)
Sum of product of absorption/track-length estimates of k-effective
**/k_combined** (*double[2]*)
Mean and standard deviation of a combined estimate of k-effective
**/cmfd_on** (*int*)
Flag indicating whether CMFD is on (1) or off (0).
if (cmfd_on)
**/cmfd/indices** (*int[4]*)
Indices for cmfd mesh (i,j,k,g)
**/cmfd/k_cmfd** (*double[]*)
CMFD eigenvalues
**/cmfd/cmfd_src** (*double[][][][]*)
CMFD fission source
**/cmfd/cmfd_entropy** (*double[]*)
CMFD estimate of Shannon entropy
**/cmfd/cmfd_balance** (*double[]*)
RMS of the residual neutron balance equation on CMFD mesh
**/cmfd/cmfd_dominance** (*double[]*)
CMFD estimate of dominance ratio
**/cmfd/cmfd_srccmp** (*double[]*)
RMS comparison of difference between OpenMC and CMFD fission source
**/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*
**/tallies/meshes/mesh i/id** (*int*)
Unique identifier of the mesh.
**/tallies/meshes/mesh i/type** (*int*)
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.
**/tallies/meshes/mesh i/lower_left** (*double[]*)
Coordinates of lower-left corner of mesh.
**/tallies/meshes/mesh i/upper_right** (*double[]*)
Coordinates of upper-right corner of mesh.
**/tallies/meshes/mesh i/width** (*double[]*)
Width of each mesh cell in each dimension.
**/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*
**/tallies/tally i/estimator** (*int*)
Type of tally estimator: analog (1) or tracklength (2).
**/tallies/tally i/n_realizations** (*int*)
Number of realizations.
**/tallies/tally i/n_filters** (*int*)
Number of filters used.
*do j = 1, tallies(i) % n_filters*
**/tallies/tally i/filter j/type** (*int*)
Type of tally filter.
**/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.
**/tallies/tally i/filter j/bins** (*int[]* or *double[]*)
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** (*int[]*)
Values of specified nuclide bins (ZAID identifiers)
**/tallies/tally i/n_score_bins** (*int*)
Number of scoring bins.
**/tallies/tally i/score_bins** (*int*)
Values of specified scoring bins (e.g. SCORE_FLUX).
**/tallies/tally i/n_user_score_bins**
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/moments/orderJ** (*char[8]*)
Tallying moment order for Legendre and spherical
harmonic tally expansions (*e.g.*, 'P2', 'Y1,2', etc.).
**/source_present** (*int*)
Flag indicated if source bank is present in the file
**/n_realizations** (*int*)
Number of realizations for global tallies.
**/n_global_tallies** (*int*)
Number of global tally scores.
**/global_tallies** (Compound type)
Accumulated sum and sum-of-squares for each global tally. The compound type
has fields named ``sum`` and ``sum_sq``.
**tallies_present** (*int*)
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)
**/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.

View file

@ -0,0 +1,32 @@
.. _usersguide_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.

View file

@ -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

View file

@ -40,70 +40,31 @@ 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()
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_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)]
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)]
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)]
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)]
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])
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

View file

@ -1,5 +1,4 @@
import copy
import struct
import sys
import numpy as np
@ -92,13 +91,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
@ -163,40 +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
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._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:
@ -206,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_generation = 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()
@ -226,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
@ -253,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 = []
@ -277,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)
@ -316,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 = []
@ -339,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)
@ -352,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)
@ -361,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}" ' \
@ -378,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)
@ -395,33 +358,31 @@ 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[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._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]
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):
@ -437,8 +398,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('\']')
@ -468,21 +429,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
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]
self._tallies_present = self._f['tallies/tallies_present'].value
base = 'tallies/tally '
@ -499,15 +455,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 +497,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 +505,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
@ -792,43 +735,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):
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)]
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)]
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)]
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)]
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)
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])

View file

@ -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")

View file

@ -18,6 +18,7 @@ Usage information can be obtained by running 'track.py --help':
import os
import argparse
import h5py
import struct
import vtk
@ -39,56 +40,26 @@ def main():
# Parse commandline arguments.
args = _parse_args()
# 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'.")
# Make sure that the output filename ends with '.pvtp'.
if not args.out:
args.out = 'tracks.pvtp'
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[0]
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.

View file

@ -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

View file

@ -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

View file

@ -9,9 +9,8 @@ module finalize
use message_passing
#endif
#ifdef HDF5
use hdf5_interface, only: h5tclose_f, h5close_f, hdf5_err
#endif
use hdf5_interface, only: hdf5_bank_t, hdf5_tallyresult_t
use hdf5, only: h5tclose_f, h5close_f
implicit none
@ -24,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
@ -39,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()
@ -51,14 +52,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

View file

@ -16,9 +16,6 @@ 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
@ -267,16 +264,6 @@ module global
real(8) :: weight_cutoff = 0.25_8
real(8) :: weight_survive = ONE
! ============================================================================
! 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

File diff suppressed because it is too large Load diff

View file

@ -1,880 +0,0 @@
module hdf5_summary
#ifdef HDF5
use ace_header, only: Reaction, UrrData, Nuclide
use constants
use endf, only: reaction_name
use geometry_header, only: Cell, Surface, Universe, Lattice, RectLattice, &
&HexLattice
use global
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
type(BinaryOutput) :: su
contains
!===============================================================================
! HDF5_WRITE_SUMMARY
!===============================================================================
subroutine hdf5_write_summary()
character(MAX_FILE_LEN) :: filename = "summary.h5"
! Create a new file using default properties.
call su % file_create(filename)
! Write header information
call hdf5_write_header()
! Write eigenvalue information
if (run_mode == MODE_EIGENVALUE) then
! Write number of particles
call su % write_data(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")
! Add description of each variable
call su % write_attribute_string("n_particles", &
"description", "Number of particles per generation")
call su % write_attribute_string("n_batches", &
"description", "Total number of batches")
call su % write_attribute_string("n_inactive", &
"description", "Number of inactive batches")
call su % write_attribute_string("n_active", &
"description", "Number of active batches")
call su % write_attribute_string("gen_per_batch", &
"description", "Number of generations per batch")
end if
call hdf5_write_geometry()
call hdf5_write_materials()
call hdf5_write_nuclides()
if (n_tallies > 0) then
call hdf5_write_tallies()
end if
! Terminate access to the file.
call su % file_close()
end subroutine hdf5_write_summary
!===============================================================================
! HDF5_WRITE_HEADER
!===============================================================================
subroutine hdf5_write_header()
! 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")
! Write current date and time
call su % write_data(time_stamp(), "date_and_time")
! Write MPI information
call su % write_data(n_procs, "n_procs")
call su % write_attribute_string("n_procs", "description", &
"Number of MPI processes")
end subroutine hdf5_write_header
!===============================================================================
! HDF5_WRITE_GEOMETRY
!===============================================================================
subroutine hdf5_write_geometry()
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()
! 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")
! ==========================================================================
! 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()
! Write information on each cell
CELL_LOOP: do i = 1, n_cells
c => cells(i)
! Write internal OpenMC index for this cell
call su % write_data(i, "index", &
group="geometry/cells/cell " // trim(to_str(c % id)))
! Write name for this cell
call su % write_data(c % name, "name", &
group="geometry/cells/cell " // trim(to_str(c % id)))
! Write universe for this cell
call su % write_data(universes(c % universe) % id, "universe", &
group="geometry/cells/cell " // trim(to_str(c % id)))
! Write information on what fills this cell
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)))
else
call su % write_data(materials(c % material) % id, "material", &
group="geometry/cells/cell " // trim(to_str(c % 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)))
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)))
else
call su % write_data(0, "translated", &
group="geometry/cells/cell " // trim(to_str(c % id)))
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)))
else
call su % write_data(0, "rotated", &
group="geometry/cells/cell " // trim(to_str(c % id)))
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)))
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)))
end if
end do CELL_LOOP
! ==========================================================================
! WRITE INFORMATION ON SURFACES
! Create surfaces group (nothing directly written here) then close
call su % open_group("geometry/surfaces")
call su % close_group()
! Write information on each surface
SURFACE_LOOP: do i = 1, n_surfaces
s => surfaces(i)
! Write internal OpenMC index for this surface
call su % write_data(i, "index", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
! Write name for this surface
call su % write_data(s % name, "name", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
! Write surface type
select case (s % type)
case (SURF_PX)
call su % write_data("X Plane", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_PY)
call su % write_data("Y Plane", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_PZ)
call su % write_data("Z Plane", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_PLANE)
call su % write_data("Plane", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_CYL_X)
call su % write_data("X Cylinder", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_CYL_Y)
call su % write_data("Y Cylinder", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_CYL_Z)
call su % write_data("Z Cylinder", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_SPHERE)
call su % write_data("Sphere", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_CONE_X)
call su % write_data("X Cone", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_CONE_Y)
call su % write_data("Y Cone", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (SURF_CONE_Z)
call su % write_data("Z Cone", "type", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
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)))
! 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)))
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)))
end if
! Write boundary condition
select case (s % bc)
case (BC_TRANSMIT)
call su % write_data("transmission", "boundary_condition", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (BC_VACUUM)
call su % write_data("vacuum", "boundary_condition", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (BC_REFLECT)
call su % write_data("reflective", "boundary_condition", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
case (BC_PERIODIC)
call su % write_data("periodic", "boundary_condition", &
group="geometry/surfaces/surface " // trim(to_str(s % id)))
end select
end do SURFACE_LOOP
! ==========================================================================
! WRITE INFORMATION ON UNIVERSES
! Create universes group (nothing directly written here) then close
call su % open_group("geometry/universes")
call su % close_group()
! Write information on each universe
UNIVERSE_LOOP: do i = 1, n_universes
u => universes(i)
! Write internal OpenMC index for this universe
call su % write_data(i, "index", &
group="geometry/universes/universe " // trim(to_str(u % id)))
! 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
end do UNIVERSE_LOOP
! ==========================================================================
! WRITE INFORMATION ON LATTICES
! Create lattices group (nothing directly written here) then close
call su % open_group("geometry/lattices")
call su % close_group()
! Write information on each lattice
LATTICE_LOOP: do i = 1, n_lattices
lat => lattices(i) % obj
! Write internal OpenMC index for this lattice
call su % write_data(i, "index", &
group="geometry/lattices/lattice " // trim(to_str(lat % id)))
! Write name for this lattice
call su % write_data(lat % name, "name", &
group="geometry/lattices/lattice " // trim(to_str(lat % id)))
! 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)))
! 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)))
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
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)))
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
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)))
deallocate(lattice_universes)
type is (HexLattice)
! Write lattice type.
call su % write_data("hexagonal", "type", &
group="geometry/lattices/lattice " // trim(to_str(lat % id)))
! 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)))
! 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
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 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)))
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
! 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
! 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
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)))
deallocate(lattice_universes)
end select
end do LATTICE_LOOP
end subroutine hdf5_write_geometry
!===============================================================================
! HDF5_WRITE_MATERIALS
!===============================================================================
subroutine hdf5_write_materials()
integer :: i
integer :: j
integer, allocatable :: zaids(:)
type(Material), pointer :: m => null()
! Use H5LT interface to write number of materials
call su % write_data(n_materials, "n_materials", group="materials")
! Write information on each material
do i = 1, n_materials
m => materials(i)
! Write internal OpenMC index for this material
call su % write_data(i, "index", &
group="materials/material " // trim(to_str(m % id)))
! Write name for this material
call su % write_data(m % name, "name", &
group="materials/material " // trim(to_str(m % id)))
! 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)))
! 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
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)))
! 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)))
! Write S(a,b) information if present
call su % write_data(m % n_sab, "n_sab", &
group="materials/material " // trim(to_str(m % id)))
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)))
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")
end do
end if
end do
end subroutine hdf5_write_materials
!===============================================================================
! HDF5_WRITE_TALLIES
!===============================================================================
subroutine hdf5_write_tallies()
integer :: i, j
integer, allocatable :: temp_array(:) ! nuclide bin array
type(StructuredMesh), pointer :: m => null()
type(TallyObject), pointer :: t => null()
! Write total number of meshes
call su % write_data(n_meshes, "n_meshes", group="tallies")
! Write information for meshes
MESH_LOOP: do i = 1, n_meshes
m => meshes(i)
! 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)))
! 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)))
end do MESH_LOOP
! Write number of tallies
call su % write_data(n_tallies, "n_tallies", group="tallies")
TALLY_METADATA: do i = 1, n_tallies
! Get pointer to tally
t => tallies(i)
! 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)))
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)))
! Write number of filters
call su % write_data(t % n_filters, "n_filters", &
group="tallies/tally " // trim(to_str(t % id)))
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)))
! 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)))
! 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)))
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)))
end if
! Write name of 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)))
case(FILTER_MATERIAL)
call su % write_data("material", "type_name", &
group="tallies/tally " // trim(to_str(t % id)) &
// "/filter " // trim(to_str(j)))
case(FILTER_CELL)
call su % write_data("cell", "type_name", &
group="tallies/tally " // trim(to_str(t % id)) &
// "/filter " // trim(to_str(j)))
case(FILTER_CELLBORN)
call su % write_data("cellborn", "type_name", &
group="tallies/tally " // trim(to_str(t % id)) &
// "/filter " // trim(to_str(j)))
case(FILTER_SURFACE)
call su % write_data("surface", "type_name", &
group="tallies/tally " // trim(to_str(t % id)) &
// "/filter " // trim(to_str(j)))
case(FILTER_MESH)
call su % write_data("mesh", "type_name", &
group="tallies/tally " // trim(to_str(t % id)) &
// "/filter " // trim(to_str(j)))
case(FILTER_ENERGYIN)
call su % write_data("energy", "type_name", &
group="tallies/tally " // trim(to_str(t % id)) &
// "/filter " // trim(to_str(j)))
case(FILTER_ENERGYOUT)
call su % write_data("energyout", "type_name", &
group="tallies/tally " // trim(to_str(t % id)) &
// "/filter " // trim(to_str(j)))
end select
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)))
! 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
else
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)))
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)))
end do TALLY_METADATA
end subroutine hdf5_write_tallies
!===============================================================================
! HDF5_WRITE_NUCLIDES
!===============================================================================
subroutine hdf5_write_nuclides()
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()
! Use H5LT interface to write number of nuclides
call su % write_data(n_nuclides_total, "n_nuclides", group="nuclides")
! Write information on each nuclide
NUCLIDE_LOOP: do i = 1, n_nuclides_total
nuc => nuclides(i)
! Write internal OpenMC index for this nuclide
call su % write_data(i, "index", &
group="nuclides/" // trim(nuc % name))
! Determine size of cross-sections
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))
! =======================================================================
! 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()
RXN_LOOP: do j = 1, nuc % n_reaction
! Information on each reaction
rxn => nuc % reactions(j)
! 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 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)))
! Accumulate data size
size_total = size_total + size_angle + size_energy
end do RXN_LOOP
! =======================================================================
! 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))
end if
! Write total memory used
call su % write_data(size_total, "size_total", &
group="nuclides/" // trim(nuc % name))
end do NUCLIDE_LOOP
end subroutine hdf5_write_nuclides
!===============================================================================
! HDF5_WRITE_TIMING
!===============================================================================
subroutine hdf5_write_timing()
integer(8) :: total_particles
real(8) :: speed
! 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")
! 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")
! 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")
end subroutine hdf5_write_timing
#endif
end module hdf5_summary

View file

@ -12,16 +12,17 @@ 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 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_interface
use output, only: title, header, print_version, write_message, &
print_usage, write_xs_summary, print_plot
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
@ -33,10 +34,9 @@ module initialize
use omp_lib
#endif
#ifdef HDF5
use hdf5_interface
use hdf5_summary, only: hdf5_write_summary
#endif
use hdf5
use, intrinsic :: ISO_C_BINDING, only: c_loc
implicit none
@ -52,18 +52,16 @@ 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
call initialize_mpi()
#endif
#ifdef HDF5
! Initialize HDF5 interface
call hdf5_initialize()
#endif
! Read command line arguments
call read_command_line()
@ -115,9 +113,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()
@ -127,9 +125,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
@ -155,11 +153,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()
@ -176,7 +170,7 @@ contains
end if
! Stop initialization timer
call time_initialize % stop()
call time_initialize%stop()
end subroutine initialize_run
@ -229,10 +223,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)
@ -248,8 +242,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
@ -275,8 +269,6 @@ contains
end subroutine initialize_mpi
#endif
#ifdef HDF5
!===============================================================================
! HDF5_INITIALIZE
!===============================================================================
@ -285,6 +277,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
@ -319,8 +312,6 @@ contains
end subroutine hdf5_initialize
#endif
!===============================================================================
! READ_COMMAND_LINE reads all parameters from the command line
!===============================================================================
@ -331,8 +322,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()
@ -369,9 +360,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)
@ -392,13 +383,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")
@ -507,26 +497,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
@ -541,17 +531,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
@ -581,15 +571,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
@ -597,40 +587,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
@ -640,41 +630,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
@ -682,13 +672,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
@ -700,68 +690,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
@ -799,46 +789,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
@ -940,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
@ -953,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
@ -985,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
@ -1034,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
@ -1042,14 +1032,14 @@ 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
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
@ -1060,8 +1050,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
@ -1083,29 +1073,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)
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
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
@ -1113,26 +1103,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

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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,47 +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))
#ifdef HDF5
filename = trim(filename) // '.h5'
#else
filename = trim(filename) // '.binary'
#endif
// '_' // 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

View file

@ -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
@ -79,14 +82,10 @@ 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()
file_id = file_create(filename, parallel=.true.)
call write_source_bank(file_id)
call file_close(file_id)
end if
end subroutine initialize_source
@ -113,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)
@ -146,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)
@ -175,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

File diff suppressed because it is too large Load diff

756
src/summary.F90 Normal file
View file

@ -0,0 +1,756 @@
module summary
use ace_header, only: Reaction, UrrData, Nuclide
use constants
use endf, only: reaction_name
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, only: time_stamp
use string, only: to_str
use tally_header, only: TallyObject
use hdf5
implicit none
private
public :: write_summary
contains
!===============================================================================
! WRITE_SUMMARY
!===============================================================================
subroutine write_summary()
integer(HID_T) :: file_id
! Create a new file using default properties.
file_id = file_create("summary.h5")
! Write header information
call write_header(file_id)
! 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 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_inactive", &
"description", "Number of inactive batches")
call write_attribute_string(file_id, "n_active", &
"description", "Number of active batches")
call write_attribute_string(file_id, "gen_per_batch", &
"description", "Number of generations per batch")
end if
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
! Terminate access to the file.
call file_close(file_id)
end subroutine write_summary
!===============================================================================
! WRITE_HEADER
!===============================================================================
subroutine write_header(file_id)
integer(HID_T), intent(in) :: file_id
! Write version information
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 write_dataset(file_id, "date_and_time", time_stamp())
! Write MPI information
call write_dataset(file_id, "n_procs", n_procs)
call write_attribute_string(file_id, "n_procs", "description", &
"Number of MPI processes")
end subroutine write_header
!===============================================================================
! WRITE_GEOMETRY
!===============================================================================
subroutine write_geometry(file_id)
integer(HID_T), intent(in) :: file_id
integer :: i, j, k, m
integer, allocatable :: lattice_universes(:,:,:)
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
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
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 write_dataset(cell_group, "index", i)
! Write name for this cell
call write_dataset(cell_group, "name", c%name)
! Write universe for this cell
call write_dataset(cell_group, "universe", universes(c%universe)%id)
! Write information on what fills this cell
select case (c%type)
case (CELL_NORMAL)
call write_dataset(cell_group, "fill_type", "normal")
if (c%material == MATERIAL_VOID) then
call write_dataset(cell_group, "material", -1)
else
call write_dataset(cell_group, "material", materials(c%material)%id)
end if
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)
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 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
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 write_dataset(surface_group, "index", i)
! Write name for this surface
call write_dataset(surface_group, "name", s%name)
! Write surface type
select case (s%type)
case (SURF_PX)
call write_dataset(surface_group, "type", "X Plane")
case (SURF_PY)
call write_dataset(surface_group, "type", "Y Plane")
case (SURF_PZ)
call write_dataset(surface_group, "type", "Z Plane")
case (SURF_PLANE)
call write_dataset(surface_group, "type", "Plane")
case (SURF_CYL_X)
call write_dataset(surface_group, "type", "X Cylinder")
case (SURF_CYL_Y)
call write_dataset(surface_group, "type", "Y Cylinder")
case (SURF_CYL_Z)
call write_dataset(surface_group, "type", "Z Cylinder")
case (SURF_SPHERE)
call write_dataset(surface_group, "type", "Sphere")
case (SURF_CONE_X)
call write_dataset(surface_group, "type", "X Cone")
case (SURF_CONE_Y)
call write_dataset(surface_group, "type", "Y Cone")
case (SURF_CONE_Z)
call write_dataset(surface_group, "type", "Z Cone")
end select
! 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)
call write_dataset(surface_group, "boundary_condition", "transmission")
case (BC_VACUUM)
call write_dataset(surface_group, "boundary_condition", "vacuum")
case (BC_REFLECT)
call write_dataset(surface_group, "boundary_condition", "reflective")
case (BC_PERIODIC)
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
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 write_dataset(univ_group, "index", i)
! Write list of cells in this universe
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
lattices_group = create_group(geom_group, "lattices")
! Write information on each lattice
LATTICE_LOOP: do i = 1, n_lattices
lat => lattices(i)%obj
lattice_group = create_group(lattices_group, "lattice " // trim(to_str(lat%id)))
! Write internal OpenMC index for this lattice
call write_dataset(lattice_group, "index", i)
! Write name for this lattice
call write_dataset(lattice_group, "name", lat%name)
! Write lattice type
select type (lat)
type is (RectLattice)
! Write lattice type.
call write_dataset(lattice_group, "type", "rectangular")
! 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), &
&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 write_dataset(lattice_group, "universes", lattice_universes)
deallocate(lattice_universes)
type is (HexLattice)
! Write lattice type.
call write_dataset(lattice_group, "type", "hexagonal")
! Write number of lattice cells.
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.
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, &
&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
! 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
end do
end do
end do
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 write_geometry
!===============================================================================
! WRITE_MATERIALS
!===============================================================================
subroutine write_materials(file_id)
integer(HID_T), intent(in) :: file_id
integer :: i
integer :: j
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")
! 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 write_dataset(material_group, "index", i)
! Write name for this material
call write_dataset(material_group, "name", m%name)
! Write atom density with units
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
end do
! Write temporary array to 'nuclides'
call write_dataset(material_group, "nuclides", zaids)
! Deallocate temporary array
deallocate(zaids)
! 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)
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 write_materials
!===============================================================================
! WRITE_TALLIES
!===============================================================================
subroutine write_tallies(file_id)
integer(HID_T), intent(in) :: file_id
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
type(StructuredMesh), pointer :: m
type(TallyObject), pointer :: t
tallies_group = create_group(file_id, "tallies")
! Write total number of meshes
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 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)
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 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 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 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)
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)
! Write filter bins
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 write_dataset(filter_group, "bins", t%filters(j)%int_bins)
end if
! Write name of type
select case (t%filters(j)%type)
case(FILTER_UNIVERSE)
call write_dataset(filter_group, "type_name", "universe")
case(FILTER_MATERIAL)
call write_dataset(filter_group, "type_name", "material")
case(FILTER_CELL)
call write_dataset(filter_group, "type_name", "cell")
case(FILTER_CELLBORN)
call write_dataset(filter_group, "type_name", "cellborn")
case(FILTER_SURFACE)
call write_dataset(filter_group, "type_name", "surface")
case(FILTER_MESH)
call write_dataset(filter_group, "type_name", "mesh")
case(FILTER_ENERGYIN)
call write_dataset(filter_group, "type_name", "energy")
case(FILTER_ENERGYOUT)
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 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
else
temp_array(j) = t%nuclide_bins(j)
end if
end do NUCLIDE_LOOP
! Write and deallocate nuclide bins
call write_dataset(tally_group, "nuclide_bins", temp_array)
deallocate(temp_array)
! Write number of score bins
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 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
!===============================================================================
subroutine write_timing(file_id)
integer(HID_T), intent(in) :: file_id
integer(8) :: total_particles
integer(HID_T) :: time_group
real(8) :: speed
time_group = create_group(file_id, "timing")
! Write timing data
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 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 write_dataset(time_group, "neutrons_per_second", speed)
call close_group(time_group)
end subroutine write_timing
end module summary

View file

@ -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
!===============================================================================

View file

@ -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,41 +95,34 @@ 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(:)
#ifdef HDF5
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'
#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)
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, '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
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

View file

@ -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 {} \;

View file

@ -107,13 +107,13 @@ tests = OrderedDict()
class Test(object):
def __init__(self, name, debug=False, optimize=False, mpi=False, openmp=False,
hdf5=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.hdf5 = hdf5
self.phdf5 = phdf5
self.valgrind = valgrind
self.coverage = coverage
self.success = True
@ -124,13 +124,9 @@ 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 = os.path.join(MPI_DIR, 'bin', 'mpifort')
else:
self.fc = FC
@ -164,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
@ -174,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)
@ -263,41 +267,29 @@ 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,
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
# 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('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)
# Check to see if we should just print build configuration information to user
if options.list_build_configs:
@ -305,7 +297,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))

View file

@ -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.'

View file

@ -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')),\

View file

@ -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.

View file

@ -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."""

View file

@ -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."""

View file

@ -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__':

View file

@ -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__':

View file

@ -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."""

View file

@ -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."""

View file

@ -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$|^omp-hdf5-debug|^mpi-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