diff --git a/.gitignore b/.gitignore index 5634632fa4..136491a4b8 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,8 @@ src/xml-fortran/xmlreader # Test results error file results_error.dat +inputs_error.dat +results_test.dat # Test build files tests/build/ @@ -62,4 +64,13 @@ data/nndc .idea/* # IPython notebook checkpoints -.ipynb_checkpoints \ No newline at end of file +.ipynb_checkpoints + +# Multi-group cross section IPython Notebook +docs/source/pythonapi/examples/*.xml +docs/source/pythonapi/examples/*.png +docs/source/pythonapi/examples/*.xls +docs/source/pythonapi/examples/mgxs +docs/source/pythonapi/examples/tracks +docs/source/pythonapi/examples/fission-rates +docs/source/pythonapi/examples/plots \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 7af617f857..efdc457a11 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ before_install: - conda config --set always_yes yes --set changeps1 no - conda update -q conda - conda info -a - - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy h5py + - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy h5py pandas - source activate test-environment # Install GCC, MPICH, HDF5, PHDF5 diff --git a/CMakeLists.txt b/CMakeLists.txt index 45b626324c..5ad537e10a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() @@ -197,6 +235,14 @@ if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/xml/fox/.git) endif() add_subdirectory(src/xml/fox) +#=============================================================================== +# RPATH information +#=============================================================================== + +# add the automatically determined parts of the RPATH +# which point to directories outside the build tree to the install RPATH +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + #=============================================================================== # Build OpenMC executable #=============================================================================== @@ -204,10 +250,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 @@ -216,14 +286,21 @@ set_target_properties(${program} PROPERTIES install(TARGETS ${program} RUNTIME DESTINATION bin) install(DIRECTORY src/relaxng DESTINATION share/openmc) install(FILES man/man1/openmc.1 DESTINATION share/man/man1) -install(FILES LICENSE DESTINATION "share/doc/${program}/copyright") +install(FILES LICENSE DESTINATION "share/doc/${program}" RENAME copyright) find_package(PythonInterp) if(PYTHONINTERP_FOUND) - install(CODE "execute_process( - COMMAND ${PYTHON_EXECUTABLE} setup.py install - --prefix=${CMAKE_INSTALL_PREFIX} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})") + if(debian) + install(CODE "execute_process( + COMMAND ${PYTHON_EXECUTABLE} setup.py install + --root=debian/openmc --install-layout=deb + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})") + else() + install(CODE "execute_process( + COMMAND ${PYTHON_EXECUTABLE} setup.py install + --prefix=${CMAKE_INSTALL_PREFIX} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})") + endif() endif() #=============================================================================== @@ -306,38 +383,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_12_616.h5) - elseif(${test} MATCHES "test_particle_restart_fixed") - set(RESTART_FILE particle_7_6144.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_12_616.binary) - elseif(${test} MATCHES "test_particle_restart_fixed") - set(RESTART_FILE particle_7_6144.binary) - else(${test} MATCHES "test_statepoint_restart") - message(FATAL_ERROR "Restart test ${test} not recognized") - endif(${test} MATCHES "test_statepoint_restart") - - endif(${HDF5_ENABLED}) + # Handle restart tests separately + if(${test} MATCHES "test_statepoint_restart") + set(RESTART_FILE statepoint.07.h5) + elseif(${test} MATCHES "test_sourcepoint_restart") + set(RESTART_FILE statepoint.07.h5 source.07.h5) + elseif(${test} MATCHES "test_particle_restart_eigval") + set(RESTART_FILE particle_9_555.h5) + elseif(${test} MATCHES "test_particle_restart_fixed") + set(RESTART_FILE particle_7_928.h5) + else(${test} MATCHES "test_statepoint_restart") + message(FATAL_ERROR "Restart test ${test} not recognized") + endif(${test} MATCHES "test_statepoint_restart") # Perform serial valgrind and coverage test add_test(NAME ${TEST_NAME} diff --git a/cmake/Modules/FindHDF5.cmake b/cmake/Modules/FindHDF5.cmake new file mode 100644 index 0000000000..7492ea750a --- /dev/null +++ b/cmake/Modules/FindHDF5.cmake @@ -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 . + +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 +) diff --git a/docs/source/conf.py b/docs/source/conf.py index 4a18f14de5..118ff2c03b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -27,6 +27,7 @@ sys.path.insert(0, os.path.abspath('../..')) extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.pngmath', + 'sphinx.ext.autosummary', 'sphinxcontrib.tikz', 'sphinx_numfig', 'notebook_sphinxext'] @@ -54,7 +55,7 @@ copyright = u'2011-2015, Massachusetts Institute of Technology' # The short X.Y version. version = "0.7" # The full version, including alpha/beta/rc tags. -release = "0.7.0" +release = "0.7.1" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -199,7 +200,7 @@ latex_elements = { \usepackage{enumitem} \usepackage{amsfonts} \usepackage{amsmath} -\setlistdepth{9} +\setlistdepth{99} \usepackage{tikz} \usetikzlibrary{shapes,snakes,shadows,arrows,calc,decorations.markings,patterns,fit,matrix,spy} \usepackage{fixltx2e} diff --git a/docs/source/devguide/index.rst b/docs/source/devguide/index.rst index 03838363c9..37b17bc0fa 100644 --- a/docs/source/devguide/index.rst +++ b/docs/source/devguide/index.rst @@ -16,6 +16,4 @@ as debugging. styleguide workflow xml-parsing - statepoint - voxel docbuild diff --git a/docs/source/devguide/statepoint.rst b/docs/source/devguide/statepoint.rst deleted file mode 100644 index 4a1db94788..0000000000 --- a/docs/source/devguide/statepoint.rst +++ /dev/null @@ -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. - diff --git a/docs/source/devguide/voxel.rst b/docs/source/devguide/voxel.rst deleted file mode 100644 index 98f5cb73b2..0000000000 --- a/docs/source/devguide/voxel.rst +++ /dev/null @@ -1,52 +0,0 @@ -.. _devguide_voxel: - -===================================== -Voxel Plot Binary File Specifications -===================================== - -The current revision of the voxel plot binary file is 1. - -**integer(4) n_voxels_x** - - Number of voxels in the x direction - -**integer(4) n_voxels_y** - - Number of voxels in the y direction - -**integer(4) n_voxels_z** - - Number of voxels in the z direction - -**real(8) width_voxel_x** - - Width of voxels in the x direction - -**real(8) width_voxel_y** - - Width of voxels in the y direction - -**real(8) width_voxel_z** - - Width of voxels in the z direction - -**real(8) lower_left_x** - - Lower left x point of the voxel grid - -**real(8) lower_left_y** - - Lower left y point of the voxel grid - -**real(8) lower_left_z** - - Lower left z point of the voxel grid - -*do x = 1, n_voxels_x* - *do y = 1, n_voxels_y* - *do z = 1, n_voxels_z* - - **integer(4) id** - - Cell or material id number at this voxel center. Set to -1 when - cell not_found. diff --git a/docs/source/methods/eigenvalue.rst b/docs/source/methods/eigenvalue.rst index fe99ba22ec..41bf865492 100644 --- a/docs/source/methods/eigenvalue.rst +++ b/docs/source/methods/eigenvalue.rst @@ -142,7 +142,7 @@ than unity. By ensuring that the expected number of fission sites in each mesh cell is constant, the collision density across all cells, and hence the variance of tallies, is more uniform than it would be otherwise. -.. _Shannon entropy: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-06-3737_entropy.pdf +.. _Shannon entropy: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-06-3737.pdf .. [Lieberoth] J. Lieberoth, "A Monte Carlo Technique to Solve the Static Eigenvalue Problem of the Boltzmann Transport Equation," *Nukleonik*, **11**, diff --git a/docs/source/methods/geometry.rst b/docs/source/methods/geometry.rst index 9eece1e919..c1be68f72e 100644 --- a/docs/source/methods/geometry.rst +++ b/docs/source/methods/geometry.rst @@ -10,7 +10,7 @@ Constructive Solid Geometry OpenMC uses a technique known as `constructive solid geometry`_ (CSG) to build arbitrarily complex three-dimensional models in Euclidean space. In a CSG model, -every unique object is described as the union, intersection, or difference of +every unique object is described as the union and/or intersection of *half-spaces* created by bounding `surfaces`_. Every surface divides all of space into exactly two half-spaces. We can mathematically define a surface as a collection of points that satisfy an equation of the form :math:`f(x,y,z) = 0` @@ -54,13 +54,12 @@ dividing space into two half-spaces. Example of an ellipse and its associated half-spaces. References to half-spaces created by surfaces are used to define regions of -space of uniform composition, known as *cells*. While some codes allow regions -to be defined by intersections, unions, and differences or half-spaces, OpenMC -is currently limited to cells defined only as intersections of -half-spaces. Thus, the specification of the cell must include a list of -half-space references whose intersection defines the region. The region is then -assigned a material defined elsewhere. Figure :num:`fig-union` shows an -example of a cell defined as the intersection of an ellipse and two planes. +space of uniform composition, which are then assigned to *cells*. OpenMC allows +regions to be defined using union, intersection, and complement operators. As in +MCNP_, the intersection operator is implicit as doesn't need to be written in a +region specification. A defined region is then associated with a material +composition in a cell. Figure :num:`fig-union` shows an example of a cell region +defined as the intersection of an ellipse and two planes. .. _fig-union: @@ -117,6 +116,10 @@ to fully define the surface. | Cone parallel to the | z-cone | :math:`(x-x_0)^2 + (y-y_0)^2 | :math:`x_0 \; y_0 \; | | :math:`z`-axis | | = R^2(z-z_0)^2` | z_0 \; R^2` | +----------------------+------------+------------------------------+-------------------------+ + | General quadric | quadric | :math:`Ax^2 + By^2 + Cz^2 + | :math:`A \; B \; C \; D | + | surface | | Dxy + Eyz + Fxz + Gx + Hy + | \; E \; F \; G \; H \; | + | | | Jz + K` | J \; K` | + +----------------------+------------+------------------------------+-------------------------+ .. _universes: diff --git a/docs/source/methods/physics.rst b/docs/source/methods/physics.rst index ed10b32343..e25057488c 100644 --- a/docs/source/methods/physics.rst +++ b/docs/source/methods/physics.rst @@ -187,11 +187,11 @@ secondary photons from nuclear de-excitation are tracked in OpenMC. ------------------------ These types of reactions are just treated as inelastic scattering and as such -are subject to the same procedure as described in -:ref:`inelastic-scatter`. Rather than tracking multiple secondary neutrons, the -weight of the outgoing neutron is multiplied by the number of secondary -neutrons, e.g. for :math:`(n,2n)`, only one outgoing neutron is tracked but its -weight is doubled. +are subject to the same procedure as described in :ref:`inelastic-scatter`. For +reactions with integral multiplicity, e.g., :math:`(n,2n)`, an appropriate +number of secondary neutrons are created. For reactions that have a multiplicity +given as a function of the incoming neutron energy (which occasionally occurs +for MT=5), the weight of the outgoing neutron is multiplied by the multiplcity. .. _fission: @@ -1027,14 +1027,19 @@ probability distribution function can be found by integrating equation Let us call the normalization factor in the denominator of equation :eq:`target-pdf-1` :math:`C`. -It is normally assumed that :math:`\sigma (v_r)` is constant over the range of + +Constant Cross Section Model +---------------------------- + +It is often assumed that :math:`\sigma (v_r)` is constant over the range of relative velocities of interest. This is a good assumption for almost all cases since the elastic scattering cross section varies slowly with velocity for light nuclei, and for heavy nuclei where large variations can occur due to resonance scattering, the moderating effect is rather small. Nonetheless, this assumption may cause incorrect answers in systems with low-lying resonances that can cause a significant amount of up-scatter that would be ignored by this assumption -(e.g. U-238 in commercial light-water reactors). Nevertheless, with this +(e.g. U-238 in commercial light-water reactors). We will revisit this assumption +later in :ref:`energy_dependent_xs_model`. For now, continuing with the assumption, we write :math:`\sigma (v_r) = \sigma_s` which simplifies :eq:`target-pdf-1` to @@ -1232,6 +1237,35 @@ If is not accepted, then we repeat the process and resample a target speed and cosine until a combination is found that satisfies equation :eq:`freegas-accept-2`. +.. _energy_dependent_xs_model: + +Energy-Dependent Cross Section Model +------------------------------------ + +As was noted earlier, assuming that the elastic scattering cross section is +constant in :eq:`reaction-rate` is not strictly correct, especially when +low-lying resonances are present in the cross sections for heavy nuclides. To +correctly account for energy dependence of the scattering cross section entails +performing another rejection step. The most common method is to sample +:math:`\mu` and :math:`v_T` as in the constant cross section approximation and +then perform a rejection on the ratio of the 0 K elastic scattering cross +section at the relative velocity to the maximum 0 K elastic scattering cross +section over the range of velocities considered: + +.. math:: + :label: dbrc + + p_{dbrc} = \frac{\sigma_s(v_r)}{\sigma_{s,max}} + +where it should be noted that the maximum is taken over the range :math:`[v_n - +4/\beta, 4_n + 4\beta]`. This method is known as Doppler broadening rejection +correction (DBRC) and was first introduced by `Becker et al.`_. OpenMC has an +implementation of DBRC as well as an accelerated sampling method that are +described fully in `Walsh et al.`_ + +.. _Becker et al.: http://dx.doi.org/10.1016/j.anucene.2008.12.001 +.. _Walsh et al.: http://dx.doi.org/10.1016/j.anucene.2014.01.017 + .. _sab_tables: ------------ diff --git a/docs/source/publications.rst b/docs/source/publications.rst index 79d089605c..369b9d9775 100644 --- a/docs/source/publications.rst +++ b/docs/source/publications.rst @@ -26,6 +26,10 @@ Overviews Benchmarking ------------ +- Khurrum S. Chaudri and Sikander M. Mirza, "Burnup dependent Monte Carlo + neutron physics calculations of IAEA MTR benchmark," *Prog. Nucl. Energy*, + **81**, 43-52 (2015). ``_ + - Daniel J. Kelly, Brian N. Aviles, Paul K. Romano, Bryan R. Herman, Nicholas E. Horelik, and Benoit Forget, "Analysis of select BEAVRS PWR benchmark cycle 1 results using MC21 and OpenMC," *Proc. PHYSOR*, Kyoto, @@ -57,13 +61,8 @@ Coupling and Multi-physics - Bryan R. Herman, Benoit Forget, and Kord Smith, "Progress toward Monte Carlo-thermal hydraulic coupling using low-order nonlinear diffusion - acceleration methods." In press, *Ann. Nucl. Energy*, - (2014). ``_ - -- Adam G. Nelson and William R. Martin, "Improved Convergence of Monte Carlo - Generated Multi-Group Scattering Moments," *Proc. Int. Conf. Mathematics and - Computational Methods Applied to Nuclear Science and Engineering*, Sun Valley, - Idaho, May 5--9 (2013). + acceleration methods." *Ann. Nucl. Energy*, **84**, 63-72 + (2015). ``_ - Bryan R. Herman, Benoit Forget, and Kord Smith, "Utilizing CMFD in OpenMC to Estimate Dominance Ratio and Adjoint," *Trans. Am. Nucl. Soc.*, **109**, @@ -81,19 +80,65 @@ Geometry Miscellaneous ------------- +- William Boyd, Sterling Harper, and Paul K. Romano, "Equipping OpenMC for the + big data era," Accepted, *PHYSOR 2016*, Sun Valley, Idaho, May 1-5, 2016. + +- Qicang Shen, William Boyd, Benoit Forget, and Kord Smith, "Tally precision + triggers for the OpenMC Monte Carlo code," *Trans. Am. Nucl. Soc.*, **112**, + 637-640 (2015). + - Timothy P. Burke, Brian C. Kiedrowski, and William R. Martin, "Flux and Reaction Rate Kernel Density Estimators in OpenMC," *Trans. Am. Nucl. Soc.*, **109**, 683-686 (2013). +------------------------------------ +Multi-group Cross Section Generation +------------------------------------ + +- Adam G. Nelson and William R. Martin, "Improved Monte Carlo tallying of + multi-group scattering moments using the NDPP code," *Trans. Am. Nucl. Soc.*, + **113**, 645-648 (2015) + +- Adam G. Nelson and William R. Martin, "Improved Monte Carlo tallying of + multi-group scattering moment matrices," *Trans. Am. Nucl. Soc.*, **110**, + 217-220 (2014). + +- Adam G. Nelson and William R. Martin, "Improved Convergence of Monte Carlo + Generated Multi-Group Scattering Moments," *Proc. Int. Conf. Mathematics and + Computational Methods Applied to Nuclear Science and Engineering*, Sun Valley, + Idaho, May 5--9 (2013). + ------------ Nuclear Data ------------ +- Colin Josey, Pablo Ducru, Benoit Forget, and Kord Smith, "Windowed multipole + for cross section Doppler broadening," *J. Comput. Phys.*, In Press + (2016). ``_ + +- Colin Josey, Benoit Forget, and Kord Smith, "Windowed multipole sensitivity to + target accuracy of the optimization procedure," *J. Nucl. Sci. Technol.*, + **52**, 987-992 (2015). ``_ + +- Jonathan A. Walsh, Paul K. Romano, Benoit Forget, and Kord S. Smith, + "Optimizations of the energy grid search algorithm in continuous-energy Monte + Carlo particle transport codes", *Comput. Phys. Commun.*, **196**, 134-142 + (2015). ``_ + - Jonathan A. Walsh, Benoit Forget, Kord S. Smith, Brian C. Kiedrowski, and Forrest B. Brown, "Direct, on-the-fly calculation of unresolved resonance region cross sections in Monte Carlo simulations," *Proc. Joint Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015). +- Amanda L. Lund, Andrew R. Siegel, Benoit Forget, Colin Josey, and + Paul K. Romano, "Using fractional cascading to accelerate cross section + lookups in Monte Carlo particle transport calculations," *Proc. Joint + Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015). + +- Ronald O. Rahaman, Andrew R. Siegel, and Paul K. Romano, "Monte Carlo + performance analysis for varying cross section parameter regimes," + *Proc. Joint Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015). + - Paul K. Romano and Timothy H. Trumbull, "Comparison of algorithms for Doppler broadening pointwise tabulated cross sections," *Ann. Nucl. Energy*, **75**, 358--364 (2015). ``_ @@ -114,6 +159,10 @@ Nuclear Data Parallelism ----------- +- Paul K. Romano, John R. Tramm, and Andrew R. Siegel, "Efficacy of hardware + threading for Monte Carlo particle transport calculations on multi- and + many-core systems," Accepted, *PHYSOR 2016*, Sun Valley, Idaho, May 1-5, 2016. + - David Ozog, Allen D. Malony, and Andrew R. Siegel, "A performance analysis of SIMD algorithms for Monte Carlo simulations of nuclear reactor cores," *Proc. IEEE Int. Parallel and Distributed Processing Symposium*, Hyderabad, diff --git a/docs/source/pythonapi/energy_groups.rst b/docs/source/pythonapi/energy_groups.rst new file mode 100644 index 0000000000..28ca6f3fe2 --- /dev/null +++ b/docs/source/pythonapi/energy_groups.rst @@ -0,0 +1,8 @@ +.. _pythonapi_energy_groups: + +============= +Energy Groups +============= + +.. automodule:: openmc.mgxs.groups + :members: diff --git a/docs/source/pythonapi/examples/images/mgxs.png b/docs/source/pythonapi/examples/images/mgxs.png new file mode 100644 index 0000000000..3946a5b3c6 Binary files /dev/null and b/docs/source/pythonapi/examples/images/mgxs.png differ diff --git a/docs/source/pythonapi/examples/mgxs-part-i.ipynb b/docs/source/pythonapi/examples/mgxs-part-i.ipynb new file mode 100644 index 0000000000..897af8e3ff --- /dev/null +++ b/docs/source/pythonapi/examples/mgxs-part-i.ipynb @@ -0,0 +1,1195 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This IPython Notebook introduces the use of the `openmc.mgxs` module to calculate multi-group cross sections for an infinite homogeneous medium. In particular, this Notebook introduces the the following features:\n", + "\n", + "* **General equations** for scalar-flux averaged multi-group cross sections\n", + "* Creation of multi-group cross sections for an **infinite homogeneous medium**\n", + "* Use of **tally arithmetic** to manipulate multi-group cross sections\n", + "\n", + "**Note:** This Notebook illustrates the use of [Pandas](http://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data. We recommend using [Pandas](http://pandas.pydata.org/) >v0.15.0 or later since OpenMC's Python API leverages the multi-indexing feature included in the most recent releases of [Pandas](http://pandas.pydata.org/)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introduction to Multi-Group Cross Sections (MGXS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Many Monte Carlo particle transport codes, including OpenMC, use continuous-energy nuclear cross section data. However, most deterministic neutron transport codes use *multi-group cross sections* defined over discretized energy bins or *energy groups*. An example of U-235's continuous-energy fission cross section along with a 16-group cross section computed for a light water reactor spectrum is displayed below." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\ncdttt+F//ud/nOZ5//33YTab8cYbb+Dxxx9HTEwMWrZsiW+++QaAfReJ3r17o2XLlrj99tthtVox\nbdo0dO/eHQCglEKvXr0wevRol9e32Wxo1aoV5s6d6/PyerIMM2bMwPXr15GVleXy+PXr11fOQ0QU\nLLhlmohIg7KyMpSVlTlNM5lMLluId+7ciX/84x/4/e9/j7CwMKxcuRLjx4/Hl19+WTnIPXbsGIYO\nHYpu3brhv//7v9G+fXvs3r0bjz32GPLy8rBkyRKn51y8eDGGDh2KNWvWwGw2o127dlizZg3+7d/+\nDf/yL/+CVatWobCwEBkZGbh+/TpMJlNl37x587BgwQJ8/fXX6NmzZ+Vzbty4EcXFxT4Ppj1dhvvu\nuw9du3bFa6+95vRa5eXl2LRpE+Lj42vcfYaIyDCKiIj8Zv369cpkMtV4a9asmdO8JpNJdejQQdls\ntspply5dUk2aNFHPP/985bT7779fdenSRRUXFzs9ft68eSokJEQVFhYqpZR67733lMlkUiNGjHCa\nr7y8XLVv317Fx8c7TT937pxq3ry56t69e+W0oqIiFRERodLT053mve2229R9991X67KfPn1amUwm\n9frrr7vcV9cyXLlypXJaRkaGMplM6tChQ5XTduzYoUwmk3r11VdrfO27775bxcXF1dpHRKQDd/Mg\nItJg06ZN+Mc//uF0O3DggMt899xzD8LCwip/jo6ORnR0NM6dOwcAuHbtGv73f/8X48ePR8uWLSu3\neJeVlWHMmDG4du0aPv74Y6fn/NWvfuX085dffolLly5h4sSJTtM7d+6MhIQEp2kWiwXTpk3Dhg0b\ncPXqVQDA3//+dxw/ftznrdLeLkNaWhrMZjNee+21ymnr169HeHg4HnroIZ8aiIh04WCaiEiD2NhY\n3HHHHU63QYMGuczXpk0bl2ktWrTAjz/+CADIz89HeXk5Vq9ejebNmzvdkpKSYDKZkJeX5/T4Dh06\nOP2cn58PALjllltcXis6Otpl2rx581BUVFS53/KLL76ILl264MEHH/Rw6Z15sgyORsA+yB85ciT+\n/Oc/o7S0FHl5edixYwdSUlKcfvEgIgoG3GeaiCiIRUVFoUmTJpg6dSoeffTRGufp1q2b08+OfaAd\nHAP277//3uWxNU3r2bMnxowZg5deegmjR49GTk4Oli9f7vK8OpdhxowZ2LNnD7Kzs3HhwgWUlZVh\n+vTpPr0+EZFOHEwTEQWx0NBQ3HPPPcjNzUVcXByaNWvm9XP07dsX7du3x1/+8hcsWLCgcvq5c+ew\nf/9+dOrUyeUx8+fPx/33349//dd/RfPmzTFr1qyALsO4cePQpk0bvPbaa7h48SL69OnjsksKEVEw\n4GCaiEiDI0eO4MaNGy7Te/bsibZt29b6WFXtWlqrVq3CsGHDMHz4cMyePRtdu3ZFcXExvv76a+zY\nsQN///vfa30+k8mEjIwMPPLII0hJSUFaWhoKCwuxfPlydOzYEWaz6x5/o0aNQmxsLN5//31MmTKl\nzua6eLsMzZo1w69//WusWrUKALBixYp6vT4RkS4cTBMR+ZFjV4i0tLQa71u7dm2duytU350iNjYW\nubm5WL58OX73u9/hhx9+QGRkJHr37o2xY8fW+liHWbNmwWQyYeXKlZgwYQK6d++O3/72t8jOzsb5\n8+drfMzEiRORkZFRr3NL+7IMDjNmzMCqVavQtGlTTJ06td4NREQ68HLiRESNVGFhIXr37o0JEybg\nT3/6k8v9d955J5o1a+ZythB3HJcTX7duHaZMmYKmTfVvr1FKoby8HPfddx8KCgpw5MgR7a9JRFQV\nz+ZBRNQIXLp0CfPmzcP27dvxf//3f9i4cSPuuecelJSUYP78+ZXzFRcXY//+/XjyySdx6NAhPPnk\nk16/1owZM9C8eXNs377dn4tQo/Hjx6N58+b48MMPfT5AkoioPrhlmoioESgsLMTUqVPx6aefoqCg\nAKGhoYiPj0dGRgYGDx5cOd/777+Pe++9F23btsXcuXNdrq5Ym9LSUqctw7feeisiIyP9uhzVnTp1\nCoWFhQCAkJAQxMbGan09IqLqOJgmIiIiIvIRd/MgIiIiIvIRB9NERERERD7iYJqIiIiIyEccTBMR\nERER+YiDaSIiIiIiH3EwTURERETkIw6miYiIiIh8xME0EREREZGPOJgmIiIiIvLR/wcwWUbzha5y\njwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "execution_count": 1, + "metadata": { + "image/png": { + "width": 350 + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "from IPython.display import Image\n", + "Image(filename='images/mgxs.png', width=350)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A variety of tools employing different methodologies have been developed over the years to compute multi-group cross sections for certain applications, including NJOY (LANL), MC$^2$-3 (ANL), and Serpent (VTT). The `openmc.mgxs` Python module is designed to leverage OpenMC's tally system to calculate multi-group cross sections with arbitrary energy discretizations for fine-mesh heterogeneous deterministic neutron transport applications.\n", + "\n", + "Before proceeding to illustrate how one may use the `openmc.mgxs` module, it is worthwhile to define the general equations used to calculate multi-group cross sections. This is only intended as a brief overview of the methodology used by `openmc.mgxs` - we refer the interested reader to the large body of literature on the subject for a more comprehensive understanding of this complex topic." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Introductory Notation\n", + "The continuous real-valued microscopic cross section may be denoted $\\sigma_{n,x}(\\mathbf{r}, E)$ for position vector $\\mathbf{r}$, energy $E$, nuclide $n$ and interaction type $x$. Similarly, the scalar neutron flux may be denoted by $\\Phi(\\mathbf{r},E)$ for position $\\mathbf{r}$ and energy $E$. **Note**: Although nuclear cross sections are dependent on the temperature $T$ of the interacting medium, the temperature variable is neglected here for brevity." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Spatial and Energy Discretization\n", + "The energy domain for critical systems such as thermal reactors spans more than 10 orders of magnitude of neutron energies from 10$^{-5}$ - 10$^7$ eV. The multi-group approximation discretization divides this energy range into one or more energy groups. In particular, for $G$ total groups, we denote an energy group index $g$ such that $g \\in \\{1, 2, ..., G\\}$. The energy group indices are defined such that the smaller group the higher the energy, and vice versa. The integration over neutron energies across a discrete energy group is commonly referred to as **energy condensation**.\n", + "\n", + "Multi-group cross sections are computed for discretized spatial zones in the geometry of interest. The spatial zones may be defined on a structured and regular fuel assembly or pin cell mesh, an arbitrary unstructured mesh or the constructive solid geometry used by OpenMC. For a geometry with $K$ distinct spatial zones, we designate each spatial zone an index $k$ such that $k \\in \\{1, 2, ..., K\\}$. The volume of each spatial zone is denoted by $V_{k}$. The integration over discrete spatial zones is commonly referred to as **spatial homogenization**." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### General Scalar-Flux Weighted MGXS\n", + "The multi-group cross sections computed by `openmc.mgxs` are defined as a *scalar flux-weighted average* of the microscopic cross sections across each discrete energy group. This formulation is employed in order to preserve the reaction rates within each energy group and spatial zone. In particular, spatial homogenization and energy condensation are used to compute the general multi-group cross section $\\sigma_{n,x,k,g}$ as follows:\n", + "\n", + "$$\\sigma_{n,x,k,g} = \\frac{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\sigma_{n,x}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\Phi(\\mathbf{r},E')}$$\n", + "\n", + "This scalar flux-weighted average microscopic cross section is computed by `openmc.mgxs` for most multi-group cross sections, including total, absorption, and fission reaction types. These double integrals are stochastically computed with OpenMC's tally system - in particular, [filters](https://mit-crpg.github.io/openmc/pythonapi/filter.html) on the energy range and spatial zone (material, cell or universe) define the bounds of integration for both numerator and denominator." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multi-Group Scattering Matrices\n", + "The general multi-group cross section $\\sigma_{n,x,k,g}$ is a vector of $G$ values for each energy group $g$. The equation presented above only discretizes the energy of the incoming neutron and neglects the outgoing energy of the neutron (if any). Hence, this formulation must be extended to account for the outgoing energy of neutrons in the discretized scattering matrix cross section used by deterministic neutron transport codes. \n", + "\n", + "We denote the incoming and outgoing neutron energy groups as $g$ and $g'$ for the microscopic scattering matrix cross section $\\sigma_{n,s}(\\mathbf{r},E)$. As before, spatial homogenization and energy condensation are used to find the multi-group scattering matrix cross section $\\sigma_{n,s,k,g \\to g'}$ as follows:\n", + "\n", + "$$\\sigma_{n,s,k,g\\rightarrow g'} = \\frac{\\int_{E_{g'}}^{E_{g'-1}}\\mathrm{d}E''\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\sigma_{n,s}(\\mathbf{r},E'\\rightarrow E'')\\Phi(\\mathbf{r},E')}{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\Phi(\\mathbf{r},E')}$$\n", + "\n", + "This scalar flux-weighted multi-group microscopic scattering matrix is computed using OpenMC tallies with both energy in and energy out filters." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multi-Group Fission Spectrum\n", + "The energy spectrum of neutrons emitted from fission is denoted by $\\chi_{n}(\\mathbf{r},E' \\rightarrow E'')$ for incoming and outgoing energies $E'$ and $E''$, respectively. Unlike the multi-group cross sections $\\sigma_{n,x,k,g}$ considered up to this point, the fission spectrum is a probability distribution and must sum to unity. The outgoing energy is typically much less dependent on the incoming energy for fission than for scattering interactions. As a result, it is common practice to integrate over the incoming neutron energy when computing the multi-group fission spectrum. The fission spectrum may be simplified as $\\chi_{n}(\\mathbf{r},E)$ with outgoing energy $E$.\n", + "\n", + "Unlike the multi-group cross sections defined up to this point, the multi-group fission spectrum is weighted by the fission production rate rather than the scalar flux. This formulation is intended to preserve the total fission production rate in the multi-group deterministic calculation. In order to mathematically define the multi-group fission spectrum, we denote the microscopic fission cross section as $\\sigma_{n,f}(\\mathbf{r},E)$ and the average number of neutrons emitted from fission interactions with nuclide $n$ as $\\nu_{n}(\\mathbf{r},E)$. The multi-group fission spectrum $\\chi_{n,k,g}$ is then the probability of fission neutrons emitted into energy group $g$. \n", + "\n", + "Similar to before, spatial homogenization and energy condensation are used to find the multi-group fission spectrum $\\chi_{n,k,g}$ as follows:\n", + "\n", + "$$\\chi_{n,k,g'} = \\frac{\\int_{E_{g'}}^{E_{g'-1}}\\mathrm{d}E''\\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\chi_{n}(\\mathbf{r},E'\\rightarrow E'')\\nu_{n}(\\mathbf{r},E')\\sigma_{n,f}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}{\\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\nu_{n}(\\mathbf{r},E')\\sigma_{n,f}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}$$\n", + "\n", + "The fission production-weighted multi-group fission spectrum is computed using OpenMC tallies with both energy in and energy out filters.\n", + "\n", + "This concludes our brief overview on the methodology to compute multi-group cross sections. The following sections detail more concretely how users may employ the `openmc.mgxs` module to power simulation workflows requiring multi-group cross sections for downstream deterministic calculations." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate Input Files" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "import openmc\n", + "import openmc.mgxs as mgxs\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate some Nuclides\n", + "h1 = openmc.Nuclide('H-1')\n", + "o16 = openmc.Nuclide('O-16')\n", + "u235 = openmc.Nuclide('U-235')\n", + "u238 = openmc.Nuclide('U-238')\n", + "zr90 = openmc.Nuclide('Zr-90')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the nuclides we defined, we will now create a material for the homogeneous medium." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate a Material and register the Nuclides\n", + "inf_medium = openmc.Material(name='moderator')\n", + "inf_medium.set_density('g/cc', 5.)\n", + "inf_medium.add_nuclide(h1, 0.028999667)\n", + "inf_medium.add_nuclide(o16, 0.01450188)\n", + "inf_medium.add_nuclide(u235, 0.000114142)\n", + "inf_medium.add_nuclide(u238, 0.006886019)\n", + "inf_medium.add_nuclide(zr90, 0.002116053)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With our material, we can now create a `MaterialsFile` object that can be exported to an actual XML file." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate a MaterialsFile, register all Materials, and export to XML\n", + "materials_file = openmc.MaterialsFile()\n", + "materials_file.default_xs = '71c'\n", + "materials_file.add_material(inf_medium)\n", + "materials_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's move on to the geometry. This problem will be a simple square cell with reflective boundary conditions to simulate an infinite homogeneous medium. The first step is to create the outer bounding surfaces of the problem." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate boundary Planes\n", + "min_x = openmc.XPlane(boundary_type='reflective', x0=-0.63)\n", + "max_x = openmc.XPlane(boundary_type='reflective', x0=0.63)\n", + "min_y = openmc.YPlane(boundary_type='reflective', y0=-0.63)\n", + "max_y = openmc.YPlane(boundary_type='reflective', y0=0.63)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the surfaces defined, we can now create a cell that is defined by intersections of half-spaces created by the surfaces." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a Cell\n", + "cell = openmc.Cell(cell_id=1, name='cell')\n", + "\n", + "# Register bounding Surfaces with the Cell\n", + "cell.region = +min_x & -max_x & +min_y & -max_y\n", + "\n", + "# Fill the Cell with the Material\n", + "cell.fill = inf_medium" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OpenMC requires that there is a \"root\" universe. Let us create a root universe and add our square cell to it." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate Universe\n", + "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", + "root_universe.add_cell(cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now must create a geometry that is assigned a root universe, put the geometry into a `GeometryFile` object, and export it to XML." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create Geometry and set root Universe\n", + "openmc_geometry = openmc.Geometry()\n", + "openmc_geometry.root_universe = root_universe\n", + "\n", + "# Instantiate a GeometryFile\n", + "geometry_file = openmc.GeometryFile()\n", + "geometry_file.geometry = openmc_geometry\n", + "\n", + "# Export to \"geometry.xml\"\n", + "geometry_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we must define simulation parameters. In this case, we will use 10 inactive batches and 40 active batches each with 2500 particles." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# OpenMC simulation parameters\n", + "batches = 50\n", + "inactive = 10\n", + "particles = 2500\n", + "\n", + "# Instantiate a SettingsFile\n", + "settings_file = openmc.SettingsFile()\n", + "settings_file.batches = batches\n", + "settings_file.inactive = inactive\n", + "settings_file.particles = particles\n", + "settings_file.output = {'tallies': True, 'summary': True}\n", + "bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n", + "settings_file.set_source_space('fission', bounds)\n", + "\n", + "# Export to \"settings.xml\"\n", + "settings_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we are ready to generate multi-group cross sections! First, let's define a 2-group structure using the built-in `EnergyGroups` class." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a 2-group EnergyGroups object\n", + "groups = mgxs.EnergyGroups()\n", + "groups.group_edges = np.array([0., 0.625e-6, 20.])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now use the `EnergyGroups` object, along with our previously created materials and geometry, to instantiate some `MGXS` objects from the `openmc.mgxs` module. In particular, the following are subclasses of the generic and abstract `MGXS` class:\n", + "\n", + "* `TotalXS`\n", + "* `TransportXS`\n", + "* `AbsorptionXS`\n", + "* `CaptureXS`\n", + "* `FissionXS`\n", + "* `NuFissionXS`\n", + "* `ScatterXS`\n", + "* `NuScatterXS`\n", + "* `ScatterMatrixXS`\n", + "* `NuScatterMatrixXS`\n", + "* `Chi`\n", + "\n", + "These classes provide us with an interface to generate the tally inputs as well as perform post-processing of OpenMC's tally data to compute the respective multi-group cross sections. In this case, let's create the multi-group total, absorption and scattering cross sections with our 2-group structure." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a few different sections\n", + "total = mgxs.TotalXS(domain=cell, domain_type='cell', groups=groups)\n", + "absorption = mgxs.AbsorptionXS(domain=cell, domain_type='cell', groups=groups)\n", + "scattering = mgxs.ScatterXS(domain=cell, domain_type='cell', groups=groups)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Each multi-group cross section object stores its tallies in a Python dictionary called `tallies`. We can inspect the tallies in the dictionary for our `Absorption` object as follows. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "OrderedDict([('flux', Tally\n", + "\tID =\t10000\n", + "\tName =\t\n", + "\tFilters =\t\n", + " \t\tcell\t[1]\n", + " \t\tenergy\t[ 0.00000000e+00 6.25000000e-07 2.00000000e+01]\n", + "\tNuclides =\ttotal \n", + "\tScores =\t['flux']\n", + "\tEstimator =\ttracklength\n", + "), ('absorption', Tally\n", + "\tID =\t10001\n", + "\tName =\t\n", + "\tFilters =\t\n", + " \t\tcell\t[1]\n", + " \t\tenergy\t[ 0.00000000e+00 6.25000000e-07 2.00000000e+01]\n", + "\tNuclides =\ttotal \n", + "\tScores =\t['absorption']\n", + "\tEstimator =\ttracklength\n", + ")])" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "absorption.tallies" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `Absorption` object includes tracklength tallies for the 'absorption' and 'flux' scores in the 2-group structure in cell 1. Now that each `MGXS` object contains the tallies that it needs, we must add these tallies to a `TalliesFile` object to generate the \"tallies.xml\" input file for OpenMC." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate an empty TalliesFile\n", + "tallies_file = openmc.TalliesFile()\n", + "\n", + "# Add total tallies to the tallies file\n", + "for tally in total.tallies.values():\n", + " tallies_file.add_tally(tally)\n", + "\n", + "# Add absorption tallies to the tallies file\n", + "for tally in absorption.tallies.values():\n", + " tallies_file.add_tally(tally)\n", + "\n", + "# Add scattering tallies to the tallies file\n", + "for tally in scattering.tallies.values():\n", + " tallies_file.add_tally(tally)\n", + " \n", + "# Export to \"tallies.xml\"\n", + "tallies_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we a have a complete set of inputs, so we can go ahead and run our simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " .d88888b. 888b d888 .d8888b.\n", + " d88P\" \"Y88b 8888b d8888 d88P Y88b\n", + " 888 888 88888b.d88888 888 888\n", + " 888 888 88888b. .d88b. 88888b. 888Y88888P888 888 \n", + " 888 888 888 \"88b d8P Y8b 888 \"88b 888 Y888P 888 888 \n", + " 888 888 888 888 88888888 888 888 888 Y8P 888 888 888\n", + " Y88b. .d88P 888 d88P Y8b. 888 888 888 \" 888 Y88b d88P\n", + " \"Y88888P\" 88888P\" \"Y8888 888 888 888 888 \"Y8888P\"\n", + "__________________888______________________________________________________\n", + " 888\n", + " 888\n", + "\n", + " Copyright: 2011-2015 Massachusetts Institute of Technology\n", + " License: http://mit-crpg.github.io/openmc/license.html\n", + " Version: 0.7.0\n", + " Git SHA1: c4b14a5ef87f004528d35cbf33fef3ed15a386ca\n", + " Date/Time: 2015-12-02 09:11:05\n", + " MPI Processes: 1\n", + "\n", + " ===========================================================================\n", + " ========================> INITIALIZATION <=========================\n", + " ===========================================================================\n", + "\n", + " Reading settings XML file...\n", + " Reading cross sections XML file...\n", + " Reading geometry XML file...\n", + " Reading materials XML file...\n", + " Reading tallies XML file...\n", + " Building neighboring cells lists for each surface...\n", + " Loading ACE cross section table: 1001.71c\n", + " Loading ACE cross section table: 8016.71c\n", + " Loading ACE cross section table: 92235.71c\n", + " Loading ACE cross section table: 92238.71c\n", + " Loading ACE cross section table: 40090.71c\n", + " Maximum neutron transport energy: 20.0000 MeV for 1001.71c\n", + " Initializing source particles...\n", + "\n", + " ===========================================================================\n", + " ====================> K EIGENVALUE SIMULATION <====================\n", + " ===========================================================================\n", + "\n", + " Bat./Gen. k Average k \n", + " ========= ======== ==================== \n", + " 1/1 1.19804 \n", + " 2/1 1.12945 \n", + " 3/1 1.15573 \n", + " 4/1 1.13929 \n", + " 5/1 1.16300 \n", + " 6/1 1.22117 \n", + " 7/1 1.19012 \n", + " 8/1 1.11299 \n", + " 9/1 1.16066 \n", + " 10/1 1.12566 \n", + " 11/1 1.20854 \n", + " 12/1 1.14691 1.17773 +/- 0.03082\n", + " 13/1 1.17204 1.17583 +/- 0.01789\n", + " 14/1 1.14148 1.16724 +/- 0.01529\n", + " 15/1 1.17272 1.16834 +/- 0.01189\n", + " 16/1 1.18575 1.17124 +/- 0.01014\n", + " 17/1 1.20498 1.17606 +/- 0.00983\n", + " 18/1 1.14754 1.17249 +/- 0.00923\n", + " 19/1 1.18141 1.17348 +/- 0.00820\n", + " 20/1 1.15074 1.17121 +/- 0.00768\n", + " 21/1 1.15914 1.17011 +/- 0.00703\n", + " 22/1 1.14586 1.16809 +/- 0.00673\n", + " 23/1 1.18999 1.16978 +/- 0.00642\n", + " 24/1 1.15101 1.16844 +/- 0.00609\n", + " 25/1 1.13791 1.16640 +/- 0.00602\n", + " 26/1 1.19791 1.16837 +/- 0.00597\n", + " 27/1 1.19818 1.17012 +/- 0.00587\n", + " 28/1 1.14160 1.16854 +/- 0.00576\n", + " 29/1 1.11487 1.16571 +/- 0.00614\n", + " 30/1 1.17538 1.16620 +/- 0.00584\n", + " 31/1 1.20210 1.16791 +/- 0.00581\n", + " 32/1 1.20078 1.16940 +/- 0.00574\n", + " 33/1 1.14624 1.16839 +/- 0.00558\n", + " 34/1 1.14618 1.16747 +/- 0.00542\n", + " 35/1 1.16866 1.16752 +/- 0.00520\n", + " 36/1 1.18565 1.16821 +/- 0.00504\n", + " 37/1 1.16824 1.16821 +/- 0.00485\n", + " 38/1 1.18299 1.16874 +/- 0.00471\n", + " 39/1 1.21418 1.17031 +/- 0.00480\n", + " 40/1 1.11167 1.16835 +/- 0.00504\n", + " 41/1 1.11545 1.16665 +/- 0.00516\n", + " 42/1 1.11114 1.16491 +/- 0.00529\n", + " 43/1 1.14227 1.16423 +/- 0.00517\n", + " 44/1 1.14104 1.16355 +/- 0.00506\n", + " 45/1 1.16756 1.16366 +/- 0.00492\n", + " 46/1 1.13065 1.16274 +/- 0.00487\n", + " 47/1 1.11251 1.16139 +/- 0.00492\n", + " 48/1 1.14731 1.16101 +/- 0.00481\n", + " 49/1 1.16691 1.16117 +/- 0.00469\n", + " 50/1 1.19679 1.16206 +/- 0.00465\n", + " Creating state point statepoint.50.h5...\n", + "\n", + " ===========================================================================\n", + " ======================> SIMULATION FINISHED <======================\n", + " ===========================================================================\n", + "\n", + "\n", + " =======================> TIMING STATISTICS <=======================\n", + "\n", + " Total time for initialization = 4.1700E-01 seconds\n", + " Reading cross sections = 8.9000E-02 seconds\n", + " Total time in simulation = 1.4728E+01 seconds\n", + " Time in transport only = 1.4712E+01 seconds\n", + " Time in inactive batches = 1.7890E+00 seconds\n", + " Time in active batches = 1.2939E+01 seconds\n", + " Time synchronizing fission bank = 5.0000E-03 seconds\n", + " Sampling source sites = 3.0000E-03 seconds\n", + " SEND/RECV source sites = 2.0000E-03 seconds\n", + " Time accumulating tallies = 1.0000E-03 seconds\n", + " Total time for finalization = 1.0000E-03 seconds\n", + " Total time elapsed = 1.5155E+01 seconds\n", + " Calculation Rate (inactive) = 13974.3 neutrons/second\n", + " Calculation Rate (active) = 7728.57 neutrons/second\n", + "\n", + " ============================> RESULTS <============================\n", + "\n", + " k-effective (Collision) = 1.16131 +/- 0.00453\n", + " k-effective (Track-length) = 1.16206 +/- 0.00465\n", + " k-effective (Absorption) = 1.16096 +/- 0.00364\n", + " Combined k-effective = 1.16120 +/- 0.00325\n", + " Leakage Fraction = 0.00000 +/- 0.00000\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Run OpenMC\n", + "executor = openmc.Executor()\n", + "executor.run_simulation()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tally Data Processing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a `StatePoint` object. " + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Load the last statepoint file\n", + "sp = openmc.StatePoint('statepoint.50.h5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. This is necessary for the `openmc.mgxs` module to properly process the tally data. We first create a `Summary` object and link it with the statepoint." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Load the summary file and link it with the statepoint\n", + "su = openmc.Summary('summary.h5')\n", + "sp.link_with_summary(su)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The statepoint is now ready to be analyzed by our multi-group cross sections. We simply have to load the tallies from the `StatePoint` into each object as follows and our `MGXS` objects will compute the cross sections for us under-the-hood." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Load the tallies from the statepoint into each MGXS object\n", + "total.load_from_statepoint(sp)\n", + "absorption.load_from_statepoint(sp)\n", + "scattering.load_from_statepoint(sp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Voila! Our multi-group cross sections are now ready to rock 'n roll!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Extracting and Storing MGXS Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's first inspect our total cross section by printing it to the screen." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Multi-Group XS\n", + "\tReaction Type =\ttotal\n", + "\tDomain Type =\tcell\n", + "\tDomain ID =\t1\n", + "\tCross Sections [cm^-1]:\n", + " Group 1 [6.25e-07 - 20.0 MeV]:\t6.81e-01 +/- 1.88e-01%\n", + " Group 2 [0.0 - 6.25e-07 MeV]:\t1.40e+00 +/- 5.91e-01%\n", + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "total.print_xs()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since the `openmc.mgxs` module uses [tally arithmetic](https://mit-crpg.github.io/openmc/pythonapi/examples/tally-arithmetic.html) under-the-hood, the cross section is stored as a \"derived\" `Tally` object. This means that it can be queried and manipulated using all of the same methods supported for the `Tally` class in the OpenMC Python API. For example, we can construct a [Pandas](http://pandas.pydata.org/) `DataFrame` of the multi-group cross section data." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellgroup innuclidemeanstd. dev.
111total0.6683230.001264
012total1.2932580.007624
\n", + "
" + ], + "text/plain": [ + " cell group in nuclide mean std. dev.\n", + "1 1 1 total 0.668323 0.001264\n", + "0 1 2 total 1.293258 0.007624" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = scattering.get_pandas_dataframe()\n", + "df.head(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Each multi-group cross section object can be easily exported to a variety of file formats, including CSV, Excel, and LaTeX for storage or data processing." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "absorption.export_xs_data(filename='absorption-xs', format='excel')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following code snippet shows how to export all three `MGXS` to the same HDF5 binary data store." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "total.build_hdf5_store(filename='mgxs', append=True)\n", + "absorption.build_hdf5_store(filename='mgxs', append=True)\n", + "scattering.build_hdf5_store(filename='mgxs', append=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comparing MGXS with Tally Arithmetic" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](https://mit-crpg.github.io/openmc/pythonapi/examples/tally-arithmetic.html) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to confirm that the `TotalXS` is equal to the sum of the `AbsorptionXS` and `ScatterXS` objects." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellenergy [MeV]nuclidescoremeanstd. dev.
01(0.0e+00 - 6.3e-07)total(((total / flux) - (absorption / flux)) - (sca...4.884981e-150.011274
11(6.3e-07 - 2.0e+01)total(((total / flux) - (absorption / flux)) - (sca...1.221245e-150.001802
\n", + "
" + ], + "text/plain": [ + " cell energy [MeV] nuclide \\\n", + "0 1 (0.0e+00 - 6.3e-07) total \n", + "1 1 (6.3e-07 - 2.0e+01) total \n", + "\n", + " score mean std. dev. \n", + "0 (((total / flux) - (absorption / flux)) - (sca... 4.884981e-15 0.011274 \n", + "1 (((total / flux) - (absorption / flux)) - (sca... 1.221245e-15 0.001802 " + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Use tally arithmetic to compute the difference between the total, absorption and scattering\n", + "difference = total.xs_tally - absorption.xs_tally - scattering.xs_tally\n", + "\n", + "# The difference is a derived tally which can generate Pandas DataFrames for inspection\n", + "difference.get_pandas_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, we can use tally arithmetic to compute the ratio of `AbsorptionXS` and `ScatterXS` to the `TotalXS`." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellenergy [MeV]nuclidescoremeanstd. dev.
01(0.0e+00 - 6.3e-07)total((absorption / flux) / (total / flux))0.0762190.000651
11(6.3e-07 - 2.0e+01)total((absorption / flux) / (total / flux))0.0193190.000086
\n", + "
" + ], + "text/plain": [ + " cell energy [MeV] nuclide score \\\n", + "0 1 (0.0e+00 - 6.3e-07) total ((absorption / flux) / (total / flux)) \n", + "1 1 (6.3e-07 - 2.0e+01) total ((absorption / flux) / (total / flux)) \n", + "\n", + " mean std. dev. \n", + "0 0.076219 0.000651 \n", + "1 0.019319 0.000086 " + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Use tally arithmetic to compute the absorption-to-total MGXS ratio\n", + "absorption_to_total = absorption.xs_tally / total.xs_tally\n", + "\n", + "# The absorption-to-total ratio is a derived tally which can generate Pandas DataFrames for inspection\n", + "absorption_to_total.get_pandas_dataframe()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellenergy [MeV]nuclidescoremeanstd. dev.
01(0.0e+00 - 6.3e-07)total((scatter / flux) / (total / flux))0.9237810.007714
11(6.3e-07 - 2.0e+01)total((scatter / flux) / (total / flux))0.9806810.002617
\n", + "
" + ], + "text/plain": [ + " cell energy [MeV] nuclide score \\\n", + "0 1 (0.0e+00 - 6.3e-07) total ((scatter / flux) / (total / flux)) \n", + "1 1 (6.3e-07 - 2.0e+01) total ((scatter / flux) / (total / flux)) \n", + "\n", + " mean std. dev. \n", + "0 0.923781 0.007714 \n", + "1 0.980681 0.002617 " + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Use tally arithmetic to compute the scattering-to-total MGXS ratio\n", + "scattering_to_total = scattering.xs_tally / total.xs_tally\n", + "\n", + "# The scattering-to-total ratio is a derived tally which can generate Pandas DataFrames for inspection\n", + "scattering_to_total.get_pandas_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lastly, we sum the derived scatter-to-total and absorption-to-total ratios to confirm that they sum to unity." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellenergy [MeV]nuclidescoremeanstd. dev.
01(0.0e+00 - 6.3e-07)total(((absorption / flux) / (total / flux)) + ((sc...10.007741
11(6.3e-07 - 2.0e+01)total(((absorption / flux) / (total / flux)) + ((sc...10.002619
\n", + "
" + ], + "text/plain": [ + " cell energy [MeV] nuclide \\\n", + "0 1 (0.0e+00 - 6.3e-07) total \n", + "1 1 (6.3e-07 - 2.0e+01) total \n", + "\n", + " score mean std. dev. \n", + "0 (((absorption / flux) / (total / flux)) + ((sc... 1 0.007741 \n", + "1 (((absorption / flux) / (total / flux)) + ((sc... 1 0.002619 " + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Use tally arithmetic to ensure that the absorption- and scattering-to-total MGXS ratios sum to unity\n", + "sum_ratio = absorption_to_total + scattering_to_total\n", + "\n", + "# The scattering-to-total ratio is a derived tally which can generate Pandas DataFrames for inspection\n", + "sum_ratio.get_pandas_dataframe()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/source/pythonapi/examples/mgxs-part-i.rst b/docs/source/pythonapi/examples/mgxs-part-i.rst new file mode 100644 index 0000000000..8b29183f05 --- /dev/null +++ b/docs/source/pythonapi/examples/mgxs-part-i.rst @@ -0,0 +1,13 @@ +.. _notebook_mgxs_part_i: + +========================= +MGXS Part I: Introduction +========================= + +.. only:: html + + .. notebook:: mgxs-part-i.ipynb + +.. only:: latex + + IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/pythonapi/examples/mgxs-part-ii.ipynb b/docs/source/pythonapi/examples/mgxs-part-ii.ipynb new file mode 100644 index 0000000000..6194b154ac --- /dev/null +++ b/docs/source/pythonapi/examples/mgxs-part-ii.ipynb @@ -0,0 +1,1947 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This IPython Notebook illustrates the use of the `openmc.mgxs` module to calculate multi-group cross sections for a heterogeneous fuel pin cell geometry. In particular, this Notebook illustrates the following features:\n", + "\n", + "* Creation of multi-group cross sections on a **heterogeneous geometry**\n", + "* Calculation of cross sections on a **nuclide-by-nuclide basis**\n", + "* The use of **[tally precision triggers](https://mit-crpg.github.io/openmc/usersguide/input.html#trigger-element)** with multi-group cross sections\n", + "* Built-in features for **energy condensation** in downstream data processing\n", + "* The use of **[PyNE](http://pyne.io/) to plot** continuous-energy vs. multi-group cross sections\n", + "* **Validation** of multi-group cross sections with **[OpenMOC](https://mit-crpg.github.io/OpenMOC/)**\n", + "\n", + "**Note:** This Notebook was created using [OpenMOC](https://mit-crpg.github.io/OpenMOC/) to verify the multi-group cross-sections generated by OpenMC. In order to run this Notebook in its entirety, you must have [OpenMOC](https://mit-crpg.github.io/OpenMOC/) installed on your system, along with OpenCG to convert the OpenMC geometries into OpenMOC geometries. In addition, this Notebook illustrates the use of [Pandas](http://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data. We recommend using [Pandas](http://pandas.pydata.org/) >v0.15.0 or later since OpenMC's Python API leverages the multi-indexing feature included in the most recent releases of [Pandas](http://pandas.pydata.org/)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate Input Files" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/lib/pymodules/python2.7/matplotlib/__init__.py:1173: UserWarning: This call to matplotlib.use() has no effect\n", + "because the backend has already been chosen;\n", + "matplotlib.use() must be called *before* pylab, matplotlib.pyplot,\n", + "or matplotlib.backends is imported for the first time.\n", + "\n", + " warnings.warn(_use_error_msg)\n", + "/usr/local/lib/python2.7/dist-packages/IPython/kernel/__main__.py:9: QAWarning: pyne.rxname is not yet QA compliant.\n", + "/usr/local/lib/python2.7/dist-packages/IPython/kernel/__main__.py:9: QAWarning: pyne.ace is not yet QA compliant.\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "import openmc\n", + "import openmc.mgxs as mgxs\n", + "import openmoc\n", + "from openmoc.compatible import get_openmoc_geometry\n", + "import pyne.ace\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate some Nuclides\n", + "h1 = openmc.Nuclide('H-1')\n", + "o16 = openmc.Nuclide('O-16')\n", + "u235 = openmc.Nuclide('U-235')\n", + "u238 = openmc.Nuclide('U-238')\n", + "zr90 = openmc.Nuclide('Zr-90')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the nuclides we defined, we will now create three distinct materials for water, clad and fuel." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 1.6% enriched fuel\n", + "fuel = openmc.Material(name='1.6% Fuel')\n", + "fuel.set_density('g/cm3', 10.31341)\n", + "fuel.add_nuclide(u235, 3.7503e-4)\n", + "fuel.add_nuclide(u238, 2.2625e-2)\n", + "fuel.add_nuclide(o16, 4.6007e-2)\n", + "\n", + "# borated water\n", + "water = openmc.Material(name='Borated Water')\n", + "water.set_density('g/cm3', 0.740582)\n", + "water.add_nuclide(h1, 4.9457e-2)\n", + "water.add_nuclide(o16, 2.4732e-2)\n", + "\n", + "# zircaloy\n", + "zircaloy = openmc.Material(name='Zircaloy')\n", + "zircaloy.set_density('g/cm3', 6.55)\n", + "zircaloy.add_nuclide(zr90, 7.2758e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With our materials, we can now create a `MaterialsFile` object that can be exported to an actual XML file." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate a MaterialsFile, add Materials\n", + "materials_file = openmc.MaterialsFile()\n", + "materials_file.add_material(fuel)\n", + "materials_file.add_material(water)\n", + "materials_file.add_material(zircaloy)\n", + "materials_file.default_xs = '71c'\n", + "\n", + "# Export to \"materials.xml\"\n", + "materials_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's move on to the geometry. Our problem will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces -- in this case two cylinders and six reflective planes." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create cylinders for the fuel and clad\n", + "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218)\n", + "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720)\n", + "\n", + "# Create boundary planes to surround the geometry\n", + "min_x = openmc.XPlane(x0=-0.63, boundary_type='reflective')\n", + "max_x = openmc.XPlane(x0=+0.63, boundary_type='reflective')\n", + "min_y = openmc.YPlane(y0=-0.63, boundary_type='reflective')\n", + "max_y = openmc.YPlane(y0=+0.63, boundary_type='reflective')\n", + "min_z = openmc.ZPlane(z0=-0.63, boundary_type='reflective')\n", + "max_z = openmc.ZPlane(z0=+0.63, boundary_type='reflective')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create a Universe to encapsulate a fuel pin\n", + "pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin')\n", + "\n", + "# Create fuel Cell\n", + "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", + "fuel_cell.fill = fuel\n", + "fuel_cell.region = -fuel_outer_radius\n", + "pin_cell_universe.add_cell(fuel_cell)\n", + "\n", + "# Create a clad Cell\n", + "clad_cell = openmc.Cell(name='1.6% Clad')\n", + "clad_cell.fill = zircaloy\n", + "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", + "pin_cell_universe.add_cell(clad_cell)\n", + "\n", + "# Create a moderator Cell\n", + "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", + "moderator_cell.fill = water\n", + "moderator_cell.region = +clad_outer_radius\n", + "pin_cell_universe.add_cell(moderator_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create root Cell\n", + "root_cell = openmc.Cell(name='root cell')\n", + "root_cell.region = +min_x & -max_x & +min_y & -max_y\n", + "root_cell.fill = pin_cell_universe\n", + "\n", + "# Create root Universe\n", + "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", + "root_universe.add_cell(root_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now must create a geometry that is assigned a root universe, put the geometry into a `GeometryFile` object, and export it to XML." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create Geometry and set root Universe\n", + "openmc_geometry = openmc.Geometry()\n", + "openmc_geometry.root_universe = root_universe\n", + "\n", + "# Instantiate a GeometryFile\n", + "geometry_file = openmc.GeometryFile()\n", + "geometry_file.geometry = openmc_geometry\n", + "\n", + "# Export to \"geometry.xml\"\n", + "geometry_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we must define simulation parameters. In this case, we will use 10 inactive batches and 190 active batches each with 10,000 particles." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# OpenMC simulation parameters\n", + "batches = 50\n", + "inactive = 10\n", + "particles = 10000\n", + "\n", + "# Instantiate a SettingsFile\n", + "settings_file = openmc.SettingsFile()\n", + "settings_file.batches = batches\n", + "settings_file.inactive = inactive\n", + "settings_file.particles = particles\n", + "settings_file.output = {'tallies': True, 'summary': True}\n", + "bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n", + "settings_file.set_source_space('fission', bounds)\n", + "\n", + "# Activate tally precision triggers\n", + "settings_file.trigger_active = True\n", + "settings_file.trigger_max_batches = settings_file.batches * 4\n", + "\n", + "# Export to \"settings.xml\"\n", + "settings_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we are finally ready to make use of the `openmc.mgxs` module to generate multi-group cross sections! First, let's define \"coarse\" 2-group and \"fine\" 8-group structures using the built-in `EnergyGroups` class." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate a \"coarse\" 2-group EnergyGroups object\n", + "coarse_groups = mgxs.EnergyGroups()\n", + "coarse_groups.group_edges = np.array([0., 0.625e-6, 20.])\n", + "\n", + "# Instantiate a \"fine\" 8-group EnergyGroups object\n", + "fine_groups = mgxs.EnergyGroups()\n", + "fine_groups.group_edges = np.array([0., 0.058e-6, 0.14e-6, 0.28e-6,\n", + " 0.625e-6, 4.e-6, 5.53e-3, 821.e-3, 20.])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we will instantiate a variety of `MGXS` objects needed to run an OpenMOC simulation to verify the accuracy of our cross sections. In particular, we define transport, fission, nu-fission, nu-scatter and chi cross sections for each of the three cells in the fuel pin with the 8-group structure as our energy groups." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Extract all Cells filled by Materials\n", + "openmc_cells = openmc_geometry.get_all_material_cells()\n", + "\n", + "# Create dictionary to store multi-group cross sections for all cells\n", + "xs_library = {}\n", + "\n", + "# Instantiate 8-group cross sections for each cell\n", + "for cell in openmc_cells:\n", + " xs_library[cell.id] = {}\n", + " xs_library[cell.id]['transport'] = mgxs.TransportXS(groups=fine_groups)\n", + " xs_library[cell.id]['fission'] = mgxs.FissionXS(groups=fine_groups)\n", + " xs_library[cell.id]['nu-fission'] = mgxs.NuFissionXS(groups=fine_groups)\n", + " xs_library[cell.id]['nu-scatter'] = mgxs.NuScatterMatrixXS(groups=fine_groups)\n", + " xs_library[cell.id]['chi'] = mgxs.Chi(groups=fine_groups)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we showcase the use of OpenMC's [tally precision trigger](https://mit-crpg.github.io/openmc/usersguide/input.html#trigger-element) feature in conjunction with the `openmc.mgxs` module. In particular, we will assign a tally trigger of 1E-2 on the standard deviation for each of the tallies used to compute multi-group cross sections." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create a tally trigger for +/- 0.01 on each tally used to compute the multi-group cross sections\n", + "tally_trigger = openmc.Trigger('std_dev', 1E-2)\n", + "\n", + "# Add the tally trigger to each of the multi-group cross section tallies\n", + "for cell in openmc_cells:\n", + " for mgxs_type in xs_library[cell.id]:\n", + " xs_library[cell.id][mgxs_type].tally_trigger = tally_trigger" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we must loop over all cells to set the cross section domains to the various cells - fuel, clad and moderator - included in the geometry. In addition, we will set each cross section to tally cross sections on a per-nuclide basis through the use of the `MGXS` class' boolean `by_nuclide` instance attribute. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate an empty TalliesFile\n", + "tallies_file = openmc.TalliesFile()\n", + "\n", + "# Iterate over all cells and cross section types\n", + "for cell in openmc_cells:\n", + " for rxn_type in xs_library[cell.id]:\n", + "\n", + " # Set the cross sections domain type to the cell\n", + " xs_library[cell.id][rxn_type].domain = cell\n", + " xs_library[cell.id][rxn_type].domain_type = 'cell'\n", + " \n", + " # Tally cross sections by nuclide\n", + " xs_library[cell.id][rxn_type].by_nuclide = True\n", + " \n", + " # Add OpenMC tallies to the tallies file for XML generation\n", + " for tally in xs_library[cell.id][rxn_type].tallies.values():\n", + " tallies_file.add_tally(tally, merge=True)\n", + "\n", + "# Export to \"tallies.xml\"\n", + "tallies_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we a have a complete set of inputs, so we can go ahead and run our simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " .d88888b. 888b d888 .d8888b.\n", + " d88P\" \"Y88b 8888b d8888 d88P Y88b\n", + " 888 888 88888b.d88888 888 888\n", + " 888 888 88888b. .d88b. 88888b. 888Y88888P888 888 \n", + " 888 888 888 \"88b d8P Y8b 888 \"88b 888 Y888P 888 888 \n", + " 888 888 888 888 88888888 888 888 888 Y8P 888 888 888\n", + " Y88b. .d88P 888 d88P Y8b. 888 888 888 \" 888 Y88b d88P\n", + " \"Y88888P\" 88888P\" \"Y8888 888 888 888 888 \"Y8888P\"\n", + "__________________888______________________________________________________\n", + " 888\n", + " 888\n", + "\n", + " Copyright: 2011-2015 Massachusetts Institute of Technology\n", + " License: http://mit-crpg.github.io/openmc/license.html\n", + " Version: 0.7.0\n", + " Git SHA1: c4b14a5ef87f004528d35cbf33fef3ed15a386ca\n", + " Date/Time: 2015-12-02 09:13:42\n", + " MPI Processes: 3\n", + "\n", + " ===========================================================================\n", + " ========================> INITIALIZATION <=========================\n", + " ===========================================================================\n", + "\n", + " Reading settings XML file...\n", + " Reading cross sections XML file...\n", + " Reading geometry XML file...\n", + " Reading materials XML file...\n", + " Reading tallies XML file...\n", + " Building neighboring cells lists for each surface...\n", + " Loading ACE cross section table: 92235.71c\n", + " Loading ACE cross section table: 92238.71c\n", + " Loading ACE cross section table: 8016.71c\n", + " Loading ACE cross section table: 1001.71c\n", + " Loading ACE cross section table: 40090.71c\n", + " Maximum neutron transport energy: 20.0000 MeV for 92235.71c\n", + " Initializing source particles...\n", + "\n", + " ===========================================================================\n", + " ====================> K EIGENVALUE SIMULATION <====================\n", + " ===========================================================================\n", + "\n", + " Bat./Gen. k Average k \n", + " ========= ======== ==================== \n", + " 1/1 1.22593 \n", + " 2/1 1.24245 \n", + " 3/1 1.24545 \n", + " 4/1 1.21868 \n", + " 5/1 1.22429 \n", + " 6/1 1.22607 \n", + " 7/1 1.21456 \n", + " 8/1 1.23816 \n", + " 9/1 1.25060 \n", + " 10/1 1.22806 \n", + " 11/1 1.19821 \n", + " 12/1 1.19897 1.19859 +/- 0.00038\n", + " 13/1 1.22119 1.20612 +/- 0.00754\n", + " 14/1 1.20701 1.20634 +/- 0.00533\n", + " 15/1 1.24784 1.21464 +/- 0.00927\n", + " 16/1 1.22413 1.21622 +/- 0.00773\n", + " 17/1 1.25050 1.22112 +/- 0.00817\n", + " 18/1 1.22006 1.22099 +/- 0.00707\n", + " 19/1 1.22813 1.22178 +/- 0.00629\n", + " 20/1 1.22791 1.22239 +/- 0.00566\n", + " 21/1 1.22729 1.22284 +/- 0.00514\n", + " 22/1 1.19867 1.22083 +/- 0.00510\n", + " 23/1 1.23796 1.22214 +/- 0.00488\n", + " 24/1 1.22412 1.22228 +/- 0.00452\n", + " 25/1 1.22638 1.22256 +/- 0.00421\n", + " 26/1 1.22181 1.22251 +/- 0.00394\n", + " 27/1 1.19055 1.22063 +/- 0.00415\n", + " 28/1 1.20683 1.21986 +/- 0.00399\n", + " 29/1 1.21689 1.21971 +/- 0.00378\n", + " 30/1 1.23670 1.22056 +/- 0.00368\n", + " 31/1 1.21396 1.22024 +/- 0.00352\n", + " 32/1 1.21389 1.21995 +/- 0.00337\n", + " 33/1 1.24649 1.22111 +/- 0.00342\n", + " 34/1 1.23204 1.22156 +/- 0.00330\n", + " 35/1 1.20768 1.22101 +/- 0.00322\n", + " 36/1 1.22271 1.22107 +/- 0.00309\n", + " 37/1 1.21796 1.22096 +/- 0.00298\n", + " 38/1 1.23842 1.22158 +/- 0.00293\n", + " 39/1 1.23080 1.22190 +/- 0.00285\n", + " 40/1 1.23572 1.22236 +/- 0.00279\n", + " 41/1 1.21691 1.22218 +/- 0.00271\n", + " 42/1 1.24616 1.22293 +/- 0.00272\n", + " 43/1 1.21903 1.22282 +/- 0.00264\n", + " 44/1 1.22967 1.22302 +/- 0.00257\n", + " 45/1 1.22053 1.22295 +/- 0.00250\n", + " 46/1 1.24087 1.22344 +/- 0.00248\n", + " 47/1 1.20251 1.22288 +/- 0.00248\n", + " 48/1 1.20331 1.22236 +/- 0.00246\n", + " 49/1 1.22724 1.22249 +/- 0.00240\n", + " 50/1 1.24798 1.22313 +/- 0.00243\n", + " Triggers unsatisfied, max unc./thresh. is 1.32110 for scatter-p1 in tally 10054\n", + " The estimated number of batches is 80\n", + " Creating state point statepoint.050.h5...\n", + " 51/1 1.22253 1.22311 +/- 0.00237\n", + " 52/1 1.24330 1.22359 +/- 0.00236\n", + " 53/1 1.23251 1.22380 +/- 0.00231\n", + " 54/1 1.21133 1.22352 +/- 0.00228\n", + " 55/1 1.24503 1.22399 +/- 0.00228\n", + " 56/1 1.22013 1.22391 +/- 0.00223\n", + " 57/1 1.23877 1.22423 +/- 0.00220\n", + " 58/1 1.23793 1.22451 +/- 0.00218\n", + " 59/1 1.21018 1.22422 +/- 0.00215\n", + " 60/1 1.22417 1.22422 +/- 0.00211\n", + " 61/1 1.23094 1.22435 +/- 0.00207\n", + " 62/1 1.23310 1.22452 +/- 0.00204\n", + " 63/1 1.22488 1.22453 +/- 0.00200\n", + " 64/1 1.22702 1.22457 +/- 0.00196\n", + " 65/1 1.18834 1.22391 +/- 0.00204\n", + " 66/1 1.23112 1.22404 +/- 0.00200\n", + " 67/1 1.21611 1.22390 +/- 0.00197\n", + " 68/1 1.22513 1.22392 +/- 0.00194\n", + " 69/1 1.21741 1.22381 +/- 0.00191\n", + " 70/1 1.22484 1.22383 +/- 0.00188\n", + " 71/1 1.19662 1.22338 +/- 0.00190\n", + " 72/1 1.23315 1.22354 +/- 0.00187\n", + " 73/1 1.22796 1.22361 +/- 0.00185\n", + " 74/1 1.21417 1.22346 +/- 0.00182\n", + " 75/1 1.21020 1.22326 +/- 0.00181\n", + " 76/1 1.23413 1.22343 +/- 0.00179\n", + " 77/1 1.22184 1.22340 +/- 0.00176\n", + " 78/1 1.20309 1.22310 +/- 0.00176\n", + " 79/1 1.23458 1.22327 +/- 0.00174\n", + " 80/1 1.20724 1.22304 +/- 0.00173\n", + " Triggers satisfied for batch 80\n", + " Creating state point statepoint.080.h5...\n", + "\n", + " ===========================================================================\n", + " ======================> SIMULATION FINISHED <======================\n", + " ===========================================================================\n", + "\n", + "\n", + " =======================> TIMING STATISTICS <=======================\n", + "\n", + " Total time for initialization = 7.5700E-01 seconds\n", + " Reading cross sections = 1.5800E-01 seconds\n", + " Total time in simulation = 1.4921E+02 seconds\n", + " Time in transport only = 1.4336E+02 seconds\n", + " Time in inactive batches = 8.6210E+00 seconds\n", + " Time in active batches = 1.4059E+02 seconds\n", + " Time synchronizing fission bank = 5.6060E+00 seconds\n", + " Sampling source sites = 1.4000E-02 seconds\n", + " SEND/RECV source sites = 4.0000E-03 seconds\n", + " Time accumulating tallies = 6.0000E-03 seconds\n", + " Total time for finalization = 1.3000E-02 seconds\n", + " Total time elapsed = 1.5002E+02 seconds\n", + " Calculation Rate (inactive) = 11599.6 neutrons/second\n", + " Calculation Rate (active) = 2845.11 neutrons/second\n", + "\n", + " ============================> RESULTS <============================\n", + "\n", + " k-effective (Collision) = 1.22327 +/- 0.00148\n", + " k-effective (Track-length) = 1.22304 +/- 0.00173\n", + " k-effective (Absorption) = 1.22407 +/- 0.00129\n", + " Combined k-effective = 1.22373 +/- 0.00113\n", + " Leakage Fraction = 0.00000 +/- 0.00000\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Run OpenMC\n", + "executor = openmc.Executor()\n", + "executor.run_simulation(output=True, mpi_procs=3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tally Data Processing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a `StatePoint` object. " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Load the last statepoint file\n", + "sp = openmc.StatePoint('statepoint.080.h5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. This is necessary for the `openmc.mgxs` module to properly process the tally data. We first create a `Summary` object and link it with the statepoint." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Load the summary file and link it with the statepoint\n", + "su = openmc.Summary('summary.h5')\n", + "sp.link_with_summary(su)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The statepoint is now ready to be analyzed by our multi-group cross sections. We simply have to load the tallies from the `StatePoint` into each object as follows and our `MGXS` objects will compute the cross sections for us under-the-hood." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Iterate over all cells and cross section types\n", + "for cell in openmc_cells:\n", + " for rxn_type in xs_library[cell.id]:\n", + " xs_library[cell.id][rxn_type].load_from_statepoint(sp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That's it! Our multi-group cross sections are now ready for the big spotlight. This time we have cross sections in three distinct spatial zones - fuel, clad and moderator - on a per-nuclide basis." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Extracting and Storing MGXS Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's first inspect one of our cross sections by printing it to the screen as a microscopic cross section in units of barns." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Multi-Group XS\n", + "\tReaction Type =\tnu-fission\n", + "\tDomain Type =\tcell\n", + "\tDomain ID =\t10000\n", + "\tNuclide =\tU-235\n", + "\tCross Sections [barns]:\n", + " Group 1 [0.821 - 20.0 MeV]:\t3.31e+00 +/- 1.88e-01%\n", + " Group 2 [0.00553 - 0.821 MeV]:\t3.97e+00 +/- 1.24e-01%\n", + " Group 3 [4e-06 - 0.00553 MeV]:\t5.50e+01 +/- 2.02e-01%\n", + " Group 4 [6.25e-07 - 4e-06 MeV]:\t8.83e+01 +/- 3.56e-01%\n", + " Group 5 [2.8e-07 - 6.25e-07 MeV]:\t2.90e+02 +/- 4.54e-01%\n", + " Group 6 [1.4e-07 - 2.8e-07 MeV]:\t4.49e+02 +/- 4.10e-01%\n", + " Group 7 [5.8e-08 - 1.4e-07 MeV]:\t6.87e+02 +/- 2.56e-01%\n", + " Group 8 [0.0 - 5.8e-08 MeV]:\t1.44e+03 +/- 2.82e-01%\n", + "\n", + "\tNuclide =\tU-238\n", + "\tCross Sections [barns]:\n", + " Group 1 [0.821 - 20.0 MeV]:\t1.06e+00 +/- 2.30e-01%\n", + " Group 2 [0.00553 - 0.821 MeV]:\t1.21e-03 +/- 2.25e-01%\n", + " Group 3 [4e-06 - 0.00553 MeV]:\t5.82e-04 +/- 3.09e+00%\n", + " Group 4 [6.25e-07 - 4e-06 MeV]:\t6.54e-06 +/- 3.27e-01%\n", + " Group 5 [2.8e-07 - 6.25e-07 MeV]:\t1.07e-05 +/- 4.39e-01%\n", + " Group 6 [1.4e-07 - 2.8e-07 MeV]:\t1.55e-05 +/- 4.12e-01%\n", + " Group 7 [5.8e-08 - 1.4e-07 MeV]:\t2.30e-05 +/- 2.57e-01%\n", + " Group 8 [0.0 - 5.8e-08 MeV]:\t4.24e-05 +/- 2.81e-01%\n", + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "nufission = xs_library[fuel_cell.id]['nu-fission']\n", + "nufission.print_xs(xs_type='micro', nuclides=['U-235', 'U-238'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our multi-group cross sections are capable of summing across all nuclides to provide us with macroscopic cross sections as well." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Multi-Group XS\n", + "\tReaction Type =\tnu-fission\n", + "\tDomain Type =\tcell\n", + "\tDomain ID =\t10000\n", + "\tCross Sections [cm^-1]:\n", + " Group 1 [0.821 - 20.0 MeV]:\t2.52e-02 +/- 2.19e-01%\n", + " Group 2 [0.00553 - 0.821 MeV]:\t1.51e-03 +/- 1.22e-01%\n", + " Group 3 [4e-06 - 0.00553 MeV]:\t2.06e-02 +/- 2.02e-01%\n", + " Group 4 [6.25e-07 - 4e-06 MeV]:\t3.31e-02 +/- 3.56e-01%\n", + " Group 5 [2.8e-07 - 6.25e-07 MeV]:\t1.09e-01 +/- 4.54e-01%\n", + " Group 6 [1.4e-07 - 2.8e-07 MeV]:\t1.69e-01 +/- 4.10e-01%\n", + " Group 7 [5.8e-08 - 1.4e-07 MeV]:\t2.58e-01 +/- 2.56e-01%\n", + " Group 8 [0.0 - 5.8e-08 MeV]:\t5.40e-01 +/- 2.82e-01%\n", + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "nufission = xs_library[fuel_cell.id]['nu-fission']\n", + "nufission.print_xs(xs_type='macro', nuclides='sum')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Although a printed report is nice, it is not scalable or flexible. Let's extract the microscopic cross section data for the moderator as a [Pandas](http://pandas.pydata.org/) `DataFrame` ." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellgroup ingroup outnuclidemeanstd. dev.
1261000211H-10.2340220.003645
1271000211O-161.5603050.006280
1241000212H-11.5880250.002815
1251000212O-160.2851470.001392
1221000213H-10.0107760.000186
1231000213O-160.0000000.000000
1201000214H-10.0000230.000010
1211000214O-160.0000000.000000
1181000215H-10.0000000.000000
1191000215O-160.0000000.000000
\n", + "
" + ], + "text/plain": [ + " cell group in group out nuclide mean std. dev.\n", + "126 10002 1 1 H-1 0.234022 0.003645\n", + "127 10002 1 1 O-16 1.560305 0.006280\n", + "124 10002 1 2 H-1 1.588025 0.002815\n", + "125 10002 1 2 O-16 0.285147 0.001392\n", + "122 10002 1 3 H-1 0.010776 0.000186\n", + "123 10002 1 3 O-16 0.000000 0.000000\n", + "120 10002 1 4 H-1 0.000023 0.000010\n", + "121 10002 1 4 O-16 0.000000 0.000000\n", + "118 10002 1 5 H-1 0.000000 0.000000\n", + "119 10002 1 5 O-16 0.000000 0.000000" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nuscatter = xs_library[moderator_cell.id]['nu-scatter']\n", + "df = nuscatter.get_pandas_dataframe(xs_type='micro')\n", + "df.head(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we illustate how one can easily take multi-group cross sections and condense them down to a coarser energy group structure. The `MGXS` class includes a `get_condensed_xs(...)` method which takes an `EnergyGroups` parameter with a coarse(r) group structure and returns a new `MGXS` condensed to the coarse groups. We illustrate this process below using the 2-group structure created earlier." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Extract the 16-group transport cross section for the fuel\n", + "fine_xs = xs_library[fuel_cell.id]['transport']\n", + "\n", + "# Condense to the 2-group structure\n", + "condensed_xs = fine_xs.get_condensed_xs(coarse_groups)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Group condensation is as simple as that! We now have a new coarse 2-group `TransportXS` in addition to our original 16-group `TransportXS`. Let's inspect the 2-group `TransportXS` by printing it to the screen and extracting a Pandas `DataFrame` as we have already learned how to do." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Multi-Group XS\n", + "\tReaction Type =\ttransport\n", + "\tDomain Type =\tcell\n", + "\tDomain ID =\t10000\n", + "\tNuclide =\tU-235\n", + "\tCross Sections [cm^-1]:\n", + " Group 1 [6.25e-07 - 20.0 MeV]:\t7.81e-03 +/- 4.75e-01%\n", + " Group 2 [0.0 - 6.25e-07 MeV]:\t1.82e-01 +/- 1.89e-01%\n", + "\n", + "\tNuclide =\tU-238\n", + "\tCross Sections [cm^-1]:\n", + " Group 1 [6.25e-07 - 20.0 MeV]:\t2.17e-01 +/- 1.31e-01%\n", + " Group 2 [0.0 - 6.25e-07 MeV]:\t2.53e-01 +/- 2.08e-01%\n", + "\n", + "\tNuclide =\tO-16\n", + "\tCross Sections [cm^-1]:\n", + " Group 1 [6.25e-07 - 20.0 MeV]:\t1.45e-01 +/- 1.50e-01%\n", + " Group 2 [0.0 - 6.25e-07 MeV]:\t1.74e-01 +/- 2.66e-01%\n", + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "condensed_xs.print_xs()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellgroup innuclidemeanstd. dev.
3100001U-23520.8281270.098842
4100001U-2389.5822950.012550
5100001O-163.1573580.004725
0100002U-235485.2176490.916465
1100002U-23811.1760810.023196
2100002O-163.7881670.010090
\n", + "
" + ], + "text/plain": [ + " cell group in nuclide mean std. dev.\n", + "3 10000 1 U-235 20.828127 0.098842\n", + "4 10000 1 U-238 9.582295 0.012550\n", + "5 10000 1 O-16 3.157358 0.004725\n", + "0 10000 2 U-235 485.217649 0.916465\n", + "1 10000 2 U-238 11.176081 0.023196\n", + "2 10000 2 O-16 3.788167 0.010090" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = condensed_xs.get_pandas_dataframe(xs_type='micro')\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Verification with OpenMOC" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's verify our cross sections using OpenMOC. First, we use OpenCG construct an equivalent OpenMOC geometry." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create an OpenMOC Geometry from the OpenCG Geometry\n", + "openmoc_geometry = get_openmoc_geometry(su.opencg_geometry)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we we can inject the multi-group cross sections into the equivalent fuel pin cell OpenMOC geometry." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Get all OpenMOC cells in the gometry\n", + "openmoc_cells = openmoc_geometry.getRootUniverse().getAllCells()\n", + "\n", + "# Inject multi-group cross sections into OpenMOC Materials\n", + "for cell_id, cell in openmoc_cells.items():\n", + " \n", + " # Ignore the root cell\n", + " if cell.getName() == 'root cell':\n", + " continue\n", + " \n", + " # Get a reference to the Material filling this Cell\n", + " openmoc_material = cell.getFillMaterial()\n", + " \n", + " # Set the number of energy groups for the Material\n", + " openmoc_material.setNumEnergyGroups(fine_groups.num_groups)\n", + " \n", + " # Extract the appropriate cross section objects for this cell\n", + " transport = xs_library[cell_id]['transport']\n", + " nufission = xs_library[cell_id]['nu-fission']\n", + " nuscatter = xs_library[cell_id]['nu-scatter']\n", + " chi = xs_library[cell_id]['chi']\n", + " \n", + " # Inject NumPy arrays of cross section data into the Material\n", + " # NOTE: Sum across nuclides to get macro cross sections needed by OpenMOC\n", + " openmoc_material.setSigmaT(transport.get_xs(nuclides='sum').flatten())\n", + " openmoc_material.setNuSigmaF(nufission.get_xs(nuclides='sum').flatten())\n", + " openmoc_material.setSigmaS(nuscatter.get_xs(nuclides='sum').flatten())\n", + " openmoc_material.setChi(chi.get_xs(nuclides='sum').flatten())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to run OpenMOC to verify our cross-sections from OpenMC." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Importing ray tracing data from file...\n", + "[ NORMAL ] Computing the eigenvalue...\n", + "[ NORMAL ] Iteration 0:\tk_eff = 0.574633\tres = 1.959E-316\n", + "[ NORMAL ] Iteration 1:\tk_eff = 0.679931\tres = 4.254E-01\n", + "[ NORMAL ] Iteration 2:\tk_eff = 0.660910\tres = 1.832E-01\n", + "[ NORMAL ] Iteration 3:\tk_eff = 0.658975\tres = 2.797E-02\n", + "[ NORMAL ] Iteration 4:\tk_eff = 0.642976\tres = 2.928E-03\n", + "[ NORMAL ] Iteration 5:\tk_eff = 0.625710\tres = 2.428E-02\n", + "[ NORMAL ] Iteration 6:\tk_eff = 0.606520\tres = 2.685E-02\n", + "[ NORMAL ] Iteration 7:\tk_eff = 0.587277\tres = 3.067E-02\n", + "[ NORMAL ] Iteration 8:\tk_eff = 0.568777\tres = 3.173E-02\n", + "[ NORMAL ] Iteration 9:\tk_eff = 0.551415\tres = 3.150E-02\n", + "[ NORMAL ] Iteration 10:\tk_eff = 0.535708\tres = 3.052E-02\n", + "[ NORMAL ] Iteration 11:\tk_eff = 0.521916\tres = 2.849E-02\n", + "[ NORMAL ] Iteration 12:\tk_eff = 0.510221\tres = 2.575E-02\n", + "[ NORMAL ] Iteration 13:\tk_eff = 0.500691\tres = 2.241E-02\n", + "[ NORMAL ] Iteration 14:\tk_eff = 0.493392\tres = 1.868E-02\n", + "[ NORMAL ] Iteration 15:\tk_eff = 0.488317\tres = 1.458E-02\n", + "[ NORMAL ] Iteration 16:\tk_eff = 0.485438\tres = 1.028E-02\n", + "[ NORMAL ] Iteration 17:\tk_eff = 0.484705\tres = 5.896E-03\n", + "[ NORMAL ] Iteration 18:\tk_eff = 0.486045\tres = 1.510E-03\n", + "[ NORMAL ] Iteration 19:\tk_eff = 0.489362\tres = 2.766E-03\n", + "[ NORMAL ] Iteration 20:\tk_eff = 0.494546\tres = 6.824E-03\n", + "[ NORMAL ] Iteration 21:\tk_eff = 0.501481\tres = 1.059E-02\n", + "[ NORMAL ] Iteration 22:\tk_eff = 0.510041\tres = 1.402E-02\n", + "[ NORMAL ] Iteration 23:\tk_eff = 0.520094\tres = 1.707E-02\n", + "[ NORMAL ] Iteration 24:\tk_eff = 0.531507\tres = 1.971E-02\n", + "[ NORMAL ] Iteration 25:\tk_eff = 0.544144\tres = 2.194E-02\n", + "[ NORMAL ] Iteration 26:\tk_eff = 0.557872\tres = 2.378E-02\n", + "[ NORMAL ] Iteration 27:\tk_eff = 0.572557\tres = 2.523E-02\n", + "[ NORMAL ] Iteration 28:\tk_eff = 0.588072\tres = 2.632E-02\n", + "[ NORMAL ] Iteration 29:\tk_eff = 0.604293\tres = 2.710E-02\n", + "[ NORMAL ] Iteration 30:\tk_eff = 0.621101\tres = 2.758E-02\n", + "[ NORMAL ] Iteration 31:\tk_eff = 0.638382\tres = 2.781E-02\n", + "[ NORMAL ] Iteration 32:\tk_eff = 0.656032\tres = 2.782E-02\n", + "[ NORMAL ] Iteration 33:\tk_eff = 0.673950\tres = 2.765E-02\n", + "[ NORMAL ] Iteration 34:\tk_eff = 0.692043\tres = 2.731E-02\n", + "[ NORMAL ] Iteration 35:\tk_eff = 0.710227\tres = 2.685E-02\n", + "[ NORMAL ] Iteration 36:\tk_eff = 0.728423\tres = 2.628E-02\n", + "[ NORMAL ] Iteration 37:\tk_eff = 0.746558\tres = 2.562E-02\n", + "[ NORMAL ] Iteration 38:\tk_eff = 0.764569\tres = 2.490E-02\n", + "[ NORMAL ] Iteration 39:\tk_eff = 0.782396\tres = 2.412E-02\n", + "[ NORMAL ] Iteration 40:\tk_eff = 0.799989\tres = 2.332E-02\n", + "[ NORMAL ] Iteration 41:\tk_eff = 0.817301\tres = 2.249E-02\n", + "[ NORMAL ] Iteration 42:\tk_eff = 0.834292\tres = 2.164E-02\n", + "[ NORMAL ] Iteration 43:\tk_eff = 0.850927\tres = 2.079E-02\n", + "[ NORMAL ] Iteration 44:\tk_eff = 0.867177\tres = 1.994E-02\n", + "[ NORMAL ] Iteration 45:\tk_eff = 0.883017\tres = 1.910E-02\n", + "[ NORMAL ] Iteration 46:\tk_eff = 0.898427\tres = 1.827E-02\n", + "[ NORMAL ] Iteration 47:\tk_eff = 0.913389\tres = 1.745E-02\n", + "[ NORMAL ] Iteration 48:\tk_eff = 0.927891\tres = 1.665E-02\n", + "[ NORMAL ] Iteration 49:\tk_eff = 0.941925\tres = 1.588E-02\n", + "[ NORMAL ] Iteration 50:\tk_eff = 0.955483\tres = 1.512E-02\n", + "[ NORMAL ] Iteration 51:\tk_eff = 0.968562\tres = 1.439E-02\n", + "[ NORMAL ] Iteration 52:\tk_eff = 0.981161\tres = 1.369E-02\n", + "[ NORMAL ] Iteration 53:\tk_eff = 0.993282\tres = 1.301E-02\n", + "[ NORMAL ] Iteration 54:\tk_eff = 1.004928\tres = 1.235E-02\n", + "[ NORMAL ] Iteration 55:\tk_eff = 1.016104\tres = 1.172E-02\n", + "[ NORMAL ] Iteration 56:\tk_eff = 1.026816\tres = 1.112E-02\n", + "[ NORMAL ] Iteration 57:\tk_eff = 1.037073\tres = 1.054E-02\n", + "[ NORMAL ] Iteration 58:\tk_eff = 1.046883\tres = 9.989E-03\n", + "[ NORMAL ] Iteration 59:\tk_eff = 1.056257\tres = 9.460E-03\n", + "[ NORMAL ] Iteration 60:\tk_eff = 1.065205\tres = 8.954E-03\n", + "[ NORMAL ] Iteration 61:\tk_eff = 1.073739\tres = 8.472E-03\n", + "[ NORMAL ] Iteration 62:\tk_eff = 1.081871\tres = 8.012E-03\n", + "[ NORMAL ] Iteration 63:\tk_eff = 1.089613\tres = 7.573E-03\n", + "[ NORMAL ] Iteration 64:\tk_eff = 1.096979\tres = 7.156E-03\n", + "[ NORMAL ] Iteration 65:\tk_eff = 1.103980\tres = 6.760E-03\n", + "[ NORMAL ] Iteration 66:\tk_eff = 1.110631\tres = 6.382E-03\n", + "[ NORMAL ] Iteration 67:\tk_eff = 1.116943\tres = 6.024E-03\n", + "[ NORMAL ] Iteration 68:\tk_eff = 1.122931\tres = 5.684E-03\n", + "[ NORMAL ] Iteration 69:\tk_eff = 1.128607\tres = 5.361E-03\n", + "[ NORMAL ] Iteration 70:\tk_eff = 1.133984\tres = 5.055E-03\n", + "[ NORMAL ] Iteration 71:\tk_eff = 1.139075\tres = 4.764E-03\n", + "[ NORMAL ] Iteration 72:\tk_eff = 1.143892\tres = 4.489E-03\n", + "[ NORMAL ] Iteration 73:\tk_eff = 1.148447\tres = 4.229E-03\n", + "[ NORMAL ] Iteration 74:\tk_eff = 1.152752\tres = 3.982E-03\n", + "[ NORMAL ] Iteration 75:\tk_eff = 1.156819\tres = 3.749E-03\n", + "[ NORMAL ] Iteration 76:\tk_eff = 1.160659\tres = 3.528E-03\n", + "[ NORMAL ] Iteration 77:\tk_eff = 1.164282\tres = 3.319E-03\n", + "[ NORMAL ] Iteration 78:\tk_eff = 1.167701\tres = 3.122E-03\n", + "[ NORMAL ] Iteration 79:\tk_eff = 1.170923\tres = 2.936E-03\n", + "[ NORMAL ] Iteration 80:\tk_eff = 1.173961\tres = 2.760E-03\n", + "[ NORMAL ] Iteration 81:\tk_eff = 1.176822\tres = 2.594E-03\n", + "[ NORMAL ] Iteration 82:\tk_eff = 1.179516\tres = 2.437E-03\n", + "[ NORMAL ] Iteration 83:\tk_eff = 1.182052\tres = 2.289E-03\n", + "[ NORMAL ] Iteration 84:\tk_eff = 1.184438\tres = 2.150E-03\n", + "[ NORMAL ] Iteration 85:\tk_eff = 1.186682\tres = 2.019E-03\n", + "[ NORMAL ] Iteration 86:\tk_eff = 1.188792\tres = 1.895E-03\n", + "[ NORMAL ] Iteration 87:\tk_eff = 1.190775\tres = 1.778E-03\n", + "[ NORMAL ] Iteration 88:\tk_eff = 1.192639\tres = 1.668E-03\n", + "[ NORMAL ] Iteration 89:\tk_eff = 1.194389\tres = 1.565E-03\n", + "[ NORMAL ] Iteration 90:\tk_eff = 1.196032\tres = 1.468E-03\n", + "[ NORMAL ] Iteration 91:\tk_eff = 1.197575\tres = 1.376E-03\n", + "[ NORMAL ] Iteration 92:\tk_eff = 1.199023\tres = 1.290E-03\n", + "[ NORMAL ] Iteration 93:\tk_eff = 1.200381\tres = 1.209E-03\n", + "[ NORMAL ] Iteration 94:\tk_eff = 1.201654\tres = 1.133E-03\n", + "[ NORMAL ] Iteration 95:\tk_eff = 1.202849\tres = 1.061E-03\n", + "[ NORMAL ] Iteration 96:\tk_eff = 1.203968\tres = 9.939E-04\n", + "[ NORMAL ] Iteration 97:\tk_eff = 1.205017\tres = 9.307E-04\n", + "[ NORMAL ] Iteration 98:\tk_eff = 1.206000\tres = 8.714E-04\n", + "[ NORMAL ] Iteration 99:\tk_eff = 1.206921\tres = 8.157E-04\n", + "[ NORMAL ] Iteration 100:\tk_eff = 1.207783\tres = 7.634E-04\n", + "[ NORMAL ] Iteration 101:\tk_eff = 1.208590\tres = 7.144E-04\n", + "[ NORMAL ] Iteration 102:\tk_eff = 1.209346\tres = 6.684E-04\n", + "[ NORMAL ] Iteration 103:\tk_eff = 1.210053\tres = 6.252E-04\n", + "[ NORMAL ] Iteration 104:\tk_eff = 1.210715\tres = 5.848E-04\n", + "[ NORMAL ] Iteration 105:\tk_eff = 1.211334\tres = 5.468E-04\n", + "[ NORMAL ] Iteration 106:\tk_eff = 1.211913\tres = 5.113E-04\n", + "[ NORMAL ] Iteration 107:\tk_eff = 1.212454\tres = 4.779E-04\n", + "[ NORMAL ] Iteration 108:\tk_eff = 1.212960\tres = 4.467E-04\n", + "[ NORMAL ] Iteration 109:\tk_eff = 1.213434\tres = 4.175E-04\n", + "[ NORMAL ] Iteration 110:\tk_eff = 1.213876\tres = 3.901E-04\n", + "[ NORMAL ] Iteration 111:\tk_eff = 1.214289\tres = 3.644E-04\n", + "[ NORMAL ] Iteration 112:\tk_eff = 1.214675\tres = 3.404E-04\n", + "[ NORMAL ] Iteration 113:\tk_eff = 1.215036\tres = 3.180E-04\n", + "[ NORMAL ] Iteration 114:\tk_eff = 1.215373\tres = 2.969E-04\n", + "[ NORMAL ] Iteration 115:\tk_eff = 1.215687\tres = 2.773E-04\n", + "[ NORMAL ] Iteration 116:\tk_eff = 1.215981\tres = 2.589E-04\n", + "[ NORMAL ] Iteration 117:\tk_eff = 1.216255\tres = 2.416E-04\n", + "[ NORMAL ] Iteration 118:\tk_eff = 1.216511\tres = 2.256E-04\n", + "[ NORMAL ] Iteration 119:\tk_eff = 1.216750\tres = 2.105E-04\n", + "[ NORMAL ] Iteration 120:\tk_eff = 1.216973\tres = 1.964E-04\n", + "[ NORMAL ] Iteration 121:\tk_eff = 1.217181\tres = 1.833E-04\n", + "[ NORMAL ] Iteration 122:\tk_eff = 1.217376\tres = 1.710E-04\n", + "[ NORMAL ] Iteration 123:\tk_eff = 1.217557\tres = 1.595E-04\n", + "[ NORMAL ] Iteration 124:\tk_eff = 1.217726\tres = 1.488E-04\n", + "[ NORMAL ] Iteration 125:\tk_eff = 1.217883\tres = 1.388E-04\n", + "[ NORMAL ] Iteration 126:\tk_eff = 1.218030\tres = 1.294E-04\n", + "[ NORMAL ] Iteration 127:\tk_eff = 1.218167\tres = 1.207E-04\n", + "[ NORMAL ] Iteration 128:\tk_eff = 1.218295\tres = 1.125E-04\n", + "[ NORMAL ] Iteration 129:\tk_eff = 1.218414\tres = 1.049E-04\n", + "[ NORMAL ] Iteration 130:\tk_eff = 1.218525\tres = 9.777E-05\n", + "[ NORMAL ] Iteration 131:\tk_eff = 1.218629\tres = 9.113E-05\n", + "[ NORMAL ] Iteration 132:\tk_eff = 1.218725\tres = 8.494E-05\n", + "[ NORMAL ] Iteration 133:\tk_eff = 1.218815\tres = 7.916E-05\n", + "[ NORMAL ] Iteration 134:\tk_eff = 1.218899\tres = 7.376E-05\n", + "[ NORMAL ] Iteration 135:\tk_eff = 1.218977\tres = 6.873E-05\n", + "[ NORMAL ] Iteration 136:\tk_eff = 1.219050\tres = 6.404E-05\n", + "[ NORMAL ] Iteration 137:\tk_eff = 1.219117\tres = 5.966E-05\n", + "[ NORMAL ] Iteration 138:\tk_eff = 1.219180\tres = 5.557E-05\n", + "[ NORMAL ] Iteration 139:\tk_eff = 1.219239\tres = 5.177E-05\n", + "[ NORMAL ] Iteration 140:\tk_eff = 1.219294\tres = 4.822E-05\n", + "[ NORMAL ] Iteration 141:\tk_eff = 1.219345\tres = 4.491E-05\n", + "[ NORMAL ] Iteration 142:\tk_eff = 1.219392\tres = 4.182E-05\n", + "[ NORMAL ] Iteration 143:\tk_eff = 1.219437\tres = 3.894E-05\n", + "[ NORMAL ] Iteration 144:\tk_eff = 1.219478\tres = 3.626E-05\n", + "[ NORMAL ] Iteration 145:\tk_eff = 1.219516\tres = 3.376E-05\n", + "[ NORMAL ] Iteration 146:\tk_eff = 1.219552\tres = 3.144E-05\n", + "[ NORMAL ] Iteration 147:\tk_eff = 1.219585\tres = 2.927E-05\n", + "[ NORMAL ] Iteration 148:\tk_eff = 1.219616\tres = 2.724E-05\n", + "[ NORMAL ] Iteration 149:\tk_eff = 1.219645\tres = 2.536E-05\n", + "[ NORMAL ] Iteration 150:\tk_eff = 1.219672\tres = 2.361E-05\n", + "[ NORMAL ] Iteration 151:\tk_eff = 1.219696\tres = 2.197E-05\n", + "[ NORMAL ] Iteration 152:\tk_eff = 1.219720\tres = 2.045E-05\n", + "[ NORMAL ] Iteration 153:\tk_eff = 1.219741\tres = 1.903E-05\n", + "[ NORMAL ] Iteration 154:\tk_eff = 1.219761\tres = 1.771E-05\n", + "[ NORMAL ] Iteration 155:\tk_eff = 1.219780\tres = 1.648E-05\n", + "[ NORMAL ] Iteration 156:\tk_eff = 1.219797\tres = 1.534E-05\n", + "[ NORMAL ] Iteration 157:\tk_eff = 1.219814\tres = 1.427E-05\n", + "[ NORMAL ] Iteration 158:\tk_eff = 1.219829\tres = 1.328E-05\n", + "[ NORMAL ] Iteration 159:\tk_eff = 1.219843\tres = 1.235E-05\n", + "[ NORMAL ] Iteration 160:\tk_eff = 1.219856\tres = 1.149E-05\n", + "[ NORMAL ] Iteration 161:\tk_eff = 1.219868\tres = 1.069E-05\n" + ] + } + ], + "source": [ + "# Generate tracks for OpenMOC\n", + "openmoc_geometry.initializeFlatSourceRegions()\n", + "track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=128, spacing=0.1)\n", + "track_generator.generateTracks()\n", + "\n", + "# Run OpenMOC\n", + "solver = openmoc.CPUSolver(track_generator)\n", + "solver.computeEigenvalue()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We report the eigenvalues computed by OpenMC and OpenMOC here together to summarize our results." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "openmc keff = 1.223729\n", + "openmoc keff = 1.219868\n", + "bias [pcm]: -386.1\n" + ] + } + ], + "source": [ + "# Print report of keff and bias with OpenMC\n", + "openmoc_keff = solver.getKeff()\n", + "openmc_keff = sp.k_combined[0]\n", + "bias = (openmoc_keff - openmc_keff) * 1e5\n", + "\n", + "print('openmc keff = {0:1.6f}'.format(openmc_keff))\n", + "print('openmoc keff = {0:1.6f}'.format(openmoc_keff))\n", + "print('bias [pcm]: {0:1.1f}'.format(bias))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As a sanity check, let's run a simulation with the coarse 2-group cross sections to ensure that they also produce a reasonable result." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "openmoc_geometry = get_openmoc_geometry(su.opencg_geometry)\n", + "openmoc_cells = openmoc_geometry.getRootUniverse().getAllCells()\n", + "\n", + "# Inject multi-group cross sections into OpenMOC Materials\n", + "for cell_id, cell in openmoc_cells.items():\n", + " \n", + " # Ignore the root cell\n", + " if cell.getName() == 'root cell':\n", + " continue\n", + " \n", + " openmoc_material = cell.getFillMaterial()\n", + " openmoc_material.setNumEnergyGroups(coarse_groups.num_groups)\n", + " \n", + " # Extract the appropriate cross section objects for this cell\n", + " transport = xs_library[cell_id]['transport']\n", + " nufission = xs_library[cell_id]['nu-fission']\n", + " nuscatter = xs_library[cell_id]['nu-scatter']\n", + " chi = xs_library[cell_id]['chi']\n", + " \n", + " # Perform group condensation\n", + " transport = transport.get_condensed_xs(coarse_groups)\n", + " nufission = nufission.get_condensed_xs(coarse_groups)\n", + " nuscatter = nuscatter.get_condensed_xs(coarse_groups)\n", + " chi = chi.get_condensed_xs(coarse_groups)\n", + " \n", + " # Inject NumPy arrays of cross section data into the Material\n", + " openmoc_material.setSigmaT(transport.get_xs(nuclides='sum').flatten())\n", + " openmoc_material.setNuSigmaF(nufission.get_xs(nuclides='sum').flatten())\n", + " openmoc_material.setSigmaS(nuscatter.get_xs(nuclides='sum').flatten())\n", + " openmoc_material.setChi(chi.get_xs(nuclides='sum').flatten())" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Importing ray tracing data from file...\n", + "[ NORMAL ] Computing the eigenvalue...\n", + "[ NORMAL ] Iteration 0:\tk_eff = 0.495594\tres = 1.959E-316\n", + "[ NORMAL ] Iteration 1:\tk_eff = 0.557312\tres = 5.044E-01\n", + "[ NORMAL ] Iteration 2:\tk_eff = 0.518115\tres = 1.245E-01\n", + "[ NORMAL ] Iteration 3:\tk_eff = 0.509016\tres = 7.033E-02\n", + "[ NORMAL ] Iteration 4:\tk_eff = 0.496279\tres = 1.756E-02\n", + "[ NORMAL ] Iteration 5:\tk_eff = 0.488357\tres = 2.502E-02\n", + "[ NORMAL ] Iteration 6:\tk_eff = 0.482659\tres = 1.596E-02\n", + "[ NORMAL ] Iteration 7:\tk_eff = 0.479523\tres = 1.167E-02\n", + "[ NORMAL ] Iteration 8:\tk_eff = 0.478568\tres = 6.497E-03\n", + "[ NORMAL ] Iteration 9:\tk_eff = 0.479590\tres = 1.991E-03\n", + "[ NORMAL ] Iteration 10:\tk_eff = 0.482388\tres = 2.136E-03\n", + "[ NORMAL ] Iteration 11:\tk_eff = 0.486774\tres = 5.834E-03\n", + "[ NORMAL ] Iteration 12:\tk_eff = 0.492575\tres = 9.091E-03\n", + "[ NORMAL ] Iteration 13:\tk_eff = 0.499632\tres = 1.192E-02\n", + "[ NORMAL ] Iteration 14:\tk_eff = 0.507799\tres = 1.433E-02\n", + "[ NORMAL ] Iteration 15:\tk_eff = 0.516943\tres = 1.635E-02\n", + "[ NORMAL ] Iteration 16:\tk_eff = 0.526942\tres = 1.801E-02\n", + "[ NORMAL ] Iteration 17:\tk_eff = 0.537681\tres = 1.934E-02\n", + "[ NORMAL ] Iteration 18:\tk_eff = 0.549060\tres = 2.038E-02\n", + "[ NORMAL ] Iteration 19:\tk_eff = 0.560984\tres = 2.116E-02\n", + "[ NORMAL ] Iteration 20:\tk_eff = 0.573368\tres = 2.172E-02\n", + "[ NORMAL ] Iteration 21:\tk_eff = 0.586133\tres = 2.207E-02\n", + "[ NORMAL ] Iteration 22:\tk_eff = 0.599207\tres = 2.226E-02\n", + "[ NORMAL ] Iteration 23:\tk_eff = 0.612528\tres = 2.231E-02\n", + "[ NORMAL ] Iteration 24:\tk_eff = 0.626035\tres = 2.223E-02\n", + "[ NORMAL ] Iteration 25:\tk_eff = 0.639676\tres = 2.205E-02\n", + "[ NORMAL ] Iteration 26:\tk_eff = 0.653402\tres = 2.179E-02\n", + "[ NORMAL ] Iteration 27:\tk_eff = 0.667170\tres = 2.146E-02\n", + "[ NORMAL ] Iteration 28:\tk_eff = 0.680942\tres = 2.107E-02\n", + "[ NORMAL ] Iteration 29:\tk_eff = 0.694681\tres = 2.064E-02\n", + "[ NORMAL ] Iteration 30:\tk_eff = 0.708356\tres = 2.018E-02\n", + "[ NORMAL ] Iteration 31:\tk_eff = 0.721940\tres = 1.969E-02\n", + "[ NORMAL ] Iteration 32:\tk_eff = 0.735406\tres = 1.918E-02\n", + "[ NORMAL ] Iteration 33:\tk_eff = 0.748734\tres = 1.865E-02\n", + "[ NORMAL ] Iteration 34:\tk_eff = 0.761904\tres = 1.812E-02\n", + "[ NORMAL ] Iteration 35:\tk_eff = 0.774897\tres = 1.759E-02\n", + "[ NORMAL ] Iteration 36:\tk_eff = 0.787700\tres = 1.705E-02\n", + "[ NORMAL ] Iteration 37:\tk_eff = 0.800299\tres = 1.652E-02\n", + "[ NORMAL ] Iteration 38:\tk_eff = 0.812684\tres = 1.600E-02\n", + "[ NORMAL ] Iteration 39:\tk_eff = 0.824844\tres = 1.547E-02\n", + "[ NORMAL ] Iteration 40:\tk_eff = 0.836772\tres = 1.496E-02\n", + "[ NORMAL ] Iteration 41:\tk_eff = 0.848462\tres = 1.446E-02\n", + "[ NORMAL ] Iteration 42:\tk_eff = 0.859908\tres = 1.397E-02\n", + "[ NORMAL ] Iteration 43:\tk_eff = 0.871105\tres = 1.349E-02\n", + "[ NORMAL ] Iteration 44:\tk_eff = 0.882052\tres = 1.302E-02\n", + "[ NORMAL ] Iteration 45:\tk_eff = 0.892745\tres = 1.257E-02\n", + "[ NORMAL ] Iteration 46:\tk_eff = 0.903184\tres = 1.212E-02\n", + "[ NORMAL ] Iteration 47:\tk_eff = 0.913367\tres = 1.169E-02\n", + "[ NORMAL ] Iteration 48:\tk_eff = 0.923297\tres = 1.128E-02\n", + "[ NORMAL ] Iteration 49:\tk_eff = 0.932972\tres = 1.087E-02\n", + "[ NORMAL ] Iteration 50:\tk_eff = 0.942394\tres = 1.048E-02\n", + "[ NORMAL ] Iteration 51:\tk_eff = 0.951566\tres = 1.010E-02\n", + "[ NORMAL ] Iteration 52:\tk_eff = 0.960490\tres = 9.733E-03\n", + "[ NORMAL ] Iteration 53:\tk_eff = 0.969168\tres = 9.378E-03\n", + "[ NORMAL ] Iteration 54:\tk_eff = 0.977604\tres = 9.035E-03\n", + "[ NORMAL ] Iteration 55:\tk_eff = 0.985800\tres = 8.704E-03\n", + "[ NORMAL ] Iteration 56:\tk_eff = 0.993761\tres = 8.384E-03\n", + "[ NORMAL ] Iteration 57:\tk_eff = 1.001491\tres = 8.076E-03\n", + "[ NORMAL ] Iteration 58:\tk_eff = 1.008992\tres = 7.778E-03\n", + "[ NORMAL ] Iteration 59:\tk_eff = 1.016271\tres = 7.490E-03\n", + "[ NORMAL ] Iteration 60:\tk_eff = 1.023330\tres = 7.213E-03\n", + "[ NORMAL ] Iteration 61:\tk_eff = 1.030174\tres = 6.946E-03\n", + "[ NORMAL ] Iteration 62:\tk_eff = 1.036809\tres = 6.688E-03\n", + "[ NORMAL ] Iteration 63:\tk_eff = 1.043238\tres = 6.440E-03\n", + "[ NORMAL ] Iteration 64:\tk_eff = 1.049466\tres = 6.201E-03\n", + "[ NORMAL ] Iteration 65:\tk_eff = 1.055498\tres = 5.970E-03\n", + "[ NORMAL ] Iteration 66:\tk_eff = 1.061339\tres = 5.748E-03\n", + "[ NORMAL ] Iteration 67:\tk_eff = 1.066993\tres = 5.534E-03\n", + "[ NORMAL ] Iteration 68:\tk_eff = 1.072465\tres = 5.327E-03\n", + "[ NORMAL ] Iteration 69:\tk_eff = 1.077760\tres = 5.129E-03\n", + "[ NORMAL ] Iteration 70:\tk_eff = 1.082882\tres = 4.937E-03\n", + "[ NORMAL ] Iteration 71:\tk_eff = 1.087837\tres = 4.753E-03\n", + "[ NORMAL ] Iteration 72:\tk_eff = 1.092628\tres = 4.575E-03\n", + "[ NORMAL ] Iteration 73:\tk_eff = 1.097260\tres = 4.404E-03\n", + "[ NORMAL ] Iteration 74:\tk_eff = 1.101737\tres = 4.239E-03\n", + "[ NORMAL ] Iteration 75:\tk_eff = 1.106065\tres = 4.081E-03\n", + "[ NORMAL ] Iteration 76:\tk_eff = 1.110247\tres = 3.928E-03\n", + "[ NORMAL ] Iteration 77:\tk_eff = 1.114288\tres = 3.781E-03\n", + "[ NORMAL ] Iteration 78:\tk_eff = 1.118191\tres = 3.639E-03\n", + "[ NORMAL ] Iteration 79:\tk_eff = 1.121961\tres = 3.503E-03\n", + "[ NORMAL ] Iteration 80:\tk_eff = 1.125603\tres = 3.372E-03\n", + "[ NORMAL ] Iteration 81:\tk_eff = 1.129119\tres = 3.245E-03\n", + "[ NORMAL ] Iteration 82:\tk_eff = 1.132513\tres = 3.124E-03\n", + "[ NORMAL ] Iteration 83:\tk_eff = 1.135790\tres = 3.007E-03\n", + "[ NORMAL ] Iteration 84:\tk_eff = 1.138954\tres = 2.894E-03\n", + "[ NORMAL ] Iteration 85:\tk_eff = 1.142007\tres = 2.785E-03\n", + "[ NORMAL ] Iteration 86:\tk_eff = 1.144953\tres = 2.681E-03\n", + "[ NORMAL ] Iteration 87:\tk_eff = 1.147796\tres = 2.580E-03\n", + "[ NORMAL ] Iteration 88:\tk_eff = 1.150539\tres = 2.483E-03\n", + "[ NORMAL ] Iteration 89:\tk_eff = 1.153185\tres = 2.390E-03\n", + "[ NORMAL ] Iteration 90:\tk_eff = 1.155738\tres = 2.300E-03\n", + "[ NORMAL ] Iteration 91:\tk_eff = 1.158200\tres = 2.214E-03\n", + "[ NORMAL ] Iteration 92:\tk_eff = 1.160575\tres = 2.130E-03\n", + "[ NORMAL ] Iteration 93:\tk_eff = 1.162865\tres = 2.050E-03\n", + "[ NORMAL ] Iteration 94:\tk_eff = 1.165073\tres = 1.973E-03\n", + "[ NORMAL ] Iteration 95:\tk_eff = 1.167202\tres = 1.899E-03\n", + "[ NORMAL ] Iteration 96:\tk_eff = 1.169255\tres = 1.828E-03\n", + "[ NORMAL ] Iteration 97:\tk_eff = 1.171234\tres = 1.759E-03\n", + "[ NORMAL ] Iteration 98:\tk_eff = 1.173142\tres = 1.693E-03\n", + "[ NORMAL ] Iteration 99:\tk_eff = 1.174980\tres = 1.629E-03\n", + "[ NORMAL ] Iteration 100:\tk_eff = 1.176753\tres = 1.567E-03\n", + "[ NORMAL ] Iteration 101:\tk_eff = 1.178461\tres = 1.508E-03\n", + "[ NORMAL ] Iteration 102:\tk_eff = 1.180107\tres = 1.452E-03\n", + "[ NORMAL ] Iteration 103:\tk_eff = 1.181694\tres = 1.397E-03\n", + "[ NORMAL ] Iteration 104:\tk_eff = 1.183222\tres = 1.344E-03\n", + "[ NORMAL ] Iteration 105:\tk_eff = 1.184695\tres = 1.294E-03\n", + "[ NORMAL ] Iteration 106:\tk_eff = 1.186115\tres = 1.245E-03\n", + "[ NORMAL ] Iteration 107:\tk_eff = 1.187482\tres = 1.198E-03\n", + "[ NORMAL ] Iteration 108:\tk_eff = 1.188799\tres = 1.153E-03\n", + "[ NORMAL ] Iteration 109:\tk_eff = 1.190068\tres = 1.109E-03\n", + "[ NORMAL ] Iteration 110:\tk_eff = 1.191290\tres = 1.067E-03\n", + "[ NORMAL ] Iteration 111:\tk_eff = 1.192468\tres = 1.027E-03\n", + "[ NORMAL ] Iteration 112:\tk_eff = 1.193602\tres = 9.883E-04\n", + "[ NORMAL ] Iteration 113:\tk_eff = 1.194694\tres = 9.510E-04\n", + "[ NORMAL ] Iteration 114:\tk_eff = 1.195746\tres = 9.151E-04\n", + "[ NORMAL ] Iteration 115:\tk_eff = 1.196759\tres = 8.805E-04\n", + "[ NORMAL ] Iteration 116:\tk_eff = 1.197735\tres = 8.473E-04\n", + "[ NORMAL ] Iteration 117:\tk_eff = 1.198674\tres = 8.152E-04\n", + "[ NORMAL ] Iteration 118:\tk_eff = 1.199579\tres = 7.844E-04\n", + "[ NORMAL ] Iteration 119:\tk_eff = 1.200450\tres = 7.548E-04\n", + "[ NORMAL ] Iteration 120:\tk_eff = 1.201289\tres = 7.262E-04\n", + "[ NORMAL ] Iteration 121:\tk_eff = 1.202097\tres = 6.988E-04\n", + "[ NORMAL ] Iteration 122:\tk_eff = 1.202874\tres = 6.723E-04\n", + "[ NORMAL ] Iteration 123:\tk_eff = 1.203623\tres = 6.469E-04\n", + "[ NORMAL ] Iteration 124:\tk_eff = 1.204344\tres = 6.224E-04\n", + "[ NORMAL ] Iteration 125:\tk_eff = 1.205038\tres = 5.989E-04\n", + "[ NORMAL ] Iteration 126:\tk_eff = 1.205706\tres = 5.762E-04\n", + "[ NORMAL ] Iteration 127:\tk_eff = 1.206349\tres = 5.544E-04\n", + "[ NORMAL ] Iteration 128:\tk_eff = 1.206968\tres = 5.334E-04\n", + "[ NORMAL ] Iteration 129:\tk_eff = 1.207564\tres = 5.132E-04\n", + "[ NORMAL ] Iteration 130:\tk_eff = 1.208138\tres = 4.938E-04\n", + "[ NORMAL ] Iteration 131:\tk_eff = 1.208690\tres = 4.751E-04\n", + "[ NORMAL ] Iteration 132:\tk_eff = 1.209221\tres = 4.570E-04\n", + "[ NORMAL ] Iteration 133:\tk_eff = 1.209733\tres = 4.397E-04\n", + "[ NORMAL ] Iteration 134:\tk_eff = 1.210225\tres = 4.231E-04\n", + "[ NORMAL ] Iteration 135:\tk_eff = 1.210699\tres = 4.070E-04\n", + "[ NORMAL ] Iteration 136:\tk_eff = 1.211155\tres = 3.916E-04\n", + "[ NORMAL ] Iteration 137:\tk_eff = 1.211594\tres = 3.767E-04\n", + "[ NORMAL ] Iteration 138:\tk_eff = 1.212017\tres = 3.624E-04\n", + "[ NORMAL ] Iteration 139:\tk_eff = 1.212423\tres = 3.487E-04\n", + "[ NORMAL ] Iteration 140:\tk_eff = 1.212815\tres = 3.355E-04\n", + "[ NORMAL ] Iteration 141:\tk_eff = 1.213191\tres = 3.227E-04\n", + "[ NORMAL ] Iteration 142:\tk_eff = 1.213554\tres = 3.105E-04\n", + "[ NORMAL ] Iteration 143:\tk_eff = 1.213902\tres = 2.987E-04\n", + "[ NORMAL ] Iteration 144:\tk_eff = 1.214238\tres = 2.874E-04\n", + "[ NORMAL ] Iteration 145:\tk_eff = 1.214561\tres = 2.764E-04\n", + "[ NORMAL ] Iteration 146:\tk_eff = 1.214872\tres = 2.659E-04\n", + "[ NORMAL ] Iteration 147:\tk_eff = 1.215171\tres = 2.558E-04\n", + "[ NORMAL ] Iteration 148:\tk_eff = 1.215458\tres = 2.461E-04\n", + "[ NORMAL ] Iteration 149:\tk_eff = 1.215735\tres = 2.368E-04\n", + "[ NORMAL ] Iteration 150:\tk_eff = 1.216002\tres = 2.278E-04\n", + "[ NORMAL ] Iteration 151:\tk_eff = 1.216258\tres = 2.191E-04\n", + "[ NORMAL ] Iteration 152:\tk_eff = 1.216504\tres = 2.108E-04\n", + "[ NORMAL ] Iteration 153:\tk_eff = 1.216742\tres = 2.028E-04\n", + "[ NORMAL ] Iteration 154:\tk_eff = 1.216970\tres = 1.951E-04\n", + "[ NORMAL ] Iteration 155:\tk_eff = 1.217190\tres = 1.876E-04\n", + "[ NORMAL ] Iteration 156:\tk_eff = 1.217401\tres = 1.805E-04\n", + "[ NORMAL ] Iteration 157:\tk_eff = 1.217604\tres = 1.736E-04\n", + "[ NORMAL ] Iteration 158:\tk_eff = 1.217800\tres = 1.670E-04\n", + "[ NORMAL ] Iteration 159:\tk_eff = 1.217988\tres = 1.607E-04\n", + "[ NORMAL ] Iteration 160:\tk_eff = 1.218169\tres = 1.546E-04\n", + "[ NORMAL ] Iteration 161:\tk_eff = 1.218344\tres = 1.487E-04\n", + "[ NORMAL ] Iteration 162:\tk_eff = 1.218511\tres = 1.430E-04\n", + "[ NORMAL ] Iteration 163:\tk_eff = 1.218673\tres = 1.376E-04\n", + "[ NORMAL ] Iteration 164:\tk_eff = 1.218828\tres = 1.324E-04\n", + "[ NORMAL ] Iteration 165:\tk_eff = 1.218977\tres = 1.273E-04\n", + "[ NORMAL ] Iteration 166:\tk_eff = 1.219121\tres = 1.225E-04\n", + "[ NORMAL ] Iteration 167:\tk_eff = 1.219259\tres = 1.178E-04\n", + "[ NORMAL ] Iteration 168:\tk_eff = 1.219392\tres = 1.133E-04\n", + "[ NORMAL ] Iteration 169:\tk_eff = 1.219520\tres = 1.090E-04\n", + "[ NORMAL ] Iteration 170:\tk_eff = 1.219643\tres = 1.049E-04\n", + "[ NORMAL ] Iteration 171:\tk_eff = 1.219761\tres = 1.009E-04\n", + "[ NORMAL ] Iteration 172:\tk_eff = 1.219875\tres = 9.702E-05\n", + "[ NORMAL ] Iteration 173:\tk_eff = 1.219984\tres = 9.332E-05\n", + "[ NORMAL ] Iteration 174:\tk_eff = 1.220090\tres = 8.976E-05\n", + "[ NORMAL ] Iteration 175:\tk_eff = 1.220191\tres = 8.634E-05\n", + "[ NORMAL ] Iteration 176:\tk_eff = 1.220288\tres = 8.305E-05\n", + "[ NORMAL ] Iteration 177:\tk_eff = 1.220382\tres = 7.989E-05\n", + "[ NORMAL ] Iteration 178:\tk_eff = 1.220472\tres = 7.684E-05\n", + "[ NORMAL ] Iteration 179:\tk_eff = 1.220559\tres = 7.392E-05\n", + "[ NORMAL ] Iteration 180:\tk_eff = 1.220643\tres = 7.110E-05\n", + "[ NORMAL ] Iteration 181:\tk_eff = 1.220723\tres = 6.839E-05\n", + "[ NORMAL ] Iteration 182:\tk_eff = 1.220800\tres = 6.578E-05\n", + "[ NORMAL ] Iteration 183:\tk_eff = 1.220874\tres = 6.327E-05\n", + "[ NORMAL ] Iteration 184:\tk_eff = 1.220946\tres = 6.086E-05\n", + "[ NORMAL ] Iteration 185:\tk_eff = 1.221015\tres = 5.854E-05\n", + "[ NORMAL ] Iteration 186:\tk_eff = 1.221081\tres = 5.631E-05\n", + "[ NORMAL ] Iteration 187:\tk_eff = 1.221144\tres = 5.416E-05\n", + "[ NORMAL ] Iteration 188:\tk_eff = 1.221206\tres = 5.209E-05\n", + "[ NORMAL ] Iteration 189:\tk_eff = 1.221264\tres = 5.011E-05\n", + "[ NORMAL ] Iteration 190:\tk_eff = 1.221321\tres = 4.820E-05\n", + "[ NORMAL ] Iteration 191:\tk_eff = 1.221375\tres = 4.636E-05\n", + "[ NORMAL ] Iteration 192:\tk_eff = 1.221428\tres = 4.459E-05\n", + "[ NORMAL ] Iteration 193:\tk_eff = 1.221478\tres = 4.289E-05\n", + "[ NORMAL ] Iteration 194:\tk_eff = 1.221527\tres = 4.125E-05\n", + "[ NORMAL ] Iteration 195:\tk_eff = 1.221573\tres = 3.968E-05\n", + "[ NORMAL ] Iteration 196:\tk_eff = 1.221618\tres = 3.816E-05\n", + "[ NORMAL ] Iteration 197:\tk_eff = 1.221661\tres = 3.671E-05\n", + "[ NORMAL ] Iteration 198:\tk_eff = 1.221703\tres = 3.531E-05\n", + "[ NORMAL ] Iteration 199:\tk_eff = 1.221743\tres = 3.396E-05\n", + "[ NORMAL ] Iteration 200:\tk_eff = 1.221781\tres = 3.266E-05\n", + "[ NORMAL ] Iteration 201:\tk_eff = 1.221818\tres = 3.142E-05\n", + "[ NORMAL ] Iteration 202:\tk_eff = 1.221853\tres = 3.022E-05\n", + "[ NORMAL ] Iteration 203:\tk_eff = 1.221888\tres = 2.906E-05\n", + "[ NORMAL ] Iteration 204:\tk_eff = 1.221920\tres = 2.795E-05\n", + "[ NORMAL ] Iteration 205:\tk_eff = 1.221952\tres = 2.689E-05\n", + "[ NORMAL ] Iteration 206:\tk_eff = 1.221982\tres = 2.586E-05\n", + "[ NORMAL ] Iteration 207:\tk_eff = 1.222012\tres = 2.487E-05\n", + "[ NORMAL ] Iteration 208:\tk_eff = 1.222040\tres = 2.392E-05\n", + "[ NORMAL ] Iteration 209:\tk_eff = 1.222067\tres = 2.301E-05\n", + "[ NORMAL ] Iteration 210:\tk_eff = 1.222093\tres = 2.213E-05\n", + "[ NORMAL ] Iteration 211:\tk_eff = 1.222118\tres = 2.129E-05\n", + "[ NORMAL ] Iteration 212:\tk_eff = 1.222142\tres = 2.047E-05\n", + "[ NORMAL ] Iteration 213:\tk_eff = 1.222165\tres = 1.969E-05\n", + "[ NORMAL ] Iteration 214:\tk_eff = 1.222187\tres = 1.894E-05\n", + "[ NORMAL ] Iteration 215:\tk_eff = 1.222209\tres = 1.822E-05\n", + "[ NORMAL ] Iteration 216:\tk_eff = 1.222229\tres = 1.752E-05\n", + "[ NORMAL ] Iteration 217:\tk_eff = 1.222249\tres = 1.685E-05\n", + "[ NORMAL ] Iteration 218:\tk_eff = 1.222268\tres = 1.621E-05\n", + "[ NORMAL ] Iteration 219:\tk_eff = 1.222287\tres = 1.559E-05\n", + "[ NORMAL ] Iteration 220:\tk_eff = 1.222304\tres = 1.499E-05\n", + "[ NORMAL ] Iteration 221:\tk_eff = 1.222321\tres = 1.442E-05\n", + "[ NORMAL ] Iteration 222:\tk_eff = 1.222337\tres = 1.387E-05\n", + "[ NORMAL ] Iteration 223:\tk_eff = 1.222353\tres = 1.334E-05\n", + "[ NORMAL ] Iteration 224:\tk_eff = 1.222368\tres = 1.283E-05\n", + "[ NORMAL ] Iteration 225:\tk_eff = 1.222383\tres = 1.234E-05\n", + "[ NORMAL ] Iteration 226:\tk_eff = 1.222397\tres = 1.187E-05\n", + "[ NORMAL ] Iteration 227:\tk_eff = 1.222410\tres = 1.142E-05\n", + "[ NORMAL ] Iteration 228:\tk_eff = 1.222423\tres = 1.098E-05\n", + "[ NORMAL ] Iteration 229:\tk_eff = 1.222435\tres = 1.056E-05\n", + "[ NORMAL ] Iteration 230:\tk_eff = 1.222447\tres = 1.016E-05\n" + ] + } + ], + "source": [ + "# Generate tracks for OpenMOC\n", + "openmoc_geometry.initializeFlatSourceRegions()\n", + "track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=128, spacing=0.1)\n", + "track_generator.generateTracks()\n", + "\n", + "# Run OpenMOC\n", + "solver = openmoc.CPUSolver(track_generator)\n", + "solver.computeEigenvalue()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "openmc keff = 1.223729\n", + "openmoc keff = 1.222447\n", + "bias [pcm]: -128.2\n" + ] + } + ], + "source": [ + "# Print report of keff and bias with OpenMC\n", + "openmoc_keff = solver.getKeff()\n", + "openmc_keff = sp.k_combined[0]\n", + "bias = (openmoc_keff - openmc_keff) * 1e5\n", + "\n", + "print('openmc keff = {0:1.6f}'.format(openmc_keff))\n", + "print('openmoc keff = {0:1.6f}'.format(openmoc_keff))\n", + "print('bias [pcm]: {0:1.1f}'.format(bias))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There is a non-trivial bias in both the 2-group and 8-group cases. In the case of a pin cell, one can show that these biases do not converge to <100 pcm with more particle histories. For heterogeneous geometries, additional measures must be taken to address the following three sources of bias:\n", + "\n", + "* Appropriate transport-corrected cross sections\n", + "* Spatial discretization of OpenMOC's mesh\n", + "* Constant-in-angle multi-group cross sections" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "## Visualizing MGXS Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is often insightful to generate visual depictions of multi-group cross sections. There are many different types of plots which may be useful for multi-group cross section visualization, only a few of which will be shown here for enrichment and inspiration.\n", + "\n", + "One particularly useful visualization is a comparison of the continuous-energy and multi-group cross sections for a particular nuclide and reaction type. We illustrate one option for generating such plots with the use of the open source [PyNE](http://pyne.io/) library to parse continuous-energy cross sections from the cross section data library provided with OpenMC. First, we instantiate a `pyne.ace.Library` object for U-235 as follows." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a PyNE ACE continuous-energy cross sections library\n", + "pyne_lib = pyne.ace.Library('../../../../data/nndc/293.6K/U_235_293.6K.ace')\n", + "pyne_lib.read('92235.71c')\n", + "\n", + "# Extract the U-235 data from the library\n", + "u235 = pyne_lib.tables['92235.71c']\n", + "\n", + "# Extract the continuous-energy U-235 fission cross section data\n", + "fission = u235.reactions[18]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we use [`matplotlib`](http://matplotlib.org/) and [`seaborn`](http://stanford.edu/~mwaskom/software/seaborn/) to plot the continuous-energy and multi-group cross sections on a single plot." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(9.9999999999999994e-12, 20.0)" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\nRETE6eQvWE4Yr8iVHuYAAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create a loglog plot of the U-235 continuous-energy fission cross section \n", + "plt.loglog(u235.energy, fission.sigma, color='b', linewidth=1)\n", + "\n", + "# Extract energy group bounds and MGXS values to plot\n", + "nufission = xs_library[fuel_cell.id]['fission']\n", + "energy_groups = nufission.energy_groups\n", + "x = energy_groups.group_edges\n", + "y = nufission.get_xs(nuclides=['U-235'], order_groups='decreasing', xs_type='micro')\n", + "\n", + "# Fix low energy bound to the value defined by the ACE library\n", + "x[0] = u235.energy[0]\n", + "\n", + "# Extend the mgxs values array for matplotlib's step plot\n", + "y = np.insert(y, 0, y[0])\n", + "\n", + "# Create a step plot for the MGXS\n", + "plt.plot(x, y, drawstyle='steps', color='r', linewidth=3)\n", + "\n", + "plt.title('U-235 Fission Cross Section')\n", + "plt.xlabel('Energy [MeV]')\n", + "plt.ylabel('Micro Fission XS')\n", + "plt.legend(['Continuous', 'Multi-Group'])\n", + "plt.xlim((x.min(), x.max()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another useful type of illustration is scattering matrix sparsity structures. First, we extract Pandas `DataFrames` for the H-1 and O-16 scattering matrices." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Construct a Pandas DataFrame for the microscopic nu-scattering matrix\n", + "nuscatter = xs_library[moderator_cell.id]['nu-scatter']\n", + "df = nuscatter.get_pandas_dataframe(xs_type='micro')\n", + "\n", + "# Slice DataFrame in two for each nuclide's mean values\n", + "h1 = df[df['nuclide'] == 'H-1']['mean']\n", + "o16 = df[df['nuclide'] == 'O-16']['mean']\n", + "\n", + "# Cast DataFrames as NumPy arrays\n", + "h1 = h1.as_matrix()\n", + "o16 = o16.as_matrix()\n", + "\n", + "# Reshape arrays to 2D matrix for plotting\n", + "h1.shape = (fine_groups.num_groups, fine_groups.num_groups)\n", + "o16.shape = (fine_groups.num_groups, fine_groups.num_groups)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Matplotlib's `imshow` routine can be used to plot the matrices to illustrate their sparsity structures." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nRK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create plot of the H-1 scattering matrix\n", + "fig = plt.subplot(121)\n", + "fig.imshow(h1, interpolation='nearest', cmap='jet')\n", + "plt.title('H-1 Scattering Matrix')\n", + "plt.xlabel('Group Out')\n", + "plt.ylabel('Group In')\n", + "plt.grid()\n", + "\n", + "# Create plot of the O-16 scattering matrix\n", + "fig2 = plt.subplot(122)\n", + "fig2.imshow(o16, interpolation='nearest', cmap='jet')\n", + "plt.title('O-16 Scattering Matrix')\n", + "plt.xlabel('Group Out')\n", + "plt.ylabel('Group In')\n", + "plt.grid()\n", + "\n", + "# Show the plot on screen\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/source/pythonapi/examples/mgxs-part-ii.rst b/docs/source/pythonapi/examples/mgxs-part-ii.rst new file mode 100644 index 0000000000..1f6dd22146 --- /dev/null +++ b/docs/source/pythonapi/examples/mgxs-part-ii.rst @@ -0,0 +1,13 @@ +.. _notebook_mgxs_part_ii: + +=============================== +MGXS Part II: Advanced Features +=============================== + +.. only:: html + + .. notebook:: mgxs-part-ii.ipynb + +.. only:: latex + + IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/pythonapi/examples/mgxs-part-iii.ipynb b/docs/source/pythonapi/examples/mgxs-part-iii.ipynb new file mode 100644 index 0000000000..9302036600 --- /dev/null +++ b/docs/source/pythonapi/examples/mgxs-part-iii.ipynb @@ -0,0 +1,1653 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This IPython Notebook illustrates the use of the **`openmc.mgxs.Library`** class. The `Library` class is designed to automate the calculation of multi-group cross sections for use cases with one or more domains, cross section types, and/or nuclides. In particular, this Notebook illustrates the following features:\n", + "\n", + "* Calculation of multi-group cross sections for a **fuel assembly**\n", + "* Automated creation, manipulation and storage of `MGXS` with **`openmc.mgxs.Library`**\n", + "* **Validation** of multi-group cross sections with **[OpenMOC](https://mit-crpg.github.io/OpenMOC/)**\n", + "* Steady-state pin-by-pin **fission rates comparison** between OpenMC and [OpenMOC](https://mit-crpg.github.io/OpenMOC/)\n", + "\n", + "**Note:** This Notebook was created using [OpenMOC](https://mit-crpg.github.io/OpenMOC/) to verify the multi-group cross-sections generated by OpenMC. In order to run this Notebook in its entirety, you must have [OpenMOC](https://mit-crpg.github.io/OpenMOC/) installed on your system, along with OpenCG to convert the OpenMC geometries into OpenMOC geometries. In addition, this Notebook illustrates the use of [Pandas](http://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data. We recommend using [Pandas](http://pandas.pydata.org/) >v0.15.0 or later since OpenMC's Python API leverages the multi-indexing feature included in the most recent releases of [Pandas](http://pandas.pydata.org/)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate Input Files" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/lib/pymodules/python2.7/matplotlib/__init__.py:1173: UserWarning: This call to matplotlib.use() has no effect\n", + "because the backend has already been chosen;\n", + "matplotlib.use() must be called *before* pylab, matplotlib.pyplot,\n", + "or matplotlib.backends is imported for the first time.\n", + "\n", + " warnings.warn(_use_error_msg)\n" + ] + } + ], + "source": [ + "import math\n", + "import pickle\n", + "from IPython.display import Image\n", + "import matplotlib.pylab as pylab\n", + "import numpy as np\n", + "\n", + "import openmc\n", + "import openmc.mgxs\n", + "from openmc.statepoint import StatePoint\n", + "from openmc.summary import Summary\n", + "\n", + "import openmoc\n", + "import openmoc.process\n", + "from openmoc.compatible import get_openmoc_geometry\n", + "from openmoc.materialize import load_openmc_mgxs_lib\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate some Nuclides\n", + "h1 = openmc.Nuclide('H-1')\n", + "b10 = openmc.Nuclide('B-10')\n", + "o16 = openmc.Nuclide('O-16')\n", + "u235 = openmc.Nuclide('U-235')\n", + "u238 = openmc.Nuclide('U-238')\n", + "zr90 = openmc.Nuclide('Zr-90')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the nuclides we defined, we will now create three materials for the fuel, water, and cladding of the fuel pins." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# 1.6 enriched fuel\n", + "fuel = openmc.Material(name='1.6% Fuel')\n", + "fuel.set_density('g/cm3', 10.31341)\n", + "fuel.add_nuclide(u235, 3.7503e-4)\n", + "fuel.add_nuclide(u238, 2.2625e-2)\n", + "fuel.add_nuclide(o16, 4.6007e-2)\n", + "\n", + "# borated water\n", + "water = openmc.Material(name='Borated Water')\n", + "water.set_density('g/cm3', 0.740582)\n", + "water.add_nuclide(h1, 4.9457e-2)\n", + "water.add_nuclide(o16, 2.4732e-2)\n", + "water.add_nuclide(b10, 8.0042e-6)\n", + "\n", + "# zircaloy\n", + "zircaloy = openmc.Material(name='Zircaloy')\n", + "zircaloy.set_density('g/cm3', 6.55)\n", + "zircaloy.add_nuclide(zr90, 7.2758e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With our three materials, we can now create a `MaterialsFile` object that can be exported to an actual XML file." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate a MaterialsFile, add Materials\n", + "materials_file = openmc.MaterialsFile()\n", + "materials_file.add_material(fuel)\n", + "materials_file.add_material(water)\n", + "materials_file.add_material(zircaloy)\n", + "materials_file.default_xs = '71c'\n", + "\n", + "# Export to \"materials.xml\"\n", + "materials_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's move on to the geometry. This problem will be a square array of fuel pins and control rod guide tubes for which we can use OpenMC's lattice/universe feature. The basic universe will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces for fuel and clad, as well as the outer bounding surfaces of the problem." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create cylinders for the fuel and clad\n", + "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218)\n", + "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720)\n", + "\n", + "# Create boundary planes to surround the geometry\n", + "min_x = openmc.XPlane(x0=-10.71, boundary_type='reflective')\n", + "max_x = openmc.XPlane(x0=+10.71, boundary_type='reflective')\n", + "min_y = openmc.YPlane(y0=-10.71, boundary_type='reflective')\n", + "max_y = openmc.YPlane(y0=+10.71, boundary_type='reflective')\n", + "min_z = openmc.ZPlane(z0=-10., boundary_type='reflective')\n", + "max_z = openmc.ZPlane(z0=+10., boundary_type='reflective')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the surfaces defined, we can now construct a fuel pin cell from cells that are defined by intersections of half-spaces created by the surfaces." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create a Universe to encapsulate a fuel pin\n", + "fuel_pin_universe = openmc.Universe(name='1.6% Fuel Pin')\n", + "\n", + "# Create fuel Cell\n", + "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", + "fuel_cell.fill = fuel\n", + "fuel_cell.region = -fuel_outer_radius\n", + "fuel_pin_universe.add_cell(fuel_cell)\n", + "\n", + "# Create a clad Cell\n", + "clad_cell = openmc.Cell(name='1.6% Clad')\n", + "clad_cell.fill = zircaloy\n", + "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", + "fuel_pin_universe.add_cell(clad_cell)\n", + "\n", + "# Create a moderator Cell\n", + "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", + "moderator_cell.fill = water\n", + "moderator_cell.region = +clad_outer_radius\n", + "fuel_pin_universe.add_cell(moderator_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Likewise, we can construct a control rod guide tube with the same surfaces." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create a Universe to encapsulate a control rod guide tube\n", + "guide_tube_universe = openmc.Universe(name='Guide Tube')\n", + "\n", + "# Create guide tube Cell\n", + "guide_tube_cell = openmc.Cell(name='Guide Tube Water')\n", + "guide_tube_cell.fill = water\n", + "guide_tube_cell.region = -fuel_outer_radius\n", + "guide_tube_universe.add_cell(guide_tube_cell)\n", + "\n", + "# Create a clad Cell\n", + "clad_cell = openmc.Cell(name='Guide Clad')\n", + "clad_cell.fill = zircaloy\n", + "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", + "guide_tube_universe.add_cell(clad_cell)\n", + "\n", + "# Create a moderator Cell\n", + "moderator_cell = openmc.Cell(name='Guide Tube Moderator')\n", + "moderator_cell.fill = water\n", + "moderator_cell.region = +clad_outer_radius\n", + "guide_tube_universe.add_cell(moderator_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using the pin cell universe, we can construct a 17x17 rectangular lattice with a 1.26 cm pitch." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create fuel assembly Lattice\n", + "assembly = openmc.RectLattice(name='1.6% Fuel Assembly')\n", + "assembly.dimension = (17, 17)\n", + "assembly.pitch = (1.26, 1.26)\n", + "assembly.lower_left = [-1.26 * 17. / 2.0] * 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we create a NumPy array of fuel pin and guide tube universes for the lattice." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create array indices for guide tube locations in lattice\n", + "template_x = np.array([5, 8, 11, 3, 13, 2, 5, 8, 11, 14, 2, 5, 8,\n", + " 11, 14, 2, 5, 8, 11, 14, 3, 13, 5, 8, 11])\n", + "template_y = np.array([2, 2, 2, 3, 3, 5, 5, 5, 5, 5, 8, 8, 8, 8,\n", + " 8, 11, 11, 11, 11, 11, 13, 13, 14, 14, 14])\n", + "\n", + "# Initialize an empty 17x17 array of the lattice universes\n", + "universes = np.empty((17, 17), dtype=openmc.Universe)\n", + "\n", + "# Fill the array with the fuel pin and guide tube universes\n", + "universes[:,:] = fuel_pin_universe\n", + "universes[template_x, template_y] = guide_tube_universe\n", + "\n", + "# Store the array of universes in the lattice\n", + "assembly.universes = universes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create root Cell\n", + "root_cell = openmc.Cell(name='root cell')\n", + "root_cell.fill = assembly\n", + "\n", + "# Add boundary planes\n", + "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", + "\n", + "# Create root Universe\n", + "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", + "root_universe.add_cell(root_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now must create a geometry that is assigned a root universe, put the geometry into a `GeometryFile` object, and export it to XML." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create Geometry and set root Universe\n", + "geometry = openmc.Geometry()\n", + "geometry.root_universe = root_universe" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate a GeometryFile\n", + "geometry_file = openmc.GeometryFile()\n", + "geometry_file.geometry = geometry\n", + "\n", + "# Export to \"geometry.xml\"\n", + "geometry_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 10 inactive batches and 40 active batches each with 2500 particles." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# OpenMC simulation parameters\n", + "batches = 50\n", + "inactive = 10\n", + "particles = 2500\n", + "\n", + "# Instantiate a SettingsFile\n", + "settings_file = openmc.SettingsFile()\n", + "settings_file.batches = batches\n", + "settings_file.inactive = inactive\n", + "settings_file.particles = particles\n", + "settings_file.output = {'tallies': False, 'summary': True}\n", + "source_bounds = [-10.71, -10.71, -10, 10.71, 10.71, 10.]\n", + "settings_file.set_source_space('fission', source_bounds)\n", + "\n", + "# Export to \"settings.xml\"\n", + "settings_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us also create a `PlotsFile` that we can use to verify that our fuel assembly geometry was created successfully." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate a Plot\n", + "plot = openmc.Plot(plot_id=1)\n", + "plot.filename = 'materials-xy'\n", + "plot.origin = [0, 0, 0]\n", + "plot.width = [21.5, 21.5]\n", + "plot.pixels = [250, 250]\n", + "plot.color = 'mat'\n", + "\n", + "# Instantiate a PlotsFile, add Plot, and export to \"plots.xml\"\n", + "plot_file = openmc.PlotsFile()\n", + "plot_file.add_plot(plot)\n", + "plot_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the plots.xml file, we can now generate and view the plot. OpenMC outputs plots in .ppm format, which can be converted into a compressed format like .png with the convert utility." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Run openmc in plotting mode\n", + "executor = openmc.Executor()\n", + "executor.plot_geometry(output=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAASWSURB\nVGje7Zs7buMwEEBzieRcaYaB48KVisSFj7Cn4BFU2I37LVan8BFc5ABb2ICtpSSaHP5EUqOAzsIO\nAjwEGjjiZ/hEDZ+eiJ9noHxe6fHvW4BPDmwHEMAaYBdAEb+5Amu/YNlyQLgP4xGhiG9avmwvsBF/\nt/FkY2vj69NLD1f41Z6Yiw3Gvy728ceVuhLhwY8bA0fij8EgO/6wjH2pF/lKxvf3tNG3Z+BRt4oH\nh/Znt5bu+iQd+/Z/Xp8BmiO8X0X/n7KQNbWIZ1wMJjEUPwBuuI1hfcMZxv9Pj19/AexrYH84KASF\nV41nhe8Ku/4f+nSpu3eNsdadjpBLFPF6pIE76Hx4QeiMfy/yVQi/cf6mxx900jk4ScfGlc4/q9v8\nc9sPxhpN4wn3n+qepeqeAK5x/3WZfieGx+8h6Uv8DCNHeAfjv3Q8q0VjwJCesrFbP2X+7NZPidAj\nE7hAyGTSFOvnLX8erfw9YCV+BL4p7DL1gH3SNvK3Z/0Qn3HE64dn/eLifx1Fd/62eP4NVyLsJx1C\nce2bf/7mfL+Kt6UB+ivtm+YasT88u6Yi2z+M+lrpT432J4F9pw+mZOH+rP3pLP2pEzFhaiCdzESG\ncOvBO5g/peMt6d2lYo39d0ivNUvwXyE6KhVb/ssh7r8LMRAs/1XrD0DcfxfiP8DrD54/AFV0/av6\neP/6acQH/NcTr/KH6JCYCnezMOi/8v5H/be7f9N/tdNyluC/sv3V+rnWTvuxUNj/tbax81+u0fDf\nSuttOt7B/Ckd3zVvb7rafzFq6XWxifqv0f8x/2XZ+PBfw39tFb5YyPTz//z+u9P+a+KnTvoO3sH4\nLx3fiyzXTutgbxrgx8F/bdNNR+2/Uq/YuH9dLRXW60cVk14DK2P/aJkinQ7yDfZfR3pH/Feg47/5\n32/6r196/cgVDu3/liK9DgLyX2260U5vMfr9dxvBh/+i+CzptVHE73V69WOj/ddBT/53toKdTV8j\n/5vrT9b+7/eun9P2f6P+m7T/G/GPkP/m481/6xHpHcNu/PJhKFbi18SFi2DhHcyf0vHYf09Sb4ON\n/iXR9d/J/U8Zf5dZxj91/s3ovzzqv3b+IfvvSNL1o5V/belNzP8P/5XxqdLhxdn9N6ZiQf+d6n8z\n+OeP919K+5P7nzr+Ss+f0vHU/EfNv8T8T11/frr/Uv1jFv+l+Ffp8V88ng9YwTT/pz5/EPuf+vz1\nH/pv1vM39fmfvP9A3f8oPn8Kx1P336j7f8T9x//Bf4n7z6T9b+r+O9l/qe8fSs+f0vHU91/U92+z\n+m/++8d7eX869f0v9f0z+f039f176fFfOp5xWv0Htf4E9fSU+hfsv1Pqb/D4h2n1P9T6I2r9E6n+\nilr/Ra4/o9a/lZ4/peOp9ZcbYv0nsf70pXUe2rLqX19acv0ttf7XfmjOrT+2kxbE/Dd4fmZC/TW5\n/ptaf156/pSOp55/mNF/Wx8y238vD//1+++k80fk80/U81elx3/peMZp5/+o5w8b2vlH7/7viP8m\nnJ/JPf9Zev/X9oes87fYf21MOf9LPn9MPf9cdv78A0xugrwgDfcHAAAAJXRFWHRkYXRlOmNyZWF0\nZQAyMDE1LTExLTMwVDIxOjIwOjA3LTA1OjAwkFvB3QAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0x\nMS0zMFQyMToyMDowNy0wNTowMOEGeWEAAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Convert OpenMC's funky ppm to png\n", + "!convert materials-xy.ppm materials-xy.png\n", + "\n", + "# Display the materials plot inline\n", + "Image(filename='materials-xy.png')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see from the plot, we have a nice array of fuel and guide tube pin cells with fuel, cladding, and water!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create an MGXS Library" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we are ready to generate multi-group cross sections! First, let's define a 2-group structure using the built-in `EnergyGroups` class." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a 2-group EnergyGroups object\n", + "groups = openmc.mgxs.EnergyGroups()\n", + "groups.group_edges = np.array([0., 0.625e-6, 20.])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we will instantiate an `openmc.mgxs.Library` for the energy groups with our the fuel assembly geometry." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Initialize an 2-group MGXS Library for OpenMOC\n", + "mgxs_lib = openmc.mgxs.Library(geometry)\n", + "mgxs_lib.energy_groups = groups" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we must specify to the `Library` which types of cross sections to compute. In particular, the following are the multi-group cross section `MGXS` subclasses that are mapped to string codes accepted by the `Library` class:\n", + "\n", + "* `TotalXS` (`\"total\"`)\n", + "* `TransportXS` (`\"transport\"`)\n", + "* `AbsorptionXS` (`\"absorption\"`)\n", + "* `CaptureXS` (`\"capture\"`)\n", + "* `FissionXS` (`\"fission\"`)\n", + "* `NuFissionXS` (`\"nu-fission\"`)\n", + "* `ScatterXS` (`\"scatter\"`)\n", + "* `NuScatterXS` (`\"nu-scatter\"`)\n", + "* `ScatterMatrixXS` (`\"scatter matrix\"`)\n", + "* `NuScatterMatrixXS` (`\"nu-scatter matrix\"`)\n", + "* `Chi` (`\"chi\"`)\n", + "\n", + "In this case, let's create the multi-group cross sections needed to run an OpenMOC simulation to verify the accuracy of our cross sections. In particular, we will define `\"transport\"`, `\"nu-fission\"`, `\"nu-scatter matrix\"` and `\"chi\"` cross sections for our `Library`.\n", + "\n", + "**Note**: A variety of different approximate transport-corrected total multi-group cross sections (and corresponding scattering matrices) can be found in the literature. At the present time, the `openmc.mgxs` module only supports the `\"P0\"` transport correction. This correction can be turned on and off through the boolean `Library.correction` property which may take values of `\"P0\"` (default) or `None`." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Specify multi-group cross section types to compute\n", + "mgxs_lib.mgxs_types = ['transport', 'nu-fission', 'nu-scatter matrix', 'chi']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we must specify the type of domain over which we would like the `Library` to compute multi-group cross sections. The domain type corresponds to the type of tally filter to be used in the tallies created to compute multi-group cross sections. At the present time, the `Library` supports `\"material,\"` `\"cell,\"` and `\"universe\"` domain types. We will use a `\"cell\"` domain type here to compute cross sections in each of the cells in the fuel assembly geometry.\n", + "\n", + "**Note:** By default, the `Library` class will instantiate `MGXS` objects for each and every domain (material, cell or universe) in the geometry of interest. However, one may specify a subset of these domains to the `Library.domains` property. In our case, we wish to compute multi-group cross sections in each and every cell since they will be needed in our downstream OpenMOC calculation on the identical combinatorial geometry mesh." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Specify a \"cell\" domain type for the cross section tally filters\n", + "mgxs_lib.domain_type = \"cell\"\n", + "\n", + "# Specify the cell domains over which to compute multi-group cross sections\n", + "mgxs_lib.domains = geometry.get_all_material_cells()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can easily instruct the `Library` to compute multi-group cross sections on a nuclide-by-nuclide basis with the boolean `Library.by_nuclide` property. By default, `by_nuclide` is set to `False`, but we will set it to `True` here." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Compute cross sections on a nuclide-by-nuclide basis\n", + "mgxs_lib.by_nuclide = True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lastly, we use the `Library` to construct the tallies needed to compute all of the requested multi-group cross sections in each domain and nuclide." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Construct all tallies needed for the multi-group cross section library\n", + "mgxs_lib.build_library()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The tallies can now be export to a \"tallies.xml\" input file for OpenMC. \n", + "\n", + "**NOTE**: At this point the `Library` has constructed nearly 100 distinct `Tally` objects. The overhead to tally in OpenMC scales as $O(N)$ for $N$ tallies, which can become a bottleneck for large tally datasets. To compensate for this, the Python API's `Tally`, `Filter` and `TalliesFile` classes allow for the smart *merging* of tallies when possible. The `Library` class supports this runtime optimization with the use of the optional `merge` paramter (`False` by default) for the `Library.add_to_tallies_file(...)` method, as shown below." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create a \"tallies.xml\" file for the MGXS Library\n", + "tallies_file = openmc.TalliesFile()\n", + "mgxs_lib.add_to_tallies_file(tallies_file, merge=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition, we instantiate a fission rate mesh tally to compare with OpenMOC." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a tally Mesh\n", + "mesh = openmc.Mesh(mesh_id=1)\n", + "mesh.type = 'regular'\n", + "mesh.dimension = [17, 17]\n", + "mesh.lower_left = [-10.71, -10.71]\n", + "mesh.width = [1.26, 1.26]\n", + "\n", + "# Instantiate tally Filter\n", + "mesh_filter = openmc.Filter()\n", + "mesh_filter.mesh = mesh\n", + "\n", + "# Instantiate the Tally\n", + "tally = openmc.Tally(name='mesh tally')\n", + "tally.add_filter(mesh_filter)\n", + "tally.add_score('fission')\n", + "tally.add_score('nu-fission')\n", + "\n", + "# Add mesh and Tally to TalliesFile\n", + "tallies_file.add_mesh(mesh)\n", + "tallies_file.add_tally(tally)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Export all tallies to a \"tallies.xml\" file\n", + "tallies_file.export_to_xml()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " .d88888b. 888b d888 .d8888b.\n", + " d88P\" \"Y88b 8888b d8888 d88P Y88b\n", + " 888 888 88888b.d88888 888 888\n", + " 888 888 88888b. .d88b. 88888b. 888Y88888P888 888 \n", + " 888 888 888 \"88b d8P Y8b 888 \"88b 888 Y888P 888 888 \n", + " 888 888 888 888 88888888 888 888 888 Y8P 888 888 888\n", + " Y88b. .d88P 888 d88P Y8b. 888 888 888 \" 888 Y88b d88P\n", + " \"Y88888P\" 88888P\" \"Y8888 888 888 888 888 \"Y8888P\"\n", + "__________________888______________________________________________________\n", + " 888\n", + " 888\n", + "\n", + " Copyright: 2011-2015 Massachusetts Institute of Technology\n", + " License: http://mit-crpg.github.io/openmc/license.html\n", + " Version: 0.7.0\n", + " Git SHA1: c4b14a5ef87f004528d35cbf33fef3ed15a386ca\n", + " Date/Time: 2015-11-30 21:20:07\n", + " MPI Processes: 1\n", + "\n", + " ===========================================================================\n", + " ========================> INITIALIZATION <=========================\n", + " ===========================================================================\n", + "\n", + " Reading settings XML file...\n", + " Reading cross sections XML file...\n", + " Reading geometry XML file...\n", + " Reading materials XML file...\n", + " Reading tallies XML file...\n", + " Building neighboring cells lists for each surface...\n", + " Loading ACE cross section table: 92235.71c\n", + " Loading ACE cross section table: 92238.71c\n", + " Loading ACE cross section table: 8016.71c\n", + " Loading ACE cross section table: 1001.71c\n", + " Loading ACE cross section table: 5010.71c\n", + " Loading ACE cross section table: 40090.71c\n", + " Maximum neutron transport energy: 20.0000 MeV for 92235.71c\n", + " Initializing source particles...\n", + "\n", + " ===========================================================================\n", + " ====================> K EIGENVALUE SIMULATION <====================\n", + " ===========================================================================\n", + "\n", + " Bat./Gen. k Average k \n", + " ========= ======== ==================== \n", + " 1/1 1.02650 \n", + " 2/1 1.01386 \n", + " 3/1 1.01045 \n", + " 4/1 1.05511 \n", + " 5/1 1.04873 \n", + " 6/1 1.04558 \n", + " 7/1 1.03840 \n", + " 8/1 1.02086 \n", + " 9/1 1.08845 \n", + " 10/1 1.03932 \n", + " 11/1 1.01271 \n", + " 12/1 1.03448 1.02360 +/- 0.01088\n", + " 13/1 1.04395 1.03038 +/- 0.00925\n", + " 14/1 1.05477 1.03648 +/- 0.00894\n", + " 15/1 1.00485 1.03015 +/- 0.00938\n", + " 16/1 1.04523 1.03267 +/- 0.00806\n", + " 17/1 1.01328 1.02990 +/- 0.00735\n", + " 18/1 1.01476 1.02800 +/- 0.00664\n", + " 19/1 1.01490 1.02655 +/- 0.00604\n", + " 20/1 1.00926 1.02482 +/- 0.00567\n", + " 21/1 0.98504 1.02120 +/- 0.00627\n", + " 22/1 1.00397 1.01977 +/- 0.00591\n", + " 23/1 1.02556 1.02021 +/- 0.00545\n", + " 24/1 0.99808 1.01863 +/- 0.00529\n", + " 25/1 0.99638 1.01715 +/- 0.00514\n", + " 26/1 0.99615 1.01584 +/- 0.00499\n", + " 27/1 1.01843 1.01599 +/- 0.00469\n", + " 28/1 1.00315 1.01528 +/- 0.00447\n", + " 29/1 1.00633 1.01480 +/- 0.00426\n", + " 30/1 1.02159 1.01514 +/- 0.00405\n", + " 31/1 1.03395 1.01604 +/- 0.00396\n", + " 32/1 1.02672 1.01652 +/- 0.00381\n", + " 33/1 1.03778 1.01745 +/- 0.00375\n", + " 34/1 1.03807 1.01831 +/- 0.00369\n", + " 35/1 1.07854 1.02072 +/- 0.00428\n", + " 36/1 1.03524 1.02128 +/- 0.00415\n", + " 37/1 1.03100 1.02164 +/- 0.00401\n", + " 38/1 1.03853 1.02224 +/- 0.00391\n", + " 39/1 1.04089 1.02288 +/- 0.00383\n", + " 40/1 1.02150 1.02284 +/- 0.00370\n", + " 41/1 0.98470 1.02161 +/- 0.00379\n", + " 42/1 1.00658 1.02114 +/- 0.00370\n", + " 43/1 0.98652 1.02009 +/- 0.00373\n", + " 44/1 1.02787 1.02032 +/- 0.00363\n", + " 45/1 0.98800 1.01939 +/- 0.00364\n", + " 46/1 1.00286 1.01893 +/- 0.00357\n", + " 47/1 1.02559 1.01911 +/- 0.00348\n", + " 48/1 1.03729 1.01959 +/- 0.00342\n", + " 49/1 1.02538 1.01974 +/- 0.00333\n", + " 50/1 1.01478 1.01962 +/- 0.00325\n", + " Creating state point statepoint.50.h5...\n", + "\n", + " ===========================================================================\n", + " ======================> SIMULATION FINISHED <======================\n", + " ===========================================================================\n", + "\n", + "\n", + " =======================> TIMING STATISTICS <=======================\n", + "\n", + " Total time for initialization = 4.2800E-01 seconds\n", + " Reading cross sections = 9.1000E-02 seconds\n", + " Total time in simulation = 4.1240E+01 seconds\n", + " Time in transport only = 4.1215E+01 seconds\n", + " Time in inactive batches = 4.0230E+00 seconds\n", + " Time in active batches = 3.7217E+01 seconds\n", + " Time synchronizing fission bank = 8.0000E-03 seconds\n", + " Sampling source sites = 6.0000E-03 seconds\n", + " SEND/RECV source sites = 2.0000E-03 seconds\n", + " Time accumulating tallies = 2.0000E-03 seconds\n", + " Total time for finalization = 0.0000E+00 seconds\n", + " Total time elapsed = 4.1683E+01 seconds\n", + " Calculation Rate (inactive) = 6214.27 neutrons/second\n", + " Calculation Rate (active) = 2686.94 neutrons/second\n", + "\n", + " ============================> RESULTS <============================\n", + "\n", + " k-effective (Collision) = 1.01805 +/- 0.00261\n", + " k-effective (Track-length) = 1.01962 +/- 0.00325\n", + " k-effective (Absorption) = 1.01554 +/- 0.00339\n", + " Combined k-effective = 1.01711 +/- 0.00235\n", + " Leakage Fraction = 0.00000 +/- 0.00000\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Run OpenMC\n", + "executor.run_simulation()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tally Data Processing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a `StatePoint` object. " + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Load the last statepoint file\n", + "sp = openmc.StatePoint('statepoint.50.h5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. This is necessary for the `openmc.mgxs` module to properly process the tally data. We first create a `Summary` object and link it with the statepoint." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "su = openmc.Summary('summary.h5')\n", + "sp.link_with_summary(su)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The statepoint is now ready to be analyzed by the `Library`. We simply have to load the tallies from the statepoint into the `Library` and our `MGXS` objects will compute the cross sections for us under-the-hood." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python2.7/dist-packages/openmc-0.7.0-py2.7.egg/openmc/tallies.py:1514: RuntimeWarning: invalid value encountered in true_divide\n", + "/usr/local/lib/python2.7/dist-packages/openmc-0.7.0-py2.7.egg/openmc/tallies.py:1515: RuntimeWarning: invalid value encountered in true_divide\n", + "/usr/local/lib/python2.7/dist-packages/openmc-0.7.0-py2.7.egg/openmc/tallies.py:1516: RuntimeWarning: invalid value encountered in true_divide\n" + ] + } + ], + "source": [ + "# Initialize MGXS Library with OpenMC statepoint data\n", + "mgxs_lib.load_from_statepoint(sp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Voila! Our multi-group cross sections are now ready to rock 'n roll!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Extracting and Storing MGXS Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `Library` supports a rich API to automate a variety of tasks, including multi-group cross section data retrieval and storage. We will highlight a few of these features here. First, the `Library.get_mgxs(...)` method allows one to extract an `MGXS` object from the `Library` for a particular domain and cross section type. The following cell illustrates how one may extract the `NuFissionXS` object for the fuel cell.\n", + "\n", + "**Note:** The `MGXS.get_mgxs(...)` method will accept either the domain *or* the integer domain ID of interest." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Retrieve the NuFissionXS object for the fuel cell from the library\n", + "fuel_mgxs = mgxs_lib.get_mgxs(fuel_cell, 'nu-fission')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `NuFissionXS` object supports all of the methods described previously the `openmc.mgxs` tutorials, such as [Pandas](http://pandas.pydata.org/) `DataFrames`:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python2.7/dist-packages/openmc-0.7.0-py2.7.egg/openmc/mgxs/mgxs.py:1254: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellgroup innuclidemeanstd. dev.
3100001U-2358.063513e-034.062984e-05
4100001U-2387.335515e-034.459335e-05
5100001O-160.000000e+000.000000e+00
0100002U-2353.613274e-011.902492e-03
1100002U-2386.738424e-073.536787e-09
2100002O-160.000000e+000.000000e+00
\n", + "
" + ], + "text/plain": [ + " cell group in nuclide mean std. dev.\n", + "3 10000 1 U-235 8.063513e-03 4.062984e-05\n", + "4 10000 1 U-238 7.335515e-03 4.459335e-05\n", + "5 10000 1 O-16 0.000000e+00 0.000000e+00\n", + "0 10000 2 U-235 3.613274e-01 1.902492e-03\n", + "1 10000 2 U-238 6.738424e-07 3.536787e-09\n", + "2 10000 2 O-16 0.000000e+00 0.000000e+00" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = fuel_mgxs.get_pandas_dataframe()\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, we can use the `MGXS.print_xs(...)` method to view a string representation of the multi-group cross section data." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Multi-Group XS\n", + "\tReaction Type =\tnu-fission\n", + "\tDomain Type =\tcell\n", + "\tDomain ID =\t10000\n", + "\tNuclide =\tU-235\n", + "\tCross Sections [cm^-1]:\n", + " Group 1 [6.25e-07 - 20.0 MeV]:\t8.06e-03 +/- 5.04e-01%\n", + " Group 2 [0.0 - 6.25e-07 MeV]:\t3.61e-01 +/- 5.27e-01%\n", + "\n", + "\tNuclide =\tU-238\n", + "\tCross Sections [cm^-1]:\n", + " Group 1 [6.25e-07 - 20.0 MeV]:\t7.34e-03 +/- 6.08e-01%\n", + " Group 2 [0.0 - 6.25e-07 MeV]:\t6.74e-07 +/- 5.25e-01%\n", + "\n", + "\tNuclide =\tO-16\n", + "\tCross Sections [cm^-1]:\n", + " Group 1 [6.25e-07 - 20.0 MeV]:\t0.00e+00 +/- nan%\n", + " Group 2 [0.0 - 6.25e-07 MeV]:\t0.00e+00 +/- nan%\n", + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "fuel_mgxs.print_xs()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One can export the entire `Library` to HDF5 with the `Library.build_hdf5_store(...)` method as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Store the cross section data in an \"mgxs/mgxs.h5\" HDF5 binary file\n", + "mgxs_lib.build_hdf5_store(filename='mgxs.h5', directory='mgxs')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The HDF5 store will contain the numerical multi-group cross section data indexed by domain, nuclide and cross section type. Some data workflows may be optimized by storing and retrieving binary representations of the `MGXS` objects in the `Library`. This feature is supported through the `Library.dump_to_file(...)` and `Library.load_from_file(...)` routines which use Python's [`pickle`](https://docs.python.org/2/library/pickle.html) module. This is illustrated as follows." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Store a Library and its MGXS objects in a pickled binary file \"mgxs/mgxs.pkl\"\n", + "mgxs_lib.dump_to_file(filename='mgxs', directory='mgxs')" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate a new MGXS Library from the pickled binary file \"mgxs/mgxs.pkl\"\n", + "mgxs_lib = openmc.mgxs.Library.load_from_file(filename='mgxs', directory='mgxs')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `Library` class may be used to leverage the energy condensation features supported by the `MGXS` class. In particular, one can use the `Library.get_condensed_library(...)` with a coarse group structure which is a subset of the original \"fine\" group structure as shown below." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create a 1-group structure\n", + "coarse_groups = openmc.mgxs.EnergyGroups(group_edges=[0., 20.])\n", + "\n", + "# Create a new MGXS Library on the coarse 1-group structure\n", + "coarse_mgxs_lib = mgxs_lib.get_condensed_library(coarse_groups)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cellgroup innuclidemeanstd. dev.
0100001U-2350.0743830.000280
1100001U-2380.0059590.000036
2100001O-160.0000000.000000
\n", + "
" + ], + "text/plain": [ + " cell group in nuclide mean std. dev.\n", + "0 10000 1 U-235 0.074383 0.000280\n", + "1 10000 1 U-238 0.005959 0.000036\n", + "2 10000 1 O-16 0.000000 0.000000" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Retrieve the NuFissionXS object for the fuel cell from the 1-group library\n", + "coarse_fuel_mgxs = coarse_mgxs_lib.get_mgxs(fuel_cell, 'nu-fission')\n", + "\n", + "# Show the Pandas DataFrame for the 1-group MGXS\n", + "coarse_fuel_mgxs.get_pandas_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Verification with OpenMOC" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Of course it is always a good idea to verify that one's cross sections are accurate. We can easily do so here with the deterministic transport code [OpenMOC](https://mit-crpg.github.io/OpenMOC/). We will extract an OpenCG geometry from the summary file and convert it into an equivalent OpenMOC geometry." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create an OpenMOC Geometry from the OpenCG Geometry\n", + "openmoc_geometry = get_openmoc_geometry(mgxs_lib.opencg_geometry)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we can inject the multi-group cross sections into the equivalent fuel assembly OpenMOC geometry. The `openmoc.materialize` module supports the loading of `Library` objects from OpenMC as illustrated below." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Load the library into the OpenMOC geometry\n", + "materials = load_openmc_mgxs_lib(mgxs_lib, openmoc_geometry)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to run OpenMOC to verify our cross-sections from OpenMC." + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Ray tracing for track segmentation...\n", + "[ NORMAL ] Dumping tracks to file...\n", + "[ NORMAL ] Computing the eigenvalue...\n", + "[ NORMAL ] Iteration 0:\tk_eff = 0.854316\tres = 0.000E+00\n", + "[ NORMAL ] Iteration 1:\tk_eff = 0.801593\tres = 1.522E-01\n", + "[ NORMAL ] Iteration 2:\tk_eff = 0.761131\tres = 6.380E-02\n", + "[ NORMAL ] Iteration 3:\tk_eff = 0.731467\tres = 5.066E-02\n", + "[ NORMAL ] Iteration 4:\tk_eff = 0.709897\tres = 3.910E-02\n", + "[ NORMAL ] Iteration 5:\tk_eff = 0.695110\tres = 2.954E-02\n", + "[ NORMAL ] Iteration 6:\tk_eff = 0.685966\tres = 2.085E-02\n", + "[ NORMAL ] Iteration 7:\tk_eff = 0.681511\tres = 1.317E-02\n", + "[ NORMAL ] Iteration 8:\tk_eff = 0.680926\tres = 6.520E-03\n", + "[ NORMAL ] Iteration 9:\tk_eff = 0.683509\tres = 1.046E-03\n", + "[ NORMAL ] Iteration 10:\tk_eff = 0.688659\tres = 3.848E-03\n", + "[ NORMAL ] Iteration 11:\tk_eff = 0.695860\tres = 7.565E-03\n", + "[ NORMAL ] Iteration 12:\tk_eff = 0.704674\tres = 1.048E-02\n", + "[ NORMAL ] Iteration 13:\tk_eff = 0.714726\tres = 1.269E-02\n", + "[ NORMAL ] Iteration 14:\tk_eff = 0.725700\tres = 1.428E-02\n", + "[ NORMAL ] Iteration 15:\tk_eff = 0.737329\tres = 1.537E-02\n", + "[ NORMAL ] Iteration 16:\tk_eff = 0.749388\tres = 1.604E-02\n", + "[ NORMAL ] Iteration 17:\tk_eff = 0.761690\tres = 1.637E-02\n", + "[ NORMAL ] Iteration 18:\tk_eff = 0.774081\tres = 1.643E-02\n", + "[ NORMAL ] Iteration 19:\tk_eff = 0.786432\tres = 1.628E-02\n", + "[ NORMAL ] Iteration 20:\tk_eff = 0.798638\tres = 1.597E-02\n", + "[ NORMAL ] Iteration 21:\tk_eff = 0.810618\tres = 1.553E-02\n", + "[ NORMAL ] Iteration 22:\tk_eff = 0.822303\tres = 1.501E-02\n", + "[ NORMAL ] Iteration 23:\tk_eff = 0.833643\tres = 1.443E-02\n", + "[ NORMAL ] Iteration 24:\tk_eff = 0.844598\tres = 1.380E-02\n", + "[ NORMAL ] Iteration 25:\tk_eff = 0.855140\tres = 1.315E-02\n", + "[ NORMAL ] Iteration 26:\tk_eff = 0.865249\tres = 1.249E-02\n", + "[ NORMAL ] Iteration 27:\tk_eff = 0.874914\tres = 1.183E-02\n", + "[ NORMAL ] Iteration 28:\tk_eff = 0.884128\tres = 1.118E-02\n", + "[ NORMAL ] Iteration 29:\tk_eff = 0.892891\tres = 1.054E-02\n", + "[ NORMAL ] Iteration 30:\tk_eff = 0.901206\tres = 9.920E-03\n", + "[ NORMAL ] Iteration 31:\tk_eff = 0.909080\tres = 9.320E-03\n", + "[ NORMAL ] Iteration 32:\tk_eff = 0.916523\tres = 8.745E-03\n", + "[ NORMAL ] Iteration 33:\tk_eff = 0.923546\tres = 8.194E-03\n", + "[ NORMAL ] Iteration 34:\tk_eff = 0.930162\tres = 7.669E-03\n", + "[ NORMAL ] Iteration 35:\tk_eff = 0.936387\tres = 7.171E-03\n", + "[ NORMAL ] Iteration 36:\tk_eff = 0.942236\tres = 6.698E-03\n", + "[ NORMAL ] Iteration 37:\tk_eff = 0.947725\tres = 6.252E-03\n", + "[ NORMAL ] Iteration 38:\tk_eff = 0.952869\tres = 5.830E-03\n", + "[ NORMAL ] Iteration 39:\tk_eff = 0.957687\tres = 5.433E-03\n", + "[ NORMAL ] Iteration 40:\tk_eff = 0.962193\tres = 5.060E-03\n", + "[ NORMAL ] Iteration 41:\tk_eff = 0.966404\tres = 4.710E-03\n", + "[ NORMAL ] Iteration 42:\tk_eff = 0.970337\tres = 4.381E-03\n", + "[ NORMAL ] Iteration 43:\tk_eff = 0.974006\tres = 4.073E-03\n", + "[ NORMAL ] Iteration 44:\tk_eff = 0.977426\tres = 3.785E-03\n", + "[ NORMAL ] Iteration 45:\tk_eff = 0.980613\tres = 3.515E-03\n", + "[ NORMAL ] Iteration 46:\tk_eff = 0.983580\tres = 3.264E-03\n", + "[ NORMAL ] Iteration 47:\tk_eff = 0.986341\tres = 3.029E-03\n", + "[ NORMAL ] Iteration 48:\tk_eff = 0.988908\tres = 2.809E-03\n", + "[ NORMAL ] Iteration 49:\tk_eff = 0.991293\tres = 2.605E-03\n", + "[ NORMAL ] Iteration 50:\tk_eff = 0.993509\tres = 2.415E-03\n", + "[ NORMAL ] Iteration 51:\tk_eff = 0.995566\tres = 2.238E-03\n", + "[ NORMAL ] Iteration 52:\tk_eff = 0.997475\tres = 2.073E-03\n", + "[ NORMAL ] Iteration 53:\tk_eff = 0.999246\tres = 1.920E-03\n", + "[ NORMAL ] Iteration 54:\tk_eff = 1.000888\tres = 1.777E-03\n", + "[ NORMAL ] Iteration 55:\tk_eff = 1.002409\tres = 1.645E-03\n", + "[ NORMAL ] Iteration 56:\tk_eff = 1.003818\tres = 1.522E-03\n", + "[ NORMAL ] Iteration 57:\tk_eff = 1.005123\tres = 1.408E-03\n", + "[ NORMAL ] Iteration 58:\tk_eff = 1.006331\tres = 1.302E-03\n", + "[ NORMAL ] Iteration 59:\tk_eff = 1.007450\tres = 1.203E-03\n", + "[ NORMAL ] Iteration 60:\tk_eff = 1.008484\tres = 1.112E-03\n", + "[ NORMAL ] Iteration 61:\tk_eff = 1.009440\tres = 1.028E-03\n", + "[ NORMAL ] Iteration 62:\tk_eff = 1.010324\tres = 9.496E-04\n", + "[ NORMAL ] Iteration 63:\tk_eff = 1.011141\tres = 8.771E-04\n", + "[ NORMAL ] Iteration 64:\tk_eff = 1.011897\tres = 8.100E-04\n", + "[ NORMAL ] Iteration 65:\tk_eff = 1.012594\tres = 7.478E-04\n", + "[ NORMAL ] Iteration 66:\tk_eff = 1.013238\tres = 6.903E-04\n", + "[ NORMAL ] Iteration 67:\tk_eff = 1.013833\tres = 6.371E-04\n", + "[ NORMAL ] Iteration 68:\tk_eff = 1.014382\tres = 5.879E-04\n", + "[ NORMAL ] Iteration 69:\tk_eff = 1.014889\tres = 5.424E-04\n", + "[ NORMAL ] Iteration 70:\tk_eff = 1.015357\tres = 5.004E-04\n", + "[ NORMAL ] Iteration 71:\tk_eff = 1.015789\tres = 4.615E-04\n", + "[ NORMAL ] Iteration 72:\tk_eff = 1.016187\tres = 4.255E-04\n", + "[ NORMAL ] Iteration 73:\tk_eff = 1.016554\tres = 3.923E-04\n", + "[ NORMAL ] Iteration 74:\tk_eff = 1.016892\tres = 3.617E-04\n", + "[ NORMAL ] Iteration 75:\tk_eff = 1.017204\tres = 3.333E-04\n", + "[ NORMAL ] Iteration 76:\tk_eff = 1.017492\tres = 3.072E-04\n", + "[ NORMAL ] Iteration 77:\tk_eff = 1.017757\tres = 2.831E-04\n", + "[ NORMAL ] Iteration 78:\tk_eff = 1.018001\tres = 2.608E-04\n", + "[ NORMAL ] Iteration 79:\tk_eff = 1.018226\tres = 2.403E-04\n", + "[ NORMAL ] Iteration 80:\tk_eff = 1.018433\tres = 2.213E-04\n", + "[ NORMAL ] Iteration 81:\tk_eff = 1.018624\tres = 2.038E-04\n", + "[ NORMAL ] Iteration 82:\tk_eff = 1.018800\tres = 1.877E-04\n", + "[ NORMAL ] Iteration 83:\tk_eff = 1.018962\tres = 1.728E-04\n", + "[ NORMAL ] Iteration 84:\tk_eff = 1.019110\tres = 1.591E-04\n", + "[ NORMAL ] Iteration 85:\tk_eff = 1.019248\tres = 1.465E-04\n", + "[ NORMAL ] Iteration 86:\tk_eff = 1.019374\tres = 1.348E-04\n", + "[ NORMAL ] Iteration 87:\tk_eff = 1.019490\tres = 1.241E-04\n", + "[ NORMAL ] Iteration 88:\tk_eff = 1.019597\tres = 1.142E-04\n", + "[ NORMAL ] Iteration 89:\tk_eff = 1.019695\tres = 1.051E-04\n", + "[ NORMAL ] Iteration 90:\tk_eff = 1.019786\tres = 9.670E-05\n", + "[ NORMAL ] Iteration 91:\tk_eff = 1.019869\tres = 8.895E-05\n", + "[ NORMAL ] Iteration 92:\tk_eff = 1.019946\tres = 8.183E-05\n", + "[ NORMAL ] Iteration 93:\tk_eff = 1.020016\tres = 7.528E-05\n", + "[ NORMAL ] Iteration 94:\tk_eff = 1.020081\tres = 6.922E-05\n", + "[ NORMAL ] Iteration 95:\tk_eff = 1.020141\tres = 6.368E-05\n", + "[ NORMAL ] Iteration 96:\tk_eff = 1.020195\tres = 5.857E-05\n", + "[ NORMAL ] Iteration 97:\tk_eff = 1.020246\tres = 5.385E-05\n", + "[ NORMAL ] Iteration 98:\tk_eff = 1.020292\tres = 4.954E-05\n", + "[ NORMAL ] Iteration 99:\tk_eff = 1.020335\tres = 4.553E-05\n", + "[ NORMAL ] Iteration 100:\tk_eff = 1.020374\tres = 4.185E-05\n", + "[ NORMAL ] Iteration 101:\tk_eff = 1.020410\tres = 3.848E-05\n", + "[ NORMAL ] Iteration 102:\tk_eff = 1.020443\tres = 3.537E-05\n", + "[ NORMAL ] Iteration 103:\tk_eff = 1.020474\tres = 3.253E-05\n", + "[ NORMAL ] Iteration 104:\tk_eff = 1.020502\tres = 2.989E-05\n", + "[ NORMAL ] Iteration 105:\tk_eff = 1.020527\tres = 2.746E-05\n", + "[ NORMAL ] Iteration 106:\tk_eff = 1.020551\tres = 2.526E-05\n", + "[ NORMAL ] Iteration 107:\tk_eff = 1.020573\tres = 2.319E-05\n", + "[ NORMAL ] Iteration 108:\tk_eff = 1.020593\tres = 2.134E-05\n", + "[ NORMAL ] Iteration 109:\tk_eff = 1.020611\tres = 1.960E-05\n", + "[ NORMAL ] Iteration 110:\tk_eff = 1.020628\tres = 1.800E-05\n", + "[ NORMAL ] Iteration 111:\tk_eff = 1.020643\tres = 1.652E-05\n", + "[ NORMAL ] Iteration 112:\tk_eff = 1.020657\tres = 1.518E-05\n", + "[ NORMAL ] Iteration 113:\tk_eff = 1.020670\tres = 1.398E-05\n", + "[ NORMAL ] Iteration 114:\tk_eff = 1.020682\tres = 1.283E-05\n", + "[ NORMAL ] Iteration 115:\tk_eff = 1.020693\tres = 1.178E-05\n", + "[ NORMAL ] Iteration 116:\tk_eff = 1.020704\tres = 1.083E-05\n" + ] + } + ], + "source": [ + "# Generate tracks for OpenMOC\n", + "openmoc_geometry.initializeFlatSourceRegions()\n", + "track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=32, spacing=0.1)\n", + "track_generator.generateTracks()\n", + "\n", + "# Run OpenMOC\n", + "solver = openmoc.CPUSolver(track_generator)\n", + "solver.computeEigenvalue()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We report the eigenvalues computed by OpenMC and OpenMOC here together to summarize our results." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "openmc keff = 1.017105\n", + "openmoc keff = 1.020704\n", + "bias [pcm]: 359.8\n" + ] + } + ], + "source": [ + "# Print report of keff and bias with OpenMC\n", + "openmoc_keff = solver.getKeff()\n", + "openmc_keff = sp.k_combined[0]\n", + "bias = (openmoc_keff - openmc_keff) * 1e5\n", + "\n", + "print('openmc keff = {0:1.6f}'.format(openmc_keff))\n", + "print('openmoc keff = {0:1.6f}'.format(openmoc_keff))\n", + "print('bias [pcm]: {0:1.1f}'.format(bias))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There is a non-trivial bias between the eigenvalues computed by OpenMC and OpenMOC. One can show that these biases do not converge to <100 pcm with more particle histories. For heterogeneous geometries, additional measures must be taken to address the following three sources of bias:\n", + "\n", + "* Appropriate transport-corrected cross sections\n", + "* Spatial discretization of OpenMOC's mesh\n", + "* Constant-in-angle multi-group cross sections" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Flux and Pin Power Visualizations" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will conclude this tutorial by illustrating how to visualize the fission rates computed by OpenMOC and OpenMC. First, we extract volume-integrated fission rates from OpenMC's mesh fission rate tally for each pin cell in the fuel assembly." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Get the OpenMC fission rate mesh tally data\n", + "mesh_tally = sp.get_tally(name='mesh tally')\n", + "openmc_fission_rates = mesh_tally.get_values(scores=['nu-fission'])\n", + "\n", + "# Reshape array to 2D for plotting\n", + "openmc_fission_rates.shape = (17,17)\n", + "\n", + "# Normalize to the average pin power\n", + "openmc_fission_rates /= np.mean(openmc_fission_rates)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we extract OpenMOC's volume-averaged fission rates into a 2D 17x17 NumPy array." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Export OpenMOC's fission rates for each pin cell instance in the fuel assembly\n", + "openmoc.process.compute_fission_rates(solver)\n", + "\n", + "# Open the pickle file with the fission rates\n", + "fission_rates = pickle.load(open('fission-rates/fission-rates.pkl', 'rb' ))\n", + "\n", + "# Allocate array for fission rates in each fuel pin\n", + "openmoc_fission_rates = np.zeros((17, 17))\n", + "\n", + "# Extract fission rates for each fuel pin\n", + "for key, value in fission_rates.items():\n", + " lat_x = int(key.split(':')[1].split()[3][1:-1])\n", + " lat_y = int(key.split(':')[1].split()[4][:-1]) \n", + " openmoc_fission_rates[lat_x, lat_y] = value\n", + "\n", + "# Normalize to the average pin fission rate\n", + "openmoc_fission_rates /= np.mean(openmoc_fission_rates)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can easily use Matplotlib to visualize the fission rates from OpenMC and OpenMOC side-by-side." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot OpenMC's fission rates in the left subplot\n", + "fig = pylab.subplot(121)\n", + "pylab.imshow(openmc_fission_rates, interpolation='none', cmap='jet')\n", + "pylab.title('OpenMC Fission Rates')\n", + "\n", + "# Plot OpenMOC's fission rates in the right subplot\n", + "fig2 = pylab.subplot(122)\n", + "pylab.imshow(openmoc_fission_rates, interpolation='none', cmap='jet')\n", + "pylab.title('OpenMOC Fission Rates')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/source/pythonapi/examples/mgxs-part-iii.rst b/docs/source/pythonapi/examples/mgxs-part-iii.rst new file mode 100644 index 0000000000..f441028628 --- /dev/null +++ b/docs/source/pythonapi/examples/mgxs-part-iii.rst @@ -0,0 +1,13 @@ +.. _notebook_mgxs_part_iii: + +======================== +MGXS Part III: Libraries +======================== + +.. only:: html + + .. notebook:: mgxs-part-iii.ipynb + +.. only:: latex + + IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/pythonapi/examples/pandas-dataframes.ipynb b/docs/source/pythonapi/examples/pandas-dataframes.ipynb index 24c5c00a02..1b05f82075 100644 --- a/docs/source/pythonapi/examples/pandas-dataframes.ipynb +++ b/docs/source/pythonapi/examples/pandas-dataframes.ipynb @@ -126,7 +126,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now let's move on to the geometry. This problem will be a square array of fuel pins, which we can use OpenMC's lattice/universe feature for. The basic universe will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces for fuel and clad, as well as the outer bounding surfaces of the problem." + "Now let's move on to the geometry. This problem will be a square array of fuel pins for which we can use OpenMC's lattice/universe feature. The basic universe will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces for fuel and clad, as well as the outer bounding surfaces of the problem." ] }, { @@ -155,7 +155,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces." + "With the surfaces defined, we can now construct a fuel pin cell from cells that are defined by intersections of half-spaces created by the surfaces." ] }, { @@ -172,20 +172,19 @@ "# Create fuel Cell\n", "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", "fuel_cell.fill = fuel\n", - "fuel_cell.add_surface(fuel_outer_radius, halfspace=-1)\n", + "fuel_cell.region = -fuel_outer_radius\n", "pin_cell_universe.add_cell(fuel_cell)\n", "\n", "# Create a clad Cell\n", "clad_cell = openmc.Cell(name='1.6% Clad')\n", "clad_cell.fill = zircaloy\n", - "clad_cell.add_surface(fuel_outer_radius, halfspace=+1)\n", - "clad_cell.add_surface(clad_outer_radius, halfspace=-1)\n", + "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", "pin_cell_universe.add_cell(clad_cell)\n", "\n", "# Create a moderator Cell\n", "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", "moderator_cell.fill = water\n", - "moderator_cell.add_surface(clad_outer_radius, halfspace=+1)\n", + "moderator_cell.region = +clad_outer_radius\n", "pin_cell_universe.add_cell(moderator_cell)" ] }, @@ -193,7 +192,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Using the pin cell universe, we can construct a 17x17 rectangular lattice with a 1.26cm pitch." + "Using the pin cell universe, we can construct a 17x17 rectangular lattice with a 1.26 cm pitch." ] }, { @@ -232,12 +231,7 @@ "root_cell.fill = assembly\n", "\n", "# Add boundary planes\n", - "root_cell.add_surface(min_x, halfspace=+1)\n", - "root_cell.add_surface(max_x, halfspace=-1)\n", - "root_cell.add_surface(min_y, halfspace=+1)\n", - "root_cell.add_surface(max_y, halfspace=-1)\n", - "root_cell.add_surface(min_z, halfspace=+1)\n", - "root_cell.add_surface(max_z, halfspace=-1)\n", + "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", "\n", "# Create root Universe\n", "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", @@ -248,7 +242,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We now must create a geometry that is assigned a root universe, put the geometry into a geometry file, and export it to XML." + "We now must create a geometry that is assigned a root universe, put the geometry into a `GeometryFile` object, and export it to XML." ] }, { @@ -358,7 +352,18 @@ "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Run openmc in plotting mode\n", "executor = openmc.Executor()\n", @@ -374,7 +379,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAAPZSURB\nVGje7Zs7buMwEIZ9iey50gyNjQpXKTYudIScgkdQYTfut1idwkdQkQNsYQO2Qj0sPiVK+mlQDmwg\nwIcgg8Cc4fCTSK5W4OeFkM8rHv+2I/rgxPZEPZgR7XtQxKdXYuUXJSUnBQ/9WCgo4vOSJ+WFUvF7\nE08mlia+rn7VcKXP8sRszFX8b2MdX2y6v1Tw6MZUw4H4ojfIjD8mvn/qRL5p4+vvlMqvp2EhR8WB\nzfiz20hXORmP9fi/bM9EeUFvV5H/0yRkeSbiGRfFJErxD9ENdz7Mbhig/h89fvtFdMiI/ePUIXV4\nlXju8K3DKv9NThOZ3q2KmUy6grxFES8rjeyic+FFQav+ncg3fXjH+Ts+/iibztFqOiZuZP/Z3Oaf\nPX40NGgST2r+uvQkXXp6cKvmr+r0e1Eef5um3+JHP3IFF1D/seNZJgaDmvY0Gav1s+2f1fqpIcub\nlfKGt6apotG/NVx3SInWtLX+7Vg/Pv1YqOsnun6JSVdOXT/X7vk75f938QP+8OmSBs0fXtymMhJb\nf8qlPynYmpKCh7OB1fzNalOj1sl0ZAruHLiA+RM73pDe/VjMVP89+aTXwjyc/x5n+u991895/utr\nJTy8/06TXh0r/5JOa2JmYmqi4r/vUm/H4wLmT+z4anhr05X+q6KUXhtzr/9qSff5L5uMT//V/NdU\n4YuBTPa/8P67l/6r44ds+hYuoP5jx9ciy6XTWlibBrmx8V/TdMfjkP+6pOsu/lvM9N90sf7r+f6m\n/65n+S8p/itN15v0UkW3/+48+PRfJX6S9Joo4g+G/1qYG9KroqP/WypcuvyXPf13wH89/hHef7MB\n6R3Cqn55U4rv4kfH3zaSgQuYP7HjVf89tXrbO+hfLdr+Ozv/SP1dgtQ/Ov8C+i/3+q/Zf2D/HWi6\nbjT6rym9I/v/03/b+LHS4cTg/utTsV7/net/Afzz4f0XGX84/2j9xZ4/sePR/of2X7D/o+vPo/sv\n6h9B/Bfxr9j1Hz2eN/hO8/wfff4A848+f/1A/530/I0+/8PvH9D3H9HnT+R49P0b+v4PfP/4E/wX\nfP8Mvf9G37/D/ovuP8SeP7Hj0f0vdP8tqP9O339cyv7p3P1fdP8Z3v9G999j13/seMax8x/o+ZN7\n+O+E8zdP/8XOf8Hnz9Dzb7HnT+x49PxlCp7/BM+fOv13wvnXBfivt2lMvD8TyH/Hnb+Gz3+j589j\nz5/Y8ej9h4D+W7qQmf57efqv239n3T+C7z+h969i13/seMax+3/o/cMcu/8Y2H9n3p+J6r98pv8m\n4fwXuH+M3n+OO3++AX9clR+4PhbRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTA4LTA4VDA5OjI2\nOjM4KzA3OjAwuRKYlgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wOC0wOFQwOToyNjozOCswNzow\nMMhPICoAAAAASUVORK5CYII=\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAAPZSURB\nVGje7Zs7buMwEIZ9iey50gyNjQpXKTYudIScgkdQYTfut1idwkdQkQNsYQO2Qj0sPiVK+mlQDmwg\nwIcgg8Cc4fCTSK5W4OeFkM8rHv+2I/rgxPZEPZgR7XtQxKdXYuUXJSUnBQ/9WCgo4vOSJ+WFUvF7\nE08mlia+rn7VcKXP8sRszFX8b2MdX2y6v1Tw6MZUw4H4ojfIjD8mvn/qRL5p4+vvlMqvp2EhR8WB\nzfiz20hXORmP9fi/bM9EeUFvV5H/0yRkeSbiGRfFJErxD9ENdz7Mbhig/h89fvtFdMiI/ePUIXV4\nlXju8K3DKv9NThOZ3q2KmUy6grxFES8rjeyic+FFQav+ncg3fXjH+Ts+/iibztFqOiZuZP/Z3Oaf\nPX40NGgST2r+uvQkXXp6cKvmr+r0e1Eef5um3+JHP3IFF1D/seNZJgaDmvY0Gav1s+2f1fqpIcub\nlfKGt6apotG/NVx3SInWtLX+7Vg/Pv1YqOsnun6JSVdOXT/X7vk75f938QP+8OmSBs0fXtymMhJb\nf8qlPynYmpKCh7OB1fzNalOj1sl0ZAruHLiA+RM73pDe/VjMVP89+aTXwjyc/x5n+u991895/utr\nJTy8/06TXh0r/5JOa2JmYmqi4r/vUm/H4wLmT+z4anhr05X+q6KUXhtzr/9qSff5L5uMT//V/NdU\n4YuBTPa/8P67l/6r44ds+hYuoP5jx9ciy6XTWlibBrmx8V/TdMfjkP+6pOsu/lvM9N90sf7r+f6m\n/65n+S8p/itN15v0UkW3/+48+PRfJX6S9Joo4g+G/1qYG9KroqP/WypcuvyXPf13wH89/hHef7MB\n6R3Cqn55U4rv4kfH3zaSgQuYP7HjVf89tXrbO+hfLdr+Ozv/SP1dgtQ/Ov8C+i/3+q/Zf2D/HWi6\nbjT6rym9I/v/03/b+LHS4cTg/utTsV7/net/Afzz4f0XGX84/2j9xZ4/sePR/of2X7D/o+vPo/sv\n6h9B/Bfxr9j1Hz2eN/hO8/wfff4A848+f/1A/530/I0+/8PvH9D3H9HnT+R49P0b+v4PfP/4E/wX\nfP8Mvf9G37/D/ovuP8SeP7Hj0f0vdP8tqP9O339cyv7p3P1fdP8Z3v9G999j13/seMax8x/o+ZN7\n+O+E8zdP/8XOf8Hnz9Dzb7HnT+x49PxlCp7/BM+fOv13wvnXBfivt2lMvD8TyH/Hnb+Gz3+j589j\nz5/Y8ej9h4D+W7qQmf57efqv239n3T+C7z+h969i13/seMax+3/o/cMcu/8Y2H9n3p+J6r98pv8m\n4fwXuH+M3n+OO3++AX9clR+4PhbRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTEwLTI4VDIwOjU1\nOjE4LTA0OjAwI9YF2QAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0xMC0yOFQyMDo1NToxOC0wNDow\nMFKLvWUAAAAASUVORK5CYII=\n", "text/plain": [ "" ] @@ -429,7 +434,7 @@ "source": [ "# Instantiate a tally Mesh\n", "mesh = openmc.Mesh(mesh_id=1)\n", - "mesh.type = 'rectangular'\n", + "mesh.type = 'regular'\n", "mesh.dimension = [17, 17]\n", "mesh.lower_left = [-10.71, -10.71]\n", "mesh.width = [1.26, 1.26]\n", @@ -562,9 +567,10 @@ "\n", " Copyright: 2011-2015 Massachusetts Institute of Technology\n", " License: http://mit-crpg.github.io/openmc/license.html\n", - " Version: 0.6.2\n", - " Date/Time: 2015-08-11 13:40:43\n", - " MPI Processes: 4\n", + " Version: 0.7.0\n", + " Git SHA1: 21738db07debeabde824c9b955bd3bf0c9a16366\n", + " Date/Time: 2015-10-28 20:55:18\n", + " MPI Processes: 1\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -576,12 +582,13 @@ " Reading materials XML file...\n", " Reading tallies XML file...\n", " Building neighboring cells lists for each surface...\n", + " Loading ACE cross section table: 92235.71c\n", " Loading ACE cross section table: 92238.71c\n", " Loading ACE cross section table: 8016.71c\n", - " Loading ACE cross section table: 92235.71c\n", - " Loading ACE cross section table: 5010.71c\n", " Loading ACE cross section table: 1001.71c\n", + " Loading ACE cross section table: 5010.71c\n", " Loading ACE cross section table: 40090.71c\n", + " Maximum neutron transport energy: 20.0000 MeV for 92235.71c\n", " Initializing source particles...\n", "\n", " ===========================================================================\n", @@ -590,38 +597,35 @@ "\n", " Bat./Gen. k Average k \n", " ========= ======== ==================== \n", - " 1/1 0.60069 \n", - " 2/1 0.62857 \n", - " 3/1 0.69431 \n", - " 4/1 0.65935 \n", - " 5/1 0.68092 \n", - " 6/1 0.64791 \n", - " 7/1 0.65859 0.65325 +/- 0.00534\n", - " 8/1 0.67381 0.66010 +/- 0.00752\n", - " 9/1 0.74149 0.68045 +/- 0.02103\n", - " 10/1 0.68244 0.68085 +/- 0.01629\n", - " 11/1 0.68068 0.68082 +/- 0.01330\n", - " 12/1 0.70394 0.68412 +/- 0.01172\n", - " 13/1 0.68624 0.68439 +/- 0.01015\n", - " 14/1 0.65667 0.68131 +/- 0.00947\n", - " 15/1 0.70080 0.68326 +/- 0.00869\n", - " 16/1 0.69639 0.68445 +/- 0.00795\n", - " 17/1 0.68786 0.68474 +/- 0.00726\n", - " 18/1 0.63698 0.68106 +/- 0.00762\n", - " 19/1 0.62785 0.67726 +/- 0.00802\n", - " 20/1 0.65759 0.67595 +/- 0.00758\n", - " Triggers unsatisfied, max unc./thresh. is 1.20713 for absorption in tally 10002\n", - " The estimated number of batches is 27\n", + " 1/1 0.54958 \n", + " 2/1 0.67628 \n", + " 3/1 0.70618 \n", + " 4/1 0.66601 \n", + " 5/1 0.70876 \n", + " 6/1 0.69708 \n", + " 7/1 0.68623 0.69166 +/- 0.00543\n", + " 8/1 0.69159 0.69163 +/- 0.00313\n", + " 9/1 0.69908 0.69349 +/- 0.00289\n", + " 10/1 0.63865 0.68253 +/- 0.01120\n", + " 11/1 0.65439 0.67784 +/- 0.01027\n", + " 12/1 0.68518 0.67889 +/- 0.00875\n", + " 13/1 0.69507 0.68091 +/- 0.00784\n", + " 14/1 0.70129 0.68317 +/- 0.00728\n", + " 15/1 0.71336 0.68619 +/- 0.00717\n", + " 16/1 0.68725 0.68629 +/- 0.00649\n", + " 17/1 0.72579 0.68958 +/- 0.00678\n", + " 18/1 0.67149 0.68819 +/- 0.00639\n", + " 19/1 0.67771 0.68744 +/- 0.00596\n", + " 20/1 0.68035 0.68697 +/- 0.00557\n", + " Triggers unsatisfied, max unc./thresh. is 1.09851 for absorption in tally 10002\n", + " The estimated number of batches is 24\n", " Creating state point statepoint.020.h5...\n", - " 21/1 0.68391 0.67645 +/- 0.00711\n", - " 22/1 0.69243 0.67739 +/- 0.00674\n", - " 23/1 0.65491 0.67614 +/- 0.00648\n", - " 24/1 0.64021 0.67425 +/- 0.00641\n", - " 25/1 0.72281 0.67668 +/- 0.00655\n", - " 26/1 0.71261 0.67839 +/- 0.00646\n", - " 27/1 0.69503 0.67914 +/- 0.00621\n", - " Triggers satisfied for batch 27\n", - " Creating state point statepoint.027.h5...\n", + " 21/1 0.68105 0.68660 +/- 0.00522\n", + " 22/1 0.67168 0.68572 +/- 0.00498\n", + " 23/1 0.67520 0.68514 +/- 0.00473\n", + " 24/1 0.67940 0.68483 +/- 0.00449\n", + " Triggers satisfied for batch 24\n", + " Creating state point statepoint.024.h5...\n", "\n", " ===========================================================================\n", " ======================> SIMULATION FINISHED <======================\n", @@ -630,28 +634,28 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 9.7300E-01 seconds\n", - " Reading cross sections = 3.0300E-01 seconds\n", - " Total time in simulation = 5.9130E+00 seconds\n", - " Time in transport only = 5.4000E+00 seconds\n", - " Time in inactive batches = 7.7300E-01 seconds\n", - " Time in active batches = 5.1400E+00 seconds\n", - " Time synchronizing fission bank = 4.4600E-01 seconds\n", - " Sampling source sites = 0.0000E+00 seconds\n", - " SEND/RECV source sites = 0.0000E+00 seconds\n", - " Time accumulating tallies = 9.0000E-03 seconds\n", + " Total time for initialization = 7.3800E-01 seconds\n", + " Reading cross sections = 1.5600E-01 seconds\n", + " Total time in simulation = 1.5998E+01 seconds\n", + " Time in transport only = 1.5965E+01 seconds\n", + " Time in inactive batches = 2.3990E+00 seconds\n", + " Time in active batches = 1.3599E+01 seconds\n", + " Time synchronizing fission bank = 3.0000E-03 seconds\n", + " Sampling source sites = 1.0000E-03 seconds\n", + " SEND/RECV source sites = 2.0000E-03 seconds\n", + " Time accumulating tallies = 3.0000E-03 seconds\n", " Total time for finalization = 0.0000E+00 seconds\n", - " Total time elapsed = 6.8870E+00 seconds\n", - " Calculation Rate (inactive) = 16170.8 neutrons/second\n", - " Calculation Rate (active) = 7295.72 neutrons/second\n", + " Total time elapsed = 1.6754E+01 seconds\n", + " Calculation Rate (inactive) = 5210.50 neutrons/second\n", + " Calculation Rate (active) = 2757.56 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 0.68117 +/- 0.00597\n", - " k-effective (Track-length) = 0.67914 +/- 0.00621\n", - " k-effective (Absorption) = 0.67898 +/- 0.00471\n", - " Combined k-effective = 0.67922 +/- 0.00479\n", - " Leakage Fraction = 0.34264 +/- 0.00301\n", + " k-effective (Collision) = 0.68264 +/- 0.00405\n", + " k-effective (Track-length) = 0.68483 +/- 0.00449\n", + " k-effective (Absorption) = 0.68225 +/- 0.00336\n", + " Combined k-effective = 0.68275 +/- 0.00346\n", + " Leakage Fraction = 0.34345 +/- 0.00167\n", "\n" ] }, @@ -671,7 +675,7 @@ "!rm statepoint.*\n", "\n", "# Run OpenMC with MPI!\n", - "executor.run_simulation(mpi_procs=4)" + "executor.run_simulation()" ] }, { @@ -694,9 +698,7 @@ "statepoints = glob.glob('statepoint.*.h5')\n", "\n", "# Load the last statepoint file\n", - "sp = StatePoint(statepoints[-1])\n", - "sp.read_results()\n", - "sp.compute_stdev()" + "sp = StatePoint(statepoints[-1])" ] }, { @@ -738,7 +740,7 @@ " \t\tmesh\t[1]\n", " \t\tenergy\t[ 0.00000000e+00 6.25000000e-07 2.00000000e+01]\n", "\tNuclides =\ttotal \n", - "\tScores =\t['fission', 'nu-fission']\n", + "\tScores =\t[u'fission', u'nu-fission']\n", "\tEstimator =\ttracklength\n", "\n" ] @@ -770,13 +772,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.14583021]]\n", + "[[[ 0.18257268]]\n", "\n", - " [[ 0.07846909]]\n", + " [[ 0.07111957]]\n", "\n", - " [[ 0.33705448]]\n", + " [[ 0.40880276]]\n", "\n", - " [[ 0.15150059]]]\n" + " [[ 0.16407535]]]\n" ] } ], @@ -799,7 +801,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", " \n", " \n", @@ -820,16 +822,6 @@ " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", @@ -837,29 +829,29 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -867,199 +859,198 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", "
bin
1110.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)fission0.0002360.0000340.0002020.000037
11110.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)nu-fission0.0005760.0000840.0004920.000090
21116.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)fission0.0000690.0000760.000004
1116.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)nu-fission0.0001830.0000110.0002040.000010
41210.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)fission0.0003660.0000520.0003750.000039
51210.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)nu-fission0.0008920.0001270.0009140.000094
61216.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)fission0.0001090.0000090.0001070.000013
71216.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)nu-fission0.0002840.0000210.0002780.000032
81310.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)fission0.0005400.0000580.0005640.000056
91310.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)nu-fission0.0013160.0001410.0013740.000137
101316.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)fission0.0001440.0000170.0001490.000007
111316.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)nu-fission0.0003760.0000410.0003880.000018
121410.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)fission0.0008300.0000850.0006690.000044
131410.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)nu-fission0.0020220.0002070.0016310.000108
141416.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)fission0.0001680.0000130.0001650.000011
151416.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)nu-fission0.0004340.0000340.0004330.000029
161510.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)fission0.0007380.0000430.0009320.000069
171510.0e+00 - 6.3e-07(0.0e+00 - 6.3e-07)nu-fission0.0017990.0001050.0022700.000168
181516.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)fission0.0001860.0000100.0001830.000011
191516.3e-07 - 2.0e+01(6.3e-07 - 2.0e+01)nu-fission0.0004860.0000260.0004770.000028
\n", "
" ], "text/plain": [ - " mesh 1 energy [MeV] score mean std. dev.\n", - " x y z \n", - "bin \n", - "0 1 1 1 0.0e+00 - 6.3e-07 fission 0.000236 0.000034\n", - "1 1 1 1 0.0e+00 - 6.3e-07 nu-fission 0.000576 0.000084\n", - "2 1 1 1 6.3e-07 - 2.0e+01 fission 0.000069 0.000004\n", - "3 1 1 1 6.3e-07 - 2.0e+01 nu-fission 0.000183 0.000011\n", - "4 1 2 1 0.0e+00 - 6.3e-07 fission 0.000366 0.000052\n", - "5 1 2 1 0.0e+00 - 6.3e-07 nu-fission 0.000892 0.000127\n", - "6 1 2 1 6.3e-07 - 2.0e+01 fission 0.000109 0.000009\n", - "7 1 2 1 6.3e-07 - 2.0e+01 nu-fission 0.000284 0.000021\n", - "8 1 3 1 0.0e+00 - 6.3e-07 fission 0.000540 0.000058\n", - "9 1 3 1 0.0e+00 - 6.3e-07 nu-fission 0.001316 0.000141\n", - "10 1 3 1 6.3e-07 - 2.0e+01 fission 0.000144 0.000017\n", - "11 1 3 1 6.3e-07 - 2.0e+01 nu-fission 0.000376 0.000041\n", - "12 1 4 1 0.0e+00 - 6.3e-07 fission 0.000830 0.000085\n", - "13 1 4 1 0.0e+00 - 6.3e-07 nu-fission 0.002022 0.000207\n", - "14 1 4 1 6.3e-07 - 2.0e+01 fission 0.000168 0.000013\n", - "15 1 4 1 6.3e-07 - 2.0e+01 nu-fission 0.000434 0.000034\n", - "16 1 5 1 0.0e+00 - 6.3e-07 fission 0.000738 0.000043\n", - "17 1 5 1 0.0e+00 - 6.3e-07 nu-fission 0.001799 0.000105\n", - "18 1 5 1 6.3e-07 - 2.0e+01 fission 0.000186 0.000010\n", - "19 1 5 1 6.3e-07 - 2.0e+01 nu-fission 0.000486 0.000026" + " mesh 1 energy [MeV] score mean std. dev.\n", + " x y z \n", + "0 1 1 1 (0.0e+00 - 6.3e-07) fission 0.000202 0.000037\n", + "1 1 1 1 (0.0e+00 - 6.3e-07) nu-fission 0.000492 0.000090\n", + "2 1 1 1 (6.3e-07 - 2.0e+01) fission 0.000076 0.000004\n", + "3 1 1 1 (6.3e-07 - 2.0e+01) nu-fission 0.000204 0.000010\n", + "4 1 2 1 (0.0e+00 - 6.3e-07) fission 0.000375 0.000039\n", + "5 1 2 1 (0.0e+00 - 6.3e-07) nu-fission 0.000914 0.000094\n", + "6 1 2 1 (6.3e-07 - 2.0e+01) fission 0.000107 0.000013\n", + "7 1 2 1 (6.3e-07 - 2.0e+01) nu-fission 0.000278 0.000032\n", + "8 1 3 1 (0.0e+00 - 6.3e-07) fission 0.000564 0.000056\n", + "9 1 3 1 (0.0e+00 - 6.3e-07) nu-fission 0.001374 0.000137\n", + "10 1 3 1 (6.3e-07 - 2.0e+01) fission 0.000149 0.000007\n", + "11 1 3 1 (6.3e-07 - 2.0e+01) nu-fission 0.000388 0.000018\n", + "12 1 4 1 (0.0e+00 - 6.3e-07) fission 0.000669 0.000044\n", + "13 1 4 1 (0.0e+00 - 6.3e-07) nu-fission 0.001631 0.000108\n", + "14 1 4 1 (6.3e-07 - 2.0e+01) fission 0.000165 0.000011\n", + "15 1 4 1 (6.3e-07 - 2.0e+01) nu-fission 0.000433 0.000029\n", + "16 1 5 1 (0.0e+00 - 6.3e-07) fission 0.000932 0.000069\n", + "17 1 5 1 (0.0e+00 - 6.3e-07) nu-fission 0.002270 0.000168\n", + "18 1 5 1 (6.3e-07 - 2.0e+01) fission 0.000183 0.000011\n", + "19 1 5 1 (6.3e-07 - 2.0e+01) nu-fission 0.000477 0.000028" ] }, "execution_count": 25, @@ -1084,9 +1075,9 @@ "outputs": [ { "data": { - "image/png": "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\nAAAAAElFTkSuQmCC\n", + "image/png": "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\nkiRJEsA/A3sng0v+IomuAAAAAElFTkSuQmCC\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1109,7 +1100,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 27, @@ -1118,9 +1109,9 @@ }, { "data": { - "image/png": "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\nTkSuQmCC\n", + "image/png": "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\n/wfC21DgNNvIcQAAAABJRU5ErkJggg==\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1130,7 +1121,7 @@ "source": [ "# Extract thermal nu-fission rates from pandas\n", "fiss = df[df['score'] == 'nu-fission']\n", - "fiss = fiss[fiss['energy [MeV]'] == '0.0e+00 - 6.3e-07']\n", + "fiss = fiss[fiss['energy [MeV]'] == '(0.0e+00 - 6.3e-07)']\n", "\n", "# Extract mean and reshape as 2D NumPy arrays\n", "mean = fiss['mean'].reshape((17,17))\n", @@ -1166,7 +1157,7 @@ "\tFilters =\t\n", " \t\tcell\t[10000]\n", "\tNuclides =\tU-235 U-238 \n", - "\tScores =\t['scatter-Y0,0', 'scatter-Y1,-1', 'scatter-Y1,0', 'scatter-Y1,1', 'scatter-Y2,-2', 'scatter-Y2,-1', 'scatter-Y2,0', 'scatter-Y2,1', 'scatter-Y2,2']\n", + "\tScores =\t[u'scatter-Y0,0', u'scatter-Y1,-1', u'scatter-Y1,0', u'scatter-Y1,1', u'scatter-Y2,-2', u'scatter-Y2,-1', u'scatter-Y2,0', u'scatter-Y2,1', u'scatter-Y2,2']\n", "\tEstimator =\tanalog\n", "\n" ] @@ -1190,7 +1181,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", " \n", " \n", @@ -1201,14 +1192,6 @@ " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", @@ -1216,170 +1199,169 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", "
meanstd. dev.
bin
10000U-235scatter-Y0,00.0364530.0009410.0370950.001150
110000U-235scatter-Y1,-1-0.0007250.0002610.0002660.000323
210000U-235scatter-Y1,0-0.0000880.000408-0.0004170.000274
310000U-235scatter-Y1,10.0009860.000412-0.0002280.000237
410000U-235scatter-Y2,-20.0000980.0002040.0000260.000199
510000U-235scatter-Y2,-1-0.0003580.000247-0.0001150.000185
610000U-235scatter-Y2,00.0001970.0001400.0001510.000159
710000U-235scatter-Y2,1-0.0000840.000196-0.0001220.000280
810000U-235scatter-Y2,20.0000520.0001680.0000080.000181
910000U-238scatter-Y0,02.3256000.0155452.3286320.013107
1010000U-238scatter-Y1,-1-0.0300890.0024600.0245300.002272
1110000U-238scatter-Y1,0-0.0044510.003663-0.0000590.002804
1210000U-238scatter-Y1,10.0208320.002831-0.0279900.002536
1310000U-238scatter-Y2,-2-0.0041490.001530-0.0048610.001575
1410000U-238scatter-Y2,-10.0007350.0017290.0005570.002018
1510000U-238scatter-Y2,00.0034310.0020980.0062360.001627
1610000U-238scatter-Y2,10.0003850.001263-0.0006480.001551
1710000U-238scatter-Y2,20.0000020.001718-0.0010310.001310
\n", "
" ], "text/plain": [ - " cell nuclide score mean std. dev.\n", - "bin \n", - "0 10000 U-235 scatter-Y0,0 0.036453 0.000941\n", - "1 10000 U-235 scatter-Y1,-1 -0.000725 0.000261\n", - "2 10000 U-235 scatter-Y1,0 -0.000088 0.000408\n", - "3 10000 U-235 scatter-Y1,1 0.000986 0.000412\n", - "4 10000 U-235 scatter-Y2,-2 0.000098 0.000204\n", - "5 10000 U-235 scatter-Y2,-1 -0.000358 0.000247\n", - "6 10000 U-235 scatter-Y2,0 0.000197 0.000140\n", - "7 10000 U-235 scatter-Y2,1 -0.000084 0.000196\n", - "8 10000 U-235 scatter-Y2,2 0.000052 0.000168\n", - "9 10000 U-238 scatter-Y0,0 2.325600 0.015545\n", - "10 10000 U-238 scatter-Y1,-1 -0.030089 0.002460\n", - "11 10000 U-238 scatter-Y1,0 -0.004451 0.003663\n", - "12 10000 U-238 scatter-Y1,1 0.020832 0.002831\n", - "13 10000 U-238 scatter-Y2,-2 -0.004149 0.001530\n", - "14 10000 U-238 scatter-Y2,-1 0.000735 0.001729\n", - "15 10000 U-238 scatter-Y2,0 0.003431 0.002098\n", - "16 10000 U-238 scatter-Y2,1 0.000385 0.001263\n", - "17 10000 U-238 scatter-Y2,2 0.000002 0.001718" + " cell nuclide score mean std. dev.\n", + "0 10000 U-235 scatter-Y0,0 0.037095 0.001150\n", + "1 10000 U-235 scatter-Y1,-1 0.000266 0.000323\n", + "2 10000 U-235 scatter-Y1,0 -0.000417 0.000274\n", + "3 10000 U-235 scatter-Y1,1 -0.000228 0.000237\n", + "4 10000 U-235 scatter-Y2,-2 0.000026 0.000199\n", + "5 10000 U-235 scatter-Y2,-1 -0.000115 0.000185\n", + "6 10000 U-235 scatter-Y2,0 0.000151 0.000159\n", + "7 10000 U-235 scatter-Y2,1 -0.000122 0.000280\n", + "8 10000 U-235 scatter-Y2,2 0.000008 0.000181\n", + "9 10000 U-238 scatter-Y0,0 2.328632 0.013107\n", + "10 10000 U-238 scatter-Y1,-1 0.024530 0.002272\n", + "11 10000 U-238 scatter-Y1,0 -0.000059 0.002804\n", + "12 10000 U-238 scatter-Y1,1 -0.027990 0.002536\n", + "13 10000 U-238 scatter-Y2,-2 -0.004861 0.001575\n", + "14 10000 U-238 scatter-Y2,-1 0.000557 0.002018\n", + "15 10000 U-238 scatter-Y2,0 0.006236 0.001627\n", + "16 10000 U-238 scatter-Y2,1 -0.000648 0.001551\n", + "17 10000 U-238 scatter-Y2,2 -0.001031 0.001310" ] }, "execution_count": 29, @@ -1413,8 +1395,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.00171834 0.01554515]\n", - " [ 0.00016768 0.00094081]]]\n" + "[[[ 0.00131009 0.01310707]\n", + " [ 0.00018089 0.00114976]]]\n" ] } ], @@ -1450,7 +1432,7 @@ "\tFilters =\t\n", " \t\tdistribcell\t[10002]\n", "\tNuclides =\ttotal \n", - "\tScores =\t['absorption', 'scatter']\n", + "\tScores =\t[u'absorption', u'scatter']\n", "\tEstimator =\ttracklength\n", "\n" ] @@ -1482,25 +1464,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.04682759]]\n", - "\n", - " [[ 0.03205271]]\n", - "\n", - " [[ 0.03592433]]\n", - "\n", - " [[ 0.02417979]]\n", - "\n", - " [[ 0.02524314]]\n", - "\n", - " [[ 0.02390359]]\n", - "\n", - " [[ 0.0274475 ]]\n", - "\n", - " [[ 0.02827721]]\n", - "\n", - " [[ 0.0231313 ]]\n", - "\n", - " [[ 0.01898386]]]\n" + "[[[ 0.04537029]]]\n" ] } ], @@ -1508,7 +1472,7 @@ "# Get the relative error for the scattering reaction rates in\n", "# the first 30 distribcell instances \n", "data = tally.get_values(scores=['scatter'], filters=['distribcell'],\n", - " filter_bins=[range(10)], value='rel_err')\n", + " filter_bins=[(i,) for i in range(10)], value='rel_err')\n", "print(data)" ] }, @@ -1529,7 +1493,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", " \n", " \n", @@ -1539,154 +1503,147 @@ " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", "
meanstd. dev.
bin
558279absorption0.0000950.0000090.0000930.000013
559279scatter0.0136110.0005440.0135040.000805
560280absorption0.0000960.0000090.0000840.000010
561280scatter0.0139990.0005680.0142150.000612
562281absorption0.0001170.0000150.0000910.000008
563281scatter0.0159510.0006820.0145450.000590
564282absorption0.0001040.0000110.0001120.000012
565282scatter0.0160570.0005740.0163210.000729
566283absorption0.0001170.0000130.0000920.000007
567283scatter0.0159970.0007060.0161630.000661
568284absorption0.0001080.0000070.0001040.000011
569284scatter0.0167200.0006390.0173840.000599
570285absorption0.0001160.0000080.0001110.000011
571285scatter0.0177640.0006390.0180150.000774
572286absorption0.0001110.0000140.0001250.000012
573286scatter0.0181010.0007660.0182940.000828
574287absorption0.0001150.0000120.0001190.000013
575287scatter0.0184110.0006550.0174830.000757
576288absorption0.0001380.0001130.000014
577288scatter0.0191540.0007630.0182480.000782
\n", @@ -1694,27 +1651,26 @@ ], "text/plain": [ " distribcell score mean std. dev.\n", - "bin \n", - "558 279 absorption 0.000095 0.000009\n", - "559 279 scatter 0.013611 0.000544\n", - "560 280 absorption 0.000096 0.000009\n", - "561 280 scatter 0.013999 0.000568\n", - "562 281 absorption 0.000117 0.000015\n", - "563 281 scatter 0.015951 0.000682\n", - "564 282 absorption 0.000104 0.000011\n", - "565 282 scatter 0.016057 0.000574\n", - "566 283 absorption 0.000117 0.000013\n", - "567 283 scatter 0.015997 0.000706\n", - "568 284 absorption 0.000108 0.000007\n", - "569 284 scatter 0.016720 0.000639\n", - "570 285 absorption 0.000116 0.000008\n", - "571 285 scatter 0.017764 0.000639\n", - "572 286 absorption 0.000111 0.000014\n", - "573 286 scatter 0.018101 0.000766\n", - "574 287 absorption 0.000115 0.000012\n", - "575 287 scatter 0.018411 0.000655\n", - "576 288 absorption 0.000138 0.000014\n", - "577 288 scatter 0.019154 0.000763" + "558 279 absorption 0.000093 0.000013\n", + "559 279 scatter 0.013504 0.000805\n", + "560 280 absorption 0.000084 0.000010\n", + "561 280 scatter 0.014215 0.000612\n", + "562 281 absorption 0.000091 0.000008\n", + "563 281 scatter 0.014545 0.000590\n", + "564 282 absorption 0.000112 0.000012\n", + "565 282 scatter 0.016321 0.000729\n", + "566 283 absorption 0.000092 0.000007\n", + "567 283 scatter 0.016163 0.000661\n", + "568 284 absorption 0.000104 0.000011\n", + "569 284 scatter 0.017384 0.000599\n", + "570 285 absorption 0.000111 0.000011\n", + "571 285 scatter 0.018015 0.000774\n", + "572 286 absorption 0.000125 0.000012\n", + "573 286 scatter 0.018294 0.000828\n", + "574 287 absorption 0.000119 0.000013\n", + "575 287 scatter 0.017483 0.000757\n", + "576 288 absorption 0.000113 0.000014\n", + "577 288 scatter 0.018248 0.000782" ] }, "execution_count": 33, @@ -1747,7 +1703,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", " \n", " \n", @@ -1787,21 +1743,6 @@ " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", @@ -1816,8 +1757,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1831,8 +1772,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1846,8 +1787,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1861,8 +1802,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1876,8 +1817,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1891,8 +1832,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1906,8 +1847,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1921,8 +1862,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1936,8 +1877,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1951,8 +1892,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1966,7 +1907,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1981,8 +1922,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -1996,8 +1937,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -2011,8 +1952,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -2026,8 +1967,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -2041,8 +1982,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -2056,8 +1997,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -2071,8 +2012,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -2086,8 +2027,8 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -2101,63 +2042,61 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", "
bin
100000absorption0.0001220.0000100.0001230.000012
1100000scatter0.0185960.0008710.0178050.000808
2100001absorption0.0002060.0000140.0002170.000020
3100001scatter0.0297330.0009530.0288670.001263
4100002absorption0.0002800.0000180.0003180.000020
5100002scatter0.0384940.0013830.0404930.001269
6100003absorption0.0003840.0000260.0003860.000018
7100003scatter0.0488390.0011810.0485760.001337
8100004absorption0.0004570.0000230.0005010.000026
9100004scatter0.0580610.0014660.0570630.001715
10100005absorption0.0004940.0004840.000026
100005scatter0.0658740.0015750.0608220.001581
12100006absorption0.0004900.0000320.0005320.000039
13100006scatter0.0724200.0019880.0691010.002249
14100007absorption0.0006050.0000420.0005770.000039
15100007scatter0.0788020.0022280.0767220.002335
16100008absorption0.0006270.0000370.0006490.000039
17100008scatter0.0836840.0019360.0815640.001610
18100009absorption0.0007110.0000400.0006800.000032
19100009scatter0.0889890.0016890.0877150.001959
\n", "
" ], "text/plain": [ - " level 1 level 2 level 3 distribcell score \\\n", - " cell univ lat cell univ \n", - " id id id x y z id id \n", - "bin \n", - "0 10003 0 10001 0 0 0 10002 10000 0 absorption \n", - "1 10003 0 10001 0 0 0 10002 10000 0 scatter \n", - "2 10003 0 10001 1 0 0 10002 10000 1 absorption \n", - "3 10003 0 10001 1 0 0 10002 10000 1 scatter \n", - "4 10003 0 10001 2 0 0 10002 10000 2 absorption \n", - "5 10003 0 10001 2 0 0 10002 10000 2 scatter \n", - "6 10003 0 10001 3 0 0 10002 10000 3 absorption \n", - "7 10003 0 10001 3 0 0 10002 10000 3 scatter \n", - "8 10003 0 10001 4 0 0 10002 10000 4 absorption \n", - "9 10003 0 10001 4 0 0 10002 10000 4 scatter \n", - "10 10003 0 10001 5 0 0 10002 10000 5 absorption \n", - "11 10003 0 10001 5 0 0 10002 10000 5 scatter \n", - "12 10003 0 10001 6 0 0 10002 10000 6 absorption \n", - "13 10003 0 10001 6 0 0 10002 10000 6 scatter \n", - "14 10003 0 10001 7 0 0 10002 10000 7 absorption \n", - "15 10003 0 10001 7 0 0 10002 10000 7 scatter \n", - "16 10003 0 10001 8 0 0 10002 10000 8 absorption \n", - "17 10003 0 10001 8 0 0 10002 10000 8 scatter \n", - "18 10003 0 10001 9 0 0 10002 10000 9 absorption \n", - "19 10003 0 10001 9 0 0 10002 10000 9 scatter \n", + " level 1 level 2 level 3 distribcell score \\\n", + " cell univ lat cell univ \n", + " id id id x y z id id \n", + "0 10003 0 10001 0 0 0 10002 10000 0 absorption \n", + "1 10003 0 10001 0 0 0 10002 10000 0 scatter \n", + "2 10003 0 10001 1 0 0 10002 10000 1 absorption \n", + "3 10003 0 10001 1 0 0 10002 10000 1 scatter \n", + "4 10003 0 10001 2 0 0 10002 10000 2 absorption \n", + "5 10003 0 10001 2 0 0 10002 10000 2 scatter \n", + "6 10003 0 10001 3 0 0 10002 10000 3 absorption \n", + "7 10003 0 10001 3 0 0 10002 10000 3 scatter \n", + "8 10003 0 10001 4 0 0 10002 10000 4 absorption \n", + "9 10003 0 10001 4 0 0 10002 10000 4 scatter \n", + "10 10003 0 10001 5 0 0 10002 10000 5 absorption \n", + "11 10003 0 10001 5 0 0 10002 10000 5 scatter \n", + "12 10003 0 10001 6 0 0 10002 10000 6 absorption \n", + "13 10003 0 10001 6 0 0 10002 10000 6 scatter \n", + "14 10003 0 10001 7 0 0 10002 10000 7 absorption \n", + "15 10003 0 10001 7 0 0 10002 10000 7 scatter \n", + "16 10003 0 10001 8 0 0 10002 10000 8 absorption \n", + "17 10003 0 10001 8 0 0 10002 10000 8 scatter \n", + "18 10003 0 10001 9 0 0 10002 10000 9 absorption \n", + "19 10003 0 10001 9 0 0 10002 10000 9 scatter \n", "\n", - " mean std. dev. \n", - " \n", - " \n", - "bin \n", - "0 0.000122 0.000010 \n", - "1 0.018596 0.000871 \n", - "2 0.000206 0.000014 \n", - "3 0.029733 0.000953 \n", - "4 0.000280 0.000018 \n", - "5 0.038494 0.001383 \n", - "6 0.000384 0.000026 \n", - "7 0.048839 0.001181 \n", - "8 0.000457 0.000023 \n", - "9 0.058061 0.001466 \n", - "10 0.000494 0.000026 \n", - "11 0.065874 0.001575 \n", - "12 0.000490 0.000032 \n", - "13 0.072420 0.001988 \n", - "14 0.000605 0.000042 \n", - "15 0.078802 0.002228 \n", - "16 0.000627 0.000037 \n", - "17 0.083684 0.001936 \n", - "18 0.000711 0.000040 \n", - "19 0.088989 0.001689 " + " mean std. dev. \n", + " \n", + " \n", + "0 0.000123 0.000012 \n", + "1 0.017805 0.000808 \n", + "2 0.000217 0.000020 \n", + "3 0.028867 0.001263 \n", + "4 0.000318 0.000020 \n", + "5 0.040493 0.001269 \n", + "6 0.000386 0.000018 \n", + "7 0.048576 0.001337 \n", + "8 0.000501 0.000026 \n", + "9 0.057063 0.001715 \n", + "10 0.000484 0.000026 \n", + "11 0.060822 0.001581 \n", + "12 0.000532 0.000039 \n", + "13 0.069101 0.002249 \n", + "14 0.000577 0.000039 \n", + "15 0.076722 0.002335 \n", + "16 0.000649 0.000039 \n", + "17 0.081564 0.001610 \n", + "18 0.000680 0.000032 \n", + "19 0.087715 0.001959 " ] }, "execution_count": 34, @@ -2183,7 +2122,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", " \n", " \n", @@ -2210,38 +2149,38 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", "
mean0.0004140.0000250.0004180.000022
std0.0002410.0000100.0002390.000009
min0.0000130.0000030.0000180.000004
25%0.0002040.0000170.0002020.000015
50%0.0003870.0000240.0004020.000021
75%0.0005940.0000310.0006150.000027
max0.0009190.0000600.0008920.000044
\n", @@ -2252,13 +2191,13 @@ " \n", " \n", "count 289.000000 289.000000\n", - "mean 0.000414 0.000025\n", - "std 0.000241 0.000010\n", - "min 0.000013 0.000003\n", - "25% 0.000204 0.000017\n", - "50% 0.000387 0.000024\n", - "75% 0.000594 0.000031\n", - "max 0.000919 0.000060" + "mean 0.000418 0.000022\n", + "std 0.000239 0.000009\n", + "min 0.000018 0.000004\n", + "25% 0.000202 0.000015\n", + "50% 0.000402 0.000021\n", + "75% 0.000615 0.000027\n", + "max 0.000892 0.000044" ] }, "execution_count": 35, @@ -2293,7 +2232,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Mann-Whitney Test p-value: 0.378626583393\n" + "Mann-Whitney Test p-value: 0.414863173548\n" ] } ], @@ -2331,7 +2270,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Mann-Whitney Test p-value: 7.18782749267e-43\n" + "Mann-Whitney Test p-value: 3.28554363741e-42\n" ] } ], @@ -2377,7 +2316,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 38, @@ -2386,9 +2325,9 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\nTkSuQmCC\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -2415,7 +2354,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 39, @@ -2424,9 +2363,9 @@ }, { "data": { - "image/png": "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\ngXbt2u1+pgym9cts2bx+2bxuiaJRUkVkp8Lx9rJOnz59oo6QEInasVyWioKIlCtZHzxSNcks2Oo+\nEhGRGBUFERGJUVEQEZEYFQUREYlRURCRjFJQUMD48eNjj0eOHEmTJk344IMPyMnJIS8vj7y8PJo2\nbcqZZ57JuHHjdmhfr1692Hx5eXlcf/31qV6NtKWiICIZxcxiR98MGzaMa6+9ljfffJNWrVoBUFxc\nzJo1a5gyZQonn3wy55xzDsOGDduu/euvv86aNWtit4ceeiiSdUlHKgoiknHcnUcffZSBAwcyZswY\njjnmmB3m2Weffbj++usZNGgQt9xySwQpM5OKgohknCFDhnD77bfzzjvv0KlTp13Oe84557B06VJm\nzJgRm6bzL8qnk9dEpFLsjsScQOW3V+wD2t0ZN24c3bp1o3379rudv3nz5gCsXLky1v7ss8+mRo3/\nfPzdd999XH755RXKka1UFESkUir6YZ4oZsY///lP7rrrLq644goef/zxXc7/ww8/ANCkSZNY+1df\nfZVu3bolPWsmUveRiGSc/Px8xo8fz4cffsg111yzy3lffvll8vPzOfjgg1OULrOpKIhIRmrWrBnj\nx4/nrbfe4sYbb4xN37a/YMmSJTz88MPceeed3HPPPdu11T6F8qn7SEQyVsuWLXnnnXc44YQTWLx4\nMQCNGjXC3alfvz5HH300L774Iqeccsp27c4880xyc3Njj0855RRGjRqV0uzpSkVBRDLK3Llzt3tc\nUFDA/PnzASgsLKxwe9meuo9ERCRGRUFERGJUFEREJEZFQUREYlQUREQkRkVBRERiVBRERCRGRUFE\nRGJUFEQkq7Rv354PPvgg6hgZS0VBROKy7YpnybzFo+zlOAGeeuopfvGLXwAwbdo0TjjhhF0uY968\neeTk5FBSUlK5X0YW0zAXIlIByRxILr6iUJECsjvJGhhv69at242tlEm0pSAiWaWgoIB33nkHgEmT\nJnHUUUfRsGFDmjZtysCBAwFiWxKNGjUiLy+PTz/9FHfn7rvvpqCggPz8fC6++GJWr14dW+7w4cNp\n3bo1e+21V2y+ba8zaNAgzjvvPPr27UvDhg0ZNmwYn332GcceeyyNGzemefPmXHfddWzevDm2vJyc\nHB555BEOPPBAGjRowG233cbs2bM59thjadSoET179txu/lRRURCRjLOrb/iltyJuuOEGBgwYQHFx\n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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAEZCAYAAAB4hzlwAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xl8VNX9//HXJIQlkEAi+xpAZREQkU1USGmlikpFwaJW\nbd14KKg/lGrVfiXVWrVqbV1ArKjgAipoFRdQAlGqCKLsFJBABCEBJBASQJZkfn+cm8lknyRz58wk\n7+fjMY/MXedzk8z93HPOPeeCiIiIiIiIiIiIiIiIiIiIiIiIiIiIiLjkPuDftoMQEanNzgO+Ag4C\n+4H/Av1ruM/fA0tLzHsVeLiG+3VTAZAH5AK7gGeAegFumwK85k5YUtcF+k8oEgzxwIfAeOBtoAFw\nPnDMZlDliAbyXf6MPsA2oCvwObAJmOryZ4qIhI3+wIFK1rkZ2AgcAjYAZznz/wRs9Zt/mTO/B3AU\nOIm56j7g7OM4JtnkAu8767YF5gF7MSfj2/0+NwWYi7kCzwFupPgVeRLm6v464AdgH3C/3/aNgJlA\nthP/PcDOCo6zAOjiN/0W8Jzf9L+AHU4sKzElLIALneM67hzbKmd+U2AGsBv4EVNKinKWnYpJOged\nuOdUEJeISMjEAT9hqnYuBBJKLB+LOaGd7Ux3BTo678cArZ33V2KqXlo509dTuvroFeAhv+ko4Fvg\nz5gScmcgHRjhLE/BnGhHOdMNgSmUTgrTMSWcPsDPQDdn+WPAEszJuR2wFnNSL0+Bc3wA3TEn8+v8\nll+D+f1EAXcBmUB9Z9kUYFaJ/b0HTMMkpxbAcuAWZ9lsTPsIzj6GVBCXiEhIdcecsHcCJzBX8S2d\nZQspfvVekVUUncB/T9lJwb9NYRDmCt/ffcDLzvsUIK3E8hRKJ4W2fsuXYxIUmARzgd+yG6m8pJCD\nSW4FmDaFimQDvcuIC0xy/BmTyApdBSx23s/EJLN2lXyGiK94KRIqm4A/AB2AXpiT7D+dZe0xJ9ey\nXIdJBAecVy/glCp8bifnsw74ve6jKCGBKaVUJsvv/RGgifO+LcWTQCD7OsvZ/reY4+vkt2wyphrq\noBNrU6B5OfvpBMRgShOFx/YCpsQApirLA6wA1mN+/yJlUkOz2LQZcxVbWM2xE1P/XVIn4EVgOLAM\n8GIShMdZ7i1jm5LzdgDbgdPLicVbxjZl7bc8mZhEt8mZ7lCFbd8BfoMpAfwB0/j+R8zxbnDWyab8\n492JaWc4BVPqKGkPRb/jc4FFmDaGbVWIUeoIlRQklLph6scLqzE6YKo5ljnTL2GukPthToCnYtoU\nGmNOhD9h/mf/gCkpFNqDKWXElJjn35C7AtMwew+m3j3a2Ufh7bAeSitrXnnexpQ8mjnHN5GqJZXH\nML+L9pi2l5OY460PPIi5c6tQFqY6qzC+TOBT4B/OtlGY9oqhzvKxzn7BlDy8lJ08RJQUJKRyMXX7\nyzF16cswDbJ3O8vnAo8Ab2LuMnoX09i6EXjKWT8LczL/r99+UzFX1FmYO4vA3InTE1OV8i7mJHgJ\n0BdzhbwPU/ooPNmWV1Lwlpguz0OYKqPtmBP0O5iG6/KU3Nd6TBvAXcAC57UFyMDcXeXfaP2O83M/\n5s4kMNVP9TG/q2xnncKG+f7A1xTdiXWHs1+RkOqAuRtjA+Yf/g5nfgrmy7PKeV1oIzgRl92K+f8X\nEUdrzFUZmMa0zZh7yqdgroZEapPWmPr6KEw12fcUXQiJRAw3G5qzKLpTIw/4H0V1yVWpqxWJBPUx\nd/x0xtTbz0a9k0XKlYS5R7wJpqSQAazB1Ps2sxaViIiEXBNMY1jhsAQtMSUFD/BXTGIQEZEw4HY1\nTgxmALRPKOqg5C8JmE9RT00Aunbt6k1PL68Pk4iIlCOdsvv6BMzNW1I9mFLARoonhDZ+70cD60pu\nmJ6ejtfrrbWvKVOmWI9Bx6fjq4vHV5uPzev1QtF4WtXmZkPzucDvMPehF47keD+mg05fzH3a2zHD\nKIuISBhwMyn8l7JLIp+4+JkiIlID6tFsQXJysu0QXKXji2y1+fhq87EFS7j2F/A69WMiIhIgj8cD\nNTyva5RUESlTYmIiBw5U9qA8sSEhIYHs7GxX9q2SgoiUyePxoO9heCrvbxOMkoLaFERExEdJQURE\nfJQURETER0lBRER8lBREJKIkJSWRmprqm54zZw6JiYl88cUXREVFERcXR1xcHK1bt+bSSy9l0aJF\npbaPjY31rRcXF8cdd+jRF4WUFEQkong8nsK7bJg5cyYTJ07k448/pmPHjgDk5OSQm5vL2rVrueCC\nCxg9ejQzZ84stv2HH35Ibm6u7/XMM89YOZZwpKQgIhHH6/Uyffp0Jk+ezKeffsrgwYNLrdOyZUvu\nuOMOUlJSuPfeey1EGZmUFEQk4kydOpUpU6awePFi+vXrV+G6o0ePZu/evWzevNk3T/0vyqcezSJS\nLZ6/BKfvq3dK1U7QXq+XRYsWMXz4cHr16lXp+m3btgXw9QD2er1cdtll1KtXdPp78sknufHGG6sU\nR22lpCBhKz4+kdzc4sMsxMUlcOiQO937pWqqejIPFo/HwwsvvMDDDz/MTTfdxIwZFT+8cdeuXYAZ\ntqNw+/fff5/hw4e7HmskUvWRhC2TELzFXiWThNRNrVq1IjU1laVLl3LbbbdVuO57771Hq1at6Nat\nW4iii2xKCiISkdq0aUNqaioLFizgrrvu8s0vbC/Ys2cPzz33HA899BCPPvposW3VplA+VR+JSMTq\n0KEDixcvZujQoWRlZQHQrFkzvF4vjRs3ZsCAAcydO5cRI0YU2+7SSy8lOjraNz1ixAjmzZsX0tjD\nlUZJlbBl7kUv+X+gkTtDRaOkhi+NkioiIiGhpCAiIj5KCiIi4qOkICIiPkoKIiLio6QgIiI+Sgoi\nIuKjpCAiIj5KCiJSq/Tq1YsvvvjCdhgRS0lBRAISH5/oe+qZG6/4+MSA4ij5OE6AV199lfPPPx+A\n9evXM3To0Ar3kZGRQVRUFAUFBdX7ZdRiGvtIRAJSNGqtW/sPbHQG/8dx1pRbw3jk5+cXG1spkqik\nICK1SlJSEosXLwZgxYoV9O/fn6ZNm9K6dWsmT54M4CtJNGvWjLi4OJYvX47X6+Wvf/0rSUlJtGrV\niuuvv55Dhw759jtr1iw6depE8+bNfesVfk5KSgpjxozh2muvpWnTpsycOZNvvvmGc845h4SEBNq2\nbcvtt9/OiRMnfPuLiopi2rRpnHbaacTHx/Pggw+Snp7OOeecQ7NmzRg3blyx9UNFSUFEIk5FV/j+\npYg777yTSZMmkZOTw7Zt2xg7diwAS5cuBSAnJ4fc3FwGDRrEK6+8wsyZM0lLS2Pbtm3k5eUxceJE\nADZu3MiECROYPXs2mZmZ5OTksHv37mKf+8EHHzB27FhycnK4+uqriY6O5l//+hf79+9n2bJlpKam\nMnXq1GLbfPrpp6xatYqvv/6axx9/nJtvvpnZs2ezY8cO1q1bx+zZs4Py+6oKJQURiSiFj9NMSEjw\nvSZMmFBmlVL9+vX5/vvv+emnn4iNjWXQoEG+fZT0xhtvcPfdd5OUlETjxo159NFHmTNnDvn5+cyd\nO5dRo0YxZMgQYmJieOihh0p93pAhQxg1ahQADRs2pF+/fgwcOJCoqCg6derELbfcwueff15sm3vu\nuYcmTZrQs2dPevfuzUUXXURSUhLx8fFcdNFFrFq1Kli/toApKYhIRCl8nOaBAwd8r6lTp5Z5op8x\nYwZbtmyhR48eDBw4kI8++qjc/WZmZtKpUyffdMeOHTl58iR79uwhMzOT9u3b+5Y1atSIU045pdj2\n/ssBtmzZwiWXXEKbNm1o2rQpDzzwAPv37y+2TqtWrYrts+R0Xl5eJb+N4FNSEJGIV1510qmnnsqb\nb77Jvn37uPfeexkzZgxHjx4ts1TRtm1bMjIyfNM7duygXr16tG7dmjZt2vDjjz/6lh09erTUCb7k\nPm+99VZ69uzJ1q1bycnJ4ZFHHomIu52UFESk1nr99dfZt28fAE2bNsXj8RAVFUWLFi2IiooiPT3d\nt+5VV13F008/TUZGBnl5edx///2MGzeOqKgorrjiCubPn8+yZcs4fvw4KSkpld65lJeXR1xcHLGx\nsWzatIlp06ZVGq//Pm094EhJQUQCEheXgHmolzsvs//qKe821YULF9KrVy/i4uKYNGkSc+bMoUGD\nBsTGxvLAAw9w7rnnkpCQwIoVK7jhhhu49tprGTp0KF26dCE2NpZnn30WgDPOOINnn32WcePG0bZt\nW+Li4mjZsiUNGjQo9/OffPJJ3nzzTeLj47nlllsYN25csXXKirfk8mDdelsVbn5iB2AW0BJzc/OL\nwDNAIvAW0AnIAK4EDpbYVo/jFD2O0zI9jrN8eXl5JCQksHXr1mLtEKESqY/jPAFMAs4ABgMTgB7A\nn4DPgNOBVGdaRCSszZ8/nyNHjnD48GEmT55Mnz59rCQEt7mZFLKA1c77POB/QDtgFDDTmT8TuMzF\nGEREguKDDz6gXbt2tGvXjvT0dObMmWM7JFeEqsIqCfgc6AXsAAorDz1Att90IVUfiaqPLFP1Ufhy\ns/ooFGMfNQHmAXcCuSWWeSlnMJWUlBTf++TkZJKTk92JTkQkQqWlpZGWlhbUfbpdUogBPgQ+Af7p\nzNsEJGOql9oAS4DuJbZTSUFUUrBMJYXwFakNzR5gBrCRooQA8AFwvfP+euA/LsYgIiJV4GZJ4Tzg\nC2AtRZd79wErgLeBjuiWVKmASgp2JSYmcuDAAdthSBkSEhLIzs4uNT8YJYXQ94wIjJKCKCmIVFG4\nVx+JiEiEUVIQEREfJQUREfFRUhARER8lBRER8VFSEBERHyUFERHxUVIQEREfJQUREfFRUhARER8l\nBRER8VFSEBERHyUFERHxUVIQEREfJQUREfFRUhARER8lBRER8VFSEBERHyUFERHxUVIQEREfJQUR\nEfFRUhARER8lBYl48fGJeDwe3ys+PtF2SCIRy2M7gHJ4vV6v7RjEMo/HA5T8P/BQ8n+j9Hql1xGp\nC8x3oWbndZUURETER0lBRER8lBRERMRHSUFERHyUFERExEdJQUREfJQURETER0lBpAIlO8apc5zU\nduq8JmErHDqvBRqDSDhQ5zUREQkqJQUREfFxOym8DOwB1vnNSwF+BFY5rwtdjkFERALkdlJ4hdIn\nfS/wD+As57XA5RhERCRAbieFpcCBMuaHawO3iEidZqtN4XZgDTADaGYpBhERKcFGUpgGdAb6ApnA\nUxZiEBGRMtSz8Jl7/d6/BMwva6WUlBTf++TkZJKTk10NSuqe+PhEcnOL127GxSVw6FC2pYhEqiYt\nLY20tLSg7jMUdftJmBN/b2e6DaaEADAJGABcXWIbdV4T1zuvBbJ/dV6TSBKMzmtulxRmA8OA5sBO\nYAqQjKk68gLbgfEuxyAiIgEK17uAVFIQlRREqkjDXIiISFAFkhTeBS4OcF0REYlggZzopwHXAFuB\nx4BurkYkIiLWBJIUPsPcHdQPyABSga+APwAxrkUmIiIhF2iV0CnA74GbgO+AZ4CzMQlDRERqiUCS\nwnvAf4FY4FJgFDAHmAjEuReaSPCU9QQ1t/evJ7RJJArkmzES+LjEvAbAseCH46NbUiWot6SWt69g\n3ZKqW1clHITqltRHypi3rCYfKiIi4amiHs1tgLZAI0wjc+GlUDymKklERGqZipLCr4HrgXYUH8k0\nF7jfzaBERMSOQOqergDmuR1ICWpTELUpiFSR2wPiXQu8hhnl9C7/z6XokZoiIlKLVJQUCtsN4ih5\nGVb6kkhERGoBjZIqYUvVRyJVE6pbUv+OueMoBjPExU+YqiWRoHG7c1m4crvTmzrVSVUF8s1bA5wJ\njAYuwbQvLAX6uBiXSgp1THWv5MveNnJKCm6XMFSCqVtCVVIobHe4BJgL5KA2BRGRWimQx3HOBzYB\nPwO3Ai2d9yIiUssEWsw4BTgI5AONMXckZbkVFKo+qnNUfVS17QKl6qO6xe1+Cv66A50oen6CF5hV\nkw8WEZHwE0hSeB3oAqzGlBQKKSmIiNQygSSFs4GeqHFZRKTWC+Tuo/WYEVNFRKSWC6Sk0ALYCKyg\n6ME6XswT2ERCrF6d6djmntK/w7i4BA4dyrYUj4STQJJCivPTS1GrtqqSxJKTlH0XkQSu9O8wN1e/\nQzECSQppmJFSTwUWYQbKC/SuJRERiSCBtCncArwDTHem2wPvuRaRiIhYE0hSmACcBxxyprdgejWL\niEgtE0g10DGKGpgLt1GbgtjlyYfTP4Iz3jL3xtXvAIdbwt7ekA5HThwhNkaPEhepqkBKCp8DD2Da\nEi7AVCXNdzMokQq12AA3DYahD8MPw8wwjS//Fz6aBj8Ohj7Q4ekO3LXwLrLy3ByNRaT2CeSWg2jg\nRmCEM70QeAl3Swsa+6iOCXhsos4eGNMCUh+B725y1ik99tGOgzt4atlTzFozi/Fnj+exix+D4xr7\nqHD/Gg+pdgrG2EeBblzYhrC3Jh9WBUoKdUxAJ6+238A1A+HtNFNCKG89vxPczpydPLD4AV5b+hos\nfAc2XkHRv72SghufKfa4nRQ8wBRgIqa0AGbso2eBh1BJQYKo0pNX470wvh98tAs2V3aSK+OkneSB\ni8+AQ+3g4+cg+7Qytiu9bbCTQnx8Irm5B0qsV93tYoATvqmyOqAFnhRiMP0XiqhDW+Rx+yE7k4Bz\ngQFAgvMa6MybVJMPFakaL1wyHtb+DjZXcxc/AC+sgvQRcNM5kDzFSm8bc2L3+r2qu50XkxCKpksn\njaoo7NAWrP1JpKooKVwHXA1s95u3DbjGWSYSGj3eg1O2wJK/1Gw/BTGw7G54YTW03AC3AacuCEqI\nIrVFRUmhHrCvjPn7UI9mCZXo4/Cre2Hh05DfIDj7PNQe3p4LHwMjJ8DYsRC/Mzj7FolwFSWFE9Vc\n5u9lYA+wzm9eIvAZphPcp0CzAPclddHZ0+FAF1PtE2xbganrYV9PuPVM+PVd5rmCInVYRUmhD5Bb\nzqt3gPt/BbiwxLw/YZLC6UCqMy1SWjRw3mOQ+qh7n3GyEaT9BZ7fAFEnYALcvfButh3Y5t5nioSx\nipJCNOZZzGW9Aq0+WgqUbK0aBcx03s8ELgs0WKljemOu4jP7uf9ZeW3gk2dhOkR5ohj474FcOvtS\n83ipmCPuf75ImAikR3OwtcJUKeH8bGUhBgl7XhgCfPXH0H5sDjwx4gl2TNrB6O6jzXMH724LY8bB\nmTMhbldo4xEJsVAMop6EGRajsMrpAOb21kLZmHYGf+qnUMeUup8+aQmMHA5TCyj+bxrIffeB9yMI\nqJ9C4z3Q7X3o+hl0ToXD2UwYOYFfJP2CoZ2G0qJxixr0Z6hZP4hgHrc6tEW+YPRTsHEX0R6gNZCF\nGcqszF7SKSkpvvfJyckkJyeHIDQJG/1mwHdQvf/vID+d7XBL+O5m8/LkQ5sGPL/qeZ5Peh46AjnA\nRUDGPPhhKBxpUcM4Qr2dRKq0tDTS0tKCuk8bJYW/A/uBxzGNzM0o3diskkIdU+yKtuFB+H9J8EwO\nHKnOVW7wro4rvdKOOgmtV0HSQEgaCR3/CzkdISMZtj8H6YfhRGzZ2wYhVvf2ZebpexhZQjn2UXXN\nBoYBzTElhAeB94G3MddYGcCVwMES2ykp1DHFTr79p0HnxfDOXGycHKuUFErO8yWJNDj1HmjbFL4f\nCevHwdZfQ37DoMaqpCD+IiEpVJeSQh1T7OR70yBIS4GtI4m4pFByXuMs6DkPes2BUzbD6r3w7VY4\n0DUosSopiD8lBak1fCffpj/A+LPhyUwoqE/EJwX/eYnfw9mnQ9/mkHUWfHMrbLkcCpQUJDjcHhBP\nJPR6zoNNl5lximqb7NNMt82nd8Ka6+DcJ+BO4Py/mVFgRcKAkoKEl57vwIaxtqNw18mGZsTXGV+Z\nVreEbTCxG1z+O2i/zHZ0UscpKUj4iN9pRkPdPtx2JKGTBXzwEjyTDplnweXXwnjgrBkQc9h2dFIH\nqU1BrCjzoTGD/gmt18D7LzszbNStl37YTLDr6SuM1VMAXaNhwCWQ9Dls/wVsGg3b/gCH1KYgFYvU\nzmsifg+NKeSBHu/Cl/fYCslR+LCZQiG+bvJGmdFbt86Hhgfg9I+g+3/gAuBEJ9h5LuzpAz91h5+A\n7BO1s/1FrFFJQawodVdPQw9MagJP7DUjl5q1sH8XTvCvvqu9/1M2QYdl0GIjNN8EzedDfEM42NkM\nHLhvHuz+j+k4d6xpUGLV9zCyqKQgtUcXYMf5fglBStnfzbx8PBB90LTDtNgILefBgKmmwXrnEPj2\nFthE6XO9SAVUUhArSpUUfuOBzGdhxUT/tbB/dR9GJYVA91XvqHmE6cBnof7X8MliyPhFtfav72Fk\nUec1iVjFkoKnAO6Ohhnp5ilrRWsRNifaoOwr1LF6oXsUjGwH666G1L9BQb0q7V/fw8iizmtSO7Re\nBT9TIiFIzXlM9dELq83veOxYU4oQqYCSgth32sfwve0garEjzeHNjyC/Plw5Vt96qZD+PcQ+JQX3\n5deHd183o7heDGp9lvIoKYhdDQ5Bq3Www3YgdUBBDLw9FzoAfWfajkbClJKC2NVxKewaWLoTsbjj\neBOYC1zwRzOUt0gJSgpiV+clZigHCZ29wOcPwqibzZ1fIn6UFMSuzovr1gB44eKb2yD6GJz1cuXr\nSp2ipCD2NMqGxK2we4DtSOoebzR8OB2GP2DadUQcSgpiT6cvYOc55s4YCb2svrD1IhjyhO1IJIwo\nKYg9qjqyb8lDZrykJrYDkXChpCD2JC0pMSaPhFxOR1hzPZxnOxAJF0oKYkcs0HQnZPazHYl8NRnO\nBGJ/sh2JhAElBbEjCdhxnjNAm1iV2xY2YkZVlTpPSUHs6IzaE8LJl5i2hfp5tiMRy5QUxI7OqNNa\nOMnGPLGt7yu2IxHLlBQk5Hbn7obGwJ4zbYci/lZMhAHT0GB5dZuSgoTcku1LIAPzkHoJHz8MBa8H\nkj63HYlYpG+lhNySjCWw3XYUUprHDH8xYKrtQMQiJQUJuSUZTklBws/aa6HLZxC323YkYomSgoTU\nDwd/IO94nhmpU8LPsXhYPw7OmmE7ErFESUFCaknGEpKTkm2HIRVZdSP0fdV2FGKJkoKE1JKMJfwi\nSbeihrXdZ8PJRtDRdiBig5KChIzX62Xx9sUM76xOa+HNA6t/D31txyE2KClIyKQfSKfAW8BpiafZ\nDkUqs/Ya6AGHjx+2HYmEmJKChMyS7abqyOPx2A5FKpPXBnbCu/9713YkEmJKChIyizMWqz0hkqyG\nV9e8ajsKCTGbSSEDWAusAlZYjENCwOv1smT7En7Z5Ze2Q5FAbYY1WWv44eAPtiORELKZFLxAMnAW\nMNBiHBICG/dtJDYmlqRmSbZDkUDlw9ieY3l97eu2I5EQsl19pMrlOkJ3HUWm6868jtfWvobXq0Hy\n6gqbTzjxAouAfGA68G+LsYhLVq9ezebNm3ntx9cYFDeIt956i/j4eNthSYAGtx9MvjeflbtXMqDd\nANvhSAjYTArnAplAC+AzYBOwtHBhSkqKb8Xk5GSSk5NDG50Exfjxk1m7/gQ/376GjU+2ZubhveTl\nzbUdlgSkHlFRUTAMBn4yED6JAU4UWyMuLoFDh7LthCekpaWRlpYW1H2GS/XNFCAPeMqZ9qq4Wjuc\nffYv+S5zDFz+LDy/EYDo6Ibk5x+j+Lj9HkqP41/deeG6rwiNNSEdbjoHntoHBaXX0Xc1fDi3e9fo\nvG6rTSEWiHPeNwZGAOssxSJu67xKj96MZAe6wv7T4FTbgUgo2EoKrTBVRauB5cCHwKeWYhG3dV6t\npBDp1l4LelBenWCrTWE7GlmlTijwFEDHDfDuMNuhSE1suBJ+dSs0PAg/N7MdjbjI9i2pUssdSTgE\n2W3h6Cm2Q5GaOJoI24CeukmgtlNSEFflNj8A28+yHYYEw1qgz2u2oxCXKSmIqw613A9b+9sOQ4Lh\ne6DlBmiWYTsScZGSgrgm+2g2R+MOw47etkORYMjHtC30fsN2JOIiJQVxzaJti2iS3QxO1rcdigTL\nmuvgzFmU7tMgtYWSgrhmwdYFxO9NtB2GBNOPg8DjhXbf2I5EXKKkIK7wer0sTF9I/F7ddVS7eGDt\n79TgXIspKYgr1u9dT8N6DWlwuJHtUCTY1v4Oer0FUScqX1cijpKCuGLB1gVc2PVCPGEzvJYEzYEu\nsP90OHWB7UjEBUoK4or5W+Yz8rSRtsMQt6y5Fs5UFVJtpKQgQbf38F7W7lmrR2/WZhuuhK4LoaHt\nQCTYlBQk6D7c8iEjuo6gYT2dMWqtnxNg2wXQ03YgEmxKChJ0/9n0Hy7rfpntMMRtazRyam2kpCBB\nlXc8j7SMNLUn1AVbL4LmkHEww3YkEkRKChJUn6Z/yuD2g2nWUMMr13r59WEDvL72dduRSBApKUhQ\nvb3hbS7vcbntMCRU1sKsNbP0SM5aRElBgib3WC6fbP2EsT3H2g5FQuVHaFCvAanbU21HIkGipCBB\n896m9xjaaSinxGpoi7rkjoF38MzyZ2yHIUGipCBB8+a6N7mm9zW2w5AQu6bPNSz7cRnp2em2Q5Eg\nUFKQoMjKy2L5ruWM6jbKdigSYrExsdzQ9wae/+Z526FIECgpSFC8suoVruhxBbExsbZDEQtuG3Ab\nM9fMJPdYru1QpIaUFKTG8gvyefG7F7m1/622QxFLOjXrxIiuI5i2cprtUKSGlBSkxhamL6R5bHPO\nbnu27VDEovvPu59/LPsHR04csR2K1ICSgtTYtJXTVEoQerfqzZAOQ3jx2xdthyI1oKQgNbJx30ZW\n7FrBuF7jbIciYeDPQ//ME189odJCBFNSkBp5/MvHuWPgHWpgFgD6tenHkA5DeHrZ07ZDkWpSUpBq\nyziYwYdbPmTCwAm2Q5Ew8tgvH+MfX/+DrLws26FINSgpSLU9uORBbut/mwa/k2K6Jnblhr43cH/q\n/bZDkWpQUpBq+S7zOz7b9hn3nHuP7VAkDP3fsP9j0bZFpG7TmEiRRklBqqzAW8CdC+5kyrApxDWI\nsx2OhKGIp6fZAAAHmUlEQVT4BvG8cMkL3Dz/Zg4fP2w7HKkCJQWpsqnfTCW/IJ+b+91sOxQJYyNP\nG8nQTkOZ+MlEDa0dQZQUpEq27N9CSloKL//mZaKjom2HI2HuuZHPsWLXCl767iXboUiA6tkOQCJH\n7rFcRr81mkeGP0L35t1thyMRoEn9Jrx75buc/8r5dEnowi+7/NJ2SFIJlRQkIMfzjzNu3jiGtB/C\n+P7jbYcjEaRb8268M/Ydrpp3Fct2LrMdjlRCSUEq9fPJn/nt3N9SP7o+Uy+eajsciUDDkoYxa/Qs\nfjPnN3yw+QPb4UgFbCWFC4FNwPfAvZZikADsOrSLYa8Oo350fd4a8xYx0TG2Q5IIdeGpF/LR1R9x\n60e38uCSBzmef9x2SFIGG0khGngOkxh6AlcBPSzEYU1aWprtECp1Iv8E01dOp+/0vlzW7TLmXDGH\n+tH1A9o2Eo5PKpLm2p4HtBvAyptXsjprNf1f7M+CrQtCemeS/jcrZyMpDAS2AhnACWAO8BsLcVgT\nzv+YWXlZ/Ovrf9HtuW7M2TCH1OtSue/8+/B4PAHvI5yPTwKR5ure28S14f1x7/PgsAeZtHASg14a\nxPSV0zlw9ICrnwv63wyEjbuP2gE7/aZ/BAZZiKNOyy/I56cjP7H94HbSs9P5NvNbvtz5JZt/2syo\nbqOYNXoW53U8z3aYUkt5PB7G9BzD6O6jWbB1Aa+sfoXJn02mR/MenN/xfHq17EWPFj1oF9eOlo1b\n0qBeA9sh1xk2kkKd7sXyyfef8Ma6N1jxxgq8zq/C6/XixVvmT6DcZYGuU/gZx/OPk3Msh4M/H+TI\niSMkNEygS0IXOid0pm+rvvz9V39nYLuBNIppFLTjjYmJIjb2AerV+6dvXm7uiaDtXyJbdFQ0F59+\nMReffjHHTh5j+a7lfLnjS5ZkLGHqyqlk5may9/BeYmNiiWsQR6N6jWhYryGNYhrRILoBUZ4oPB4P\nHjzlvi/8CbBl3RZWvrmy2vE+MvwRzmx9ZrAOPywFXicQPIOBFEybAsB9QAHwuN86W4GuoQ1LRCTi\npQOn2g6iquphAk8C6gOrqWMNzSIiUtxFwGZMieA+y7GIiIiIiEg4SQQ+A7YAnwLlPanlZWAPsK6a\n29sSaHzldeRLwdyZtcp5XVhqSzsC6Xj4jLN8DXBWFbe1qSbHlgGsxfytVrgXYo1UdnzdgWXAz8Dd\nVdw2HNTk+DKI/L/fNZj/y7XAl0CfKmwbFv4OFD6h5V7gsXLWOx/z5SuZFALd3pZA4ovGVKElATEU\nb1+ZAtzlbohVVlG8hUYCHzvvBwFfV2Fbm2pybADbMRcC4SqQ42sB9Af+SvGTZrj/7aBmxwe14+93\nDtDUeX8h1fzu2Rz7aBQw03k/E7isnPWWAmX1agl0e1sCia+yjnw27g6rSCAdD/2PezmmhNQ6wG1t\nqu6xtfJbHm5/L3+BHN8+YKWzvKrb2laT4ysU6X+/ZUCO83450L4K2/rYTAqtMNVCOD9bVbCuG9u7\nLZD4yurI185v+nZMcXAG4VE9Vlm8Fa3TNoBtbarJsYHpf7MIc9IJx6cPBXJ8bmwbKjWNsbb9/W6k\nqFRbpW3d7rz2GeYqsaQHSkx7qVmntppuX101Pb6KYp4GPOS8fxh4CvOHtinQ33E4X3GVp6bHdh6w\nG1NF8Rmm/nZpEOIKlpp+v8JdTWM8F8ikdvz9fgHcgDmmqm7relK4oIJlezAn1CygDbC3ivuu6fbB\nUNPj2wV08JvugMnilFj/JWB+9cMMmoriLW+d9s46MQFsa1N1j22X836383Mf8B6myB5OJ5VAjs+N\nbUOlpjFmOj8j/e/XB/g3pk2hsNo9Ev5+gGmILWwF/xMVNxQnUXZDc6Db2xBIfBV15Gvjt94k4E1X\noqyaQDoe+jfGDqaosSvcOy3W5NhigTjnfWPMnR8jXIy1Oqry+0+heENsuP/toGbHV1v+fh0xbQeD\nq7FtWEjE1OGVvGWzLfCR33qzMVdhxzD1Yn+oZPtwEejxldeRbxbm1rI1wH8InzaTsuId77wKPecs\nXwP0q2TbcFLdY+uC+aKtBtYTnscGlR9fa8x3LAdzlbkDaFLBtuGmusdXW/5+LwH7KbqNfUUl24qI\niIiIiIiIiIiIiIiIiIiIiIiIiIhI8BUAr/lN18P0ag2HHuQiIWdzQDyRcHAYOANo6ExfgBkCIBLG\n+xEJOiUFETN0xcXO+6swvegLB75rjHnQ03LgO8zw2WCGDPgC+NZ5nePMTwbSgHeA/wGvuxm4iIgE\nVy7QG3MSb4AZHmAYRdVHf8M80QrMUCWbMWPlNHLWBzgN+MZ5nwwcxAxn4gG+omi0SpGw5/YoqSKR\nYB3myv8qio9LBWZgtEuByc50A8wok1mYcZDOBPIxiaHQCopGTV3t7PvL4IctEnxKCiLGB8CTmFJC\nixLLLsc829ZfCma45Wsxjzv82W/ZMb/3+eh7JhFEbQoixsuYE/2GEvMXAnf4TZ/l/IzHlBYArsMk\nBpGIp6QgdV3hXUa7MNVBhfMK5z+MeUDQWsywyn9x5k8FrsdUD3UD8srYZ3nTIiIiIiIiIiIiIiIi\nIiIiIiIiIiIiIiIiIiIiInXH/wcEsNz5+JgaMgAAAABJRU5ErkJggg==\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -2459,7 +2398,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.8" + "version": "2.7.6" } }, "nbformat": 4, diff --git a/docs/source/pythonapi/examples/post-processing.ipynb b/docs/source/pythonapi/examples/post-processing.ipynb new file mode 100644 index 0000000000..6e2dd94299 --- /dev/null +++ b/docs/source/pythonapi/examples/post-processing.ipynb @@ -0,0 +1,1134 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook demonstrates some basic post-processing tasks that can be performed with the Python API, such as plotting a 2D mesh tally and plotting neutron source sites from an eigenvalue calculation. The problem we will use is a simple reflected pin-cell." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import Image\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "import openmc\n", + "from openmc.statepoint import StatePoint\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate Input Files" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate some Nuclides\n", + "h1 = openmc.Nuclide('H-1')\n", + "b10 = openmc.Nuclide('B-10')\n", + "o16 = openmc.Nuclide('O-16')\n", + "u235 = openmc.Nuclide('U-235')\n", + "u238 = openmc.Nuclide('U-238')\n", + "zr90 = openmc.Nuclide('Zr-90')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the nuclides we defined, we will now create three materials for the fuel, water, and cladding of the fuel pin." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 1.6 enriched fuel\n", + "fuel = openmc.Material(name='1.6% Fuel')\n", + "fuel.set_density('g/cm3', 10.31341)\n", + "fuel.add_nuclide(u235, 3.7503e-4)\n", + "fuel.add_nuclide(u238, 2.2625e-2)\n", + "fuel.add_nuclide(o16, 4.6007e-2)\n", + "\n", + "# borated water\n", + "water = openmc.Material(name='Borated Water')\n", + "water.set_density('g/cm3', 0.740582)\n", + "water.add_nuclide(h1, 4.9457e-2)\n", + "water.add_nuclide(o16, 2.4732e-2)\n", + "water.add_nuclide(b10, 8.0042e-6)\n", + "\n", + "# zircaloy\n", + "zircaloy = openmc.Material(name='Zircaloy')\n", + "zircaloy.set_density('g/cm3', 6.55)\n", + "zircaloy.add_nuclide(zr90, 7.2758e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With our three materials, we can now create a materials file object that can be exported to an actual XML file." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a MaterialsFile, add Materials\n", + "materials_file = openmc.MaterialsFile()\n", + "materials_file.add_material(fuel)\n", + "materials_file.add_material(water)\n", + "materials_file.add_material(zircaloy)\n", + "materials_file.default_xs = '71c'\n", + "\n", + "# Export to \"materials.xml\"\n", + "materials_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's move on to the geometry. Our problem will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces -- in this case two cylinders and six reflective planes." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create cylinders for the fuel and clad\n", + "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218)\n", + "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720)\n", + "\n", + "# Create boundary planes to surround the geometry\n", + "# Use both reflective and vacuum boundaries to make life interesting\n", + "min_x = openmc.XPlane(x0=-0.63, boundary_type='reflective')\n", + "max_x = openmc.XPlane(x0=+0.63, boundary_type='reflective')\n", + "min_y = openmc.YPlane(y0=-0.63, boundary_type='reflective')\n", + "max_y = openmc.YPlane(y0=+0.63, boundary_type='reflective')\n", + "min_z = openmc.ZPlane(z0=-0.63, boundary_type='reflective')\n", + "max_z = openmc.ZPlane(z0=+0.63, boundary_type='reflective')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create a Universe to encapsulate a fuel pin\n", + "pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin')\n", + "\n", + "# Create fuel Cell\n", + "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", + "fuel_cell.fill = fuel\n", + "fuel_cell.region = -fuel_outer_radius\n", + "pin_cell_universe.add_cell(fuel_cell)\n", + "\n", + "# Create a clad Cell\n", + "clad_cell = openmc.Cell(name='1.6% Clad')\n", + "clad_cell.fill = zircaloy\n", + "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", + "pin_cell_universe.add_cell(clad_cell)\n", + "\n", + "# Create a moderator Cell\n", + "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", + "moderator_cell.fill = water\n", + "moderator_cell.region = +clad_outer_radius\n", + "pin_cell_universe.add_cell(moderator_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create root Cell\n", + "root_cell = openmc.Cell(name='root cell')\n", + "root_cell.fill = pin_cell_universe\n", + "\n", + "# Add boundary planes\n", + "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", + "\n", + "# Create root Universe\n", + "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", + "root_universe.add_cell(root_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now must create a geometry that is assigned a root universe, put the geometry into a geometry file, and export it to XML." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create Geometry and set root Universe\n", + "geometry = openmc.Geometry()\n", + "geometry.root_universe = root_universe" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a GeometryFile\n", + "geometry_file = openmc.GeometryFile()\n", + "geometry_file.geometry = geometry\n", + "\n", + "# Export to \"geometry.xml\"\n", + "geometry_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 10 inactive batches and 90 active batches each with 5000 particles." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# OpenMC simulation parameters\n", + "batches = 100\n", + "inactive = 10\n", + "particles = 5000\n", + "\n", + "# Instantiate a SettingsFile\n", + "settings_file = openmc.SettingsFile()\n", + "settings_file.batches = batches\n", + "settings_file.inactive = inactive\n", + "settings_file.particles = particles\n", + "source_bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n", + "settings_file.set_source_space('box', source_bounds)\n", + "\n", + "# Export to \"settings.xml\"\n", + "settings_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us also create a plot file that we can use to verify that our pin cell geometry was created successfully." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate a Plot\n", + "plot = openmc.Plot(plot_id=1)\n", + "plot.filename = 'materials-xy'\n", + "plot.origin = [0, 0, 0]\n", + "plot.width = [1.26, 1.26]\n", + "plot.pixels = [250, 250]\n", + "plot.color = 'mat'\n", + "\n", + "# Instantiate a PlotsFile, add Plot, and export to \"plots.xml\"\n", + "plot_file = openmc.PlotsFile()\n", + "plot_file.add_plot(plot)\n", + "plot_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the plots.xml file, we can now generate and view the plot. OpenMC outputs plots in .ppm format, which can be converted into a compressed format like .png with the convert utility." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Run openmc in plotting mode\n", + "executor = openmc.Executor()\n", + "executor.plot_geometry(output=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAALKSURB\nVGje7dpLcqQwDAbgHHE2YeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmN\nP+HDhw8fPnz48Kf6VH9G+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4\nzPji99z0/AJ4n1lfvJ6fnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6\npA0wfln+ho/fwgYYn19C/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tN\nDbSGz7T0SBEWw4vLXzbQ6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X5\n8wZaxWd1+fMGiuFvir8bvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV\n873hB8UnM3xzANtf8nb4dwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7\nT/ppARBvp48UwJnelT5SACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4/\n/Jve+fhsH6Ctv7n8PTzjvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V\n32/o9+fl389Xnx+g5x/o+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6\n/4Le/6D3T/D9V67Y/ZsVQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/\ngPs/0P4TtP8F7r9J3AIO9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTu\nf4X7b+H+X7T/+BPuf3aM8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIw\nMTUtMTEtMjlUMTY6NDY6NTMtMDU6MDCSkLewAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTExLTI5\nVDE2OjQ2OjUzLTA1OjAw480PDAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Convert OpenMC's funky ppm to png\n", + "!convert materials-xy.ppm materials-xy.png\n", + "\n", + "# Display the materials plot inline\n", + "Image(filename='materials-xy.png')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see from the plot, we have a nice pin cell with fuel, cladding, and water! Before we run our simulation, we need to tell the code what we want to tally. The following code shows how to create a 2D mesh tally." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Instantiate an empty TalliesFile\n", + "tallies_file = openmc.TalliesFile()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create mesh which will be used for tally\n", + "mesh = openmc.Mesh()\n", + "mesh.dimension = [100, 100]\n", + "mesh.lower_left = [-0.63, -0.63]\n", + "mesh.upper_right = [0.63, 0.63]\n", + "tallies_file.add_mesh(mesh)\n", + "\n", + "# Create mesh filter for tally\n", + "mesh_filter = openmc.Filter(type='mesh', bins=[1])\n", + "mesh_filter.mesh = mesh\n", + "\n", + "# Create mesh tally to score flux and fission rate\n", + "tally = openmc.Tally(name='flux')\n", + "tally.add_filter(mesh_filter)\n", + "tally.add_score('flux')\n", + "tally.add_score('fission')\n", + "tallies_file.add_tally(tally)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Export to \"tallies.xml\"\n", + "tallies_file.export_to_xml()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we a have a complete set of inputs, so we can go ahead and run our simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " .d88888b. 888b d888 .d8888b.\n", + " d88P\" \"Y88b 8888b d8888 d88P Y88b\n", + " 888 888 88888b.d88888 888 888\n", + " 888 888 88888b. .d88b. 88888b. 888Y88888P888 888 \n", + " 888 888 888 \"88b d8P Y8b 888 \"88b 888 Y888P 888 888 \n", + " 888 888 888 888 88888888 888 888 888 Y8P 888 888 888\n", + " Y88b. .d88P 888 d88P Y8b. 888 888 888 \" 888 Y88b d88P\n", + " \"Y88888P\" 88888P\" \"Y8888 888 888 888 888 \"Y8888P\"\n", + "__________________888______________________________________________________\n", + " 888\n", + " 888\n", + "\n", + " Copyright: 2011-2015 Massachusetts Institute of Technology\n", + " License: http://mit-crpg.github.io/openmc/license.html\n", + " Version: 0.7.0\n", + " Git SHA1: c4b14a5ef87f004528d35cbf33fef3ed15a386ca\n", + " Date/Time: 2015-11-29 16:46:53\n", + " MPI Processes: 1\n", + "\n", + " ===========================================================================\n", + " ========================> INITIALIZATION <=========================\n", + " ===========================================================================\n", + "\n", + " Reading settings XML file...\n", + " Reading cross sections XML file...\n", + " Reading geometry XML file...\n", + " Reading materials XML file...\n", + " Reading tallies XML file...\n", + " Building neighboring cells lists for each surface...\n", + " Loading ACE cross section table: 92235.71c\n", + " Loading ACE cross section table: 92238.71c\n", + " Loading ACE cross section table: 8016.71c\n", + " Loading ACE cross section table: 1001.71c\n", + " Loading ACE cross section table: 5010.71c\n", + " Loading ACE cross section table: 40090.71c\n", + " Maximum neutron transport energy: 20.0000 MeV for 92235.71c\n", + " Initializing source particles...\n", + "\n", + " ===========================================================================\n", + " ====================> K EIGENVALUE SIMULATION <====================\n", + " ===========================================================================\n", + "\n", + " Bat./Gen. k Average k \n", + " ========= ======== ==================== \n", + " 1/1 1.04894 \n", + " 2/1 1.01711 \n", + " 3/1 1.05357 \n", + " 4/1 1.03052 \n", + " 5/1 1.06523 \n", + " 6/1 1.06806 \n", + " 7/1 1.05161 \n", + " 8/1 1.04199 \n", + " 9/1 1.05010 \n", + " 10/1 1.04617 \n", + " 11/1 1.04894 \n", + " 12/1 1.06806 1.05850 +/- 0.00956\n", + " 13/1 1.05002 1.05567 +/- 0.00620\n", + " 14/1 1.03471 1.05043 +/- 0.00683\n", + " 15/1 1.01803 1.04395 +/- 0.00837\n", + " 16/1 1.05588 1.04594 +/- 0.00712\n", + " 17/1 1.07503 1.05010 +/- 0.00731\n", + " 18/1 1.02786 1.04732 +/- 0.00691\n", + " 19/1 1.00071 1.04214 +/- 0.00800\n", + " 20/1 1.05587 1.04351 +/- 0.00729\n", + " 21/1 1.03886 1.04309 +/- 0.00660\n", + " 22/1 1.04335 1.04311 +/- 0.00603\n", + " 23/1 1.04057 1.04292 +/- 0.00555\n", + " 24/1 1.01976 1.04126 +/- 0.00540\n", + " 25/1 1.05811 1.04238 +/- 0.00515\n", + " 26/1 1.02351 1.04120 +/- 0.00496\n", + " 27/1 1.05261 1.04188 +/- 0.00471\n", + " 28/1 1.03355 1.04141 +/- 0.00446\n", + " 29/1 1.02797 1.04071 +/- 0.00428\n", + " 30/1 1.03758 1.04055 +/- 0.00406\n", + " 31/1 1.04883 1.04094 +/- 0.00388\n", + " 32/1 1.03557 1.04070 +/- 0.00371\n", + " 33/1 1.02947 1.04021 +/- 0.00358\n", + " 34/1 1.03651 1.04006 +/- 0.00343\n", + " 35/1 1.03331 1.03979 +/- 0.00330\n", + " 36/1 1.05947 1.04054 +/- 0.00326\n", + " 37/1 1.05093 1.04093 +/- 0.00316\n", + " 38/1 1.06787 1.04189 +/- 0.00319\n", + " 39/1 1.01451 1.04095 +/- 0.00322\n", + " 40/1 1.02351 1.04037 +/- 0.00317\n", + " 41/1 1.04826 1.04062 +/- 0.00307\n", + " 42/1 1.04228 1.04067 +/- 0.00298\n", + " 43/1 1.03214 1.04041 +/- 0.00290\n", + " 44/1 1.04950 1.04068 +/- 0.00282\n", + " 45/1 1.06616 1.04141 +/- 0.00284\n", + " 46/1 1.07039 1.04221 +/- 0.00287\n", + " 47/1 1.00292 1.04115 +/- 0.00299\n", + " 48/1 1.04477 1.04125 +/- 0.00291\n", + " 49/1 1.03360 1.04105 +/- 0.00284\n", + " 50/1 1.04783 1.04122 +/- 0.00277\n", + " 51/1 1.03985 1.04119 +/- 0.00271\n", + " 52/1 1.02507 1.04080 +/- 0.00267\n", + " 53/1 1.03477 1.04066 +/- 0.00261\n", + " 54/1 1.00412 1.03983 +/- 0.00268\n", + " 55/1 1.02239 1.03945 +/- 0.00265\n", + " 56/1 1.04308 1.03952 +/- 0.00259\n", + " 57/1 1.05534 1.03986 +/- 0.00256\n", + " 58/1 1.06667 1.04042 +/- 0.00257\n", + " 59/1 1.06458 1.04091 +/- 0.00256\n", + " 60/1 1.00304 1.04015 +/- 0.00262\n", + " 61/1 1.05038 1.04036 +/- 0.00258\n", + " 62/1 1.02904 1.04014 +/- 0.00254\n", + " 63/1 1.00249 1.03943 +/- 0.00259\n", + " 64/1 1.01779 1.03903 +/- 0.00257\n", + " 65/1 1.05335 1.03929 +/- 0.00254\n", + " 66/1 1.06231 1.03970 +/- 0.00253\n", + " 67/1 1.02382 1.03942 +/- 0.00250\n", + " 68/1 1.03796 1.03939 +/- 0.00245\n", + " 69/1 1.03672 1.03935 +/- 0.00241\n", + " 70/1 1.02926 1.03918 +/- 0.00238\n", + " 71/1 1.05834 1.03950 +/- 0.00236\n", + " 72/1 1.04332 1.03956 +/- 0.00232\n", + " 73/1 1.05613 1.03982 +/- 0.00230\n", + " 74/1 1.01963 1.03950 +/- 0.00228\n", + " 75/1 1.02228 1.03924 +/- 0.00226\n", + " 76/1 1.04842 1.03938 +/- 0.00223\n", + " 77/1 1.02157 1.03911 +/- 0.00222\n", + " 78/1 1.02810 1.03895 +/- 0.00219\n", + " 79/1 1.05030 1.03912 +/- 0.00216\n", + " 80/1 1.02391 1.03890 +/- 0.00214\n", + " 81/1 1.02488 1.03870 +/- 0.00212\n", + " 82/1 1.04957 1.03885 +/- 0.00210\n", + " 83/1 1.03499 1.03880 +/- 0.00207\n", + " 84/1 1.05922 1.03907 +/- 0.00206\n", + " 85/1 1.05898 1.03934 +/- 0.00205\n", + " 86/1 1.02242 1.03912 +/- 0.00204\n", + " 87/1 1.03278 1.03904 +/- 0.00201\n", + " 88/1 1.06134 1.03932 +/- 0.00201\n", + " 89/1 1.04521 1.03940 +/- 0.00198\n", + " 90/1 1.04277 1.03944 +/- 0.00196\n", + " 91/1 1.04214 1.03947 +/- 0.00193\n", + " 92/1 1.05610 1.03967 +/- 0.00192\n", + " 93/1 1.04531 1.03974 +/- 0.00190\n", + " 94/1 1.01534 1.03945 +/- 0.00190\n", + " 95/1 1.03971 1.03945 +/- 0.00187\n", + " 96/1 1.07183 1.03983 +/- 0.00189\n", + " 97/1 1.07214 1.04020 +/- 0.00191\n", + " 98/1 1.03710 1.04017 +/- 0.00188\n", + " 99/1 1.02532 1.04000 +/- 0.00187\n", + " 100/1 1.03965 1.04000 +/- 0.00185\n", + " Creating state point statepoint.100.h5...\n", + "\n", + " ===========================================================================\n", + " ======================> SIMULATION FINISHED <======================\n", + " ===========================================================================\n", + "\n", + "\n", + " =======================> TIMING STATISTICS <=======================\n", + "\n", + " Total time for initialization = 3.7900E-01 seconds\n", + " Reading cross sections = 8.7000E-02 seconds\n", + " Total time in simulation = 2.2064E+02 seconds\n", + " Time in transport only = 2.2060E+02 seconds\n", + " Time in inactive batches = 8.7100E+00 seconds\n", + " Time in active batches = 2.1193E+02 seconds\n", + " Time synchronizing fission bank = 1.4000E-02 seconds\n", + " Sampling source sites = 8.0000E-03 seconds\n", + " SEND/RECV source sites = 2.0000E-03 seconds\n", + " Time accumulating tallies = 1.3000E-02 seconds\n", + " Total time for finalization = 1.6600E-01 seconds\n", + " Total time elapsed = 2.2120E+02 seconds\n", + " Calculation Rate (inactive) = 5740.53 neutrons/second\n", + " Calculation Rate (active) = 2123.37 neutrons/second\n", + "\n", + " ============================> RESULTS <============================\n", + "\n", + " k-effective (Collision) = 1.03912 +/- 0.00160\n", + " k-effective (Track-length) = 1.04000 +/- 0.00185\n", + " k-effective (Absorption) = 1.04240 +/- 0.00156\n", + " Combined k-effective = 1.04078 +/- 0.00127\n", + " Leakage Fraction = 0.00000 +/- 0.00000\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Run OpenMC!\n", + "executor.run_simulation()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tally Data Processing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our simulation ran successfully and created a statepoint file with all the tally data in it. We begin our analysis here loading the statepoint file and 'reading' the results. By default, data from the statepoint file is only read into memory when it is requested. This helps keep the memory use to a minimum even when a statepoint file may be huge." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "# Load the statepoint file\n", + "sp = StatePoint('statepoint.100.h5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we need to get the tally, which can be done with the ``StatePoint.get_tally(...)`` method." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tally\n", + "\tID =\t10000\n", + "\tName =\t\n", + "\tFilters =\t\n", + " \t\tmesh\t[10000]\n", + "\tNuclides =\ttotal \n", + "\tScores =\t[u'flux', u'fission']\n", + "\tEstimator =\ttracklength\n", + "\n" + ] + } + ], + "source": [ + "tally = sp.get_tally(scores=['flux'])\n", + "print(tally)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The statepoint file actually stores the sum and sum-of-squares for each tally bin from which the mean and variance can be calculated as described [here](http://mit-crpg.github.io/openmc/methods/tallies.html#variance). The sum and sum-of-squares can be accessed using the ``sum`` and ``sum_sq`` properties:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 0.4107676 , 0. ]],\n", + "\n", + " [[ 0.40849402, 0. ]],\n", + "\n", + " [[ 0.41014343, 0. ]],\n", + "\n", + " ..., \n", + " [[ 0.41049467, 0. ]],\n", + "\n", + " [[ 0.40982242, 0. ]],\n", + "\n", + " [[ 0.40996987, 0. ]]])" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tally.sum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, the mean and standard deviation of the mean are usually what you are more interested in. The Tally class also has properties ``mean`` and ``std_dev`` which automatically calculate these statistics on-the-fly." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(10000, 1, 2)\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([[[ 0.00456408, 0. ]],\n", + " \n", + " [[ 0.00453882, 0. ]],\n", + " \n", + " [[ 0.00455715, 0. ]],\n", + " \n", + " ..., \n", + " [[ 0.00456105, 0. ]],\n", + " \n", + " [[ 0.00455358, 0. ]],\n", + " \n", + " [[ 0.00455522, 0. ]]]),\n", + " array([[[ 1.95085625e-05, 0.00000000e+00]],\n", + " \n", + " [[ 1.78129859e-05, 0.00000000e+00]],\n", + " \n", + " [[ 1.89709648e-05, 0.00000000e+00]],\n", + " \n", + " ..., \n", + " [[ 1.56286612e-05, 0.00000000e+00]],\n", + " \n", + " [[ 1.65813279e-05, 0.00000000e+00]],\n", + " \n", + " [[ 1.67530331e-05, 0.00000000e+00]]]))" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(tally.mean.shape)\n", + "(tally.mean, tally.std_dev)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The tally data has three dimensions: one for filter combinations, one for nuclides, and one for scores. We see that there are 10000 filter combinations (corresponding to the 100 x 100 mesh bins), a single nuclide (since none was specified), and two scores. If we only want to look at a single score, we can use the ``get_slice(...)`` method as follows." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tally\n", + "\tID =\t10000\n", + "\tName =\t\n", + "\tFilters =\t\n", + " \t\tmesh\t[10000]\n", + "\tNuclides =\ttotal \n", + "\tScores =\t[u'flux']\n", + "\tEstimator =\ttracklength\n", + "\n" + ] + } + ], + "source": [ + "flux = tally.get_slice(scores=['flux'])\n", + "fission = tally.get_slice(scores=['fission'])\n", + "print(flux)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To get the bins into a form that we can plot, we can simply change the shape of the array since it is a numpy array." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "flux.std_dev.shape = (100, 100)\n", + "flux.mean.shape = (100, 100)\n", + "fission.std_dev.shape = (100, 100)\n", + "fission.mean.shape = (100, 100)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig = plt.subplot(121)\n", + "fig.imshow(flux.mean)\n", + "fig2 = plt.subplot(122)\n", + "fig2.imshow(fission.mean)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's say we want to look at the distribution of relative errors of our tally bins for flux. First we create a new variable called ``relative_error`` and set it to the ratio of the standard deviation and the mean, being careful not to divide by zero in case some bins were never scored to." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Determine relative error\n", + "relative_error = np.zeros_like(flux.std_dev)\n", + "nonzero = flux.mean > 0\n", + "relative_error[nonzero] = flux.std_dev[nonzero] / flux.mean[nonzero]\n", + "\n", + "# distribution of relative errors\n", + "ret = plt.hist(relative_error[nonzero], bins=50)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Source Sites" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Source sites can be accessed from the ``source`` property. As shown below, the source sites are represented as a numpy array with a structured datatype." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ (1.0, [0.2712169917165897, -0.04844236597355761, -0.1887902218343974], [0.3889598463000694, 0.8470657529949065, 0.36220139158953857], 2.2746035619924734, 0),\n", + " (1.0, [0.080729018085932, 0.19838688738571317, -0.38053428394017363], [-0.6604834049157511, -0.6893239101986768, 0.2976478097673534], 0.7833467555325838, 0),\n", + " (1.0, [0.019430574216787868, 0.06594180627832635, 0.23329810254580194], [-0.7472138923667574, 0.13227244377548197, -0.651287493870243], 1.1632342240714935, 0),\n", + " ...,\n", + " (1.0, [0.18544614514351207, -0.0113070561851496, 0.5468392238881264], [-0.8006491411918817, 0.43855795172388223, -0.4082007786475368], 1.4358240241589555, 0),\n", + " (1.0, [0.18544614514351207, -0.0113070561851496, 0.5468392238881264], [-0.5150076397044656, -0.34922134026850293, 0.7828228321575105], 1.5771133724329802, 0),\n", + " (1.0, [-0.2722999793764598, 0.22680062445008103, 0.2987060438567475], [0.9207818175032396, -0.2884020326181676, 0.26265017063984586], 2.932342523379745, 0)], \n", + " dtype=[('wgt', '" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\nluKTIylGlUqYsKkZZ/mbetoFju0tliVNMWOz/EnQvh/v08Djdeszgd8lyzuJY2Y+3+OQuiCW9w/K\nLpZ8LHJY9cFOLypJ6l9pBjmUJOkZBg5JUiYGDklSJgYOSUDocjsw0Pxjl1vV67hVPRL2qpJyEkuP\nn34WSx53YwZASZKeYeCQJGVi4JAkZWLgkCRlYuCQJGVi4JCkLhkaat3luVLpderSszuuJCCerqJT\nVTfz3+64kqSuMnBIkjIxcEiSMjFwSJIyMXBIkjIxcEiSMjFwSJIyMXBIkjIxcEiSMjFwSJIy6Ubg\nOALYANwPnNrimHOS/euAQ5Jtc4HrgfXA3cDJxSZTkpRG0YFjEFhFCB4HAsuA+Q3HLAb2A/YHTgDO\nTbY/BfwN8HJgIXBik3MlSV1WdOBYAGwENhMCwWpgacMxS4BLkuWbgFnAPsAvgTuS7b8F7gX2LTa5\nkqSJFB04ZgNb6ta3JtsmOmZOwzHDhCqsm3JOnyQpo+kFXz/tIMGNw/vWn/ds4ArgFELJY5yRkZFn\nlqvVKtVqNVMCpamkUoHR0eb7hoa6mxZ1T61Wo1ar5Xa9oufjWAiMENo4AE4DdgBn1h1zHlAjVGNB\naEhfBDwE7AH8O/A94Owm13c+DikD59yIl/Nx7HIrodF7GJgBHAOsaThmDXBcsrwQ+DUhaAwAFwH3\n0DxoSJJ6oOiqqu3AScC1hB5WFxEauVck+88Hrib0rNoIPAYsT/a9FngPcCdwe7LtNOCagtMsSWrD\nqWOlKcSqqnhN1P60bVt+95psVZWBQ5pCDBzllPf/W+xtHJKkPmPgkCRlYuCQJGVi4JAkZWLgkPpM\npRIaU5t9fDtcebBXldRn7DnVf+xVJUkqNQOHJCkTA4ckKRMDh1RSrRrBbQBX0Wwcl0rKRvCpw8Zx\nSVKpGTgkSZkYOCRJmRg4JEmZGDgkSZkYOCRJmRg4JEmZGDgkKXJDQ81f9qxUepMeXwCUSsoXANXp\nz4AvAEp9zLk1FCNLHFLELFWoHUsc0hRlqUJlY+CQuqBdcIDwV2Ozz7ZtvU231IxVVVIXWOWkIlhV\nJUkqBQOHlBPbKjRVWFUl5cTqKHWbVVWSpFKY3usESJI6MzYUSStFlYCtqpJyYlWVysKqKqmLbACX\nLHFImViqUD+wxCEVoFXJwlKFVHzgOALYANwPnNrimHOS/euAQzKeKxVidNQhQKRWigwcg8AqQgA4\n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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create log-spaced energy bins from 1 keV to 100 MeV\n", + "energy_bins = np.logspace(-3,1)\n", + "\n", + "# Calculate pdf for source energies\n", + "probability, bin_edges = np.histogram(sp.source['E'], energy_bins, density=True)\n", + "\n", + "# Make sure integrating the PDF gives us unity\n", + "print(sum(probability*np.diff(energy_bins)))\n", + "\n", + "# Plot source energy PDF\n", + "plt.semilogx(energy_bins[:-1], probability*np.diff(energy_bins), linestyle='steps')\n", + "plt.xlabel('Energy (MeV)')\n", + "plt.ylabel('Probability/MeV')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's also look at the spatial distribution of the sites. To make the plot a little more interesting, we can also include the direction of the particle emitted from the source and color each source by the logarithm of its energy." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(-0.5, 0.5)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/lib/pymodules/python2.7/matplotlib/collections.py:548: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison\n", + " if self._edgecolors == 'face':\n" + ] + }, + { + "data": { + "image/png": "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\ngg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.quiver(sp.source['xyz'][:,0], sp.source['xyz'][:,1],\n", + " sp.source['uvw'][:,0], sp.source['uvw'][:,1],\n", + " np.log(sp.source['E']), cmap='jet', scale=20.0)\n", + "plt.colorbar()\n", + "plt.xlim((-0.5,0.5))\n", + "plt.ylim((-0.5,0.5))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/source/pythonapi/examples/post-processing.rst b/docs/source/pythonapi/examples/post-processing.rst new file mode 100644 index 0000000000..b488d15ffb --- /dev/null +++ b/docs/source/pythonapi/examples/post-processing.rst @@ -0,0 +1,13 @@ +.. _notebook_post_processing: + +=============== +Post Processing +=============== + +.. only:: html + + .. notebook:: post-processing.ipynb + +.. only:: latex + + IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/pythonapi/examples/tally-arithmetic.ipynb b/docs/source/pythonapi/examples/tally-arithmetic.ipynb index 2b12052046..3ec974e057 100644 --- a/docs/source/pythonapi/examples/tally-arithmetic.ipynb +++ b/docs/source/pythonapi/examples/tally-arithmetic.ipynb @@ -182,20 +182,19 @@ "# Create fuel Cell\n", "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", "fuel_cell.fill = fuel\n", - "fuel_cell.add_surface(fuel_outer_radius, halfspace=-1)\n", + "fuel_cell.region = -fuel_outer_radius\n", "pin_cell_universe.add_cell(fuel_cell)\n", "\n", "# Create a clad Cell\n", "clad_cell = openmc.Cell(name='1.6% Clad')\n", "clad_cell.fill = zircaloy\n", - "clad_cell.add_surface(fuel_outer_radius, halfspace=+1)\n", - "clad_cell.add_surface(clad_outer_radius, halfspace=-1)\n", + "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", "pin_cell_universe.add_cell(clad_cell)\n", "\n", "# Create a moderator Cell\n", "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", "moderator_cell.fill = water\n", - "moderator_cell.add_surface(clad_outer_radius, halfspace=+1)\n", + "moderator_cell.region = +clad_outer_radius\n", "pin_cell_universe.add_cell(moderator_cell)" ] }, @@ -219,12 +218,7 @@ "root_cell.fill = pin_cell_universe\n", "\n", "# Add boundary planes\n", - "root_cell.add_surface(min_x, halfspace=+1)\n", - "root_cell.add_surface(max_x, halfspace=-1)\n", - "root_cell.add_surface(min_y, halfspace=+1)\n", - "root_cell.add_surface(max_y, halfspace=-1)\n", - "root_cell.add_surface(min_z, halfspace=+1)\n", - "root_cell.add_surface(max_z, halfspace=-1)\n", + "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", "\n", "# Create root Universe\n", "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", @@ -342,7 +336,18 @@ "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Run openmc in plotting mode\n", "executor = openmc.Executor()\n", @@ -358,7 +363,26 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAALKSURB\nVGje7dpLcqQwDAbgHHE2YeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmN\nP+HDhw8fPnz48Kf6VH9G+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4\nzPji99z0/AJ4n1lfvJ6fnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6\npA0wfln+ho/fwgYYn19C/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tN\nDbSGz7T0SBEWw4vLXzbQ6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X5\n8wZaxWd1+fMGiuFvir8bvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV\n873hB8UnM3xzANtf8nb4dwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7\nT/ppARBvp48UwJnelT5SACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4/\n/Jve+fhsH6Ctv7n8PTzjvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V\n32/o9+fl389Xnx+g5x/o+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6\n/4Le/6D3T/D9V67Y/ZsVQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/\ngPs/0P4TtP8F7r9J3AIO9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTu\nf4X7b+H+X7T/+BPuf3aM8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIw\nMTUtMDgtMDZUMTY6NDM6MTMrMDc6MDBtUQj+AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA4LTA2\nVDE2OjQzOjEzKzA3OjAwHAywQgAAAABJRU5ErkJggg==\n", + "image/png": [ + "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\n", + "AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\n", + "QYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98LGQ4UM+6dthcAAALKSURBVGje7dpLcqQwDAbgHHE2\n", + "YeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n", + "+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\n", + "nl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n", + "/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n", + "6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\n", + "vjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\n", + "dwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\n", + "ACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\n", + "vY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n", + "+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\n", + "QBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n", + "9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n", + "8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTUtMTEtMjVUMTQ6MjA6\n", + "NTEtMDg6MDDVsKLDAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTExLTI1VDE0OjIwOjUxLTA4OjAw\n", + "pO0afwAAAABJRU5ErkJggg==\n" + ], "text/plain": [ "" ] @@ -387,13 +411,12 @@ "cell_type": "code", "execution_count": 15, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ "# Instantiate an empty TalliesFile\n", - "tallies_file = openmc.TalliesFile()\n", - "tallies_file.tallies = []" + "tallies_file = openmc.TalliesFile()" ] }, { @@ -569,7 +592,9 @@ " Copyright: 2011-2015 Massachusetts Institute of Technology\n", " License: http://mit-crpg.github.io/openmc/license.html\n", " Version: 0.7.0\n", - " Date/Time: 2015-08-15 10:52:49\n", + " Git SHA1: 74ffcb447521c968fb64fdaa63e40598783f2fba\n", + " Date/Time: 2015-11-25 14:20:51\n", + " MPI Processes: 1\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -581,12 +606,13 @@ " Reading materials XML file...\n", " Reading tallies XML file...\n", " Building neighboring cells lists for each surface...\n", + " Loading ACE cross section table: 92235.71c\n", " Loading ACE cross section table: 92238.71c\n", " Loading ACE cross section table: 8016.71c\n", - " Loading ACE cross section table: 92235.71c\n", - " Loading ACE cross section table: 5010.71c\n", " Loading ACE cross section table: 1001.71c\n", + " Loading ACE cross section table: 5010.71c\n", " Loading ACE cross section table: 40090.71c\n", + " Maximum neutron transport energy: 20.0000 MeV for 92235.71c\n", " Initializing source particles...\n", "\n", " ===========================================================================\n", @@ -595,26 +621,26 @@ "\n", " Bat./Gen. k Average k \n", " ========= ======== ==================== \n", - " 1/1 1.00465 \n", - " 2/1 1.05814 \n", - " 3/1 1.05114 \n", - " 4/1 1.09189 \n", - " 5/1 1.03731 \n", - " 6/1 1.03510 \n", - " 7/1 1.09378 1.06444 +/- 0.02934\n", - " 8/1 1.04522 1.05803 +/- 0.01811\n", - " 9/1 1.06557 1.05992 +/- 0.01294\n", - " 10/1 1.05757 1.05945 +/- 0.01004\n", - " 11/1 1.04858 1.05764 +/- 0.00839\n", - " 12/1 1.01832 1.05202 +/- 0.00905\n", - " 13/1 1.05822 1.05279 +/- 0.00787\n", - " 14/1 1.07684 1.05547 +/- 0.00744\n", - " 15/1 1.00349 1.05027 +/- 0.00844\n", - " 16/1 1.06969 1.05203 +/- 0.00784\n", - " 17/1 1.06377 1.05301 +/- 0.00722\n", - " 18/1 1.02897 1.05116 +/- 0.00690\n", - " 19/1 1.00685 1.04800 +/- 0.00713\n", - " 20/1 1.02644 1.04656 +/- 0.00679\n", + " 1/1 1.05992 \n", + " 2/1 1.05251 \n", + " 3/1 1.05204 \n", + " 4/1 1.02100 \n", + " 5/1 1.07784 \n", + " 6/1 1.04814 \n", + " 7/1 1.02335 1.03574 +/- 0.01239\n", + " 8/1 1.02415 1.03188 +/- 0.00813\n", + " 9/1 1.10331 1.04974 +/- 0.01876\n", + " 10/1 1.05452 1.05069 +/- 0.01456\n", + " 11/1 1.07867 1.05536 +/- 0.01277\n", + " 12/1 1.04203 1.05345 +/- 0.01096\n", + " 13/1 1.04482 1.05237 +/- 0.00955\n", + " 14/1 1.04116 1.05113 +/- 0.00852\n", + " 15/1 1.07569 1.05358 +/- 0.00800\n", + " 16/1 1.04188 1.05252 +/- 0.00732\n", + " 17/1 1.03775 1.05129 +/- 0.00679\n", + " 18/1 0.98462 1.04616 +/- 0.00808\n", + " 19/1 1.08613 1.04902 +/- 0.00801\n", + " 20/1 1.00571 1.04613 +/- 0.00800\n", " Creating state point statepoint.20.h5...\n", "\n", " ===========================================================================\n", @@ -624,27 +650,27 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 4.4100E-01 seconds\n", - " Reading cross sections = 1.1300E-01 seconds\n", - " Total time in simulation = 1.8418E+01 seconds\n", - " Time in transport only = 1.8403E+01 seconds\n", - " Time in inactive batches = 2.1070E+00 seconds\n", - " Time in active batches = 1.6311E+01 seconds\n", + " Total time for initialization = 7.9600E-01 seconds\n", + " Reading cross sections = 2.1200E-01 seconds\n", + " Total time in simulation = 1.8740E+01 seconds\n", + " Time in transport only = 1.8727E+01 seconds\n", + " Time in inactive batches = 2.5970E+00 seconds\n", + " Time in active batches = 1.6143E+01 seconds\n", " Time synchronizing fission bank = 2.0000E-03 seconds\n", - " Sampling source sites = 2.0000E-03 seconds\n", - " SEND/RECV source sites = 0.0000E+00 seconds\n", + " Sampling source sites = 1.0000E-03 seconds\n", + " SEND/RECV source sites = 1.0000E-03 seconds\n", " Time accumulating tallies = 0.0000E+00 seconds\n", - " Total time for finalization = 1.0000E-03 seconds\n", - " Total time elapsed = 1.8861E+01 seconds\n", - " Calculation Rate (inactive) = 5932.61 neutrons/second\n", - " Calculation Rate (active) = 2299.06 neutrons/second\n", + " Total time for finalization = 2.0000E-03 seconds\n", + " Total time elapsed = 1.9553E+01 seconds\n", + " Calculation Rate (inactive) = 4813.25 neutrons/second\n", + " Calculation Rate (active) = 2322.99 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 1.04599 +/- 0.00622\n", - " k-effective (Track-length) = 1.04656 +/- 0.00679\n", - " k-effective (Absorption) = 1.04614 +/- 0.00461\n", - " Combined k-effective = 1.04651 +/- 0.00368\n", + " k-effective (Collision) = 1.04597 +/- 0.00663\n", + " k-effective (Track-length) = 1.04613 +/- 0.00800\n", + " k-effective (Absorption) = 1.04087 +/- 0.00627\n", + " Combined k-effective = 1.04322 +/- 0.00570\n", " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] @@ -692,8 +718,7 @@ "outputs": [], "source": [ "# Load the statepoint file\n", - "sp = StatePoint('statepoint.20.h5')\n", - "sp.read_results()" + "sp = StatePoint('statepoint.20.h5')" ] }, { @@ -746,30 +771,22 @@ " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " total\n", - " (nu-fission / absorption)\n", - " 1.042726\n", - " 0.008661\n", + " total\n", + " (nu-fission / absorption)\n", + " 1.040687\n", + " 0.010913\n", " \n", " \n", "\n", "
" ], "text/plain": [ - " nuclide score mean std. dev.\n", - "bin \n", - "0 total (nu-fission / absorption) 1.042726 0.008661" + " nuclide score mean std. dev.\n", + "0 total (nu-fission / absorption) 1.040687 0.010913" ] }, "execution_count": 26, @@ -809,35 +826,29 @@ " \n", " \n", " \n", + " energy [MeV]\n", " nuclide\n", " score\n", " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " total\n", - " absorption\n", - " 0.958874\n", - " 0.007146\n", + " (0.0e+00 - 6.2e-01)\n", + " total\n", + " absorption\n", + " 0.959302\n", + " 0.010033\n", " \n", " \n", "\n", "
" ], "text/plain": [ - " nuclide score mean std. dev.\n", - "bin \n", - "0 total absorption 0.958874 0.007146" + " energy [MeV] nuclide score mean std. dev.\n", + "0 (0.0e+00 - 6.2e-01) total absorption 0.959302 0.010033" ] }, "execution_count": 27, @@ -875,35 +886,29 @@ " \n", " \n", " \n", + " energy [MeV]\n", " nuclide\n", " score\n", " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " total\n", - " nu-fission\n", - " 1.09186\n", - " 0.010424\n", + " (0.0e+00 - 6.2e-01)\n", + " total\n", + " nu-fission\n", + " 1.09103\n", + " 0.012491\n", " \n", " \n", "\n", "
" ], "text/plain": [ - " nuclide score mean std. dev.\n", - "bin \n", - "0 total nu-fission 1.09186 0.010424" + " energy [MeV] nuclide score mean std. dev.\n", + "0 (0.0e+00 - 6.2e-01) total nu-fission 1.09103 0.012491" ] }, "execution_count": 28, @@ -949,25 +954,16 @@ " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " 0.0e+00 - 6.2e-01\n", - " 10000\n", - " total\n", - " absorption\n", - " 0.802921\n", - " 0.006109\n", + " (0.0e+00 - 6.2e-01)\n", + " 10000\n", + " total\n", + " absorption\n", + " 0.803182\n", + " 0.008664\n", " \n", " \n", "\n", @@ -975,8 +971,7 @@ ], "text/plain": [ " energy [MeV] cell nuclide score mean std. dev.\n", - "bin \n", - "0 0.0e+00 - 6.2e-01 10000 total absorption 0.802921 0.006109" + "0 (0.0e+00 - 6.2e-01) 10000 total absorption 0.803182 0.008664" ] }, "execution_count": 29, @@ -1020,25 +1015,16 @@ " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " 0.0e+00 - 6.2e-01\n", - " 10000\n", - " total\n", - " (nu-fission / absorption)\n", - " 1.240421\n", - " 0.010978\n", + " (0.0e+00 - 6.2e-01)\n", + " 10000\n", + " total\n", + " (nu-fission / absorption)\n", + " 1.237982\n", + " 0.014179\n", " \n", " \n", "\n", @@ -1046,12 +1032,10 @@ ], "text/plain": [ " energy [MeV] cell nuclide score mean \\\n", - "bin \n", - "0 0.0e+00 - 6.2e-01 10000 total (nu-fission / absorption) 1.240421 \n", + "0 (0.0e+00 - 6.2e-01) 10000 total (nu-fission / absorption) 1.237982 \n", "\n", - " std. dev. \n", - "bin \n", - "0 0.010978 " + " std. dev. \n", + "0 0.014179 " ] }, "execution_count": 30, @@ -1087,39 +1071,34 @@ " \n", " \n", " \n", + " energy [MeV]\n", + " cell\n", " nuclide\n", " score\n", " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " total\n", - " (((absorption * nu-fission) * absorption) * (n...\n", - " 1.042726\n", - " 0.017538\n", + " (0.0e+00 - 6.2e-01)\n", + " 10000\n", + " total\n", + " (((absorption * nu-fission) * absorption) * (n...\n", + " 1.040687\n", + " 0.022989\n", " \n", " \n", "\n", "
" ], "text/plain": [ - " nuclide score mean \\\n", - "bin \n", - "0 total (((absorption * nu-fission) * absorption) * (n... 1.042726 \n", + " energy [MeV] cell nuclide \\\n", + "0 (0.0e+00 - 6.2e-01) 10000 total \n", "\n", - " std. dev. \n", - "bin \n", - "0 0.017538 " + " score mean std. dev. \n", + "0 (((absorption * nu-fission) * absorption) * (n... 1.040687 0.022989 " ] }, "execution_count": 31, @@ -1179,115 +1158,104 @@ " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " 10000\n", - " 0.0e+00 - 6.3e-07\n", - " (U-238 / total)\n", - " (nu-fission / flux)\n", - " 0.000001\n", - " 6.985151e-09\n", + " 10000\n", + " (0.0e+00 - 6.3e-07)\n", + " (U-238 / total)\n", + " (nu-fission / flux)\n", + " 0.000001\n", + " 8.078651e-09\n", " \n", " \n", " 1\n", - " 10000\n", - " 0.0e+00 - 6.3e-07\n", - " (U-238 / total)\n", - " (scatter / flux)\n", - " 0.209988\n", - " 2.206753e-03\n", + " 10000\n", + " (0.0e+00 - 6.3e-07)\n", + " (U-238 / total)\n", + " (scatter / flux)\n", + " 0.209990\n", + " 2.449396e-03\n", " \n", " \n", " 2\n", - " 10000\n", - " 0.0e+00 - 6.3e-07\n", - " (U-235 / total)\n", - " (nu-fission / flux)\n", - " 0.355276\n", - " 3.741612e-03\n", + " 10000\n", + " (0.0e+00 - 6.3e-07)\n", + " (U-235 / total)\n", + " (nu-fission / flux)\n", + " 0.356117\n", + " 4.364366e-03\n", " \n", " \n", " 3\n", - " 10000\n", - " 0.0e+00 - 6.3e-07\n", - " (U-235 / total)\n", - " (scatter / flux)\n", - " 0.005555\n", - " 5.842517e-05\n", + " 10000\n", + " (0.0e+00 - 6.3e-07)\n", + " (U-235 / total)\n", + " (scatter / flux)\n", + " 0.005555\n", + " 6.495710e-05\n", " \n", " \n", " 4\n", - " 10000\n", - " 6.3e-07 - 2.0e+01\n", - " (U-238 / total)\n", - " (nu-fission / flux)\n", - " 0.007229\n", - " 5.951357e-05\n", + " 10000\n", + " (6.3e-07 - 2.0e+01)\n", + " (U-238 / total)\n", + " (nu-fission / flux)\n", + " 0.007190\n", + " 7.596666e-05\n", " \n", " \n", " 5\n", - " 10000\n", - " 6.3e-07 - 2.0e+01\n", - " (U-238 / total)\n", - " (scatter / flux)\n", - " 0.227642\n", - " 9.496469e-04\n", + " 10000\n", + " (6.3e-07 - 2.0e+01)\n", + " (U-238 / total)\n", + " (scatter / flux)\n", + " 0.227843\n", + " 1.024510e-03\n", " \n", " \n", " 6\n", - " 10000\n", - " 6.3e-07 - 2.0e+01\n", - " (U-235 / total)\n", - " (nu-fission / flux)\n", - " 0.008076\n", - " 5.699123e-05\n", + " 10000\n", + " (6.3e-07 - 2.0e+01)\n", + " (U-235 / total)\n", + " (nu-fission / flux)\n", + " 0.008086\n", + " 6.251590e-05\n", " \n", " \n", " 7\n", - " 10000\n", - " 6.3e-07 - 2.0e+01\n", - " (U-235 / total)\n", - " (scatter / flux)\n", - " 0.003369\n", - " 1.369755e-05\n", + " 10000\n", + " (6.3e-07 - 2.0e+01)\n", + " (U-235 / total)\n", + " (scatter / flux)\n", + " 0.003365\n", + " 1.646663e-05\n", " \n", " \n", "\n", "
" ], "text/plain": [ - " cell energy [MeV] nuclide score mean \\\n", - "bin \n", - "0 10000 0.0e+00 - 6.3e-07 (U-238 / total) (nu-fission / flux) 0.000001 \n", - "1 10000 0.0e+00 - 6.3e-07 (U-238 / total) (scatter / flux) 0.209988 \n", - "2 10000 0.0e+00 - 6.3e-07 (U-235 / total) (nu-fission / flux) 0.355276 \n", - "3 10000 0.0e+00 - 6.3e-07 (U-235 / total) (scatter / flux) 0.005555 \n", - "4 10000 6.3e-07 - 2.0e+01 (U-238 / total) (nu-fission / flux) 0.007229 \n", - "5 10000 6.3e-07 - 2.0e+01 (U-238 / total) (scatter / flux) 0.227642 \n", - "6 10000 6.3e-07 - 2.0e+01 (U-235 / total) (nu-fission / flux) 0.008076 \n", - "7 10000 6.3e-07 - 2.0e+01 (U-235 / total) (scatter / flux) 0.003369 \n", + " cell energy [MeV] nuclide score mean \\\n", + "0 10000 (0.0e+00 - 6.3e-07) (U-238 / total) (nu-fission / flux) 0.000001 \n", + "1 10000 (0.0e+00 - 6.3e-07) (U-238 / total) (scatter / flux) 0.209990 \n", + "2 10000 (0.0e+00 - 6.3e-07) (U-235 / total) (nu-fission / flux) 0.356117 \n", + "3 10000 (0.0e+00 - 6.3e-07) (U-235 / total) (scatter / flux) 0.005555 \n", + "4 10000 (6.3e-07 - 2.0e+01) (U-238 / total) (nu-fission / flux) 0.007190 \n", + "5 10000 (6.3e-07 - 2.0e+01) (U-238 / total) (scatter / flux) 0.227843 \n", + "6 10000 (6.3e-07 - 2.0e+01) (U-235 / total) (nu-fission / flux) 0.008086 \n", + "7 10000 (6.3e-07 - 2.0e+01) (U-235 / total) (scatter / flux) 0.003365 \n", "\n", - " std. dev. \n", - "bin \n", - "0 6.985151e-09 \n", - "1 2.206753e-03 \n", - "2 3.741612e-03 \n", - "3 5.842517e-05 \n", - "4 5.951357e-05 \n", - "5 9.496469e-04 \n", - "6 5.699123e-05 \n", - "7 1.369755e-05 " + " std. dev. \n", + "0 8.078651e-09 \n", + "1 2.449396e-03 \n", + "2 4.364366e-03 \n", + "3 6.495710e-05 \n", + "4 7.596666e-05 \n", + "5 1.024510e-03 \n", + "6 6.251590e-05 \n", + "7 1.646663e-05 " ] }, "execution_count": 33, @@ -1318,11 +1286,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 6.63809296e-07]\n", - " [ 3.55275544e-01]]\n", + "[[[ 6.65302296e-07]\n", + " [ 3.56116716e-01]]\n", "\n", - " [[ 7.22895528e-03]\n", - " [ 8.07565148e-03]]]\n" + " [[ 7.19004460e-03]\n", + " [ 8.08598751e-03]]]\n" ] } ], @@ -1350,9 +1318,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.00555505]]\n", + "[[[ 0.00555516]]\n", "\n", - " [[ 0.0033688 ]]]\n" + " [[ 0.00336498]]]\n" ] } ], @@ -1374,8 +1342,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[[ 0.2276418]\n", - " [ 0.0033688]]]\n" + "[[[ 0.22784316]\n", + " [ 0.00336498]]]\n" ] } ], @@ -1416,64 +1384,54 @@ " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " 10000\n", - " 0.0e+00 - 6.3e-07\n", - " U-238\n", - " nu-fission\n", - " 0.000002\n", - " 1.211808e-08\n", + " 10000\n", + " (0.0e+00 - 6.3e-07)\n", + " U-238\n", + " nu-fission\n", + " 0.000002\n", + " 1.450189e-08\n", " \n", " \n", " 1\n", - " 10000\n", - " 0.0e+00 - 6.3e-07\n", - " U-235\n", - " nu-fission\n", - " 0.870360\n", - " 6.496431e-03\n", + " 10000\n", + " (0.0e+00 - 6.3e-07)\n", + " U-235\n", + " nu-fission\n", + " 0.870882\n", + " 7.895515e-03\n", " \n", " \n", " 2\n", - " 10000\n", - " 6.3e-07 - 2.0e+01\n", - " U-238\n", - " nu-fission\n", - " 0.083226\n", - " 6.367951e-04\n", + " 10000\n", + " (6.3e-07 - 2.0e+01)\n", + " U-238\n", + " nu-fission\n", + " 0.082484\n", + " 8.253437e-04\n", " \n", " \n", " 3\n", - " 10000\n", - " 6.3e-07 - 2.0e+01\n", - " U-235\n", - " nu-fission\n", - " 0.092974\n", - " 5.921990e-04\n", + " 10000\n", + " (6.3e-07 - 2.0e+01)\n", + " U-235\n", + " nu-fission\n", + " 0.092762\n", + " 6.444580e-04\n", " \n", " \n", "\n", "
" ], "text/plain": [ - " cell energy [MeV] nuclide score mean std. dev.\n", - "bin \n", - "0 10000 0.0e+00 - 6.3e-07 U-238 nu-fission 0.000002 1.211808e-08\n", - "1 10000 0.0e+00 - 6.3e-07 U-235 nu-fission 0.870360 6.496431e-03\n", - "2 10000 6.3e-07 - 2.0e+01 U-238 nu-fission 0.083226 6.367951e-04\n", - "3 10000 6.3e-07 - 2.0e+01 U-235 nu-fission 0.092974 5.921990e-04" + " cell energy [MeV] nuclide score mean std. dev.\n", + "0 10000 (0.0e+00 - 6.3e-07) U-238 nu-fission 0.000002 1.450189e-08\n", + "1 10000 (0.0e+00 - 6.3e-07) U-235 nu-fission 0.870882 7.895515e-03\n", + "2 10000 (6.3e-07 - 2.0e+01) U-238 nu-fission 0.082484 8.253437e-04\n", + "3 10000 (6.3e-07 - 2.0e+01) U-235 nu-fission 0.092762 6.444580e-04" ] }, "execution_count": 37, @@ -1509,114 +1467,104 @@ " mean\n", " std. dev.\n", " \n", - " \n", - " bin\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " \n", " 0\n", - " 10002\n", - " 1.0e-08 - 1.1e-07\n", - " H-1\n", - " scatter\n", - " 4.638428\n", - " 0.034134\n", + " 10002\n", + " (1.0e-08 - 1.1e-07)\n", + " H-1\n", + " scatter\n", + " 4.630154\n", + " 0.044512\n", " \n", " \n", " 1\n", - " 10002\n", - " 1.1e-07 - 1.2e-06\n", - " H-1\n", - " scatter\n", - " 2.050818\n", - " 0.010745\n", + " 10002\n", + " (1.1e-07 - 1.2e-06)\n", + " H-1\n", + " scatter\n", + " 2.042984\n", + " 0.011429\n", " \n", " \n", " 2\n", - " 10002\n", - " 1.2e-06 - 1.3e-05\n", - " H-1\n", - " scatter\n", - " 1.656905\n", - " 0.009480\n", + " 10002\n", + " (1.2e-06 - 1.3e-05)\n", + " H-1\n", + " scatter\n", + " 1.657517\n", + " 0.008617\n", " \n", " \n", " 3\n", - " 10002\n", - " 1.3e-05 - 1.4e-04\n", - " H-1\n", - " scatter\n", - " 1.870808\n", - " 0.011883\n", + " 10002\n", + " (1.3e-05 - 1.4e-04)\n", + " H-1\n", + " scatter\n", + " 1.863326\n", + " 0.008848\n", " \n", " \n", " 4\n", - " 10002\n", - " 1.4e-04 - 1.5e-03\n", - " H-1\n", - " scatter\n", - " 2.045621\n", - " 0.011414\n", + " 10002\n", + " (1.4e-04 - 1.5e-03)\n", + " H-1\n", + " scatter\n", + " 2.043916\n", + " 0.014195\n", " \n", " \n", " 5\n", - " 10002\n", - " 1.5e-03 - 1.6e-02\n", - " H-1\n", - " scatter\n", - " 2.163297\n", - " 0.008725\n", + " 10002\n", + " (1.5e-03 - 1.6e-02)\n", + " H-1\n", + " scatter\n", + " 2.134458\n", + " 0.007561\n", " \n", " \n", " 6\n", - " 10002\n", - " 1.6e-02 - 1.7e-01\n", - " H-1\n", - " scatter\n", - " 2.202045\n", - " 0.013500\n", + " 10002\n", + " (1.6e-02 - 1.7e-01)\n", + " H-1\n", + " scatter\n", + " 2.209947\n", + " 0.013848\n", " \n", " \n", " 7\n", - " 10002\n", - " 1.7e-01 - 1.9e+00\n", - " H-1\n", - " scatter\n", - " 1.996977\n", - " 0.010791\n", + " 10002\n", + " (1.7e-01 - 1.9e+00)\n", + " H-1\n", + " scatter\n", + " 2.006967\n", + " 0.009368\n", " \n", " \n", " 8\n", - " 10002\n", - " 1.9e+00 - 2.0e+01\n", - " H-1\n", - " scatter\n", - " 0.370890\n", - " 0.003597\n", + " 10002\n", + " (1.9e+00 - 2.0e+01)\n", + " H-1\n", + " scatter\n", + " 0.373895\n", + " 0.002964\n", " \n", " \n", "\n", "
" ], "text/plain": [ - " cell energy [MeV] nuclide score mean std. dev.\n", - "bin \n", - "0 10002 1.0e-08 - 1.1e-07 H-1 scatter 4.638428 0.034134\n", - "1 10002 1.1e-07 - 1.2e-06 H-1 scatter 2.050818 0.010745\n", - "2 10002 1.2e-06 - 1.3e-05 H-1 scatter 1.656905 0.009480\n", - "3 10002 1.3e-05 - 1.4e-04 H-1 scatter 1.870808 0.011883\n", - "4 10002 1.4e-04 - 1.5e-03 H-1 scatter 2.045621 0.011414\n", - "5 10002 1.5e-03 - 1.6e-02 H-1 scatter 2.163297 0.008725\n", - "6 10002 1.6e-02 - 1.7e-01 H-1 scatter 2.202045 0.013500\n", - "7 10002 1.7e-01 - 1.9e+00 H-1 scatter 1.996977 0.010791\n", - "8 10002 1.9e+00 - 2.0e+01 H-1 scatter 0.370890 0.003597" + " cell energy [MeV] nuclide score mean std. dev.\n", + "0 10002 (1.0e-08 - 1.1e-07) H-1 scatter 4.630154 0.044512\n", + "1 10002 (1.1e-07 - 1.2e-06) H-1 scatter 2.042984 0.011429\n", + "2 10002 (1.2e-06 - 1.3e-05) H-1 scatter 1.657517 0.008617\n", + "3 10002 (1.3e-05 - 1.4e-04) H-1 scatter 1.863326 0.008848\n", + "4 10002 (1.4e-04 - 1.5e-03) H-1 scatter 2.043916 0.014195\n", + "5 10002 (1.5e-03 - 1.6e-02) H-1 scatter 2.134458 0.007561\n", + "6 10002 (1.6e-02 - 1.7e-01) H-1 scatter 2.209947 0.013848\n", + "7 10002 (1.7e-01 - 1.9e+00) H-1 scatter 2.006967 0.009368\n", + "8 10002 (1.9e+00 - 2.0e+01) H-1 scatter 0.373895 0.002964" ] }, "execution_count": 38, @@ -1649,7 +1597,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.8" + "version": "2.7.10" } }, "nbformat": 4, diff --git a/docs/source/pythonapi/index.rst b/docs/source/pythonapi/index.rst index 8c42f2d7e2..6d513d5d5b 100644 --- a/docs/source/pythonapi/index.rst +++ b/docs/source/pythonapi/index.rst @@ -57,13 +57,26 @@ on a given module or class. summary tallies +**Multi-Group Cross Section Generation** + +.. toctree:: + :maxdepth: 1 + + mgxs + energy_groups + mgxs_library + **Example Jupyter Notebooks:** .. toctree:: :maxdepth: 1 + examples/post-processing examples/pandas-dataframes examples/tally-arithmetic + examples/mgxs-part-i + examples/mgxs-part-ii + examples/mgxs-part-iii .. _Jupyter: https://jupyter.org/ .. _NumPy: http://www.numpy.org/ diff --git a/docs/source/pythonapi/mgxs.rst b/docs/source/pythonapi/mgxs.rst new file mode 100644 index 0000000000..c7084e5653 --- /dev/null +++ b/docs/source/pythonapi/mgxs.rst @@ -0,0 +1,66 @@ +.. _pythonapi_mgxs: + +========================== +Multi-Group Cross Sections +========================== + +.. currentmodule:: openmc.mgxs.mgxs + +---------------------------- +Summary of Available Classes +---------------------------- + +.. autosummary:: + + MGXS + AbsorptionXS + CaptureXS + Chi + FissionXS + NuFissionXS + NuScatterXS + NuScatterMatrixXS + ScatterXS + ScatterMatrixXS + TotalXS + TransportXS + +------------------- +Class Documentation +------------------- + +.. autoclass:: MGXS + :members: + +.. autoclass:: AbsorptionXS + :members: + +.. autoclass:: CaptureXS + :members: + +.. autoclass:: Chi + :members: + +.. autoclass:: FissionXS + :members: + +.. autoclass:: NuFissionXS + :members: + +.. autoclass:: NuScatterXS + :members: + +.. autoclass:: NuScatterMatrixXS + :members: + +.. autoclass:: ScatterXS + :members: + +.. autoclass:: ScatterMatrixXS + :members: + +.. autoclass:: TotalXS + :members: + +.. autoclass:: TransportXS + :members: diff --git a/docs/source/pythonapi/mgxs_library.rst b/docs/source/pythonapi/mgxs_library.rst new file mode 100644 index 0000000000..8ac5457004 --- /dev/null +++ b/docs/source/pythonapi/mgxs_library.rst @@ -0,0 +1,8 @@ +.. _pythonapi_mgxs_library: + +============ +MGXS Library +============ + +.. automodule:: openmc.mgxs.library + :members: diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index b64dfebda1..9ce752be7c 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -35,8 +35,8 @@ Installing from Source on Linux or Mac OS X ------------------------------------------- All OpenMC source code is hosted on GitHub_. If you have git_, the gfortran_ -compiler, and CMake_ installed, you can download and install OpenMC be entering -the following commands in a terminal: +compiler, CMake_, and HDF5_ installed, you can download and install OpenMC be +entering the following commands in a terminal: .. code-block:: sh diff --git a/docs/source/releasenotes.rst b/docs/source/releasenotes.rst index dffc17201f..65309fd70a 100644 --- a/docs/source/releasenotes.rst +++ b/docs/source/releasenotes.rst @@ -1,9 +1,30 @@ .. _releasenotes: ============================== -Release Notes for OpenMC 0.7.0 +Release Notes for OpenMC 0.7.1 ============================== +This release of OpenMC provides some substantial improvements over version +0.7.0. Non-simple cell regions can now be defined through the ``|`` (union) and +``~`` (complement) operators. Similar changes in the Python API also allow +complex cell regions to be defined. A true secondary particle bank now exists; +this is crucial for photon transport (to be added in the next minor release). A +rich API for multi-group cross section generation has been added via the +``openmc.mgxs`` Python module. + +Various improvements to tallies have also been made. It is now possible to +explicitly specify that a collision estimator be used in a tally. A new +``delayedgroup`` filter and ``delayed-nu-fission`` score allow a user to obtain +delayed fission neutron production rates filtered by delayed group. Finally, the +new ``inverse-velocity`` score may be useful for calculating kinetics +parameters. + +.. caution:: In previous versions, depending on how OpenMC was compiled binary + output was either given in HDF5 or a flat binary format. With this + version, all binary output is now HDF5 which means you **must** + have HDF5 in order to install OpenMC. Please consult the user's + guide for instructions on how to compile with HDF5. + ------------------- System Requirements ------------------- @@ -17,36 +38,41 @@ the problem at hand (mostly on the number of nuclides in the problem). New Features ------------ -- Complete Python API -- Python 3 compatability for all scripts -- All scripts consistently named openmc-* and installed together -- New 'distribcell' tally filter for repeated cells -- Ability to specify outer lattice universe -- XML input validation utility (openmc-validate-xml) -- Support for hexagonal lattices -- Material union energy grid method -- Tally triggers -- Remove dependence on PETSc -- Significant OpenMP performance improvements -- Support for Fortran 2008 MPI interface -- Use of Travis CI for continuous integration -- Simplifications and improvements to test suite +- Support for complex cell regions (union and complement operators) +- Generic quadric surface type +- Improved handling of secondary particles +- Binary output is now solely HDF5 +- ``openmc.mgxs`` Python module enabling multi-group cross section generation +- Collision estimator for tallies +- Delayed fission neutron production tallies with ability to filter by delayed + group +- Inverse velocity tally score +- Performance improvements for binary search +- Performance improvements for reaction rate tallies --------- Bug Fixes --------- -- b5f712_: Fix bug in spherical harmonics tallies -- e6675b_: Ensure all constants are double precision -- 04e2c1_: Fix potential bug in sample_nuclide routine -- 6121d9_: Fix bugs related to particle track files -- 2f0e89_: Fixes for nuclide specification in tallies +- 299322_: Bug with material filter when void material present +- d74840_: Fix triggers on tallies with multiple filters +- c29a81_: Correctly handle maximum transport energy +- 3edc23_: Fixes in the nu-scatter score +- 629e3b_: Assume unspecified surface coefficients are zero in Python API +- 5dbe8b_: Fix energy filters for openmc-plot-mesh-tally +- ff66f4_: Fixes in the openmc-plot-mesh-tally script +- 441fd4_: Fix bug in kappa-fission score +- 7e5974_: Allow fixed source simulations from Python API -.. _b5f712: https://github.com/mit-crpg/openmc/commit/b5f712 -.. _e6675b: https://github.com/mit-crpg/openmc/commit/e6675b -.. _04e2c1: https://github.com/mit-crpg/openmc/commit/04e2c1 -.. _6121d9: https://github.com/mit-crpg/openmc/commit/6121d9 -.. _2f0e89: https://github.com/mit-crpg/openmc/commit/2f0e89 +.. _299322: https://github.com/mit-crpg/openmc/commit/299322 +.. _d74840: https://github.com/mit-crpg/openmc/commit/d74840 +.. _c29a81: https://github.com/mit-crpg/openmc/commit/c29a81 +.. _3edc23: https://github.com/mit-crpg/openmc/commit/3edc23 +.. _629e3b: https://github.com/mit-crpg/openmc/commit/629e3b +.. _5dbe8b: https://github.com/mit-crpg/openmc/commit/5dbe8b +.. _ff66f4: https://github.com/mit-crpg/openmc/commit/ff66f4 +.. _441fd4: https://github.com/mit-crpg/openmc/commit/441fd4 +.. _7e5974: https://github.com/mit-crpg/openmc/commit/7e5974 ------------ Contributors @@ -55,13 +81,11 @@ Contributors This release contains new contributions from the following people: - `Will Boyd `_ -- `Matt Ellis `_ - `Sterling Harper `_ -- `Bryan Herman `_ -- `Nicholas Horelik `_ +- `Bryan Herman `_ - `Colin Josey `_ -- `William Lyu `_ - `Adam Nelson `_ - `Paul Romano `_ -- `Anthony Scopatz `_ +- `Kelly Rowland `_ +- `Sam Shaner `_ - `Jon Walsh `_ diff --git a/docs/source/usersguide/index.rst b/docs/source/usersguide/index.rst index 675ed4081a..5a7e7addfa 100644 --- a/docs/source/usersguide/index.rst +++ b/docs/source/usersguide/index.rst @@ -5,7 +5,7 @@ User's Guide ============ Welcome to the OpenMC User's Guide! This tutorial will guide you through the -essential aspects of using OpenMC to perform neutronic simulations. +essential aspects of using OpenMC to perform simulations. .. toctree:: :numbered: @@ -14,5 +14,6 @@ essential aspects of using OpenMC to perform neutronic simulations. beginners install input + output/index processing troubleshoot diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 93e8236ec1..fa43ca1d2c 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -79,14 +79,13 @@ Message Description [VALID] XML file matches RelaxNG. ======================== =================================== -As an example, if OpenMC is installed in the directory -``/opt/openmc/0.6.2`` and the current working directory is where -OpenMC XML input files are located, they can be validated using -the following command: +As an example, if OpenMC is installed in the directory ``/opt/openmc/`` and the +current working directory is where OpenMC XML input files are located, they can +be validated using the following command: .. code-block:: bash - /opt/openmc/0.6.2/bin/xml_validate + /opt/openmc/bin/openmc-validate-xml -------------------------------------- Settings Specification -- settings.xml @@ -721,9 +720,8 @@ Geometry Specification -- geometry.xml The geometry in OpenMC is described using `constructive solid geometry`_ (CSG), also sometimes referred to as combinatorial geometry. CSG allows a user to create complex objects using Boolean operators on a set of simpler surfaces. In -the geometry model, each unique closed volume in defined by its bounding -surfaces. In OpenMC, most `quadratic surfaces`_ can be modeled and used as -bounding surfaces. +the geometry model, each unique volume is defined by its bounding surfaces. In +OpenMC, most `quadratic surfaces`_ can be modeled and used as bounding surfaces. Every geometry.xml must have an XML declaration at the beginning of the file and a root element named geometry. Within the root element the user can define any @@ -746,7 +744,7 @@ number of cells, surfaces, and lattices. Let us look at the following example: 1 0 1 - -1 + -1 @@ -764,7 +762,7 @@ could be written as: - + @@ -788,7 +786,8 @@ Each ```` element can have the following attributes or sub-elements: :type: The type of the surfaces. This can be "x-plane", "y-plane", "z-plane", - "plane", "x-cylinder", "y-cylinder", "z-cylinder", or "sphere". + "plane", "x-cylinder", "y-cylinder", "z-cylinder", "sphere", "x-cone", + "y-cone", "z-cone", or "quadric". *Default*: None @@ -856,6 +855,12 @@ The following quadratic surfaces can be modeled: R^2 (z - z_0)^2`. The coefficients specified are ":math:`x_0 \: y_0 \: z_0 \: R^2`". + :quadric: + A general quadric surface of the form :math:`Ax^2 + By^2 + Cz^2 + Dxy + + Eyz + Fxz + Gx + Hy + Jz + K = 0` The coefficients specified are ":math:`A + \: B \: C \: D \: E \: F \: G \: H \: J \: K`". + + ```` Element ------------------ @@ -892,15 +897,29 @@ Each ```` element can have the following attributes or sub-elements: *Default*: None - :surfaces: - A list of the ``ids`` for surfaces that bound this cell, e.g. if the cell - is on the negative side of surface 3 and the positive side of surface 5, the - bounding surfaces would be given as "-3 5". + :region: + A Boolean expression of half-spaces that defines the spatial region which + the cell occupies. Each half-space is identified by the unique ID of the + surface prefixed by `-` or `+` to indicate that it is the negative or + positive half-space, respectively. The `+` sign for a positive half-space + can be omitted. Valid Boolean operators are parentheses, union `|`, + complement `~`, and intersection. Intersection is implicit and indicated by + the presence of whitespace. The order of operator precedence is parentheses, + complement, intersection, and then union. - .. note:: The surface attribute/element can be omitted to make a cell fill - its entire universe. + As an example, the following code gives a cell that is the union of the + negative half-space of surface 3 and the complement of the intersection of + the positive half-space of surface 5 and the negative half-space of surface + 2: - *Default*: No surfaces + .. code-block:: xml + + + + .. note:: The ``region`` attribute/element can be omitted to make a cell + fill its entire universe. + + *Default*: A region filling all space. :rotation: If the cell is filled with a universe, this element specifies the angles in @@ -1095,8 +1114,10 @@ Each ``material`` element can have the following attributes or sub-elements: An element with attributes/sub-elements called ``value`` and ``units``. The ``value`` attribute is the numeric value of the density while the ``units`` can be "g/cm3", "kg/m3", "atom/b-cm", "atom/cm3", or "sum". The "sum" unit - indicates that the density should be calculated as the sum of the atom - fractions for each nuclide in the material. This should not be used in + indicates that values appearing in ``ao`` attributes for ```` and + ```` sub-elements are to be interpreted as nuclide/element + densities in atom/b-cm, and the total density of the material is taken as + the sum of all nuclides/elements. The "sum" option cannot be used in conjunction with weight percents. *Default*: None @@ -1117,6 +1138,15 @@ Each ``material`` element can have the following attributes or sub-elements: .. note:: If one nuclide is specified in atom percent, all others must also be given in atom percent. The same applies for weight percentages. + An optional attribute/sub-element for each nuclide is ``scattering``. This + attribute may be set to "data" to use the scattering laws specified by the + cross section library (default). Alternatively, when set to "iso-in-lab", + the scattering laws are used to sample the outgoing energy but an + isotropic-in-lab distribution is used to sample the outgoing angle at each + scattering interaction. The ``scattering`` attribute may be most useful + when using OpenMC to compute multi-group cross-sections for deterministic + transport codes and to quantify the effects of anisotropic scattering. + *Default*: None :element: @@ -1143,6 +1173,16 @@ Each ``material`` element can have the following attributes or sub-elements: *Default*: None + An optional attribute/sub-element for each element is ``scattering``. This + attribute may be set to "data" to use the scattering laws specified by the + cross section library (default). Alternatively, when set to "iso-in-lab", + the scattering laws are used to sample the outgoing energy but an + isotropic-in-lab distribution is used to sample the outgoing angle at each + scattering interaction. The ``scattering`` attribute may be most useful + when using OpenMC to compute multi-group cross-sections for deterministic + transport codes and to quantify the effects of anisotropic scattering. + + *Default*: None :sab: Associates an S(a,b) table with the material. This element has @@ -1214,8 +1254,8 @@ The ```` element accepts the following sub-elements: :type: The type of the filter. Accepted options are "cell", "cellborn", - "material", "universe", "energy", "energyout", "mesh", and - "distribcell". + "material", "universe", "energy", "energyout", "mesh", "distribcell", + and "delayedgroup". :bins: For each filter type, the corresponding ``bins`` entry is given as @@ -1240,17 +1280,87 @@ The ```` element accepts the following sub-elements: :energy: A monotonically increasing list of bounding **pre-collision** energies for a number of groups. For example, if this filter is specified as - ````, then two energy bins - will be created, one with energies between 0 and 1 MeV and the other - with energies between 1 and 20 MeV. + + .. code-block:: xml + + + + then two energy bins will be created, one with energies between 0 and + 1 MeV and the other with energies between 1 and 20 MeV. :energyout: A monotonically increasing list of bounding **post-collision** energies for a number of groups. For example, if this filter is - specified as ````, then - two post-collision energy bins will be created, one with energies + specified as + + .. code-block:: xml + + + + then two post-collision energy bins will be created, one with energies between 0 and 1 MeV and the other with energies between 1 and 20 MeV. + :mu: + A monotonically increasing list of bounding **post-collision** cosines + of the change in a particle's angle (i.e., :math:`\mu = \hat{\Omega} + \cdot \hat{\Omega}'`), which represents a portion of the possible + values of :math:`[-1,1]`. For example, spanning all of :math:`[-1,1]` + with five equi-width bins can be specified as: + + .. code-block:: xml + + + + Alternatively, if only one value is provided as a bin, OpenMC will + interpret this to mean the complete range of :math:`[-1,1]` should + be automatically subdivided in to the provided value for the bin. + That is, the above example of five equi-width bins spanning + :math:`[-1,1]` can be instead written as: + + .. code-block:: xml + + + + :polar: + A monotonically increasing list of bounding particle polar angles + which represents a portion of the possible values of :math:`[0,\pi]`. + For example, spanning all of :math:`[0,\pi]` with five equi-width + bins can be specified as: + + .. code-block:: xml + + + + Alternatively, if only one value is provided as a bin, OpenMC will + interpret this to mean the complete range of :math:`[0,\pi]` should + be automatically subdivided in to the provided value for the bin. + That is, the above example of five equi-width bins spanning + :math:`[0,\pi]` can be instead written as: + + .. code-block:: xml + + + + :azimuthal: + A monotonically increasing list of bounding particle azimuthal angles + which represents a portion of the possible values of :math:`[-\pi,\pi)`. + For example, spanning all of :math:`[-\pi,\pi)` with two equi-width + bins can be specified as: + + .. code-block:: xml + + + + Alternatively, if only one value is provided as a bin, OpenMC will + interpret this to mean the complete range of :math:`[-\pi,\pi)` should + be automatically subdivided in to the provided value for the bin. + That is, the above example of five equi-width bins spanning + :math:`[-\pi,\pi)` can be instead written as: + + .. code-block:: xml + + + :mesh: The ``id`` of a structured mesh to be tallied over. @@ -1263,6 +1373,15 @@ The ```` element accepts the following sub-elements: not accept more than one cell ID. It is not recommended to combine this filter with a cell or mesh filter. + :delayedgroup: + A list of delayed neutron precursor groups for which the tally should + be accumulated. For instance, to tally to all 6 delayed groups in the + ENDF/B-VII.1 library the filter is specified as: + + .. code-block:: xml + + + :nuclides: If specified, the scores listed will be for particular nuclides, not the summation of reactions from all nuclides. The format for nuclides should be @@ -1278,26 +1397,32 @@ The ```` element accepts the following sub-elements: *Default*: total :estimator: - The estimator element is used to force the use of either ``analog`` or - ``tracklength`` tally estimation. ''analog'' is generally less efficient - though it can be used with every score type. ''tracklength'' is generally - the most efficient, though its usage is restricted to tallies that do not - score particle information which requires a collision to have occured, such - as a scattering tally which utilizes outgoing energy filters. + The estimator element is used to force the use of either ``analog``, + ``collision``, or ``tracklength`` tally estimation. ``analog`` is generally + the least efficient though it can be used with every score type. + ``tracklength`` is generally the most efficient, but neither ``tracklength`` + nor ``collision`` can be used to score a tally that requires post-collision + information. For example, a scattering tally with outgoing energy filters + cannot be used with ``tracklength`` or ``collision`` because the code will + not know the outgoing energy distribution. - *Default*: ``tracklength`` but will revert to analog if necessary. + *Default*: ``tracklength`` but will revert to ``analog`` if necessary. :scores: A space-separated list of the desired responses to be accumulated. Accepted options are "flux", "total", "scatter", "absorption", "fission", - "nu-fission", "kappa-fission", "nu-scatter", "scatter-N", "scatter-PN", - "scatter-YN", "nu-scatter-N", "nu-scatter-PN", "nu-scatter-YN", "flux-YN", - "total-YN", "current", and "events". These corresponding to the following - physical quantities: + "nu-fission", "delayed-nu-fission", "kappa-fission", "nu-scatter", + "scatter-N", "scatter-PN", "scatter-YN", "nu-scatter-N", "nu-scatter-PN", + "nu-scatter-YN", "flux-YN", "total-YN", "current", "inverse-velocity" and + "events". These correspond to the following physical quantities: :flux: Total flux in particle-cm per source particle. + .. note:: + The ``analog`` estimator is actually identical to the ``collision`` + estimator for the flux score. + :total: Total reaction rate in reactions per source particle. @@ -1316,6 +1441,10 @@ The ```` element accepts the following sub-elements: Total production of neutrons due to fission. Units are neutrons produced per source neutron. + :delayed-nu-fission: + Total production of delayed neutrons due to fission. Units are neutrons produced + per source neutron. + :kappa-fission: The recoverable energy production rate due to fission. The recoverable energy is defined as the fission product kinetic energy, prompt and @@ -1378,6 +1507,14 @@ The ```` element accepts the following sub-elements: specified. Furthermore, it may not be used in conjunction with any other score. + :inverse-velocity: + The flux-weighted inverse velocity where the velocity is in units of + centimeters per second. + + .. note:: + The ``analog`` estimator is actually identical to the ``collision`` + estimator for the inverse-velocity score. + :events: Number of scoring events. Units are events per source particle. @@ -1423,8 +1560,7 @@ a separate element with the tag name ````. This element has the following attributes/sub-elements: :type: - The type of structured mesh. Valid options include "rectangular" and - "hexagonal". + The type of structured mesh. The only valid option is "regular". :dimension: The number of mesh cells in each direction. @@ -1526,16 +1662,16 @@ sub-elements: *Default*: None - Required entry :type: - Keyword for type of plot to be produced. Currently only "slice" and - "voxel" plots are implemented. The "slice" plot type creates 2D pixel - maps saved in the PPM file format. PPM files can be displayed in most - viewers (e.g. the default Gnome viewer, IrfanView, etc.). The "voxel" - plot type produces a binary datafile containing voxel grid positioning and - the cell or material (specified by the ``color`` tag) at the center of each - voxel. These datafiles can be processed into 3D SILO files using the - ``voxel.py`` utility provided with the OpenMC source, and subsequently - viewed with a 3D viewer such as VISIT or Paraview. See the - :ref:`devguide_voxel` for information about the datafile structure. + Keyword for type of plot to be produced. Currently only "slice" and "voxel" + plots are implemented. The "slice" plot type creates 2D pixel maps saved in + the PPM file format. PPM files can be displayed in most viewers (e.g. the + default Gnome viewer, IrfanView, etc.). The "voxel" plot type produces a + binary datafile containing voxel grid positioning and the cell or material + (specified by the ``color`` tag) at the center of each voxel. These + datafiles can be processed into 3D SILO files using the + ``openmc-voxel-to-silovtk`` utility provided with the OpenMC source, and + subsequently viewed with a 3D viewer such as VISIT or Paraview. See the + :ref:`usersguide_voxel` for information about the datafile structure. .. note:: Since the PPM format is saved without any kind of compression, the resulting file sizes can be quite large. Saving the image in diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 7d3cda1733..e3f0df5e91 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -8,7 +8,7 @@ Installation and Configuration Installing on Ubuntu with PPA ----------------------------- -For users with Ubuntu 11.10 or later, a binary package for OpenMC is available +For users with Ubuntu 15.04 or later, a binary package for OpenMC is available through a Personal Package Archive (PPA) and can be installed through the APT package manager. First, add the following PPA to the repository sources: @@ -28,6 +28,9 @@ Now OpenMC should be recognized within the repository and can be installed: sudo apt-get install openmc +Binary packages from this PPA may exist for earlier versions of Ubuntu, but they +are no longer supported. + -------------------- Building from Source -------------------- @@ -59,6 +62,37 @@ 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. + + .. important:: + + OpenMC uses various parts of the HDF5 Fortran 2003 API; as such you + must include ``--enable-fortran2003`` or else OpenMC will not be able + to compile. + + 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 +106,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 +214,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 +327,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 ------------- diff --git a/docs/source/usersguide/output/index.rst b/docs/source/usersguide/output/index.rst new file mode 100644 index 0000000000..31bd1da917 --- /dev/null +++ b/docs/source/usersguide/output/index.rst @@ -0,0 +1,16 @@ +.. _usersguide_output: + +=================== +Output File Formats +=================== + +.. toctree:: + :numbered: + :maxdepth: 3 + + statepoint + source + summary + particle_restart + track + voxel diff --git a/docs/source/usersguide/output/particle_restart.rst b/docs/source/usersguide/output/particle_restart.rst new file mode 100644 index 0000000000..e0d89a5156 --- /dev/null +++ b/docs/source/usersguide/output/particle_restart.rst @@ -0,0 +1,57 @@ +.. _usersguide_particle_restart: + +============================ +Particle Restart File Format +============================ + +The current revision of the particle restart file format is 1. + +**/filetype** (*char[]*) + + String indicating the type of 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. diff --git a/docs/source/usersguide/output/source.rst b/docs/source/usersguide/output/source.rst new file mode 100644 index 0000000000..2981b0f662 --- /dev/null +++ b/docs/source/usersguide/output/source.rst @@ -0,0 +1,19 @@ +.. _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** (*char[]*) + + String indicating the type of 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. diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst new file mode 100644 index 0000000000..d3c1729af6 --- /dev/null +++ b/docs/source/usersguide/output/statepoint.rst @@ -0,0 +1,259 @@ +.. _usersguide_statepoint: + +======================= +State Point File Format +======================= + +The current revision of the statepoint file format is 14. + +**/filetype** (*char[]*) + + String indicating the type of 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 + +**/date_and_time** (*char[]*) + + Date and time the state point was written. + +**/path** (*char[]*) + + Absolute path to directory containing input files. + +**/seed** (*int8_t*) + + Pseudo-random number generator seed. + +**/run_mode** (*char[]*) + + 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 == 'k-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. + +**/tallies/meshes/mesh /type** (*char[]*) + + Type of mesh. + +**/tallies/meshes/mesh /dimension** (*int*) + + Number of mesh cells in each dimension. + +**/tallies/meshes/mesh /lower_left** (*double[]*) + + Coordinates of lower-left corner of mesh. + +**/tallies/meshes/mesh /upper_right** (*double[]*) + + Coordinates of upper-right corner of mesh. + +**/tallies/meshes/mesh /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. + +**/tallies/tally /estimator** (*char[]*) + + Type of tally estimator, either 'analog', 'tracklength', or 'collision'. + +**/tallies/tally /n_realizations** (*int*) + + Number of realizations. + +**/tallies/tally /n_filters** (*int*) + + Number of filters used. + +**/tallies/tally /filter /type** (*char[]*) + + Type of the j-th filter. Can be 'universe', 'material', 'cell', 'cellborn', + 'surface', 'mesh', 'energy', 'energyout', or 'distribcell'. + +**/tallies/tally /filter /offset** (*int*) + + Filter offset (used for distribcell filter). + +**/tallies/tally /filter /n_bins** (*int*) + + Number of bins for the j-th filter. + +**/tallies/tally /filter /bins** (*int[]* or *double[]*) + + Value for each filter bin of this type. + +**/tallies/tally /nuclides** (*char[][]*) + + Array of nuclides to tally. Note that if no nuclide is specified in the user + input, a single 'total' nuclide appears here. + +**/tallies/tally /n_score_bins** (*int*) + + Number of scoring bins for a single nuclide. In general, this can be greater + than the number of user-specified scores since each score might have + multiple scoring bins, e.g., scatter-PN. + +**/tallies/tally /score_bins** (*char[][]*) + + Values of specified scores. + +**/tallies/tally /n_user_scores** (*int*) + + Number of scores without accounting for those added by expansions, + e.g. scatter-PN. + +**/tallies/tally /moment_orders** (*char[][]*) + + Tallying moment orders for Legendre and spherical harmonic tally expansions + (*e.g.*, 'P2', 'Y1,2', etc.). + +**/tallies/tally /results** (Compound type) + + Accumulated sum and sum-of-squares for each bin of the i-th tally. This is a + two-dimensional array, the first dimension of which represents combinations + of filter bins and the second dimensions of which represents scoring + bins. Each element of the array has fields 'sum' and 'sum_sq'. + +**/source_present** (*int*) + + 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. + +if (run_mode == 'k-eigenvalue' and source_present > 0) + + **/source_bank** (Compound type) + + Source bank information for each particle. The compound type has fields + ``wgt``, ``xyz``, ``uvw``, and ``E`` which represent the weight, + position, direction, and energy of the source particle, respectively. diff --git a/docs/source/usersguide/output/summary.rst b/docs/source/usersguide/output/summary.rst new file mode 100644 index 0000000000..f87f60c4a0 --- /dev/null +++ b/docs/source/usersguide/output/summary.rst @@ -0,0 +1,311 @@ +.. _usersguide_summary: + +=================== +Summary File Format +=================== + +The current revision of the summary file format is 1. + +**/filetype** (*char[]*) + + String indicating the type of file. + +**/revision** (*int*) + + Revision of the summary file format. Any time a change is made in the + format, this integer is incremented. + +**/version_major** (*int*) + + Major version number for OpenMC + +**/version_minor** (*int*) + + Minor version number for OpenMC + +**/version_release** (*int*) + + Release version number for OpenMC + +**/date_and_time** (*char[]*) + + Date and time the summary was written. + +**/n_procs** (*int*) + + Number of MPI processes used. + +**/n_particles** (*int8_t*) + + Number of particles used per generation. + +**/n_batches** (*int*) + + Number of batches to simulate. + +**/n_inactive** (*int*) + + Number of inactive batches. Only present if /run_mode is set to + 'k-eigenvalue'. + +**/n_active** (*int*) + + Number of active batches. Only present if /run_mode is set to + 'k-eigenvalue'. + +**/gen_per_batch** (*int*) + + Number of generations per batch. Only present if /run_mode is set to + 'k-eigenvalue'. + +**/geometry/n_cells** (*int*) + + Number of cells in the problem. + +**/geometry/n_surfaces** (*int*) + + Number of surfaces in the problem. + +**/geometry/n_universes** (*int*) + + Number of unique universes in the problem. + +**/geometry/n_lattices** (*int*) + + Number of lattices in the problem. + +**/geometry/cells/cell /index** (*int*) + + Index in cells array used internally in OpenMC. + +**/geometry/cells/cell /name** (*char[]*) + + Name of the cell. + +**/geometry/cells/cell /universe** (*int*) + + Universe assigned to the cell. If none is specified, the default + universe (0) is assigned. + +**/geometry/cells/cell /fill_type** (*char[]*) + + Type of fill for the cell. Can be 'normal', 'universe', or 'lattice'. + +**/geometry/cells/cell /material** (*int*) + + Unique ID of the material assigned to the cell. This dataset is present only + if fill_type is set to 'normal'. + +**/geometry/cells/cell /offset** (*int[]*) + + Offsets used for distribcell tally filter. This dataset is present only if + fill_type is set to 'universe'. + +**/geometry/cells/cell /translation** (*double[3]*) + + Translation applied to the fill universe. This dataset is present only if + fill_type is set to 'universe'. + +**/geometry/cells/cell /rotation** (*double[3]*) + + Angles in degrees about the x-, y-, and z-axes for which the fill universe + should be rotated. This dataset is present only if fill_type is set to + 'universe'. + +**/geometry/cells/cell /lattice** (*int*) + + Unique ID of the lattice which fills the cell. Only present if fill_type is + set to 'lattice'. + +**/geometry/cells/cell /region** (*char[]*) + + Region specification for the cell. + +**/geometry/surfaces/surface /index** (*int*) + + Index in surfaces array used internally in OpenMC. + +**/geometry/surfaces/surface /name** (*char[]*) + + Name of the surface. + +**/geometry/surfaces/surface /type** (*char[]*) + + Type of the surface. Can be 'x-plane', 'y-plane', 'z-plane', 'plane', + 'x-cylinder', 'y-cylinder', 'sphere', 'x-cone', 'y-cone', 'z-cone', or + 'quadric'. + +**/geometry/surfaces/surface /coefficients** (*double[]*) + + Array of coefficients that define the surface. See :ref:`surface_element` + for what coefficients are defined for each surface type. + +**/geometry/surfaces/surface /boundary_condition** (*char[]*) + + Boundary condition applied to the surface. Can be 'transmission', 'vacuum', + 'reflective', or 'periodic'. + +**/geometry/universes/universe /index** (*int*) + + Index in the universes array used internally in OpenMC. + +**/geometry/universes/universe /cells** (*int[]*) + + Array of unique IDs of cells that appear in the universe. + +**/geometry/lattices/lattice /index** (*int*) + + Index in the lattices array used internally in OpenMC. + +**/geometry/lattices/lattice /name** (*char[]*) + + Name of the lattice. + +**/geometry/lattices/lattice /type** (*char[]*) + + Type of the lattice, either 'rectangular' or 'hexagonal'. + +**/geometry/lattices/lattice /pitch** (*double[]*) + + Pitch of the lattice. + +**/geometry/lattices/lattice /outer** (*int*) + + Outer universe assigned to lattice cells outside the defined range. + +**/geometry/lattices/lattice /offsets** (*int[]*) + + Offsets used for distribcell tally filter. + +**/geometry/lattices/lattice /universes** (*int[]*) + + Three-dimensional array of universes assigned to each cell of the lattice. + +**/geometry/lattices/lattice /dimension** (*int[]*) + + The number of lattice cells in each direction. This dataset is present only + when the 'type' dataset is set to 'rectangular'. + +**/geometry/lattices/lattice /lower_left** (*double[]*) + + The coordinates of the lower-left corner of the lattice. This dataset is + present only when the 'type' dataset is set to 'rectangular'. + +**/geometry/lattices/lattice /n_rings** (*int*) + + Number of radial ring positions in the xy-plane. This dataset is present + only when the 'type' dataset is set to 'hexagonal'. + +**/geometry/lattices/lattice /n_axial** (*int*) + + Number of lattice positions along the z-axis. This dataset is present only + when the 'type' dataset is set to 'hexagonal'. + +**/geometry/lattices/lattice /center** (*double[]*) + + Coordinates of the center of the lattice. This dataset is present only when + the 'type' dataset is set to 'hexagonal'. + +**/n_materials** (*int*) + + Number of materials in the problem. + +**/materials/material /index** (*int*) + + Index in materials array used internally in OpenMC. + +**/materials/material /name** (*char[]*) + + Name of the material. + +**/materials/material /atom_density** (*double[]*) + + Total atom density of the material in atom/b-cm. + +**/materials/material /nuclides** (*char[][]*) + + Array of nuclides present in the material, e.g., 'U-235.71c'. + +**/materials/material /nuclide_densities** (*double[]*) + + Atom density of each nuclide. + +**/materials/material /sab_names** (*char[][]*) + + Names of S(:math:`\alpha`,:math:`\beta`) tables assigned to the material. + +**/tallies/n_tallies** (*int*) + + Number of tallies in the problem. + +**/tallies/n_meshes** (*int*) + + Number of meshes in the problem. + +**/tallies/mesh /index** (*int*) + + Index in the meshes array used internally in OpenMC. + +**/tallies/mesh /type** (*char[]*) + + Type of the mesh. The only valid option is currently 'regular'. + +**/tallies/mesh /dimension** (*int[]*) + + Number of mesh cells in each direction. + +**/tallies/mesh /lower_left** (*double[]*) + + Coordinates of the lower-left corner of the mesh. + +**/tallies/mesh /upper_right** (*double[]*) + + Coordinates of the upper-right corner of the mesh. + +**/tallies/mesh /width** (*double[]*) + + Width of a single mesh cell in each direction. + +**/tallies/tally /index** (*int*) + + Index in tallies array used internally in OpenMC. + +**/tallies/tally /name** (*char[]*) + + Name of the tally. + +**/tallies/tally /n_filters** (*int*) + + Number of filters applied to the tally. + +**/tallies/tally /filter /type** (*char[]*) + + Type of the j-th filter. Can be 'universe', 'material', 'cell', 'cellborn', + 'surface', 'mesh', 'energy', 'energyout', or 'distribcell'. + +**/tallies/tally /filter /offset** (*int*) + + Filter offset (used for distribcell filter). + +**/tallies/tally /filter /n_bins** (*int*) + + Number of bins for the j-th filter. + +**/tallies/tally /filter /bins** (*int[]* or *double[]*) + + Value for each filter bin of this type. + +**/tallies/tally /nuclides** (*char[][]*) + + Array of nuclides to tally. Note that if no nuclide is specified in the user + input, a single 'total' nuclide appears here. + +**/tallies/tally /n_score_bins** (*int*) + + Number of scoring bins for a single nuclide. In general, this can be greater + than the number of user-specified scores since each score might have + multiple scoring bins, e.g., scatter-PN. + +**/tallies/tally /score_bins** (*char[][]*) + + Scoring bins for the tally. diff --git a/docs/source/usersguide/output/track.rst b/docs/source/usersguide/output/track.rst new file mode 100644 index 0000000000..d3c7a27d83 --- /dev/null +++ b/docs/source/usersguide/output/track.rst @@ -0,0 +1,30 @@ +.. _usersguide_track: + +================= +Track File Format +================= + +The current revision of the particle track file format is 1. + +**/filetype** (*char[]*) + + String indicating the type of file. + +**/revision** (*int*) + + Revision of the track file format. Any time a change is made in the format, + this integer is incremented. + +**/n_particles** (*int*) + + Number of particles for which tracks are recorded. + +**/n_coords** (*int[]*) + + Number of coordinates for each particle. + +*do i = 1, n_particles* + + **/coordinates_i** (*double[][3]*) + + (x,y,z) coordinates for the *i*-th particle. diff --git a/docs/source/usersguide/output/voxel.rst b/docs/source/usersguide/output/voxel.rst new file mode 100644 index 0000000000..1da501fb54 --- /dev/null +++ b/docs/source/usersguide/output/voxel.rst @@ -0,0 +1,25 @@ +.. _usersguide_voxel: + +====================== +Voxel Plot File Format +====================== + +**/filetype** (*char[]*) + + String indicating the type of file. + +**/num_voxels** (*int[3]*) + + Number of voxels in the x-, y-, and z- directions. + +**/voxel_width** (*double[3]*) + + Width of a voxel in centimeters. + +**/lower_left** (*double[3]*) + + Cartesian coordinates of the lower-left corner of the plot. + +**/data** (*int[][][]*) + + Data for each voxel that represents a material or cell ID. diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst index e773cf1563..b18569ec6a 100644 --- a/docs/source/usersguide/processing.rst +++ b/docs/source/usersguide/processing.rst @@ -6,31 +6,34 @@ Data Processing and Visualization This section is intended to explain in detail the recommended procedures for carrying out common post-processing tasks with OpenMC. While several utilities -of varying complexity are provided to help automate the process, in many cases -it will be extremely beneficial to do some coding in Python to quickly obtain -results. In these cases, and for many of the provided utilities, it is necessary -for your Python installation to contain: +of varying complexity are provided to help automate the process, the most +powerful capabilities for post-processing derive from use of the :ref:`Python +API `. Both the provided scripts and the Python API rely on a number +third-party Python packages, including: -* [1]_ `Numpy `_ -* [1]_ `Scipy `_ -* [2]_ `h5py `_ -* [3]_ `Matplotlib `_ -* [3]_ `Silomesh `_ -* [3]_ `VTK `_ +* [1]_ `NumPy `_ +* [2]_ `h5py `_ +* [3]_ `pandas `_ +* [4]_ `matplotlib `_ +* [4]_ `Silomesh `_ +* [4]_ `VTK `_ +* [4]_ `lxml `_ -Most of these are easily obtainable in Ubuntu through the package manager, or -are easily installed with distutils. +Most of these are can easily be installed with `pip `_ +or alternatively obtaining through a package manager. -.. [1] Required for tally data extraction from statepoints with statepoint.py -.. [2] Required only if reading HDF5 statepoint files. -.. [3] Optional for plotting utilities +.. [1] Required for most post-processing tasks +.. [2] Required for reading HDF5 output files +.. [3] Optional dependency for advanced features in Python API +.. [4] Not used directly by the Python API, but are optional dependencies for a + number of scripts. ---------------------- Geometry Visualization ---------------------- Geometry plotting is carried out by creating a plots.xml, specifying plots, and -running OpenMC with the -plot or -p command-line option (See +running OpenMC with the --plot or -p command-line option (See :ref:`usersguide_plotting`). Plotting in 2D @@ -128,27 +131,26 @@ capabilities of 3D voxel plots. Voxel plots are built the same way 2D slice plots are, by determining the cell or material id of a particle at the center of each voxel. In this example, the space covered is the cube between the points (-5,-5,-5) and (5,5,5), with voxel -centers 10/500 = 0.02 cm apart. The binary VOXEL files that are produced do not +centers 10/500 = 0.02 cm apart. The HDF5 voxel files that are produced do not specify any color - instead containing only material or cell ids (material id in this example) - and thus the ``background``, ``col_spec``, and ``mask`` elements are not used. If no cell is found at a voxel center, an id of -1 is stored. -The binary VOXEL files output by OpenMC can not be viewed directly by any -existing viewers. In order to view them, they must be converted into a standard -mesh format that can be viewed in ParaView, Visit, etc. This typically will -compress the size of the file significantly. The provided utility voxel.py -accomplishes this for SILO: +The voxel plot data is written to an HDF5 file. The voxel file can subsequently +be converted into a standard mesh format that can be viewed in ParaView, Visit, +etc. This typically will compress the size of the file significantly. The +provided utility openmc-voxel-to-silovtk accomplishes this for SILO: .. code-block:: sh - /src/utils/voxel.py myplot.voxel -o output.silo + openmc-voxel-to-silovtk myplot.voxel -o output.silo and VTK file formats: .. code-block:: sh - /src/utils/voxel.py myplot.voxel --vtk -o output.vti + openmc-voxel-to-silovtk myplot.voxel --vtk -o output.vti To use this utility you need either @@ -156,11 +158,10 @@ To use this utility you need either or -* `VTK `_ with python bindings - On Ubuntu, these are - easily obtained with ``sudo apt-get install python-vtk`` +* `VTK `_ with python bindings. On debian derivatives, + these are easily obtained with ``sudo apt-get install python-vtk`` -Users can process the binary into any other format if desired by following the -example of voxel.py. For the binary file structure, see :ref:`devguide_voxel`. +For the HDF5 file structure, see :ref:`usersguide_voxel`. Once processed into a standard 3D file format, colors and masks can be defined using the stored id numbers to better explore the geometry. The process for @@ -183,150 +184,38 @@ doing this will depend on the 3D viewer, but should be straightforward. Tally Visualization ------------------- -Tally results are saved in both a text file (tallies.out) as well as a binary +Tally results are saved in both a text file (tallies.out) as well as an HDF5 statepoint file. While the tallies.out file may be fine for simple tallies, in -many cases the user requires more information about the tally or the run, or -has to deal with a large number of result values (e.g. for mesh tallies). In -these cases, extracting data from the statepoint file via Python scripting is -the preferred method of data analysis and visualization. +many cases the user requires more information about the tally or the run, or has +to deal with a large number of result values (e.g. for mesh tallies). In these +cases, extracting data from the statepoint file via the :ref:`pythonapi` is the +preferred method of data analysis and visualization. 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 -utility statepoint.py. This utility provides a Python class to load statepoints -and extract data - it is used in many of the provided plotting utilities, and -can be used in user-created scripts to carry out manipulations of the data. To -read tallies using this utility, make sure statepoint.py is in your PYTHONPATH, -and then import the class, instantiate it, and call read_results: +:ref:`usersguide_statepoint`), all of which is accessible through the Python +API. The ``openmc.statepoint`` module (see :ref:`pythonapi_statepoint`) provides +a class to load statepoints and access data as requested; it is used in many of +the provided plotting utilities, OpenMC's regression test suite, and can be used +in user-created scripts to carry out manipulations of the data. -.. code-block:: python - - from statepoint import StatePoint - sp = StatePoint('statepoint.100.binary') - sp.read_results() - -At this point the user can extract entire scores from tallies into a data -dictionary containing numpy arrays: - -.. code-block:: python - - tallyid = 1 - score = 'flux' - data = sp.extract_results(tallyid, score) - means = data['means'] - print data.keys() - -The results from this function contain all filter bins (all mesh points, all -energy groups, etc.), which can be reshaped with the bin ordering also contained -in the output dictionary. This is the best choice of output for easily -integrating ranges of data. - -Alternatively the user can extract specific values for a single score/filter -combination: - -.. code-block:: python - - tallyid = 1 - score = 'flux' - filters = [('mesh', (1, 1, 5)), ('energyin', 0)] - value, error = sp.get_value(tallyid, filters, score) - -In the future more documentation may become available here for statepoint.py and -the data extraction functions of StatePoint objects. However, for now it is up -to the user to explore the classes in statepoint.py to discover what data is -available in StatePoint objects (we highly recommend interactively exploring -with `IPython `_). Many examples can be found by looking -through the other utilities that use statepoint.py, and a few common -visualization tasks will be described here in the following sections. +An :ref:`example IPython notebook ` demonstrates how +to extract data from a statepoint using the Python API. Plotting in 2D -------------- +The :ref:`IPython notebook example ` also demonstrates +how to plot a mesh tally in two dimensions using the Python API. Note, however, +that there is also a script distributed with OpenMC, ``openmc-plot-mesh-tally``, +that provides an interactive GUI to explore and plot mesh tallies for any scores +and filter bins. + .. image:: ../_images/plotmeshtally.png :height: 200px -For simple viewing of 2D slices of a mesh plot, the utility plot_mesh_tally.py -is provided. This utility provides an interactive GUI to explore and plot -mesh tallies for any scores and filter bins. It requires statepoint.py. - -.. image:: ../_images/fluxplot.png - :height: 200px - -Alternatively, the user can write their own Python script to manipulate the data -appropriately. Consider a run where the first tally contains a 105x105x20 mesh -over a small core, with a flux score and two energyin filter bins. To explicitly -extract the data and create a plot with gnuplot, the following script can be -used. The script operates in several steps for clarity, and is not necessarily -the most efficient way to extract data from large mesh tallies. This creates the -two heatmaps in the previous figure. - -.. code-block:: python - - #!/usr/bin/env python - - import os - - import statepoint - - # load and parse the statepoint file - sp = statepoint.StatePoint('statepoint.300.binary') - sp.read_results() - - tallyid = 0 # This is tally 1 - score = 0 # This corresponds to flux (see tally.scores) - - # get mesh dimensions - meshid = sp.tallies[tallyid].filters['mesh'].bins[0] - for i,m in enumerate(sp.meshes): - if m.id == meshid: - mesh = m - break - nx,ny,nz = mesh.dimension - - # loop through mesh and extract values to python dictionaries - thermal = {} - fast = {} - for x in range(1,nx+1): - for y in range(1,ny+1): - for z in range(1,nz+1): - val,err = sp.get_value(tallyid, - [('mesh',(x,y,z)),('energyin',0)], - score) - thermal[(x,y,z)] = val - val,err = sp.get_value(tallyid, - [('mesh',(x,y,z)),('energyin',1)], - score) - fast[(x,y,z)] = val - - # sum up the axial values and write datafile for gnuplot - with open('meshdata.dat','w') as fh: - for x in range(1,nx+1): - for y in range(1,ny+1): - thermalval = 0. - fastval = 0. - for z in range(1,nz+1): - thermalval += thermal[(x,y,z)] - fastval += fast[(x,y,z)] - fh.write("{} {} {} {}\n".format(x,y,thermalval,fastval)) - - # write gnuplot file - with open('tmp.gnuplot','w') as fh: - fh.write(r"""set terminal png size 1000 400 - set output 'fluxplot.png' - set nokey - set autoscale fix - set multiplot layout 1,2 title "Pin Mesh Flux Tally" - set title "Thermal" - plot 'meshdata.dat' using 1:2:3 with image - set title "Fast" - plot 'meshdata.dat' using 1:2:4 with image - """) - - # make plot - os.system("gnuplot < tmp.gnuplot") - Plotting in 3D -------------- @@ -334,22 +223,23 @@ Plotting in 3D :height: 200px As with 3D plots of the geometry, meshtally data needs to be put into a standard -format for viewing. The utility statepoint_3d.py is provided to accomplish this -for both VTK and SILO. By default statepoint_3d.py processes a statepoint into a -3D file with all mesh tallies and filter/score combinations, +format for viewing. The utility ``openmc-statepoint-3d`` is provided to +accomplish this for both VTK and SILO. By default ``openmc-statepoint-3d`` +processes a statepoint into a 3D file with all mesh tallies and filter/score +combinations, .. code-block:: sh - /src/utils/statepoint_3d.py -o output.silo - /src/utils/statepoint_3d.py --vtk -o output.vtm + openmc-statepoint-3d -o output.silo + openmc-statepoint-3d --vtk -o output.vtm but it also provides several command-line options to selectively process only certain data arrays in order to keep file sizes down. .. code-block:: sh - statepoint_3d.py --tallies 2,4 --scores 4.1,4.3 -o output.silo - statepoint_3d.py --filters 2.energyin.1 --vtk -o output.vtm + openmc-statepoint-3d --tallies 2,4 --scores 4.1,4.3 -o output.silo + openmc-statepoint-3d --filters 2.energyin.1 --vtk -o output.vtm All available options for specifying a subset of tallies, scores, and filters can be listed with the ``--list`` or ``-l`` command line options. @@ -426,13 +316,11 @@ Getting Data into MATLAB ------------------------ There is currently no front-end utility to dump tally data to MATLAB files, but -the process is straightforward. First extract the data using a custom Python -script with statepoint.py, put the data into appropriately-shaped numpy arrays, -and then use the `Scipy MATLAB IO routines +the process is straightforward. First extract the data using the Python API via +``openmc.statepoint`` and then use the `Scipy MATLAB IO routines `_ to save to a MAT -file. Note that the data contained in the output from -``StatePoint.extract_result`` is already in a Numpy array that can be reshaped -and dumped to MATLAB in one step. +file. Note that all arrays that are accessible in a statepoint are already in +NumPy arrays that can be reshaped and dumped to MATLAB in one step. ---------------------------- Particle Track Visualization @@ -463,15 +351,15 @@ particle numbers, respectively. For example, to output the tracks for particles After running OpenMC, the directory should contain a file of the form -"track_(batch #)_(generation #)_(particle #).(binary or h5)" for each particle -tracked. These track files can be converted into VTK poly data files with the -"track.py" utility. The usage of track.py is of the form "track.py [-o OUT] IN" -where OUT is the optional output filename and IN is one or more filenames -describing track files. The default output name is "track.pvtp". A common -usage of track.py is "track.py track*.binary" which will use the data from all -binary track files in the directory to write a "track.pvtp" VTK output file. -The .pvtp file can then be read and plotted by 3d visualization programs such as -ParaView. +"track_(batch #)_(generation #)_(particle #).h5" for each particle tracked. +These track files can be converted into VTK poly data files with the +``openmc-track-to-vtk`` utility. The usage of ``openmc-track-to-vtk`` is of the +form "openmc-track-to-vtk [-o OUT] IN" where OUT is the optional output filename +and IN is one or more filenames describing track files. The default output name +is "track.pvtp". A common usage of track.py is "openmc-track-to-vtk track*.h5" +which will use the data from all binary track files in the directory to write a +"track.pvtp" VTK output file. The .pvtp file can then be read and plotted by 3d +visualization programs such as ParaView. ---------------------- Source Site Processing @@ -480,43 +368,6 @@ Source Site Processing For eigenvalue problems, OpenMC will store information on the fission source sites in the statepoint file by default. For each source site, the weight, position, sampled direction, and sampled energy are stored. To extract this data -from a statepoint file, the statepoint.py Python module can be used. Below is an -example of an interactive ipython session using the statepoint.py Python module: - -.. code-block:: python - - In [1]: import statepoint - - In [2]: sp = statepoint.StatePoint('statepoint.100.h5') - - In [3]: sp.read_source() - - In [4]: len(sp.source) - Out[4]: 1000 - - In [5]: sp.source[0:10] - Out[5]: - [, - , - , - , - , - , - , - , - , - ] - - In [6]: site = sp.source[0] - - In [7]: site.weight - Out[7]: 1.0 - - In [8]: site.xyz - Out[8]: array([ 2.21980946, -8.92686048, 87.93720485]) - - In [9]: site.uvw - Out[9]: array([ 0.06740523, 0.50612814, 0.85982024]) - - In [10]: site.E - Out[10]: 0.93292326356564159 +from a statepoint file, the ``openmc.statepoint`` module can be used. An +:ref:`example IPython notebook ` demontrates how to +analyze and plot source information. diff --git a/docs/source/usersguide/troubleshoot.rst b/docs/source/usersguide/troubleshoot.rst index 10ac12184f..c5e4e7c1e1 100644 --- a/docs/source/usersguide/troubleshoot.rst +++ b/docs/source/usersguide/troubleshoot.rst @@ -31,21 +31,6 @@ f951: error: unrecognized command line option "-fbacktrace" You are probably using a version of the gfortran compiler that is too old. Download and install the latest version of gfortran_. - -make[1]: ifort: Command not found -********************************* - -You tried compiling with the Intel Fortran compiler and it was not found on your -:envvar:`PATH`. If you have the Intel compiler installed, make sure the shell -can locate it (this can be tested with :program:`which ifort`). - -make[1]: pgf90: Command not found -********************************* - -You tried compiling with the PGI Fortran compiler and it was not found on your -:envvar:`PATH`. If you have the PGI compiler installed, make sure the shell can -locate it (this can be tested with :program:`which pgf90`). - ------------------------- Problems with Simulations ------------------------- @@ -56,13 +41,13 @@ Segmentation Fault A segmentation fault occurs when the program tries to access a variable in memory that was outside the memory allocated for the program. The best way to debug a segmentation fault is to re-compile OpenMC with debug options turned -on. First go to your ``openmc/src`` directory where OpenMC was compiled and type -the following commands: +on. Create a new build directory and type the following commands: .. code-block:: sh - make distclean - make DEBUG=yes + mkdir build-debug && cd build-debug + cmake -Ddebug=on /path/to/openmc + make Now when you re-run your problem, it should report exactly where the program failed. If after reading the debug output, you are still unsure why the program diff --git a/examples/python/basic/build-xml.py b/examples/python/basic/build-xml.py index fb850f3add..488603d33f 100644 --- a/examples/python/basic/build-xml.py +++ b/examples/python/basic/build-xml.py @@ -1,6 +1,5 @@ import openmc - ############################################################################### # Simulation Input File Parameters ############################################################################### @@ -54,12 +53,11 @@ cell2 = openmc.Cell(cell_id=100, name='cell 2') cell3 = openmc.Cell(cell_id=101, name='cell 3') cell4 = openmc.Cell(cell_id=2, name='cell 4') -# Register Surfaces with Cells -cell1.add_surface(surface=surf2, halfspace=-1) -cell2.add_surface(surface=surf1, halfspace=-1) -cell3.add_surface(surface=surf1, halfspace=+1) -cell4.add_surface(surface=surf2, halfspace=+1) -cell4.add_surface(surface=surf3, halfspace=-1) +# Use surface half-spaces to define regions +cell1.region = -surf2 +cell2.region = -surf1 +cell3.region = +surf1 +cell4.region = +surf2 & -surf3 # Register Materials with Cells cell2.fill = fuel diff --git a/examples/python/boxes/build-xml.py b/examples/python/boxes/build-xml.py new file mode 100644 index 0000000000..9c28d37bb3 --- /dev/null +++ b/examples/python/boxes/build-xml.py @@ -0,0 +1,136 @@ +import numpy as np + +import openmc + +############################################################################### +# Simulation Input File Parameters +############################################################################### + +# OpenMC simulation parameters +batches = 15 +inactive = 5 +particles = 10000 + + +############################################################################### +# Exporting to OpenMC materials.xml File +############################################################################### + +# Instantiate some Nuclides +h1 = openmc.Nuclide('H-1') +o16 = openmc.Nuclide('O-16') +u235 = openmc.Nuclide('U-235') +u238 = openmc.Nuclide('U-238') + +# Instantiate some Materials and register the appropriate Nuclides +fuel1 = openmc.Material(material_id=1, name='fuel') +fuel1.set_density('g/cc', 4.5) +fuel1.add_nuclide(u235, 1.) + +fuel2 = openmc.Material(material_id=2, name='depleted fuel') +fuel2.set_density('g/cc', 4.5) +fuel2.add_nuclide(u238, 1.) + +moderator = openmc.Material(material_id=3, name='moderator') +moderator.set_density('g/cc', 1.0) +moderator.add_nuclide(h1, 2.) +moderator.add_nuclide(o16, 1.) +moderator.add_s_alpha_beta('HH2O', '71t') + +# Instantiate a MaterialsFile, register all Materials, and export to XML +materials_file = openmc.MaterialsFile() +materials_file.default_xs = '71c' +materials_file.add_materials([fuel1, fuel2, moderator]) +materials_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC geometry.xml File +############################################################################### + +# Instantiate planar surfaces +x1 = openmc.XPlane(surface_id=1, x0=-10) +x2 = openmc.XPlane(surface_id=2, x0=-7) +x3 = openmc.XPlane(surface_id=3, x0=-4) +x4 = openmc.XPlane(surface_id=4, x0=4) +x5 = openmc.XPlane(surface_id=5, x0=7) +x6 = openmc.XPlane(surface_id=6, x0=10) +y1 = openmc.YPlane(surface_id=11, y0=-10) +y2 = openmc.YPlane(surface_id=12, y0=-7) +y3 = openmc.YPlane(surface_id=13, y0=-4) +y4 = openmc.YPlane(surface_id=14, y0=4) +y5 = openmc.YPlane(surface_id=15, y0=7) +y6 = openmc.YPlane(surface_id=16, y0=10) +z1 = openmc.ZPlane(surface_id=21, z0=-10) +z2 = openmc.ZPlane(surface_id=22, z0=-7) +z3 = openmc.ZPlane(surface_id=23, z0=-4) +z4 = openmc.ZPlane(surface_id=24, z0=4) +z5 = openmc.ZPlane(surface_id=25, z0=7) +z6 = openmc.ZPlane(surface_id=26, z0=10) + +# Set vacuum boundary conditions on outside +for surface in [x1, x6, y1, y6, z1, z6]: + surface.boundary_type = 'vacuum' + +# Instantiate Cells +inner_box = openmc.Cell(cell_id=1, name='inner box') +middle_box = openmc.Cell(cell_id=2, name='middle box') +outer_box = openmc.Cell(cell_id=3, name='outer box') + +# Use each set of six planes to create solid cube regions. We can then use these +# to create cubic shells. +inner_cube = +x3 & -x4 & +y3 & -y4 & +z3 & -z4 +middle_cube = +x2 & -x5 & +y2 & -y5 & +z2 & -z5 +outer_cube = +x1 & -x6 & +y1 & -y6 & +z1 & -z6 +outside_inner_cube = -x3 | +x4 | -y3 | +y4 | -z3 | +z4 + +# Use surface half-spaces to define regions +inner_box.region = inner_cube +middle_box.region = middle_cube & outside_inner_cube +outer_box.region = outer_cube & ~middle_cube + +# Register Materials with Cells +inner_box.fill = fuel1 +middle_box.fill = fuel2 +outer_box.fill = moderator + +# Instantiate root universe +root = openmc.Universe(universe_id=0, name='root universe') +root.add_cells([inner_box, middle_box, outer_box]) + +# Instantiate a Geometry and register the root Universe +geometry = openmc.Geometry() +geometry.root_universe = root + +# Instantiate a GeometryFile, register Geometry, and export to XML +geometry_file = openmc.GeometryFile() +geometry_file.geometry = geometry +geometry_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC settings.xml File +############################################################################### + +# Instantiate a SettingsFile, set all runtime parameters, and export to XML +settings_file = openmc.SettingsFile() +settings_file.batches = batches +settings_file.inactive = inactive +settings_file.particles = particles +settings_file.set_source_space('box', np.concatenate(outer_cube.bounding_box)) +settings_file.export_to_xml() + +############################################################################### +# Exporting to OpenMC plots.xml File +############################################################################### + +plot = openmc.Plot(plot_id=1) +plot.origin = [0, 0, 0] +plot.width = [20, 20] +plot.pixels = [200, 200] +plot.color = 'cell' + +# Instantiate a PlotsFile, add Plot, and export to XML +plot_file = openmc.PlotsFile() +plot_file.add_plot(plot) +plot_file.export_to_xml() diff --git a/examples/python/lattice/hexagonal/build-xml.py b/examples/python/lattice/hexagonal/build-xml.py index 5cf8eed062..5fa0f9b1b9 100644 --- a/examples/python/lattice/hexagonal/build-xml.py +++ b/examples/python/lattice/hexagonal/build-xml.py @@ -67,15 +67,12 @@ cell4 = openmc.Cell(cell_id=500, name='cell 4') cell5 = openmc.Cell(cell_id=600, name='cell 5') cell6 = openmc.Cell(cell_id=601, name='cell 6') -# Register Surfaces with Cells -cell1.add_surface(left, halfspace=+1) -cell1.add_surface(right, halfspace=-1) -cell1.add_surface(bottom, halfspace=+1) -cell1.add_surface(top, halfspace=-1) -cell2.add_surface(fuel_surf, halfspace=-1) -cell3.add_surface(fuel_surf, halfspace=+1) -cell5.add_surface(fuel_surf, halfspace=-1) -cell6.add_surface(fuel_surf, halfspace=+1) +# Use surface half-spaces to define regions +cell1.region = +left & -right & +bottom & -top +cell2.region = -fuel_surf +cell3.region = +fuel_surf +cell5.region = -fuel_surf +cell6.region = +fuel_surf # Register Materials with Cells cell2.fill = fuel diff --git a/examples/python/lattice/nested/build-xml.py b/examples/python/lattice/nested/build-xml.py index ce67665429..501b3ee4b4 100644 --- a/examples/python/lattice/nested/build-xml.py +++ b/examples/python/lattice/nested/build-xml.py @@ -66,21 +66,15 @@ cell6 = openmc.Cell(cell_id=202, name='cell 6') cell7 = openmc.Cell(cell_id=301, name='cell 7') cell8 = openmc.Cell(cell_id=302, name='cell 8') -# Register Surfaces with Cells -cell1.add_surface(left, halfspace=+1) -cell1.add_surface(right, halfspace=-1) -cell1.add_surface(bottom, halfspace=+1) -cell1.add_surface(top, halfspace=-1) -cell2.add_surface(left, halfspace=+1) -cell2.add_surface(right, halfspace=-1) -cell2.add_surface(bottom, halfspace=+1) -cell2.add_surface(top, halfspace=-1) -cell3.add_surface(fuel1, halfspace=-1) -cell4.add_surface(fuel1, halfspace=+1) -cell5.add_surface(fuel2, halfspace=-1) -cell6.add_surface(fuel2, halfspace=+1) -cell7.add_surface(fuel3, halfspace=-1) -cell8.add_surface(fuel3, halfspace=+1) +# Use surface half-space to define regions +cell1.region = +left & -right & +bottom & -top +cell2.region = +left & -right & +bottom & -top +cell3.region = -fuel1 +cell4.region = +fuel1 +cell5.region = -fuel2 +cell6.region = +fuel2 +cell7.region = -fuel3 +cell8.region = +fuel3 # Register Materials with Cells cell3.fill = fuel @@ -168,7 +162,7 @@ plot_file.export_to_xml() # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) -mesh.type = 'rectangular' +mesh.type = 'regular' mesh.dimension = [4, 4] mesh.lower_left = [-2, -2] mesh.width = [1, 1] diff --git a/examples/python/lattice/simple/build-xml.py b/examples/python/lattice/simple/build-xml.py index 675c7e08ba..00fbea22a4 100644 --- a/examples/python/lattice/simple/build-xml.py +++ b/examples/python/lattice/simple/build-xml.py @@ -1,6 +1,5 @@ import openmc - ############################################################################### # Simulation Input File Parameters ############################################################################### @@ -65,17 +64,14 @@ cell5 = openmc.Cell(cell_id=202, name='cell 5') cell6 = openmc.Cell(cell_id=301, name='cell 6') cell7 = openmc.Cell(cell_id=302, name='cell 7') -# Register Surfaces with Cells -cell1.add_surface(left, halfspace=+1) -cell1.add_surface(right, halfspace=-1) -cell1.add_surface(bottom, halfspace=+1) -cell1.add_surface(top, halfspace=-1) -cell2.add_surface(fuel1, halfspace=-1) -cell3.add_surface(fuel1, halfspace=+1) -cell4.add_surface(fuel2, halfspace=-1) -cell5.add_surface(fuel2, halfspace=+1) -cell6.add_surface(fuel3, halfspace=-1) -cell7.add_surface(fuel3, halfspace=+1) +# Use surface half-spaces to define regions +cell1.region = +left & -right & +bottom & -top +cell2.region = -fuel1 +cell3.region = +fuel1 +cell4.region = -fuel2 +cell5.region = +fuel2 +cell6.region = -fuel3 +cell7.region = +fuel3 # Register Materials with Cells cell2.fill = fuel @@ -157,7 +153,7 @@ plot_file.export_to_xml() # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) -mesh.type = 'rectangular' +mesh.type = 'regular' mesh.dimension = [4, 4] mesh.lower_left = [-2, -2] mesh.width = [1, 1] diff --git a/examples/python/pincell/build-xml.py b/examples/python/pincell/build-xml.py index 9338aff0e9..b3bb932dc8 100644 --- a/examples/python/pincell/build-xml.py +++ b/examples/python/pincell/build-xml.py @@ -1,6 +1,5 @@ import openmc - ############################################################################### # Simulation Input File Parameters ############################################################################### @@ -132,17 +131,11 @@ gap = openmc.Cell(cell_id=2, name='cell 2') clad = openmc.Cell(cell_id=3, name='cell 3') water = openmc.Cell(cell_id=4, name='cell 4') -# Register Surfaces with Cells -fuel.add_surface(fuel_or, halfspace=-1) -gap.add_surface(fuel_or, halfspace=+1) -gap.add_surface(clad_ir, halfspace=-1) -clad.add_surface(clad_ir, halfspace=+1) -clad.add_surface(clad_or, halfspace=-1) -water.add_surface(clad_or, halfspace=+1) -water.add_surface(left, halfspace=+1) -water.add_surface(right, halfspace=-1) -water.add_surface(bottom, halfspace=+1) -water.add_surface(top, halfspace=-1) +# Use surface half-spaces to define regions +fuel.region = -fuel_or +gap.region = +fuel_or & -clad_ir +clad.region = +clad_ir & -clad_or +water.region = +clad_or & +left & -right & +bottom & -top # Register Materials with Cells fuel.fill = uo2 @@ -189,7 +182,7 @@ settings_file.export_to_xml() # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) -mesh.type = 'rectangular' +mesh.type = 'regular' mesh.dimension = [100, 100, 1] mesh.lower_left = [-0.62992, -0.62992, -1.e50] mesh.upper_right = [0.62992, 0.62992, 1.e50] diff --git a/examples/python/reflective/build-xml.py b/examples/python/reflective/build-xml.py index 9a182903e1..44b544d20d 100644 --- a/examples/python/reflective/build-xml.py +++ b/examples/python/reflective/build-xml.py @@ -1,5 +1,6 @@ -import openmc +import numpy as np +import openmc ############################################################################### # Simulation Input File Parameters @@ -52,13 +53,8 @@ surf6.boundary_type = 'reflective' # Instantiate Cell cell = openmc.Cell(cell_id=1, name='cell 1') -# Register Surfaces with Cell -cell.add_surface(surface=surf1, halfspace=+1) -cell.add_surface(surface=surf2, halfspace=-1) -cell.add_surface(surface=surf3, halfspace=+1) -cell.add_surface(surface=surf4, halfspace=-1) -cell.add_surface(surface=surf5, halfspace=+1) -cell.add_surface(surface=surf6, halfspace=-1) +# Use surface half-spaces to define region +cell.region = +surf1 & -surf2 & +surf3 & -surf4 & +surf5 & -surf6 # Register Material with Cell cell.fill = fuel @@ -88,5 +84,5 @@ settings_file = openmc.SettingsFile() settings_file.batches = batches settings_file.inactive = inactive settings_file.particles = particles -settings_file.set_source_space('box', [-1, -1, -1, 1, 1, 1]) +settings_file.set_source_space('box', np.concatenate(cell.region.bounding_box)) settings_file.export_to_xml() diff --git a/examples/xml/basic/geometry.xml b/examples/xml/basic/geometry.xml index e9483306c0..b30884f8ca 100644 --- a/examples/xml/basic/geometry.xml +++ b/examples/xml/basic/geometry.xml @@ -2,14 +2,14 @@ - - - - + + + + - + diff --git a/examples/xml/boxes/geometry.xml b/examples/xml/boxes/geometry.xml new file mode 100644 index 0000000000..abe4924e66 --- /dev/null +++ b/examples/xml/boxes/geometry.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/xml/boxes/materials.xml b/examples/xml/boxes/materials.xml new file mode 100644 index 0000000000..6f6114a7da --- /dev/null +++ b/examples/xml/boxes/materials.xml @@ -0,0 +1,23 @@ + + + + 71c + + + + + + + + + + + + + + + + + + + diff --git a/examples/xml/boxes/plots.xml b/examples/xml/boxes/plots.xml new file mode 100644 index 0000000000..b7a3093d25 --- /dev/null +++ b/examples/xml/boxes/plots.xml @@ -0,0 +1,9 @@ + + + + cell + 0. 0. 0. + 20. 20. + 200 200 + + diff --git a/examples/xml/boxes/settings.xml b/examples/xml/boxes/settings.xml new file mode 100644 index 0000000000..eff7c1c105 --- /dev/null +++ b/examples/xml/boxes/settings.xml @@ -0,0 +1,16 @@ + + + + + + 15 + 5 + 10000 + + + + + + + + diff --git a/examples/xml/lattice/nested/geometry.xml b/examples/xml/lattice/nested/geometry.xml index 9df9b9e931..324f71cb36 100644 --- a/examples/xml/lattice/nested/geometry.xml +++ b/examples/xml/lattice/nested/geometry.xml @@ -1,14 +1,14 @@ - - - - - - - - + + + + + + + + diff --git a/examples/xml/lattice/nested/tallies.xml b/examples/xml/lattice/nested/tallies.xml index 5730e6b12c..89c0774f15 100644 --- a/examples/xml/lattice/nested/tallies.xml +++ b/examples/xml/lattice/nested/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular 4 4 -2.0 -2.0 1.0 1.0 diff --git a/examples/xml/lattice/simple/geometry.xml b/examples/xml/lattice/simple/geometry.xml index c1f8d78644..bda7246c79 100644 --- a/examples/xml/lattice/simple/geometry.xml +++ b/examples/xml/lattice/simple/geometry.xml @@ -1,13 +1,13 @@ - - - - - - - + + + + + + + 4 4 diff --git a/examples/xml/lattice/simple/tallies.xml b/examples/xml/lattice/simple/tallies.xml index 5730e6b12c..89c0774f15 100644 --- a/examples/xml/lattice/simple/tallies.xml +++ b/examples/xml/lattice/simple/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular 4 4 -2.0 -2.0 1.0 1.0 diff --git a/examples/xml/pincell/geometry.xml b/examples/xml/pincell/geometry.xml index 53cb2f15dc..f67f9e74c2 100644 --- a/examples/xml/pincell/geometry.xml +++ b/examples/xml/pincell/geometry.xml @@ -19,9 +19,9 @@ - - - - + + + + diff --git a/examples/xml/pincell/tallies.xml b/examples/xml/pincell/tallies.xml index bbfd588360..73242b9136 100644 --- a/examples/xml/pincell/tallies.xml +++ b/examples/xml/pincell/tallies.xml @@ -1,7 +1,7 @@ - + 100 100 1 -0.62992 -0.62992 -1.e50 0.62992 0.62992 1.e50 @@ -13,4 +13,4 @@ flux fission nu-fission - \ No newline at end of file + diff --git a/examples/xml/reflective/geometry.xml b/examples/xml/reflective/geometry.xml index 664ef0705f..51cdf1ecb0 100644 --- a/examples/xml/reflective/geometry.xml +++ b/examples/xml/reflective/geometry.xml @@ -5,15 +5,15 @@ 0 1 - 1 -2 3 -4 5 -6 + 1 -2 3 -4 5 -6 - + - + - + diff --git a/openmc/__init__.py b/openmc/__init__.py index d966a155a4..397d9f3e27 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -12,6 +12,8 @@ from openmc.trigger import * from openmc.tallies import * from openmc.cmfd import * from openmc.executor import * +from openmc.statepoint import * +from openmc.summary import * try: from openmc.opencg_compatible import * diff --git a/openmc/clean_xml.py b/openmc/clean_xml.py index 2bb3f39f1b..564281a5cc 100644 --- a/openmc/clean_xml.py +++ b/openmc/clean_xml.py @@ -1,7 +1,7 @@ def sort_xml_elements(tree): # Retrieve all children of the root XML node in the tree - elements = tree.getchildren() + elements = list(tree) # Initialize empty lists for the sorted and comment elements sorted_elements = [] @@ -29,7 +29,7 @@ def sort_xml_elements(tree): comment_elements.append((element, next_element)) # Now iterate over all tags and order the elements within each tag - for tag in tags: + for tag in sorted(list(tags)): # Retrieve all of the elements for this tag try: diff --git a/openmc/constants.py b/openmc/constants.py deleted file mode 100644 index a6b535e6d1..0000000000 --- a/openmc/constants.py +++ /dev/null @@ -1,123 +0,0 @@ -"""Dictionaries of integer-to-string mappings from openmc/src/constants.F90""" - -SURFACE_TYPES = {1: 'x-plane', - 2: 'y-plane', - 3: 'z-plane', - 4: 'plane', - 5: 'x-cylinder', - 6: 'y-cylinder', - 7: 'z-cylinder', - 8: 'sphere', - 9: 'x-cone', - 10: 'y-cone', - 11: 'z-cone'} - -BC_TYPES = {0: 'transmission', - 1: 'vacuum', - 2: 'reflective', - 3: 'periodic'} - -FILL_TYPES = {1: 'normal', - 2: 'fill', - 3: 'lattice'} - -LATTICE_TYPES = {1: 'rectangular', - 2: 'hexagonal'} - -ESTIMATOR_TYPES = {1: 'analog', - 2: 'tracklength'} - -FILTER_TYPES = {1: 'universe', - 2: 'material', - 3: 'cell', - 4: 'cellborn', - 5: 'surface', - 6: 'mesh', - 7: 'energy', - 8: 'energyout', - 9: 'distribcell'} - -SCORE_TYPES = {-1: 'flux', - -2: 'total', - -3: 'scatter', - -4: 'nu-scatter', - -5: 'scatter-n', - -6: 'scatter-pn', - -7: 'nu-scatter-n', - -8: 'nu-scatter-pn', - -9: 'transport', - -10: 'n1n', - -11: 'absorption', - -12: 'fission', - -13: 'nu-fission', - -14: 'kappa-fission', - -15: 'current', - -16: 'flux-yn', - -17: 'total-yn', - -18: 'scatter-yn', - -19: 'nu-scatter-yn', - -20: 'events', - 1: '(n,total)', - 2: '(n,elastic)', - 4: '(n,level)', - 11: '(n,2nd)', - 16: '(n,2n)', - 17: '(n,3n)', - 18: '(n,fission)', - 19: '(n,f)', - 20: '(n,nf)', - 21: '(n,2nf)', - 22: '(n,na)', - 23: '(n,n3a)', - 24: '(n,2na)', - 25: '(n,3na)', - 28: '(n,np)', - 29: '(n,n2a)', - 30: '(n,2n2a)', - 32: '(n,nd)', - 33: '(n,nt)', - 34: '(n,nHe-3)', - 35: '(n,nd2a)', - 36: '(n,nt2a)', - 37: '(n,4n)', - 38: '(n,3nf)', - 41: '(n,2np)', - 42: '(n,3np)', - 44: '(n,n2p)', - 45: '(n,npa)', - 91: '(n,nc)', - 101: '(n,disappear)', - 102: '(n,gamma)', - 103: '(n,p)', - 104: '(n,d)', - 105: '(n,t)', - 106: '(n,3He)', - 107: '(n,a)', - 108: '(n,2a)', - 109: '(n,3a)', - 111: '(n,2p)', - 112: '(n,pa)', - 113: '(n,t2a)', - 114: '(n,d2a)', - 115: '(n,pd)', - 116: '(n,pt)', - 117: '(n,da)', - 201: '(n,Xn)', - 202: '(n,Xgamma)', - 203: '(n,Xp)', - 204: '(n,Xd)', - 205: '(n,Xt)', - 206: '(n,X3He)', - 207: '(n,Xa)', - 444: '(damage)', - 649: '(n,pc)', - 699: '(n,dc)', - 749: '(n,tc)', - 799: '(n,3Hec)', - 849: '(n,tc)'} -SCORE_TYPES.update({MT: '(n,n' + str(MT-50) + ')' for MT in range(51,91)}) -SCORE_TYPES.update({MT: '(n,p' + str(MT-600) + ')' for MT in range(600,649)}) -SCORE_TYPES.update({MT: '(n,d' + str(MT-650) + ')' for MT in range(650,699)}) -SCORE_TYPES.update({MT: '(n,t' + str(MT-700) + ')' for MT in range(700,749)}) -SCORE_TYPES.update({MT: '(n,3He' + str(MT-750) + ')' for MT in range(750,649)}) -SCORE_TYPES.update({MT: '(n,a' + str(MT-800) + ')' for MT in range(800,849)}) diff --git a/openmc/cross.py b/openmc/cross.py index 735bb4cd26..c03ee51885 100644 --- a/openmc/cross.py +++ b/openmc/cross.py @@ -1,9 +1,20 @@ +import sys + from openmc import Filter, Nuclide +from openmc.filter import _FILTER_TYPES +import openmc.checkvalue as cv + + +if sys.version_info[0] >= 3: + basestring = str + +# Acceptable tally arithmetic binary operations +_TALLY_ARITHMETIC_OPS = ['+', '-', '*', '/', '^'] class CrossScore(object): """A special-purpose tally score used to encapsulate all combinations of two - tally's scores as a outer product for tally arithmetic. + tally's scores as an outer product for tally arithmetic. Parameters ---------- @@ -40,6 +51,38 @@ class CrossScore(object): if binary_op is not None: self.binary_op = binary_op + def __hash__(self): + return hash(repr(self)) + + def __eq__(self, other): + return str(other) == str(self) + + def __ne__(self, other): + return not self == other + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy this object, create a copy + if existing is None: + clone = type(self).__new__(type(self)) + clone._left_score = self.left_score + clone._right_score = self.right_score + clone._binary_op = self.binary_op + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + + def __repr__(self): + string = '({0} {1} {2})'.format(self.left_score, + self.binary_op, self.right_score) + return string + @property def left_score(self): return self._left_score @@ -54,28 +97,24 @@ class CrossScore(object): @left_score.setter def left_score(self, left_score): + cv.check_type('left_score', left_score, (basestring, CrossScore)) self._left_score = left_score @right_score.setter def right_score(self, right_score): + cv.check_type('right_score', right_score, (basestring, CrossScore)) self._right_score = right_score @binary_op.setter def binary_op(self, binary_op): + cv.check_type('binary_op', binary_op, (basestring, CrossScore)) + cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) self._binary_op = binary_op - def __eq__(self, other): - return str(other) == str(self) - - def __repr__(self): - string = '({0} {1} {2})'.format(self.left_score, - self.binary_op, self.right_score) - return string - class CrossNuclide(object): """A special-purpose nuclide used to encapsulate all combinations of two - tally's nuclides as a outer product for tally arithmetic. + tally's nuclides as an outer product for tally arithmetic. Parameters ---------- @@ -112,33 +151,33 @@ class CrossNuclide(object): if binary_op is not None: self.binary_op = binary_op - @property - def left_nuclide(self): - return self._left_nuclide - - @property - def right_nuclide(self): - return self._right_nuclide - - @property - def binary_op(self): - return self._binary_op - - @left_nuclide.setter - def left_nuclide(self, left_nuclide): - self._left_nuclide = left_nuclide - - @right_nuclide.setter - def right_nuclide(self, right_nuclide): - self._right_nuclide = right_nuclide - - @binary_op.setter - def binary_op(self, binary_op): - self._binary_op = binary_op + def __hash__(self): + return hash(repr(self)) def __eq__(self, other): return str(other) == str(self) + def __ne__(self, other): + return not self == other + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy this object, create a copy + if existing is None: + clone = type(self).__new__(type(self)) + clone._left_nuclide = self.left_nuclide + clone._right_nuclide = self.right_nuclide + clone._binary_op = self.binary_op + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + def __repr__(self): string = '' @@ -161,10 +200,38 @@ class CrossNuclide(object): return string + @property + def left_nuclide(self): + return self._left_nuclide + + @property + def right_nuclide(self): + return self._right_nuclide + + @property + def binary_op(self): + return self._binary_op + + @left_nuclide.setter + def left_nuclide(self, left_nuclide): + cv.check_type('left_nuclide', left_nuclide, (Nuclide, CrossNuclide)) + self._left_nuclide = left_nuclide + + @right_nuclide.setter + def right_nuclide(self, right_nuclide): + cv.check_type('right_nuclide', right_nuclide, (Nuclide, CrossNuclide)) + self._right_nuclide = right_nuclide + + @binary_op.setter + def binary_op(self, binary_op): + cv.check_type('binary_op', binary_op, basestring) + cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) + self._binary_op = binary_op + class CrossFilter(object): """A special-purpose filter used to encapsulate all combinations of two - tally's filter bins as a outer product for tally arithmetic. + tally's filter bins as an outer product for tally arithmetic. Parameters ---------- @@ -192,12 +259,10 @@ class CrossFilter(object): left_type = left_filter.type right_type = right_filter.type - self.type = '({0} {1} {2})'.format(left_type, binary_op, right_type) + self._type = '({0} {1} {2})'.format(left_type, binary_op, right_type) self._bins = {} - self._bins['left'] = left_filter.bins - self._bins['right'] = right_filter.bins - self._num_bins = left_filter.num_bins * right_filter.num_bins + self._stride = None self._left_filter = None self._right_filter = None @@ -205,13 +270,34 @@ class CrossFilter(object): if left_filter is not None: self.left_filter = left_filter + self._bins['left'] = left_filter.bins if right_filter is not None: self.right_filter = right_filter + self._bins['right'] = right_filter.bins if binary_op is not None: self.binary_op = binary_op def __hash__(self): - return hash((self.type, self.bins)) + return hash((self.left_filter, self.right_filter)) + + def __eq__(self, other): + return str(other) == str(self) + + def __ne__(self, other): + return not self == other + + def __repr__(self): + + string = 'CrossFilter\n' + filter_type = '({0} {1} {2})'.format(self.left_filter.type, + self.binary_op, + self.right_filter.type) + filter_bins = '({0} {1} {2})'.format(self.left_filter.bins, + self.binary_op, + self.right_filter.bins) + string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', filter_type) + string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', filter_bins) + return string def __deepcopy__(self, memo): existing = memo.get(id(self)) @@ -221,9 +307,12 @@ class CrossFilter(object): clone = type(self).__new__(type(self)) clone._left_filter = self.left_filter clone._right_filter = self.right_filter + clone._binary_op = self.binary_op clone._type = self.type - clone._bins = self.bins + clone._bins = self._bins clone._num_bins = self.num_bins + clone._stride = self.stride + memo[id(self)] = clone return clone @@ -250,54 +339,49 @@ class CrossFilter(object): @property def bins(self): - return (self._bins['left'], self._bins['right']) + return self._bins['left'], self._bins['right'] @property def num_bins(self): - return self._num_bins + if self.left_filter is not None and self.right_filter is not None: + return self.left_filter.num_bins * self.right_filter.num_bins + else: + return 0 @property def stride(self): - return self.left_filter.stride * self.right_filter.stride + return self._stride @type.setter def type(self, filter_type): + if filter_type not in _FILTER_TYPES.values(): + msg = 'Unable to set Filter type to "{0}" since it is not one ' \ + 'of the supported types'.format(filter_type) + raise ValueError(msg) + self._type = filter_type @left_filter.setter def left_filter(self, left_filter): + cv.check_type('left_filter', left_filter, (Filter, CrossFilter)) self._left_filter = left_filter + self._bins['left'] = left_filter.bins @right_filter.setter def right_filter(self, right_filter): + cv.check_type('right_filter', right_filter, (Filter, CrossFilter)) self._right_filter = right_filter + self._bins['right'] = right_filter.bins @binary_op.setter def binary_op(self, binary_op): + cv.check_type('binary_op', binary_op, basestring) + cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) self._binary_op = binary_op - def __eq__(self, other): - return str(other) == str(self) - - def split_filters(self): - - split_filters = [] - - # If left Filter is not a CrossFilter, simply append to list - if isinstance(self.left_filter, Filter): - split_filters.append(self.left_filter) - # Recursively descend CrossFilter tree to collect all Filters - else: - split_filters.extend(self.left_filter.split_filters()) - - # If right Filter is not a CrossFilter, simply append to list - if isinstance(self.right_filter, Filter): - split_filters.append(self.right_filter) - # Recursively descend CrossFilter tree to collect all Filters - else: - split_filters.extend(self.right_filter.split_filters()) - - return split_filters + @stride.setter + def stride(self, stride): + self._stride = stride def get_bin_index(self, filter_bin): """Returns the index in the CrossFilter for some bin. @@ -316,7 +400,7 @@ class CrossFilter(object): Returns ------- - filter_index : int + filter_index : Integral The index in the Tally data array for this filter bin. """ @@ -326,15 +410,56 @@ class CrossFilter(object): filter_index = left_index * self.right_filter.num_bins + right_index return filter_index - def __repr__(self): + def get_pandas_dataframe(self, datasize, summary=None): + """Builds a Pandas DataFrame for the CrossFilter's bins. - string = 'CrossFilter\n' - filter_type = '({0} {1} {2})'.format(self.left_filter.type, - self.binary_op, - self.right_filter.type) - filter_bins = '({0} {1} {2})'.format(self.left_filter.bins, - self.binary_op, - self.right_filter.bins) - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', filter_type) - string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', filter_bins) - return string + This method constructs a Pandas DataFrame object for the CrossFilter + with columns annotated by filter bin information. This is a helper + method for the Tally.get_pandas_dataframe(...) method. This method + recursively builds and concatenates Pandas DataFrames for the left + and right filters and crossfilters. + + This capability has been tested for Pandas >=0.13.1. However, it is + recommended to use v0.16 or newer versions of Pandas since this method + uses Pandas' Multi-index functionality. + + Parameters + ---------- + datasize : Integral + The total number of bins in the tally corresponding to this filter + summary : None or Summary + An optional Summary object to be used to construct columns for + distribcell tally filters (default is None). The geometric + information in the Summary object is embedded into a Multi-index + column with a geometric "path" to each distribcell instance. + NOTE: This option requires the OpenCG Python package. + + Returns + ------- + pandas.DataFrame + A Pandas DataFrame with columns of strings that characterize the + crossfilter's bins. Each entry in the DataFrame will include one + or more binary operations used to construct the crossfilter's bins. + The number of rows in the DataFrame is the same as the total number + of bins in the corresponding tally, with the filter bins + appropriately tiled to map to the corresponding tally bins. + + See also + -------- + Tally.get_pandas_dataframe(), Filter.get_pandas_dataframe() + + """ + + # If left and right filters are identical, do not combine bins + if self.left_filter == self.right_filter: + df = self.left_filter.get_pandas_dataframe(datasize, summary) + + # If left and right filters are different, combine their bins + else: + left_df = self.left_filter.get_pandas_dataframe(datasize, summary) + right_df = self.right_filter.get_pandas_dataframe(datasize, summary) + left_df = left_df.astype(str) + right_df = right_df.astype(str) + df = '(' + left_df + ' ' + self.binary_op + ' ' + right_df + ')' + + return df diff --git a/openmc/element.py b/openmc/element.py index 2f81b9f308..9f04abfdab 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -24,6 +24,8 @@ class Element(object): Chemical symbol of the element, e.g. Pu xs : str Cross section identifier, e.g. 71c + scattering : 'data' or 'iso-in-lab' or None + The type of angular scattering distribution to use """ @@ -31,6 +33,7 @@ class Element(object): # Initialize class attributes self._name = '' self._xs = None + self._scattering = None # Set class attributes self.name = name @@ -38,21 +41,33 @@ class Element(object): if xs is not None: self.xs = xs - def __eq__(self, element2): - # Check type - if not isinstance(element2, Element): + def __eq__(self, other): + if isinstance(other, Element): + if self._name != other._name: + return False + elif self._xs != other._xs: + return False + else: + return True + elif isinstance(other, basestring) and other == self.name: + return True + else: return False - # Check name and xs - if self._name != element2._name: - return False - elif self._xs != element2._xs: - return False - else: - return True + def __ne__(self, other): + return not self == other def __hash__(self): - return hash((self._name, self._xs)) + return hash(repr(self)) + + def __repr__(self): + string = 'Element - {0}\n'.format(self._name) + string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs) + if self.scattering is not None: + string += '{0: <16}{1}{2}\n'.format('\tscattering', '=\t', + self.scattering) + + return string @property def xs(self): @@ -62,6 +77,10 @@ class Element(object): def name(self): return self._name + @property + def scattering(self): + return self._scattering + @xs.setter def xs(self, xs): check_type('cross section identifier', xs, basestring) @@ -72,7 +91,12 @@ class Element(object): check_type('name', name, basestring) self._name = name - def __repr__(self): - string = 'Element - {0}\n'.format(self._name) - string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs) - return string + @scattering.setter + def scattering(self, scattering): + + if not scattering in ['data', 'iso-in-lab']: + msg = 'Unable to set scattering for Element to {0} ' \ + 'which is not "data" or "iso-in-lab"'.format(scattering) + raise ValueError(msg) + + self._scattering = scattering diff --git a/openmc/executor.py b/openmc/executor.py index 54c8a64c1a..58cb912465 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -30,14 +30,16 @@ class Executor(object): stdout=subprocess.PIPE) # Capture and re-print OpenMC output in real-time - while (True and output): - line = p.stdout.readline() - print(line, end='') - + while True: # If OpenMC is finished, break loop + line = p.stdout.readline() if not line and p.poll() != None: break + # If user requested output, print to screen + if output: + print(line, end='') + # Return the returncode (integer, zero if no problems encountered) return p.returncode diff --git a/openmc/filter.py b/openmc/filter.py index 5a81906762..04935b8edc 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1,17 +1,26 @@ from collections import Iterable import copy from numbers import Real, Integral +import sys import numpy as np from openmc import Mesh -from openmc.constants import * -from openmc.checkvalue import check_type, check_iterable_type, \ - check_greater_than +from openmc.summary import Summary +import openmc.checkvalue as cv + + +if sys.version_info[0] >= 3: + basestring = str + + +_FILTER_TYPES = ['universe', 'material', 'cell', 'cellborn', 'surface', + 'mesh', 'energy', 'energyout', 'mu', 'polar', 'azimuthal', + 'distribcell', 'delayedgroup'] class Filter(object): - """A filter used to constrain a tally to a specific criterion, e.g. only tally - events when the particle is in a certain cell and energy range. + """A filter used to constrain a tally to a specific criterion, e.g. only + tally events when the particle is in a certain cell and energy range. Parameters ---------- @@ -19,46 +28,60 @@ class Filter(object): The type of the tally filter. Acceptable values are "universe", "material", "cell", "cellborn", "surface", "mesh", "energy", "energyout", and "distribcell". - bins : int or Iterable of int or Iterable of float + bins : Integral or Iterable of Integral or Iterable of Real The bins for the filter. This takes on different meaning for different - filters. + filters. See the OpenMC online documentation for more details. Attributes ---------- type : str The type of the tally filter. - bins : int or Iterable of int or Iterable of float + bins : Integral or Iterable of Integral or Iterable of Real The bins for the filter + num_bins : Integral + The number of filter bins + mesh : Mesh or None + A Mesh object for 'mesh' type filters. + offset : Integral + A value used to index tally bins for 'distribcell' tallies. + stride : Integral + The number of filter, nuclide and score bins within each of this + filter's bins. """ # Initialize Filter class attributes def __init__(self, type=None, bins=None): - self.type = type + + self._type = None self._num_bins = 0 - self.bins = bins + self._bins = None self._mesh = None self._offset = -1 self._stride = None - def __eq__(self, filter2): - # Check type - if self.type != filter2.type: - return False + if type is not None: + self.type = type + if bins is not None: + self.bins = bins - # Check number of bins - elif len(self.bins) != len(filter2.bins): + def __eq__(self, other): + if not isinstance(other, Filter): return False - - # Check bin edges - elif not np.allclose(self.bins, filter2.bins): + elif self.type != other.type: + return False + elif len(self.bins) != len(other.bins): + return False + elif not np.allclose(self.bins, other.bins): return False - else: return True + def __ne__(self, other): + return not self == other + def __hash__(self): - return hash((self._type, self._bins)) + return hash(repr(self)) def __deepcopy__(self, memo): existing = memo.get(id(self)) @@ -81,6 +104,13 @@ class Filter(object): else: return existing + def __repr__(self): + string = 'Filter\n' + string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type) + string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins) + string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self.offset) + return string + @property def type(self): return self._type @@ -91,7 +121,14 @@ class Filter(object): @property def num_bins(self): - return self._num_bins + if self.bins is None: + return 0 + elif self.type in ['energy', 'energyout']: + return len(self.bins) - 1 + elif self.type in ['cell', 'cellborn', 'surface', 'universe', 'material']: + return len(self.bins) + else: + return self._num_bins @property def mesh(self): @@ -109,7 +146,7 @@ class Filter(object): def type(self, type): if type is None: self._type = type - elif type not in FILTER_TYPES.values(): + elif type not in _FILTER_TYPES: msg = 'Unable to set Filter type to "{0}" since it is not one ' \ 'of the supported types'.format(type) raise ValueError(msg) @@ -118,9 +155,7 @@ class Filter(object): @bins.setter def bins(self, bins): - if bins is None: - self.num_bins = 0 - elif self._type is None: + if self.type is None: msg = 'Unable to set bins for Filter to "{0}" since ' \ 'the Filter type has not yet been set'.format(bins) raise ValueError(msg) @@ -134,14 +169,14 @@ class Filter(object): bins = list(bins) if self.type in ['cell', 'cellborn', 'surface', 'material', - 'universe', 'distribcell']: - check_iterable_type('filter bins', bins, Integral) + 'universe', 'distribcell', 'delayedgroup']: + cv.check_iterable_type('filter bins', bins, Integral) for edge in bins: - check_greater_than('filter bin', edge, 0, equality=True) + cv.check_greater_than('filter bin', edge, 0, equality=True) - elif self._type in ['energy', 'energyout']: + elif self.type in ['energy', 'energyout']: for edge in bins: - if not isinstance(edge, Real): + if not cv._isinstance(edge, Real): msg = 'Unable to add bin edge "{0}" to a "{1}" Filter ' \ 'since it is a non-integer or floating point ' \ 'value'.format(edge, self.type) @@ -160,12 +195,12 @@ class Filter(object): raise ValueError(msg) # mesh filters - elif self._type == 'mesh': + elif self.type == 'mesh': if not len(bins) == 1: msg = 'Unable to add bins "{0}" to a mesh Filter since ' \ 'only a single mesh can be used per tally'.format(bins) raise ValueError(msg) - elif not isinstance(bins[0], Integral): + elif not cv._isinstance(bins[0], Integral): msg = 'Unable to add bin "{0}" to mesh Filter since it ' \ 'is a non-integer'.format(bins[0]) raise ValueError(msg) @@ -177,16 +212,15 @@ class Filter(object): # If all error checks passed, add bin edges self._bins = np.array(bins) - # FIXME @num_bins.setter def num_bins(self, num_bins): - check_type('filter num_bins', num_bins, Integral) - check_greater_than('filter num_bins', num_bins, 0, equality=True) + cv.check_type('filter num_bins', num_bins, Integral) + cv.check_greater_than('filter num_bins', num_bins, 0, equality=True) self._num_bins = num_bins @mesh.setter def mesh(self, mesh): - check_type('filter mesh', mesh, Mesh) + cv.check_type('filter mesh', mesh, Mesh) self._mesh = mesh self.type = 'mesh' @@ -194,12 +228,12 @@ class Filter(object): @offset.setter def offset(self, offset): - check_type('filter offset', offset, Integral) + cv.check_type('filter offset', offset, Integral) self._offset = offset @stride.setter def stride(self, stride): - check_type('filter stride', stride, Integral) + cv.check_type('filter stride', stride, Integral) if stride < 0: msg = 'Unable to set stride "{0}" for a "{1}" Filter since it ' \ 'is a negative value'.format(stride, self.type) @@ -268,31 +302,69 @@ class Filter(object): merged_filter = copy.deepcopy(self) # Merge unique filter bins - merged_bins = list(set(self.bins + filter.bins)) + merged_bins = list(set(np.concatenate((self.bins, filter.bins)))) merged_filter.bins = merged_bins merged_filter.num_bins = len(merged_bins) return merged_filter + def is_subset(self, other): + """Determine if another filter is a subset of this filter. + + If all of the bins in the other filter are included as bins in this + filter, then it is a subset of this filter. + + Parameters + ---------- + other : Filter + The filter to query as a subset of this filter + + Returns + ------- + bool + Whether or not the other filter is a subset of this filter + + """ + + if not isinstance(other, Filter): + return False + elif self.type != other.type: + return False + elif self.type in ['energy', 'energyout']: + if len(self.bins) != len(other.bins): + return False + else: + return np.allclose(self.bins, other.bins) + + for bin in other.bins: + if bin not in self.bins: + return False + + return True + def get_bin_index(self, filter_bin): """Returns the index in the Filter for some bin. Parameters ---------- - filter_bin : int or tuple + filter_bin : Integral or tuple The bin is the integer ID for 'material', 'surface', 'cell', 'cellborn', and 'universe' Filters. The bin is an integer for the cell instance ID for 'distribcell' Filters. The bin is a 2-tuple of floats for 'energy' and 'energyout' filters corresponding to the - energy boundaries of the bin of interest. The bin is a (x,y,z) - 3-tuple for 'mesh' filters corresponding to the mesh cell of + energy boundaries of the bin of interest. The bin is an (x,y,z) + 3-tuple for 'mesh' filters corresponding to the mesh cell interest. Returns ------- - filter_index : int + filter_index : Integral The index in the Tally data array for this filter bin. + See also + -------- + Filter.get_bin() + """ try: @@ -314,10 +386,14 @@ class Filter(object): # Use lower energy bound to find index for energy Filters elif self.type in ['energy', 'energyout']: - val = np.where(self.bins == filter_bin[0])[0][0] - filter_index = val + deltas = np.abs(self.bins - filter_bin[1]) / filter_bin[1] + min_delta = np.min(deltas) + if min_delta < 1E-3: + filter_index = deltas.argmin() - 1 + else: + raise ValueError - # Filter bins for distribcell are the "IDs" of each unique placement + # Filter bins for distribcells are "IDs" of each unique placement # of the Cell in the Geometry (integers starting at 0) elif self.type == 'distribcell': filter_index = filter_bin @@ -329,14 +405,354 @@ class Filter(object): except ValueError: msg = 'Unable to get the bin index for Filter since "{0}" ' \ - 'is not one of the bins'.format(filter_bin) + 'is not one of the bins'.format(filter_bin) raise ValueError(msg) return filter_index - def __repr__(self): - string = 'Filter\n' - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type) - string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins) - string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self.offset) - return string + def get_bin(self, bin_index): + """Returns the filter bin for some filter bin index. + + Parameters + ---------- + bin_index : Integral + The zero-based index into the filter's array of bins. The bin + index for 'material', 'surface', 'cell', 'cellborn', and 'universe' + filters corresponds to the ID in the filter's list of bins. For + 'distribcell' tallies the bin index necessarily can only be zero + since only one cell can be tracked per tally. The bin index for + 'energy' and 'energyout' filters corresponds to the energy range of + interest in the filter bins of energies. The bin index for 'mesh' + filters is the index into the flattened array of (x,y) or (x,y,z) + mesh cell bins. + + Returns + ------- + bin : 1-, 2-, or 3-tuple of Real + The bin in the Tally data array. The bin for 'material', surface', + 'cell', 'cellborn', 'universe' and 'distribcell' filters is a + 1-tuple of the ID corresponding to the appropriate filter bin. + The bin for 'energy' and 'energyout' filters is a 2-tuple of the + lower and upper energies bounding the energy interval for the filter + bin. The bin for 'mesh' tallies is a 2-tuple or 3-tuple of the x,y + or x,y,z mesh cell indices corresponding to the bin in a 2D/3D mesh. + + See also + -------- + Filter.get_bin_index() + + """ + + cv.check_type('bin_index', bin_index, Integral) + cv.check_greater_than('bin_index', bin_index, 0, equality=True) + cv.check_less_than('bin_index', bin_index, self.num_bins) + + if self.type == 'mesh': + + # Construct 3-tuple of x,y,z cell indices for a 3D mesh + if len(self.mesh.dimension) == 3: + nx, ny, nz = self.mesh.dimension + x = bin_index / (ny * nz) + y = (bin_index - (x * ny * nz)) / nz + z = bin_index - (x * ny * nz) - (y * nz) + filter_bin = (x, y, z) + + # Construct 2-tuple of x,y cell indices for a 2D mesh + else: + nx, ny = self.mesh.dimension + x = bin_index / ny + y = bin_index - (x * ny) + filter_bin = (x, y) + + # Construct 2-tuple of lower, upper energies for energy(out) filters + elif self.type in ['energy', 'energyout']: + filter_bin = (self.bins[bin_index], self.bins[bin_index+1]) + # Construct 1-tuple of with the cell ID for distribcell filters + elif self.type == 'distribcell': + filter_bin = (self.bins[0],) + # Construct 1-tuple with domain ID (e.g., material) for other filters + else: + filter_bin = (self.bins[bin_index],) + + return filter_bin + + def get_pandas_dataframe(self, data_size, summary=None): + """Builds a Pandas DataFrame for the Filter's bins. + + This method constructs a Pandas DataFrame object for the filter with + columns annotated by filter bin information. This is a helper method + for the Tally.get_pandas_dataframe(...) method. + + This capability has been tested for Pandas >=0.13.1. However, it is + recommended to use v0.16 or newer versions of Pandas since this method + uses Pandas' Multi-index functionality. + + Parameters + ---------- + data_size : Integral + The total number of bins in the tally corresponding to this filter + summary : None or Summary + An optional Summary object to be used to construct columns for + distribcell tally filters (default is None). The geometric + information in the Summary object is embedded into a Multi-index + column with a geometric "path" to each distribcell instance. + NOTE: This option requires the OpenCG Python package. + + Returns + ------- + pandas.DataFrame + A Pandas DataFrame with columns of strings that characterize the + filter's bins. The number of rows in the DataFrame is the same as + the total number of bins in the corresponding tally, with the filter + bin appropriately tiled to map to the corresponding tally bins. + + For 'cell', 'cellborn', 'surface', 'material', and 'universe' + filters, the DataFrame includes a single column with the cell, + surface, material or universe ID corresponding to each filter bin. + + For 'distribcell' filters, the DataFrame either includes: + + 1. a single column with the cell instance IDs (without summary info) + 2. separate columns for the cell IDs, universe IDs, and lattice IDs + and x,y,z cell indices corresponding to each (with summary info). + + For 'energy' and 'energyout' filters, the DataFrame include a single + column with each element comprising a string with the lower, upper + energy bounds for each filter bin. + + For 'mesh' filters, the DataFrame includes three columns for the + x,y,z mesh cell indices corresponding to each filter bin. + + Raises + ------ + ImportError + When Pandas is not installed, or summary info is requested but + OpenCG is not installed. + + See also + -------- + Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() + + """ + + # Attempt to import Pandas + try: + import pandas as pd + except ImportError: + msg = 'The Pandas Python package must be installed on your system' + raise ImportError(msg) + + # Initialize Pandas DataFrame + df = pd.DataFrame() + + # mesh filters + if self.type == 'mesh': + + # Initialize dictionary to build Pandas Multi-index column + filter_dict = {} + + # Append Mesh ID as outermost index of mult-index + mesh_key = 'mesh {0}'.format(self.mesh.id) + + # Find mesh dimensions - use 3D indices for simplicity + if (len(self.mesh.dimension) == 3): + nx, ny, nz = self.mesh.dimension + else: + nx, ny = self.mesh.dimension + nz = 1 + + # Generate multi-index sub-column for x-axis + filter_bins = np.arange(1, nx+1) + repeat_factor = ny * nz * self.stride + filter_bins = np.repeat(filter_bins, repeat_factor) + tile_factor = data_size / len(filter_bins) + filter_bins = np.tile(filter_bins, tile_factor) + filter_dict[(mesh_key, 'x')] = filter_bins + + # Generate multi-index sub-column for y-axis + filter_bins = np.arange(1, ny+1) + repeat_factor = nz * self.stride + filter_bins = np.repeat(filter_bins, repeat_factor) + tile_factor = data_size / len(filter_bins) + filter_bins = np.tile(filter_bins, tile_factor) + filter_dict[(mesh_key, 'y')] = filter_bins + + # Generate multi-index sub-column for z-axis + filter_bins = np.arange(1, nz+1) + repeat_factor = self.stride + filter_bins = np.repeat(filter_bins, repeat_factor) + tile_factor = data_size / len(filter_bins) + filter_bins = np.tile(filter_bins, tile_factor) + filter_dict[(mesh_key, 'z')] = filter_bins + + # Initialize a Pandas DataFrame from the mesh dictionary + df = pd.concat([df, pd.DataFrame(filter_dict)]) + + # distribcell filters + elif self.type == 'distribcell': + level_df = None + + if isinstance(summary, Summary): + # Attempt to import the OpenCG package + try: + import opencg + except ImportError: + msg = 'The OpenCG package must be installed ' \ + 'to use a Summary for distribcell dataframes' + raise ImportError(msg) + + # Extract the OpenCG geometry from the Summary + opencg_geometry = summary.opencg_geometry + openmc_geometry = summary.openmc_geometry + + # Use OpenCG to compute the number of regions + opencg_geometry.initialize_cell_offsets() + num_regions = opencg_geometry.num_regions + + # Initialize a dictionary mapping OpenMC distribcell + # offsets to OpenCG LocalCoords linked lists + offsets_to_coords = {} + + # Use OpenCG to compute LocalCoords linked list for + # each region and store in dictionary + for region in range(num_regions): + coords = opencg_geometry.find_region(region) + path = opencg.get_path(coords) + cell_id = path[-1] + + # If this region is in Cell corresponding to the + # distribcell filter bin, store it in dictionary + if cell_id == self.bins[0]: + offset = openmc_geometry.get_offset(path, self.offset) + offsets_to_coords[offset] = coords + + # Each distribcell offset is a DataFrame bin + # Unravel the paths into DataFrame columns + num_offsets = len(offsets_to_coords) + + # Initialize termination condition for while loop + levels_remain = True + counter = 0 + + # Iterate over each level in the CSG tree hierarchy + while levels_remain: + levels_remain = False + + # Initialize dictionary to build Pandas Multi-index + # column for this level in the CSG tree hierarchy + level_dict = {} + + # Initialize prefix Multi-index keys + counter += 1 + level_key = 'level {0}'.format(counter) + univ_key = (level_key, 'univ', 'id') + cell_key = (level_key, 'cell', 'id') + lat_id_key = (level_key, 'lat', 'id') + lat_x_key = (level_key, 'lat', 'x') + lat_y_key = (level_key, 'lat', 'y') + lat_z_key = (level_key, 'lat', 'z') + + # Allocate NumPy arrays for each CSG level and + # each Multi-index column in the DataFrame + level_dict[univ_key] = np.empty(num_offsets) + level_dict[cell_key] = np.empty(num_offsets) + level_dict[lat_id_key] = np.empty(num_offsets) + level_dict[lat_x_key] = np.empty(num_offsets) + level_dict[lat_y_key] = np.empty(num_offsets) + level_dict[lat_z_key] = np.empty(num_offsets) + + # Initialize Multi-index columns to NaN - this is + # necessary since some distribcell instances may + # have very different LocalCoords linked lists + level_dict[univ_key][:] = np.NAN + level_dict[cell_key][:] = np.NAN + level_dict[lat_id_key][:] = np.NAN + level_dict[lat_x_key][:] = np.NAN + level_dict[lat_y_key][:] = np.NAN + level_dict[lat_z_key][:] = np.NAN + + # Iterate over all regions (distribcell instances) + for offset in range(num_offsets): + coords = offsets_to_coords[offset] + + # If entire LocalCoords has been unraveled into + # Multi-index columns already, continue + if coords is None: + continue + + # Assign entry to Universe Multi-index column + if coords._type == 'universe': + level_dict[univ_key][offset] = coords._universe._id + level_dict[cell_key][offset] = coords._cell._id + + # Assign entry to Lattice Multi-index column + else: + level_dict[lat_id_key][offset] = coords._lattice._id + level_dict[lat_x_key][offset] = coords._lat_x + level_dict[lat_y_key][offset] = coords._lat_y + level_dict[lat_z_key][offset] = coords._lat_z + + # Move to next node in LocalCoords linked list + if coords._next is None: + offsets_to_coords[offset] = None + else: + offsets_to_coords[offset] = coords._next + levels_remain = True + + # Tile the Multi-index columns + for level_key, level_bins in level_dict.items(): + level_bins = np.repeat(level_bins, self.stride) + tile_factor = data_size / len(level_bins) + level_bins = np.tile(level_bins, tile_factor) + level_dict[level_key] = level_bins + + # Initialize a Pandas DataFrame from the level dictionary + if level_df is None: + level_df = pd.DataFrame(level_dict) + else: + level_df = pd.concat([level_df, pd.DataFrame(level_dict)], axis=1) + + # Create DataFrame column for distribcell instances IDs + # NOTE: This is performed regardless of whether the user + # requests Summary geometric information + filter_bins = np.arange(self.num_bins) + filter_bins = np.repeat(filter_bins, self.stride) + tile_factor = data_size / len(filter_bins) + filter_bins = np.tile(filter_bins, tile_factor) + filter_bins = filter_bins + df = pd.DataFrame({self.type : filter_bins}) + + # If OpenCG level info DataFrame was created, concatenate + # with DataFrame of distribcell instance IDs + if level_df is not None: + level_df = level_df.dropna(axis=1, how='all') + level_df = level_df.astype(np.int) + df = pd.concat([level_df, df], axis=1) + + # energy, energyout filters + elif 'energy' in self.type: + bins = self.bins + num_bins = self.num_bins + + # Create strings for + template = '({0:.1e} - {1:.1e})' + filter_bins = [] + for i in range(num_bins): + filter_bins.append(template.format(bins[i], bins[i+1])) + + # Tile the energy bins into a DataFrame column + filter_bins = np.repeat(filter_bins, self.stride) + tile_factor = data_size / len(filter_bins) + filter_bins = np.tile(filter_bins, tile_factor) + filter_bins = filter_bins + df = pd.concat([df, pd.DataFrame({self.type + ' [MeV]' : filter_bins})]) + + # universe, material, surface, cell, and cellborn filters + else: + filter_bins = np.repeat(self.bins, self.stride) + tile_factor = data_size / len(filter_bins) + filter_bins = np.tile(filter_bins, tile_factor) + filter_bins = filter_bins + df = pd.concat([df, pd.DataFrame({self.type : filter_bins})]) + + return df diff --git a/openmc/geometry.py b/openmc/geometry.py index 18fa698b50..e848e0cddf 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -1,3 +1,4 @@ +from collections import OrderedDict from xml.etree import ElementTree as ET import openmc @@ -110,7 +111,7 @@ class Geometry(object): """ - nuclides = {} + nuclides = OrderedDict() materials = self.get_all_materials() for material in materials: @@ -134,7 +135,9 @@ class Geometry(object): for cell in material_cells: materials.add(cell._fill) - return list(materials) + materials = list(materials) + materials.sort(key=lambda x: x.id) + return materials def get_all_material_cells(self): all_cells = self.get_all_cells() @@ -144,7 +147,9 @@ class Geometry(object): if cell._type == 'normal': material_cells.add(cell) - return list(material_cells) + material_cells = list(material_cells) + material_cells.sort(key=lambda x: x.id) + return material_cells def get_all_material_universes(self): """Return all universes composed of at least one non-fill cell @@ -165,7 +170,9 @@ class Geometry(object): if cell._type == 'normal': material_universes.add(universe) - return list(material_universes) + material_universes = list(material_universes) + material_universes.sort(key=lambda x: x.id) + return material_universes class GeometryFile(object): @@ -198,7 +205,13 @@ class GeometryFile(object): """ - root_universe = self._geometry._root_universe + # Clear OpenMC written IDs used to optimize XML generation + openmc.universe.WRITTEN_IDS = {} + + # Reset xml element tree + self._geometry_file.clear() + + root_universe = self.geometry.root_universe root_universe.create_xml_subelement(self._geometry_file) # Clean the indentation in the file to be user-readable diff --git a/openmc/material.py b/openmc/material.py index e495357b54..37ebc8a77f 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1,4 +1,4 @@ -from collections import Iterable +from collections import Iterable, OrderedDict from copy import deepcopy from numbers import Real, Integral import warnings @@ -33,8 +33,8 @@ NO_DENSITY = 99999. class Material(object): - """A material composed of a collection of nuclides/elements that can be assigned - to a region of space. + """A material composed of a collection of nuclides/elements that can be + assigned to a region of space. Parameters ---------- @@ -64,15 +64,15 @@ class Material(object): self._density = None self._density_units = '' - # A dictionary of Nuclides + # An ordered dictionary of Nuclides (order affects OpenMC results) # Keys - Nuclide names # Values - tuple (nuclide, percent, percent type) - self._nuclides = {} + self._nuclides = OrderedDict() - # A dictionary of Elements + # An ordered dictionary of Elements (order affects OpenMC results) # Keys - Element names # Values - tuple (element, percent, percent type) - self._elements = {} + self._elements = OrderedDict() # If specified, a list of tuples of (table name, xs identifier) self._sab = [] @@ -83,6 +83,89 @@ class Material(object): # If specified, this file will be used instead of composition values self._distrib_otf_file = None + def __eq__(self, other): + if not isinstance(other, Material): + return False + elif self.id != other.id: + return False + elif self.name != other.name: + return False + # FIXME: We cannot compare densities since OpenMC outputs densities + # in atom/b-cm in summary.h5 irregardless of input units, and we + # cannot compute the sum percent in Python since we lack AWR + #elif self.density != other.density: + # return False + #elif self._nuclides != other._nuclides: + # return False + #elif self._elements != other._elements: + # return False + elif self._sab != other._sab: + return False + else: + return True + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(repr(self)) + + def __repr__(self): + string = 'Material\n' + string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) + string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) + + string += '{0: <16}{1}{2}'.format('\tDensity', '=\t', self._density) + string += ' [{0}]\n'.format(self._density_units) + + string += '{0: <16}\n'.format('\tS(a,b) Tables') + + for sab in self._sab: + string += '{0: <16}{1}[{2}{3}]\n'.format('\tS(a,b)', '=\t', + sab[0], sab[1]) + + string += '{0: <16}\n'.format('\tNuclides') + + for nuclide in self._nuclides: + percent = self._nuclides[nuclide][1] + percent_type = self._nuclides[nuclide][2] + string += '{0: <16}'.format('\t{0}'.format(nuclide)) + string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type) + + string += '{0: <16}\n'.format('\tElements') + + for element in self._elements: + percent = self._nuclides[element][1] + percent_type = self._nuclides[element][2] + string += '{0: >16}'.format('\t{0}'.format(element)) + string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type) + + return string + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + if existing is None: + # If this is the first time we have tried to copy this object, create a copy + clone = type(self).__new__(type(self)) + clone._id = self._id + clone._name = self._name + clone._density = self._density + clone._density_units = self._density_units + clone._nuclides = deepcopy(self._nuclides, memo) + clone._elements = deepcopy(self._elements, memo) + clone._sab = deepcopy(self._sab, memo) + clone._convert_to_distrib_comps = self._convert_to_distrib_comps + clone._distrib_otf_file = self._distrib_otf_file + + memo[id(self)] = clone + + return clone + + else: + # If this object has been copied before, return the first copy made + return existing + @property def id(self): return self._id @@ -125,16 +208,19 @@ class Material(object): msg = 'Unable to set Material ID to "{0}" since a Material with ' \ 'this ID was already initialized'.format(material_id) raise ValueError(msg) - check_greater_than('material ID', material_id, 0) + check_greater_than('material ID', material_id, 0, equality=True) self._id = material_id MATERIAL_IDS.append(material_id) @name.setter def name(self, name): - check_type('name for Material ID="{0}"'.format(self._id), - name, basestring) - self._name = name + if name is not None: + check_type('name for Material ID="{0}"'.format(self._id), + name, basestring) + self._name = name + else: + self._name = '' def set_density(self, units, density=NO_DENSITY): """Set the density of the material @@ -312,6 +398,12 @@ class Material(object): self._sab.append((name, xs)) + def make_isotropic_in_lab(self): + for nuclide_name in self._nuclides: + self._nuclides[nuclide_name][0].scattering = 'iso-in-lab' + for element_name in self._elements: + self._element[element_name][0].scattering = 'iso-in-lab' + def get_all_nuclides(self): """Returns all nuclides in the material @@ -323,7 +415,7 @@ class Material(object): """ - nuclides = {} + nuclides = OrderedDict() for nuclide_name, nuclide_tuple in self._nuclides.items(): nuclide = nuclide_tuple[0] @@ -332,38 +424,6 @@ class Material(object): return nuclides - def __repr__(self): - string = 'Material\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - - string += '{0: <16}{1}{2}'.format('\tDensity', '=\t', self._density) - string += ' [{0}]\n'.format(self._density_units) - - string += '{0: <16}\n'.format('\tS(a,b) Tables') - - for sab in self._sab: - string += '{0: <16}{1}[{2}{3}]\n'.format('\tS(a,b)', '=\t', - sab[0], sab[1]) - - string += '{0: <16}\n'.format('\tNuclides') - - for nuclide in self._nuclides: - percent = self._nuclides[nuclide][1] - percent_type = self._nuclides[nuclide][2] - string += '{0: <16}'.format('\t{0}'.format(nuclide)) - string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type) - - string += '{0: <16}\n'.format('\tElements') - - for element in self._elements: - percent = self._nuclides[element][1] - percent_type = self._nuclides[element][2] - string += '{0: >16}'.format('\t{0}'.format(element)) - string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type) - - return string - def _get_nuclide_xml(self, nuclide, distrib=False): xml_element = ET.Element("nuclide") xml_element.set("name", nuclide[0]._name) @@ -374,8 +434,11 @@ class Material(object): else: xml_element.set("wo", str(nuclide[1])) - if nuclide[0]._xs is not None: - xml_element.set("xs", nuclide[0]._xs) + if nuclide[0].xs is not None: + xml_element.set("xs", nuclide[0].xs) + + if not nuclide[0].scattering is None: + xml_element.set("scattering", nuclide[0].scattering) return xml_element @@ -389,6 +452,9 @@ class Material(object): else: xml_element.set("wo", str(element[1])) + if not element[0].scattering is None: + xml_element.set("scattering", element[0].scattering) + return xml_element def _get_nuclides_xml(self, nuclides, distrib=False): @@ -563,6 +629,10 @@ class MaterialsFile(object): self._materials.remove(material) + def make_isotropic_in_lab(self): + for material in self._materials: + material.make_isotropic_in_lab() + def _create_material_subelements(self): subelement = ET.SubElement(self._materials_file, "default_xs") @@ -578,6 +648,9 @@ class MaterialsFile(object): """ + # Reset xml element tree + self._materials_file.clear() + self._create_material_subelements() # Clean the indentation in the file to be user-readable diff --git a/openmc/mesh.py b/openmc/mesh.py index 7e907aaa57..8bad6c5374 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -4,8 +4,10 @@ from numbers import Real, Integral from xml.etree import ElementTree as ET import sys -from openmc.checkvalue import (check_type, check_length, check_value, - check_greater_than) +import numpy as np + +import openmc.checkvalue as cv + if sys.version_info[0] >= 3: basestring = str @@ -54,7 +56,7 @@ class Mesh(object): # Initialize Mesh class attributes self.id = mesh_id self.name = name - self._type = 'rectangular' + self._type = 'regular' self._dimension = None self._lower_left = None self._upper_right = None @@ -142,47 +144,54 @@ class Mesh(object): self._id = AUTO_MESH_ID AUTO_MESH_ID += 1 else: - check_type('mesh ID', mesh_id, Integral) - check_greater_than('mesh ID', mesh_id, 0) + cv.check_type('mesh ID', mesh_id, Integral) + cv.check_greater_than('mesh ID', mesh_id, 0, equality=True) self._id = mesh_id @name.setter def name(self, name): - check_type('name for mesh ID="{0}"'.format(self._id), name, basestring) - self._name = name + if name is not None: + cv.check_type('name for mesh ID="{0}"'.format(self._id), + name, basestring) + self._name = name + else: + self._name = '' @type.setter def type(self, meshtype): - check_type('type for mesh ID="{0}"'.format(self._id), + cv.check_type('type for mesh ID="{0}"'.format(self._id), meshtype, basestring) - check_value('type for mesh ID="{0}"'.format(self._id), - meshtype, ['rectangular', 'hexagonal']) + cv.check_value('type for mesh ID="{0}"'.format(self._id), + meshtype, ['regular']) self._type = meshtype @dimension.setter def dimension(self, dimension): - check_type('mesh dimension', dimension, Iterable, Integral) - check_length('mesh dimension', dimension, 2, 3) + cv.check_type('mesh dimension', dimension, Iterable, Integral) + cv.check_length('mesh dimension', dimension, 2, 3) self._dimension = dimension @lower_left.setter def lower_left(self, lower_left): - check_type('mesh lower_left', lower_left, Iterable, Real) - check_length('mesh lower_left', lower_left, 2, 3) + cv.check_type('mesh lower_left', lower_left, Iterable, Real) + cv.check_length('mesh lower_left', lower_left, 2, 3) self._lower_left = lower_left @upper_right.setter def upper_right(self, upper_right): - check_type('mesh upper_right', upper_right, Iterable, Real) - check_length('mesh upper_right', upper_right, 2, 3) + cv.check_type('mesh upper_right', upper_right, Iterable, Real) + cv.check_length('mesh upper_right', upper_right, 2, 3) self._upper_right = upper_right @width.setter def width(self, width): - check_type('mesh width', width, Iterable, Real) - check_length('mesh width', width, 2, 3) + cv.check_type('mesh width', width, Iterable, Real) + cv.check_length('mesh width', width, 2, 3) self._width = width + def __hash__(self): + return hash(repr(self)) + def __repr__(self): string = 'Mesh\n' string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py new file mode 100644 index 0000000000..4fcf8b6aed --- /dev/null +++ b/openmc/mgxs/__init__.py @@ -0,0 +1,3 @@ +from openmc.mgxs.groups import EnergyGroups +from openmc.mgxs.library import Library +from openmc.mgxs.mgxs import * diff --git a/openmc/mgxs/groups.py b/openmc/mgxs/groups.py new file mode 100644 index 0000000000..3436c0e037 --- /dev/null +++ b/openmc/mgxs/groups.py @@ -0,0 +1,238 @@ +from collections import Iterable +from numbers import Real +import copy +import sys + +import numpy as np + +import openmc.checkvalue as cv + + +if sys.version_info[0] >= 3: + basestring = str + + +class EnergyGroups(object): + """An energy groups structure used for multi-group cross-sections. + + Parameters + ---------- + group_edges : Iterable of Real + The energy group boundaries [MeV] + + Attributes + ---------- + group_edges : Iterable of Real + The energy group boundaries [MeV] + num_group : Integral + The number of energy groups + + """ + + def __init__(self, group_edges=None): + self._group_edges = None + + if group_edges is not None: + self.group_edges = group_edges + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy object, create copy + if existing is None: + clone = type(self).__new__(type(self)) + clone._group_edges = copy.deepcopy(self.group_edges, memo) + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + + def __eq__(self, other): + if not isinstance(other, EnergyGroups): + return False + elif self.group_edges != other.group_edges: + return False + else: + return True + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(tuple(self.group_edges)) + + @property + def group_edges(self): + return self._group_edges + + @property + def num_groups(self): + return len(self.group_edges) - 1 + + @group_edges.setter + def group_edges(self, edges): + cv.check_type('group edges', edges, Iterable, Real) + cv.check_greater_than('number of group edges', len(edges), 1) + self._group_edges = np.array(edges) + + def get_group(self, energy): + """Returns the energy group in which the given energy resides. + + Parameters + ---------- + energy : Real + The energy of interest in MeV + + Returns + ------- + Integral + The energy group index, starting at 1 for the highest energies + + Raises + ------ + ValueError + If the group edges have not yet been set. + + """ + + if self.group_edges is None: + msg = 'Unable to get energy group for energy "{0}" MeV since ' \ + 'the group edges have not yet been set'.format(energy) + raise ValueError(msg) + + index = np.where(self.group_edges > energy)[0][0] + group = self.num_groups - index + 1 + return group + + def get_group_bounds(self, group): + """Returns the energy boundaries for the energy group of interest. + + Parameters + ---------- + group : Integral + The energy group index, starting at 1 for the highest energies + + Returns + ------- + 2-tuple + The low and high energy bounds for the group in MeV + + Raises + ------ + ValueError + If the group edges have not yet been set. + + """ + + if self.group_edges is None: + msg = 'Unable to get energy group bounds for group "{0}" since ' \ + 'the group edges have not yet been set'.format(group) + raise ValueError(msg) + + cv.check_greater_than('group', group, 0) + cv.check_less_than('group', group, self.num_groups, equality=True) + + lower = self.group_edges[self.num_groups-group] + upper = self.group_edges[self.num_groups-group+1] + return lower, upper + + def get_group_indices(self, groups='all'): + """Returns the array indices for one or more energy groups. + + Parameters + ---------- + groups : str, tuple + The energy groups of interest - a tuple of the energy group indices, + starting at 1 for the highest energies (default is 'all') + + Returns + ------- + ndarray + The ndarray array indices for each energy group of interest + + Raises + ------ + ValueError + If the group edges have not yet been set, or if a group is requested + that is outside the bounds of the number of energy groups. + + """ + + if self.group_edges is None: + msg = 'Unable to get energy group indices for groups "{0}" since ' \ + 'the group edges have not yet been set'.format(groups) + raise ValueError(msg) + + if groups == 'all': + return np.arange(self.num_groups) + else: + indices = np.zeros(len(groups), dtype=np.int) + + for i, group in enumerate(groups): + cv.check_greater_than('group', group, 0) + cv.check_less_than('group', group, self.num_groups, equality=True) + indices[i] = group - 1 + + return indices + + def get_condensed_groups(self, coarse_groups): + """Return a coarsened version of this EnergyGroups object. + + This method merges together energy groups in this object into wider + energy groups as defined by the list of groups specified by the user, + and returns a new, coarse EnergyGroups object. + + Parameters + ---------- + coarse_groups : Iterable of 2-tuple + The energy groups of interest - a list of 2-tuples, each directly + corresponding to one of the new coarse groups. The values in the + 2-tuples are upper/lower energy groups used to construct a new + coarse group. For example, if [(1,2), (3,4)] was used as the coarse + groups, fine groups 1 and 2 would be merged into coarse group 1 + while fine groups 3 and 4 would be merged into coarse group 2. + + Returns + ------- + EnergyGroups + A coarsened version of this EnergyGroups object. + + Raises + ------ + ValueError + If the group edges have not yet been set. + """ + + cv.check_type('group edges', coarse_groups, Iterable) + for group in coarse_groups: + cv.check_type('group edges', group, Iterable) + cv.check_length('group edges', group, 2) + cv.check_greater_than('lower group', group[0], 1, True) + cv.check_less_than('lower group', group[0], self.num_groups, True) + cv.check_greater_than('upper group', group[0], 1, True) + cv.check_less_than('upper group', group[0], self.num_groups, True) + cv.check_less_than('lower group', group[0], group[1], False) + + # Compute the group indices into the coarse group + group_bounds = [group[1] for group in coarse_groups] + group_bounds.insert(0, coarse_groups[0][0]) + + # Determine the indices mapping the fine-to-coarse energy groups + group_bounds = np.asarray(group_bounds) + group_indices = np.flipud(self.num_groups - group_bounds) + group_indices[-1] += 1 + + # Determine the edges between coarse energy groups and sort + # in increasing order in case the user passed in unordered groups + group_edges = self.group_edges[group_indices] + group_edges = np.sort(group_edges) + + # Create a new condensed EnergyGroups object + condensed_groups = EnergyGroups() + condensed_groups.group_edges = group_edges + + return condensed_groups diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py new file mode 100644 index 0000000000..ef3e90fc41 --- /dev/null +++ b/openmc/mgxs/library.py @@ -0,0 +1,681 @@ +import sys +import os +import copy +import pickle +from numbers import Integral +from collections import OrderedDict + +import openmc +import openmc.mgxs +import openmc.checkvalue as cv + + +if sys.version_info[0] >= 3: + basestring = str + + +class Library(object): + """A multi-group cross section library for some energy group structure. + + This class can be used for both OpenMC input generation and tally data + post-processing to compute spatially-homogenized and energy-integrated + multi-group cross sections for deterministic neutronics calculations. + + This class helps automate the generation of MGXS objects for some energy + group structure and domain type. The Library serves as a collection for + MGXS objects with routines to automate the initialization of tallies for + input files, the loading of tally data from statepoint files, data storage, + energy group condensation and more. + + Parameters + ---------- + openmc_geometry : openmc.Geometry + An geometry which has been initialized with a root universe + by_nuclide : bool + If true, computes cross sections for each nuclide in each domain + mgxs_types : Iterable of str + The types of cross sections in the library (e.g., ['total', 'scatter']) + name : str, optional + Name of the multi-group cross section. library Used as a label to + identify tallies in OpenMC 'tallies.xml' file. + + Attributes + ---------- + openmc_geometry : openmc.Geometry + An geometry which has been initialized with a root universe + opencg_geometry : opencg.Geometry + An OpenCG geometry object equivalent to the OpenMC geometry + encapsulated by the summary file. Use of this attribute requires + installation of the OpenCG Python module. + by_nuclide : bool + If true, computes cross sections for each nuclide in each domain + mgxs_types : Iterable of str + The types of cross sections in the library (e.g., ['total', 'scatter']) + domain_type : {'material', 'cell', 'distribcell', 'universe'} + Domain type for spatial homogenization + domains : Iterable of Material, Cell or Universe + The spatial domain(s) for which MGXS in the Library are computed + correction : 'P0' or None + Apply the P0 correction to scattering matrices if set to 'P0' + energy_groups : EnergyGroups + Energy group structure for energy condensation + tally_trigger : Trigger + An (optional) tally precision trigger given to each tally used to + compute the cross section + all_mgxs : OrderedDict + MGXS objects keyed by domain ID and cross section type + sp_filename : str + The filename of the statepoint with tally data used to the + compute cross sections + keff : Real or None + The combined keff from the statepoint file with tally data used to + compute cross sections (for eigenvalue calculations only) + name : str, optional + Name of the multi-group cross section library. Used as a label to + identify tallies in OpenMC 'tallies.xml' file. + + """ + + def __init__(self, openmc_geometry, by_nuclide=False, + mgxs_types=None, name=''): + + self._name = '' + self._openmc_geometry = None + self._opencg_geometry = None + self._by_nuclide = None + self._mgxs_types = [] + self._domain_type = None + self._domains = 'all' + self._correction = 'P0' + self._energy_groups = None + self._tally_trigger = None + self._all_mgxs = OrderedDict() + self._sp_filename = None + self._keff = None + + self.name = name + self.openmc_geometry = openmc_geometry + self.by_nuclide = by_nuclide + + if mgxs_types is not None: + self.mgxs_types = mgxs_types + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy this object, copy it + if existing is None: + clone = type(self).__new__(type(self)) + clone._name = self.name + clone._openmc_geometry = self.openmc_geometry + clone._opencg_geometry = None + clone._by_nuclide = self.by_nuclide + clone._mgxs_types = self.mgxs_types + clone._domain_type = self.domain_type + clone._domains = self.domains + clone._correction = self.correction + clone._energy_groups = copy.deepcopy(self.energy_groups, memo) + clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo) + clone._all_mgxs = self.all_mgxs + clone._sp_filename = self._sp_filename + clone._keff = self._keff + + clone._all_mgxs = OrderedDict() + for domain in self.domains: + clone.all_mgxs[domain.id] = OrderedDict() + for mgxs_type in self.mgxs_types: + mgxs = copy.deepcopy(self.all_mgxs[domain.id][mgxs_type]) + clone.all_mgxs[domain.id][mgxs_type] = mgxs + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + + @property + def openmc_geometry(self): + return self._openmc_geometry + + @property + def openmc_geometry(self): + return self._openmc_geometry + + @property + def opencg_geometry(self): + if self._opencg_geometry is None: + from openmc.opencg_compatible import get_opencg_geometry + self._opencg_geometry = get_opencg_geometry(self._openmc_geometry) + return self._opencg_geometry + + @property + def name(self): + return self._name + + @property + def mgxs_types(self): + return self._mgxs_types + + @property + def by_nuclide(self): + return self._by_nuclide + + @property + def domain_type(self): + return self._domain_type + + @property + def domains(self): + if self._domains == 'all': + if self.domain_type == 'material': + return self.openmc_geometry.get_all_materials() + elif self.domain_type in ['cell', 'distribcell']: + return self.openmc_geometry.get_all_material_cells() + elif self.domain_type == 'universe': + return self.openmc_geometry.get_all_universes() + else: + raise ValueError('Unable to get domains without a domain type') + else: + return self._domains + + @property + def correction(self): + return self._correction + + @property + def energy_groups(self): + return self._energy_groups + + @property + def tally_trigger(self): + return self._tally_trigger + + @property + def num_groups(self): + return self.energy_groups.num_groups + + @property + def all_mgxs(self): + return self._all_mgxs + + @property + def sp_filename(self): + return self._sp_filename + + @property + def keff(self): + return self._keff + + @openmc_geometry.setter + def openmc_geometry(self, openmc_geometry): + cv.check_type('openmc_geometry', openmc_geometry, openmc.Geometry) + self._openmc_geometry = openmc_geometry + self._opencg_geometry = None + + @name.setter + def name(self, name): + cv.check_type('name', name, basestring) + self._name = name + + @mgxs_types.setter + def mgxs_types(self, mgxs_types): + if mgxs_types == 'all': + self._mgxs_types = openmc.mgxs.MGXS_TYPES + else: + cv.check_iterable_type('mgxs_types', mgxs_types, basestring) + for mgxs_type in mgxs_types: + cv.check_value('mgxs_type', mgxs_type, openmc.mgxs.MGXS_TYPES) + self._mgxs_types = mgxs_types + + @by_nuclide.setter + def by_nuclide(self, by_nuclide): + cv.check_type('by_nuclide', by_nuclide, bool) + self._by_nuclide = by_nuclide + + @domain_type.setter + def domain_type(self, domain_type): + cv.check_value('domain type', domain_type, tuple(openmc.mgxs.DOMAIN_TYPES)) + self._domain_type = domain_type + + @domains.setter + def domains(self, domains): + + # Use all materials, cells or universes in the geometry as domains + if domains == 'all': + self._domains = domains + + # User specified a list of material, cell or universe domains + else: + if self.domain_type == 'material': + cv.check_iterable_type('domain', domains, openmc.Material) + all_domains = self.openmc_geometry.get_all_materials() + elif self.domain_type in ['cell', 'distribcell']: + cv.check_iterable_type('domain', domains, openmc.Cell) + all_domains = self.openmc_geometry.get_all_material_cells() + elif self.domain_type == 'universe': + cv.check_iterable_type('domain', domains, openmc.Universe) + all_domains = self.openmc_geometry.get_all_universes() + else: + msg = 'Unable to set domains with ' \ + 'domain type "{}"'.format(self.domain_type) + raise ValueError(msg) + + # Check that each domain can be found in the geometry + for domain in domains: + if domain not in all_domains: + msg = 'Domain "{}" could not be found in the ' \ + 'geometry.'.format(domain) + raise ValueError(msg) + + self._domains = domains + + @correction.setter + def correction(self, correction): + cv.check_value('correction', correction, ('P0', None)) + self._correction = correction + + @energy_groups.setter + def energy_groups(self, energy_groups): + cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) + self._energy_groups = energy_groups + + @tally_trigger.setter + def tally_trigger(self, tally_trigger): + cv.check_type('tally trigger', tally_trigger, openmc.Trigger) + self._tally_trigger = tally_trigger + + def build_library(self): + """Initialize MGXS objects in each domain and for each reaction type + in the library. + + This routine will populate the all_mgxs instance attribute dictionary + with MGXS subclass objects keyed by each domain ID (e.g., Material IDs) + and cross section type (e.g., 'nu-fission', 'total', etc.). + + """ + + # Initialize MGXS for each domain and mgxs type and store in dictionary + for domain in self.domains: + self.all_mgxs[domain.id] = OrderedDict() + for mgxs_type in self.mgxs_types: + mgxs = openmc.mgxs.MGXS.get_mgxs(mgxs_type, name=self.name) + mgxs.domain = domain + mgxs.domain_type = self.domain_type + mgxs.energy_groups = self.energy_groups + mgxs.by_nuclide = self.by_nuclide + + # If a tally trigger was specified, add it to the MGXS + if self.tally_trigger: + mgxs.tally_trigger = self.tally_trigger + + # Specify whether to use a transport ('P0') correction + if isinstance(mgxs, openmc.mgxs.ScatterMatrixXS): + mgxs.correction = self.correction + + self.all_mgxs[domain.id][mgxs_type] = mgxs + + def add_to_tallies_file(self, tallies_file, merge=True): + """Add all tallies from all MGXS objects to a tallies file. + + NOTE: This assumes that build_library() has been called + + Parameters + ---------- + tallies_file : openmc.TalliesFile + A TalliesFile object to add each MGXS' tallies to generate a + "tallies.xml" input file for OpenMC + merge : bool + Indicate whether tallies should be merged when possible. Defaults + to True. + + """ + + cv.check_type('tallies_file', tallies_file, openmc.TalliesFile) + + # Add tallies from each MGXS for each domain and mgxs type + for domain in self.domains: + for mgxs_type in self.mgxs_types: + mgxs = self.get_mgxs(domain, mgxs_type) + for tally_id, tally in mgxs.tallies.items(): + tallies_file.add_tally(tally, merge=merge) + + def load_from_statepoint(self, statepoint): + """Extracts tallies in an OpenMC StatePoint with the data needed to + compute multi-group cross sections. + + This method is needed to compute cross section data from tallies + in an OpenMC StatePoint object. + + NOTE: The statepoint must first be linked with an OpenMC Summary object. + + Parameters + ---------- + statepoint : openmc.StatePoint + An OpenMC StatePoint object with tally data + + Raises + ------ + ValueError + When this method is called with a statepoint that has not been + linked with a summary object. + + """ + + cv.check_type('statepoint', statepoint, openmc.StatePoint) + + if not statepoint.with_summary: + msg = 'Unable to load data from a statepoint which has not been ' \ + 'linked with a summary file' + raise ValueError(msg) + + self._sp_filename = statepoint._f.filename + self._openmc_geometry = statepoint.summary.openmc_geometry + + if statepoint.run_mode == 'k-eigenvalue': + self._keff = statepoint.k_combined[0] + + # Load tallies for each MGXS for each domain and mgxs type + for domain in self.domains: + for mgxs_type in self.mgxs_types: + mgxs = self.get_mgxs(domain, mgxs_type) + mgxs.load_from_statepoint(statepoint) + + def get_mgxs(self, domain, mgxs_type): + """Return the MGXS object for some domain and reaction rate type. + + This routine searches the library for an MGXS object for the spatial + domain and reaction rate type requested by the user. + + NOTE: This routine must be called after the build_library() routine. + + Parameters + ---------- + domain : Material or Cell or Universe or Integral + The material, cell, or universe object of interest (or its ID) + mgxs_type : {'total', 'transport', 'absorption', 'capture', 'fission', 'nu-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'chi'} + The type of multi-group cross section object to return + + Returns + ------- + openmc.mgxs.MGXS + The MGXS object for the requested domain and reaction rate type + + Raises + ------ + ValueError + If no MGXS object can be found for the requested domain or + multi-group cross section type + + """ + + if self.domain_type == 'material': + cv.check_type('domain', domain, (openmc.Material, Integral)) + elif self.domain_type == 'cell' or self.domain_type == 'distribcell': + cv.check_type('domain', domain, (openmc.Cell, Integral)) + elif self.domain_type == 'universe': + cv.check_type('domain', domain, (openmc.Universe, Integral)) + + # Check that requested domain is included in library + if cv._isinstance(domain, Integral): + domain_id = domain + for domain in self.domains: + if domain_id == domain.id: + break + else: + msg = 'Unable to find MGXS for {0} "{1}" in ' \ + 'library'.format(self.domain_type, domain) + raise ValueError(msg) + else: + domain_id = domain.id + + # Check that requested domain is included in library + if mgxs_type not in self.mgxs_types: + msg = 'Unable to find MGXS type "{0}"'.format(mgxs_type) + raise ValueError(msg) + + return self.all_mgxs[domain_id][mgxs_type] + + def get_condensed_library(self, coarse_groups): + """Construct an energy-condensed version of this library. + + This routine condenses each of the multi-group cross sections in the + library to a coarse energy group structure. NOTE: This routine must + be called after the load_from_statepoint(...) routine loads the tallies + from the statepoint into each of the cross sections. + + Parameters + ---------- + coarse_groups : openmc.mgxs.EnergyGroups + The coarse energy group structure of interest + + Returns + ------- + Library + A new multi-group cross section library condensed to the group + structure of interest + + Raises + ------ + ValueError + When this method is called before a statepoint has been loaded + + See also + -------- + MGXS.get_condensed_xs(coarse_groups) + + """ + + if self.sp_filename is None: + msg = 'Unable to get a condensed coarse group cross section ' \ + 'library since the statepoint has not yet been loaded' + raise ValueError(msg) + + cv.check_type('coarse_groups', coarse_groups, openmc.mgxs.EnergyGroups) + cv.check_less_than('coarse groups', coarse_groups.num_groups, + self.num_groups, equality=True) + cv.check_value('upper coarse energy', coarse_groups.group_edges[-1], + [self.energy_groups.group_edges[-1]]) + cv.check_value('lower coarse energy', coarse_groups.group_edges[0], + [self.energy_groups.group_edges[0]]) + + # Clone this Library to initialize the condensed version + condensed_library = copy.deepcopy(self) + condensed_library.energy_groups = coarse_groups + + # Condense the MGXS for each domain and mgxs type + for domain in self.domains: + for mgxs_type in self.mgxs_types: + mgxs = condensed_library.get_mgxs(domain, mgxs_type) + condensed_mgxs = mgxs.get_condensed_xs(coarse_groups) + condensed_library.all_mgxs[domain.id][mgxs_type] = condensed_mgxs + + return condensed_library + + def get_subdomain_avg_library(self): + """Construct a subdomain-averaged version of this library. + + This routine averages each multi-group cross section across distribcell + instances. The method performs spatial homogenization to compute the + scalar flux-weighted average cross section across the subdomains. + + NOTE: This method is only relevant for distribcell domain types and + simplys returns a deep copy of the library for all other domains types. + + Returns + ------- + Library + A new multi-group cross section library averaged across subdomains + + Raises + ------ + ValueError + When this method is called before a statepoint has been loaded + + See also + -------- + MGXS.get_subdomain_avg_xs(subdomains) + + """ + + if self.sp_filename is None: + msg = 'Unable to get a subdomain-averaged cross section ' \ + 'library since the statepoint has not yet been loaded' + raise ValueError(msg) + + # Clone this Library to initialize the subdomain-averaged version + subdomain_avg_library = copy.deepcopy(self) + + if subdomain_avg_library.domain_type == 'distribcell': + subdomain_avg_library.domain_type = 'cell' + else: + return subdomain_avg_library + + # Subdomain average the MGXS for each domain and mgxs type + for domain in self.domains: + for mgxs_type in self.mgxs_types: + mgxs = subdomain_avg_library.get_mgxs(domain, mgxs_type) + avg_mgxs = mgxs.get_subdomain_avg_xs() + subdomain_avg_library.all_mgxs[domain.id][mgxs_type] = avg_mgxs + + return subdomain_avg_library + + def build_hdf5_store(self, filename='mgxs.h5', directory='mgxs', + subdomains='all', nuclides='all', xs_type='macro'): + """Export the multi-group cross section library to an HDF5 binary file. + + This method constructs an HDF5 file which stores the library's + multi-group cross section data. The data is stored in a hierarchy of + HDF5 groups from the domain type, domain id, subdomain id (for + distribcell domains), nuclides and cross section types. Two datasets for + the mean and standard deviation are stored for each subdomain entry in + the HDF5 file. The number of groups is stored as a file attribute. + + NOTE: This requires the h5py Python package. + + Parameters + ---------- + filename : str + Filename for the HDF5 file. Defaults to 'mgxs.h5'. + directory : str + Directory for the HDF5 file. Defaults to 'mgxs'. + subdomains : {'all', 'avg'} + Report all subdomains or the average of all subdomain cross sections + in the report. Defaults to 'all'. + nuclides : {'all', 'sum'} + The nuclides of the cross-sections to include in the report. This + may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). + The special string 'all' will report the cross sections for all + nuclides in the spatial domain. The special string 'sum' will report + the cross sections summed over all nuclides. Defaults to 'all'. + xs_type: {'macro', 'micro'} + Store the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + + Raises + ------ + ValueError + When this method is called before a statepoint has been loaded + + See also + -------- + MGXS.build_hdf5_store(filename, directory, xs_type) + + """ + + if self.sp_filename is None: + msg = 'Unable to export multi-group cross section library ' \ + 'since a statepoint has not yet been loaded' + raise ValueError(msg) + + cv.check_type('filename', filename, basestring) + cv.check_type('directory', directory, basestring) + + import h5py + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + # Add an attribute for the number of energy groups to the HDF5 file + full_filename = os.path.join(directory, filename) + full_filename = full_filename.replace(' ', '-') + f = h5py.File(full_filename, 'w') + f.attrs["# groups"] = self.num_groups + f.close() + + # Export MGXS for each domain and mgxs type to an HDF5 file + for domain in self.domains: + for mgxs_type in self.mgxs_types: + mgxs = self.all_mgxs[domain.id][mgxs_type] + + if subdomains == 'avg': + mgxs = mgxs.get_subdomain_avg_xs() + + mgxs.build_hdf5_store(filename, directory, + xs_type=xs_type, nuclides=nuclides) + + def dump_to_file(self, filename='mgxs', directory='mgxs'): + """Store this Library object in a pickle binary file. + + Parameters + ---------- + filename : str + Filename for the pickle file. Defaults to 'mgxs'. + directory : str + Directory for the pickle file. Defaults to 'mgxs'. + + See also + -------- + Library.load_from_file(filename, directory) + + """ + + cv.check_type('filename', filename, basestring) + cv.check_type('directory', directory, basestring) + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + full_filename = os.path.join(directory, filename + '.pkl') + full_filename = full_filename.replace(' ', '-') + + # Load and return pickled Library object + pickle.dump(self, open(full_filename, 'wb')) + + @staticmethod + def load_from_file(filename='mgxs', directory='mgxs'): + """Load a Library object from a pickle binary file. + + Parameters + ---------- + filename : str + Filename for the pickle file. Defaults to 'mgxs'. + directory : str + Directory for the pickle file. Defaults to 'mgxs'. + + Returns + ------- + Library + A Library object loaded from the pickle binary file + + See also + -------- + Library.dump_to_file(mgxs_lib, filename, directory) + + """ + + cv.check_type('filename', filename, basestring) + cv.check_type('directory', directory, basestring) + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + full_filename = os.path.join(directory, filename + '.pkl') + full_filename = full_filename.replace(' ', '-') + + # Load and return pickled Library object + return pickle.load(open(full_filename, 'rb')) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py new file mode 100644 index 0000000000..635c822e31 --- /dev/null +++ b/openmc/mgxs/mgxs.py @@ -0,0 +1,2276 @@ +from __future__ import division + +from collections import Iterable, OrderedDict +from numbers import Integral +import os +import sys +import copy +import abc + +import numpy as np + +import openmc +import openmc.checkvalue as cv +from openmc.mgxs import EnergyGroups + + +if sys.version_info[0] >= 3: + basestring = str + + +# Supported cross section types +MGXS_TYPES = ['total', + 'transport', + 'absorption', + 'capture', + 'fission', + 'nu-fission', + 'scatter', + 'nu-scatter', + 'scatter matrix', + 'nu-scatter matrix', + 'chi'] + + +# Supported domain types +# TODO: Implement Mesh domains +DOMAIN_TYPES = ['cell', + 'distribcell', + 'universe', + 'material'] + +# Supported domain classes +# TODO: Implement Mesh domains +_DOMAINS = [openmc.Cell, + openmc.Universe, + openmc.Material] + + +class MGXS(object): + """An abstract multi-group cross section for some energy group structure + within some spatial domain. + + This class can be used for both OpenMC input generation and tally data + post-processing to compute spatially-homogenized and energy-integrated + multi-group cross sections for deterministic neutronics calculations. + + NOTE: Users should instantiate the subclasses of this abstract class. + + Parameters + ---------- + domain : Material or Cell or Universe + The domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe'} + The domain type for spatial homogenization + energy_groups : EnergyGroups + The energy group structure for energy condensation + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + name : str, optional + Name of the multi-group cross section. Used as a label to identify + tallies in OpenMC 'tallies.xml' file. + + Attributes + ---------- + name : str, optional + Name of the multi-group cross section + rxn_type : str + Reaction type (e.g., 'total', 'nu-fission', etc.) + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + domain : Material or Cell or Universe + Domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe'} + Domain type for spatial homogenization + energy_groups : EnergyGroups + Energy group structure for energy condensation + tally_trigger : Trigger + An (optional) tally precision trigger given to each tally used to + compute the cross section + tallies : OrderedDict + OpenMC tallies needed to compute the multi-group cross section + xs_tally : Tally + Derived tally for the multi-group cross section. This attribute + is None unless the multi-group cross section has been computed. + num_sumbdomains : Integral + The number of subdomains is unity for 'material', 'cell' and 'universe' + domain types. When the This is equal to the number of cell instances + for 'distribcell' domain types (it is equal to unity prior to loading + tally data from a statepoint file). + num_nuclides : Integral + The number of nuclides for which the multi-group cross section is + being tracked. This is unity if the by_nuclide attribute is False. + nuclides : list of str or 'sum' + A list of nuclide string names (e.g., 'U-238', 'O-16') when by_nuclide + is True and 'sum' when by_nuclide is False. + + """ + + # This is an abstract class which cannot be instantiated + __metaclass__ = abc.ABCMeta + + def __init__(self, domain=None, domain_type=None, + energy_groups=None, by_nuclide=False, name=''): + + self._name = '' + self._rxn_type = None + self._by_nuclide = None + self._domain = None + self._domain_type = None + self._energy_groups = None + self._tally_trigger = None + self._tallies = None + self._xs_tally = None + + self.name = name + self.by_nuclide = by_nuclide + + if domain_type is not None: + self.domain_type = domain_type + if domain is not None: + self.domain = domain + if energy_groups is not None: + self.energy_groups = energy_groups + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy this object, copy it + if existing is None: + clone = type(self).__new__(type(self)) + clone._name = self.name + clone._rxn_type = self.rxn_type + clone._by_nuclide = self.by_nuclide + clone._domain = self.domain + clone._domain_type = self.domain_type + clone._energy_groups = copy.deepcopy(self.energy_groups, memo) + clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo) + clone._xs_tally = copy.deepcopy(self.xs_tally, memo) + + clone._tallies = OrderedDict() + for tally_type, tally in self.tallies.items(): + clone.tallies[tally_type] = copy.deepcopy(tally, memo) + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + + @property + def name(self): + return self._name + + @property + def rxn_type(self): + return self._rxn_type + + @property + def by_nuclide(self): + return self._by_nuclide + + @property + def domain(self): + return self._domain + + @property + def domain_type(self): + return self._domain_type + + @property + def energy_groups(self): + return self._energy_groups + + @property + def tally_trigger(self): + return self._tally_trigger + + @property + def num_groups(self): + return self.energy_groups.num_groups + + @property + def tallies(self): + return self._tallies + + @property + def xs_tally(self): + return self._xs_tally + + @property + def num_subdomains(self): + tally = list(self.tallies.values())[0] + domain_filter = tally.find_filter(self.domain_type) + return domain_filter.num_bins + + @property + def num_nuclides(self): + if self.by_nuclide: + return len(self.get_all_nuclides()) + else: + return 1 + + @property + def nuclides(self): + if self.by_nuclide: + return self.get_all_nuclides() + else: + return 'sum' + + @name.setter + def name(self, name): + cv.check_type('name', name, basestring) + self._name = name + + @by_nuclide.setter + def by_nuclide(self, by_nuclide): + cv.check_type('by_nuclide', by_nuclide, bool) + self._by_nuclide = by_nuclide + + @domain.setter + def domain(self, domain): + cv.check_type('domain', domain, tuple(_DOMAINS)) + self._domain = domain + + @domain_type.setter + def domain_type(self, domain_type): + cv.check_value('domain type', domain_type, tuple(DOMAIN_TYPES)) + self._domain_type = domain_type + + @energy_groups.setter + def energy_groups(self, energy_groups): + cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) + self._energy_groups = energy_groups + + @tally_trigger.setter + def tally_trigger(self, tally_trigger): + cv.check_type('tally trigger', tally_trigger, openmc.Trigger) + self._tally_trigger = tally_trigger + + @staticmethod + def get_mgxs(mgxs_type, domain=None, domain_type=None, + energy_groups=None, by_nuclide=False, name=''): + """Return a MGXS subclass object for some energy group structure within + some spatial domain for some reaction type. + + This is a factory method which can be used to quickly create MGXS + subclass objects for various reaction types. + + Parameters + ---------- + mgxs_type : {'total', 'transport', 'absorption', 'capture', 'fission', 'nu-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'chi'} + The type of multi-group cross section object to return + domain : Material or Cell or Universe + The domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe'} + The domain type for spatial homogenization + energy_groups : EnergyGroups + The energy group structure for energy condensation + by_nuclide : bool + If true, computes cross sections for each nuclide in domain. + Defaults to False + name : str, optional + Name of the multi-group cross section. Used as a label to identify + tallies in OpenMC 'tallies.xml' file. Defaults to the empty string. + + Returns + ------- + MGXS + A subclass of the abstract MGXS class for the multi-group cross + section type requested by the user + + """ + + cv.check_value('mgxs_type', mgxs_type, MGXS_TYPES) + + if mgxs_type == 'total': + mgxs = TotalXS(domain, domain_type, energy_groups) + elif mgxs_type == 'transport': + mgxs = TransportXS(domain, domain_type, energy_groups) + elif mgxs_type == 'absorption': + mgxs = AbsorptionXS(domain, domain_type, energy_groups) + elif mgxs_type == 'capture': + mgxs = CaptureXS(domain, domain_type, energy_groups) + elif mgxs_type == 'fission': + mgxs = FissionXS(domain, domain_type, energy_groups) + elif mgxs_type == 'nu-fission': + mgxs = NuFissionXS(domain, domain_type, energy_groups) + elif mgxs_type == 'scatter': + mgxs = ScatterXS(domain, domain_type, energy_groups) + elif mgxs_type == 'nu-scatter': + mgxs = NuScatterXS(domain, domain_type, energy_groups) + elif mgxs_type == 'scatter matrix': + mgxs = ScatterMatrixXS(domain, domain_type, energy_groups) + elif mgxs_type == 'nu-scatter matrix': + mgxs = NuScatterMatrixXS(domain, domain_type, energy_groups) + elif mgxs_type == 'chi': + mgxs = Chi(domain, domain_type, energy_groups) + + mgxs.by_nuclide = by_nuclide + mgxs.name = name + return mgxs + + def get_all_nuclides(self): + """Get all nuclides in the cross section's spatial domain. + + Returns + ------- + list of str + A list of the string names for each nuclide in the spatial domain + (e.g., ['U-235', 'U-238', 'O-16']) + + Raises + ------ + ValueError + When this method is called before the spatial domain has been set. + + """ + + if self.domain is None: + raise ValueError('Unable to get all nuclides without a domain') + + nuclides = self.domain.get_all_nuclides() + return nuclides.keys() + + def get_nuclide_density(self, nuclide): + """Get the atomic number density in units of atoms/b-cm for a nuclide + in the cross section's spatial domain. + + Parameters + ---------- + nuclide : str + A nuclide name string (e.g., 'U-235') + + Returns + ------- + Real + The atomic number density (atom/b-cm) for the nuclide of interest + + Raises + ------- + ValueError + When the density is requested for a nuclide which is not found in + the spatial domain. + + """ + + cv.check_type('nuclide', nuclide, basestring) + + # Get list of all nuclides in the spatial domain + nuclides = self.domain.get_all_nuclides() + + if nuclide not in nuclides: + msg = 'Unable to get density for nuclide "{0}" which is not in ' \ + '{1} "{2}"'.format(nuclide, self.domain_type, self.domain.id) + ValueError(msg) + + density = nuclides[nuclide][1] + return density + + def get_nuclide_densities(self, nuclides='all'): + """Get an array of atomic number densities in units of atom/b-cm for all + nuclides in the cross section's spatial domain. + + Parameters + ---------- + nuclides : Iterable of str or 'all' or 'sum' + A list of nuclide name strings (e.g., ['U-235', 'U-238']). The + special string 'all' will return the atom densities for all nuclides + in the spatial domain. The special string 'sum' will return the atom + density summed across all nuclides in the spatial domain. Defaults + to 'all'. + + Returns + ------- + ndarray of Real + An array of the atomic number densities (atom/b-cm) for each of the + nuclides in the spatial domain + + Raises + ------ + ValueError + When this method is called before the spatial domain has been set. + + """ + + if self.domain is None: + raise ValueError('Unable to get nuclide densities without a domain') + + # Sum the atomic number densities for all nuclides + if nuclides == 'sum': + nuclides = self.get_all_nuclides() + densities = np.zeros(1, dtype=np.float) + for nuclide in nuclides: + densities[0] += self.get_nuclide_density(nuclide) + + # Tabulate the atomic number densities for all nuclides + elif nuclides == 'all': + nuclides = self.get_all_nuclides() + densities = np.zeros(self.num_nuclides, dtype=np.float) + for i, nuclide in enumerate(nuclides): + densities[i] += self.get_nuclide_density(nuclide) + + # Tabulate the atomic number densities for each specified nuclide + else: + densities = np.zeros(len(nuclides), dtype=np.float) + for i, nuclide in enumerate(nuclides): + densities[i] = self.get_nuclide_density(nuclide) + + return densities + + def _create_tallies(self, scores, all_filters, keys, estimator): + """Instantiates tallies needed to compute the multi-group cross section. + + This is a helper method for MGXS subclasses to create tallies + for input file generation. The tallies are stored in the tallies dict. + This method is called by each subclass' tallies property getter + which define the parameters given to this parent class method. + + Parameters + ---------- + scores : Iterable of str + Scores for each tally + all_filters : Iterable of tuple of Filter + Tuples of non-spatial domain filters for each tally + keys : Iterable of str + Key string used to store each tally in the tallies dictionary + estimator : {'analog' or 'tracklength'} + Type of estimator to use for each tally + + """ + + cv.check_iterable_type('scores', scores, basestring) + cv.check_length('scores', scores, len(keys)) + cv.check_iterable_type('filters', all_filters, openmc.Filter, 1, 2) + cv.check_type('keys', keys, Iterable, basestring) + cv.check_value('estimator', estimator, ['analog', 'tracklength']) + + self._tallies = OrderedDict() + + # Create a domain Filter object + domain_filter = openmc.Filter(self.domain_type, self.domain.id) + + # Create each Tally needed to compute the multi group cross section + for score, key, filters in zip(scores, keys, all_filters): + self.tallies[key] = openmc.Tally(name=self.name) + self.tallies[key].add_score(score) + self.tallies[key].estimator = estimator + self.tallies[key].add_filter(domain_filter) + + # If a tally trigger was specified, add it to each tally + if self.tally_trigger: + trigger_clone = copy.deepcopy(self.tally_trigger) + trigger_clone.add_score(score) + self.tallies[key].add_trigger(trigger_clone) + + # Add all non-domain specific Filters (e.g., 'energy') to the Tally + for filter in filters: + self.tallies[key].add_filter(filter) + + # If this is a by-nuclide cross-section, add all nuclides to Tally + if self.by_nuclide and score != 'flux': + all_nuclides = self.domain.get_all_nuclides() + for nuclide in all_nuclides: + self.tallies[key].add_nuclide(nuclide) + else: + self.tallies[key].add_nuclide('total') + + @abc.abstractmethod + def compute_xs(self): + """Performs generic cleanup after a subclass' uses tally arithmetic to + compute a multi-group cross section as a derived tally. + + This method replaces CrossNuclides generated by tally arithmetic with + the original Nuclide objects in the xs_tally instance attribute. The + simple Nuclides allow for cleaner output through Pandas DataFrames as + well as simpler data access through the get_xs(...) class method. + + In addition, this routine resets NaNs in the multi group cross section + array to 0.0. This may be needed occur if no events were scored in + certain tally bins, which will lead to a divide-by-zero situation. + + """ + + # If computing xs for each nuclide, replace CrossNuclides with originals + if self.by_nuclide: + self.xs_tally._nuclides = [] + nuclides = self.domain.get_all_nuclides() + for nuclide in nuclides: + self.xs_tally.add_nuclide(openmc.Nuclide(nuclide)) + + # Remove NaNs which may have resulted from divide-by-zero operations + self._xs_tally._mean = np.nan_to_num(self.xs_tally.mean) + self._xs_tally._std_dev = np.nan_to_num(self.xs_tally.std_dev) + + def load_from_statepoint(self, statepoint): + """Extracts tallies in an OpenMC StatePoint with the data needed to + compute multi-group cross sections. + + This method is needed to compute cross section data from tallies + in an OpenMC StatePoint object. + + NOTE: The statepoint must first be linked with an OpenMC Summary object. + + Parameters + ---------- + statepoint : openmc.StatePoint + An OpenMC StatePoint object with tally data + + Raises + ------ + ValueError + When this method is called with a statepoint that has not been + linked with a summary object. + + """ + + cv.check_type('statepoint', statepoint, openmc.statepoint.StatePoint) + + if not statepoint.with_summary: + msg = 'Unable to load data from a statepoint which has not been ' \ + 'linked with a summary file' + raise ValueError(msg) + + # Override the domain object that loaded from an OpenMC summary file + # NOTE: This is necessary for micro cross-sections which require + # the isotopic number densities as computed by OpenMC + if self.domain_type == 'cell' or self.domain_type == 'distribcell': + self.domain = statepoint.summary.get_cell_by_id(self.domain.id) + elif self.domain_type == 'universe': + self.domain = statepoint.summary.get_universe_by_id(self.domain.id) + elif self.domain_type == 'material': + self.domain = statepoint.summary.get_material_by_id(self.domain.id) + else: + msg = 'Unable to load data from a statepoint for domain type {0} ' \ + 'which is not yet supported'.format(self.domain_type) + raise ValueError(msg) + + # Use tally "slicing" to ensure that tallies correspond to our domain + # NOTE: This is important if tally merging was used + if self.domain_type != 'distribcell': + filters = [self.domain_type] + filter_bins = [(self.domain.id,)] + # Distribcell filters only accept single cell - neglect it when slicing + else: + filters = [] + filter_bins = [] + + # Find, slice and store Tallies from StatePoint + # The tally slicing is needed if tally merging was used + for tally_type, tally in self.tallies.items(): + sp_tally = statepoint.get_tally(tally.scores, tally.filters, + tally.nuclides, + estimator=tally.estimator) + sp_tally = sp_tally.get_slice(tally.scores, filters, + filter_bins, tally.nuclides) + self.tallies[tally_type] = sp_tally + + # Compute the cross section from the tallies + self.compute_xs() + + def get_xs(self, groups='all', subdomains='all', nuclides='all', + xs_type='macro', order_groups='increasing', value='mean'): + """Returns an array of multi-group cross sections. + + This method constructs a 2D NumPy array for the requested multi-group + cross section data data for one or more energy groups and subdomains. + + Parameters + ---------- + groups : Iterable of Integral or 'all' + Energy groups of interest. Defaults to 'all'. + subdomains : Iterable of Integral or 'all' + Subdomain IDs of interest. Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + A list of nuclide name strings (e.g., ['U-235', 'U-238']). The + special string 'all' will return the cross sections for all nuclides + in the spatial domain. The special string 'sum' will return the + cross section summed over all nuclides. Defaults to 'all'. + xs_type: {'macro', 'micro'} + Return the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + order_groups: {'increasing', 'decreasing'} + Return the cross section indexed according to increasing or + decreasing energy groups (decreasing or increasing energies). + Defaults to 'increasing'. + value : str + A string for the type of value to return - 'mean', 'std_dev' or + 'rel_err' are accepted. Defaults to 'mean'. + + Returns + ------- + ndarray + A NumPy array of the multi-group cross section indexed in the order + each group, subdomain and nuclide is listed in the parameters. + + Raises + ------ + ValueError + When this method is called before the multi-group cross section is + computed from tally data. + + """ + + if self.xs_tally is None: + msg = 'Unable to get cross section since it has not been computed' + raise ValueError(msg) + + cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + filters = [] + filter_bins = [] + + # Construct a collection of the domain filter bins + if subdomains != 'all': + cv.check_iterable_type('subdomains', subdomains, Integral) + for subdomain in subdomains: + filters.append(self.domain_type) + filter_bins.append((subdomain,)) + + # Construct list of energy group bounds tuples for all requested groups + if groups != 'all': + cv.check_iterable_type('groups', groups, Integral) + for group in groups: + filters.append('energy') + filter_bins.append((self.energy_groups.get_group_bounds(group),)) + + # Construct a collection of the nuclides to retrieve from the xs tally + if self.by_nuclide: + if nuclides == 'all' or nuclides == 'sum' or nuclides == ['sum']: + query_nuclides = self.get_all_nuclides() + else: + query_nuclides = nuclides + else: + query_nuclides = ['total'] + + # If user requested the sum for all nuclides, use tally summation + if nuclides == 'sum' or nuclides == ['sum']: + xs_tally = self.xs_tally.summation(nuclides=query_nuclides) + xs = xs_tally.get_values(filters=filters, + filter_bins=filter_bins, value=value) + else: + xs = self.xs_tally.get_values(filters=filters, filter_bins=filter_bins, + nuclides=query_nuclides, value=value) + + # Divide by atom number densities for microscopic cross sections + if xs_type == 'micro': + if self.by_nuclide: + densities = self.get_nuclide_densities(nuclides) + else: + densities = self.get_nuclide_densities('sum') + if value == 'mean' or value == 'std_dev': + xs /= densities[np.newaxis, :, np.newaxis] + + # Reverse data if user requested increasing energy groups since + # tally data is stored in order of increasing energies + if order_groups == 'increasing': + if groups == 'all': + num_groups = self.num_groups + else: + num_groups = len(groups) + + # Reshape tally data array with separate axes for domain and energy + num_subdomains = int(xs.shape[0] / num_groups) + new_shape = (num_subdomains, num_groups) + xs.shape[1:] + xs = np.reshape(xs, new_shape) + + # Reverse energies to align with increasing energy groups + xs = xs[:, ::-1, :] + + # Eliminate trivial dimensions + xs = np.squeeze(xs) + xs = np.atleast_1d(xs) + + return xs + + def get_condensed_xs(self, coarse_groups): + """Construct an energy-condensed version of this cross section. + + Parameters + ---------- + coarse_groups : openmc.mgxs.EnergyGroups + The coarse energy group structure of interest + + Returns + ------- + MGXS + A new MGXS condensed to the group structure of interest + + """ + + if self.xs_tally is None: + msg = 'Unable to get a condensed coarse group cross section ' \ + 'since the fine group cross section has not been computed' + raise ValueError(msg) + + cv.check_type('coarse_groups', coarse_groups, EnergyGroups) + cv.check_less_than('coarse groups', coarse_groups.num_groups, + self.num_groups, equality=True) + cv.check_value('upper coarse energy', coarse_groups.group_edges[-1], + [self.energy_groups.group_edges[-1]]) + cv.check_value('lower coarse energy', coarse_groups.group_edges[0], + [self.energy_groups.group_edges[0]]) + + # Clone this MGXS to initialize the condensed version + condensed_xs = copy.deepcopy(self) + condensed_xs.energy_groups = coarse_groups + + # Build energy indices to sum across + energy_indices = [] + for group in range(coarse_groups.num_groups, 0, -1): + low, high = coarse_groups.get_group_bounds(group) + low_index = np.where(self.energy_groups.group_edges == low)[0][0] + energy_indices.append(low_index) + + fine_edges = self.energy_groups.group_edges + + # Condense each of the tallies to the coarse group structure + for tally_type, tally in condensed_xs.tallies.items(): + + # Make condensed tally derived and null out sum, sum_sq + tally._derived = True + tally._sum = None + tally._sum_sq = None + + # Get tally data arrays reshaped with one dimension per filter + mean = tally.get_reshaped_data(value='mean') + std_dev = tally.get_reshaped_data(value='std_dev') + + # Sum across all applicable fine energy group filters + for i, filter in enumerate(tally.filters): + if 'energy' not in filter.type: + continue + elif len(filter.bins) != len(fine_edges): + continue + elif not np.allclose(filter.bins, fine_edges): + continue + else: + filter.bins = coarse_groups.group_edges + mean = np.add.reduceat(mean, energy_indices, axis=i) + std_dev = np.add.reduceat(std_dev**2, energy_indices, axis=i) + std_dev = np.sqrt(std_dev) + + # Reshape condensed data arrays with one dimension for all filters + new_shape = \ + (tally.num_filter_bins, tally.num_nuclides, tally.num_score_bins,) + mean = np.reshape(mean, new_shape) + std_dev = np.reshape(std_dev, new_shape) + + # Override tally's data with the new condensed data + tally._mean = mean + tally._std_dev = std_dev + + # Compute the energy condensed multi-group cross section + condensed_xs.compute_xs() + return condensed_xs + + def get_subdomain_avg_xs(self, subdomains='all'): + """Construct a subdomain-averaged version of this cross section. + + This method is useful for averaging cross sections across distribcell + instances. The method performs spatial homogenization to compute the + scalar flux-weighted average cross section across the subdomains. + + Parameters + ---------- + subdomains : Iterable of Integral or 'all' + The subdomain IDs to average across. Defaults to 'all'. + + Returns + ------- + MGXS + A new MGXS averaged across the subdomains of interest + + Raises + ------ + ValueError + When this method is called before the multi-group cross section is + computed from tally data. + + """ + + if self.xs_tally is None: + msg = 'Unable to get subdomain-averaged cross section since the ' \ + 'subdomain-distributed cross section has not been computed' + raise ValueError(msg) + + # Construct a collection of the subdomain filter bins to average across + if subdomains != 'all': + cv.check_iterable_type('subdomains', subdomains, Integral) + elif self.domain_type == 'distribcell': + subdomains = np.arange(self.num_subdomains) + else: + subdomains = [0] + + # Clone this MGXS to initialize the subdomain-averaged version + avg_xs = copy.deepcopy(self) + + # If domain is distribcell, make the new domain 'cell' + if self.domain_type == 'distribcell': + avg_xs.domain_type = 'cell' + + # Average each of the tallies across subdomains + for tally_type, tally in avg_xs.tallies.items(): + + # Make condensed tally derived and null out sum, sum_sq + tally._derived = True + tally._sum = None + tally._sum_sq = None + + # Get tally data arrays reshaped with one dimension per filter + mean = tally.get_reshaped_data(value='mean') + std_dev = tally.get_reshaped_data(value='std_dev') + + # Get the mean, std. dev. across requested subdomains + mean = np.sum(mean[subdomains, ...], axis=0) + std_dev = np.sum(std_dev[subdomains, ...]**2, axis=0) + std_dev = np.sqrt(std_dev) + + # If domain is distribcell, make subdomain-averaged a 'cell' domain + domain_filter = tally.find_filter(self._domain_type) + if domain_filter.type == 'distribcell': + domain_filter.type = 'cell' + domain_filter.num_bins = 1 + + # Reshape averaged data arrays with one dimension for all filters + new_shape = \ + (tally.num_filter_bins, tally.num_nuclides, tally.num_score_bins,) + mean = np.reshape(mean, new_shape) + std_dev = np.reshape(std_dev, new_shape) + + # Override tally's data with the new condensed data + tally._mean = mean + tally._std_dev = std_dev + + # Compute the subdomain-averaged multi-group cross section + avg_xs.compute_xs() + + return avg_xs + + def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'): + """Print a string representation for the multi-group cross section. + + Parameters + ---------- + subdomains : Iterable of Integral or 'all' + The subdomain IDs of the cross sections to include in the report. + Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + The nuclides of the cross-sections to include in the report. This + may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). + The special string 'all' will report the cross sections for all + nuclides in the spatial domain. The special string 'sum' will report + the cross sections summed over all nuclides. Defaults to 'all'. + xs_type: {'macro', 'micro'} + Return the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + + """ + + # Construct a collection of the subdomains to report + if subdomains != 'all': + cv.check_iterable_type('subdomains', subdomains, Integral) + elif self.domain_type == 'distribcell': + subdomains = np.arange(self.num_subdomains, dtype=np.int) + else: + subdomains = [self.domain.id] + + # Construct a collection of the nuclides to report + if self.by_nuclide: + if nuclides == 'all': + nuclides = self.get_all_nuclides() + elif nuclides == 'sum': + nuclides = ['sum'] + else: + cv.check_iterable_type('nuclides', nuclides, basestring) + else: + nuclides = ['sum'] + + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + # Build header for string with type and domain info + string = 'Multi-Group XS\n' + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) + string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) + string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) + + # If cross section data has not been computed, only print string header + if self.xs_tally is None: + print(string) + return + + # Loop over all subdomains + for subdomain in subdomains: + + if self.domain_type == 'distribcell': + string += '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain) + + # Loop over all Nuclides + for nuclide in nuclides: + + # Build header for nuclide type + if nuclide != 'sum': + string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide) + + # Build header for cross section type + if xs_type == 'macro': + string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:') + else: + string += '{0: <16}\n'.format('\tCross Sections [barns]:') + + template = '{0: <12}Group {1} [{2: <10} - {3: <10}MeV]:\t' + + # Loop over energy groups ranges + for group in range(1, self.num_groups+1): + bounds = self.energy_groups.get_group_bounds(group) + string += template.format('', group, bounds[0], bounds[1]) + average = self.get_xs([group], [subdomain], [nuclide], + xs_type=xs_type, value='mean') + rel_err = self.get_xs([group], [subdomain], [nuclide], + xs_type=xs_type, value='rel_err') + average = average.flatten()[0] + rel_err = rel_err.flatten()[0] * 100. + string += '{:.2e} +/- {:1.2e}%'.format(average, rel_err) + string += '\n' + string += '\n' + string += '\n' + + print(string) + + def build_hdf5_store(self, filename='mgxs.h5', directory='mgxs', + subdomains='all', nuclides='all', + xs_type='macro', append=True): + """Export the multi-group cross section data to an HDF5 binary file. + + This method constructs an HDF5 file which stores the multi-group + cross section data. The data is stored in a hierarchy of HDF5 groups + from the domain type, domain id, subdomain id (for distribcell domains), + nuclides and cross section type. Two datasets for the mean and standard + deviation are stored for each subdomain entry in the HDF5 file. + + NOTE: This requires the h5py Python package. + + Parameters + ---------- + filename : str + Filename for the HDF5 file. Defaults to 'mgxs.h5'. + directory : str + Directory for the HDF5 file. Defaults to 'mgxs'. + subdomains : Iterable of Integral or 'all' + The subdomain IDs of the cross sections to include in the report. + Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + The nuclides of the cross-sections to include in the report. This + may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). + The special string 'all' will report the cross sections for all + nuclides in the spatial domain. The special string 'sum' will report + the cross sections summed over all nuclides. Defaults to 'all'. + xs_type: {'macro', 'micro'} + Store the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + append : bool + If true, appends to an existing HDF5 file with the same filename + directory (if one exists). Defaults to True. + + Raises + ------ + ValueError + When this method is called before the multi-group cross section is + computed from tally data. + ImportError + When h5py is not installed. + + """ + + if self.xs_tally is None: + msg = 'Unable to get build HDF5 store since the ' \ + 'cross section has not been computed' + raise ValueError(msg) + + import h5py + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + filename = os.path.join(directory, filename) + filename = filename.replace(' ', '-') + + if append and os.path.isfile(filename): + xs_results = h5py.File(filename, 'a') + else: + xs_results = h5py.File(filename, 'w') + + # Construct a collection of the subdomains to report + if subdomains != 'all': + cv.check_iterable_type('subdomains', subdomains, Integral) + elif self.domain_type == 'distribcell': + subdomains = np.arange(self.num_subdomains, dtype=np.int) + else: + subdomains = [self.domain.id] + + # Construct a collection of the nuclides to report + if self.by_nuclide: + if nuclides == 'all': + nuclides = self.get_all_nuclides() + densities = np.zeros(len(nuclides), dtype=np.float) + elif nuclides == 'sum': + nuclides = ['sum'] + else: + cv.check_iterable_type('nuclides', nuclides, basestring) + else: + nuclides = ['sum'] + + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + # Create an HDF5 group within the file for the domain + domain_type_group = xs_results.require_group(self.domain_type) + domain_group = domain_type_group.require_group(str(self.domain.id)) + + # Determine number of digits to pad subdomain group keys + num_digits = len(str(self.num_subdomains)) + + # Create a separate HDF5 group for each subdomain + for i, subdomain in enumerate(subdomains): + + # Create an HDF5 group for the subdomain + if self.domain_type == 'distribcell': + group_name = ''.zfill(num_digits) + subdomain_group = domain_group.require_group(group_name) + else: + subdomain_group = domain_group + + # Create a separate HDF5 group for the rxn type + rxn_group = subdomain_group.require_group(self.rxn_type) + + # Create a separate HDF5 group for each nuclide + for j, nuclide in enumerate(nuclides): + + if nuclide != 'sum': + density = densities[j] + nuclide_group = rxn_group.require_group(nuclide) + nuclide_group.require_dataset('density', dtype=np.float64, + data=[density], shape=(1,)) + else: + nuclide_group = rxn_group + + # Extract the cross section for this subdomain and nuclide + average = self.get_xs(subdomains=[subdomain], nuclides=[nuclide], + xs_type=xs_type, value='mean') + std_dev = self.get_xs(subdomains=[subdomain], nuclides=[nuclide], + xs_type=xs_type, value='std_dev') + average = average.squeeze() + std_dev = std_dev.squeeze() + + # Add MGXS results data to the HDF5 group + nuclide_group.require_dataset('average', dtype=np.float64, + shape=average.shape, data=average) + nuclide_group.require_dataset('std. dev.', dtype=np.float64, + shape=std_dev.shape, data=std_dev) + + # Close the results HDF5 file + xs_results.close() + + def export_xs_data(self, filename='mgxs', directory='mgxs', + format='csv', groups='all', xs_type='macro'): + """Export the multi-group cross section data to a file. + + This method leverages the functionality in the Pandas library to export + the multi-group cross section data in a variety of output file formats + for storage and/or post-processing. + + Parameters + ---------- + filename : str + Filename for the exported file. Defaults to 'mgxs'. + directory : str + Directory for the exported file. Defaults to 'mgxs'. + format : {'csv', 'excel', 'pickle', 'latex'} + The format for the exported data file. Defaults to 'csv'. + groups : Iterable of Integral or 'all' + Energy groups of interest. Defaults to 'all'. + xs_type: {'macro', 'micro'} + Store the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + + """ + + cv.check_type('filename', filename, basestring) + cv.check_type('directory', directory, basestring) + cv.check_value('format', format, ['csv', 'excel', 'pickle', 'latex']) + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + filename = os.path.join(directory, filename) + filename = filename.replace(' ', '-') + + # Get a Pandas DataFrame for the data + df = self.get_pandas_dataframe(groups=groups, xs_type=xs_type) + + # Capitalize column label strings + df.columns = df.columns.astype(str) + df.columns = map(str.title, df.columns) + + # Export the data using Pandas IO API + if format == 'csv': + df.to_csv(filename + '.csv', index=False) + elif format == 'excel': + df.to_excel(filename + '.xls', index=False) + elif format == 'pickle': + df.to_pickle(filename + '.pkl') + elif format == 'latex': + if self.domain_type == 'distribcell': + msg = 'Unable to export distribcell multi-group cross section' \ + 'data to a LaTeX table' + raise NotImplementedError(msg) + + df.to_latex(filename + '.tex', bold_rows=True, + longtable=True, index=False) + + # Surround LaTeX table with code needed to run pdflatex + with open(filename + '.tex','r') as original: + data = original.read() + with open(filename + '.tex','w') as modified: + modified.write( + '\\documentclass[preview, 12pt, border=1mm]{standalone}\n') + modified.write('\\usepackage{caption}\n') + modified.write('\\usepackage{longtable}\n') + modified.write('\\usepackage{booktabs}\n') + modified.write('\\begin{document}\n\n') + modified.write(data) + modified.write('\n\\end{document}') + + def get_pandas_dataframe(self, groups='all', nuclides='all', + xs_type='macro', summary=None): + """Build a Pandas DataFrame for the MGXS data. + + This method leverages the Tally.get_pandas_dataframe(...) method, but + renames the columns with terminology appropriate for cross section data. + + Parameters + ---------- + groups : Iterable of Integral or 'all' + Energy groups of interest. Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + The nuclides of the cross-sections to include in the dataframe. This + may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). + The special string 'all' will include the cross sections for all + nuclides in the spatial domain. The special string 'sum' will + include the cross sections summed over all nuclides. Defaults + to 'all'. + xs_type: {'macro', 'micro'} + Return macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + summary : None or Summary + An optional Summary object to be used to construct columns for + distribcell tally filters (default is None). The geometric + information in the Summary object is embedded into a multi-index + column with a geometric "path" to each distribcell intance. + NOTE: This option requires the OpenCG Python package. + + Returns + ------- + pandas.DataFrame + A Pandas DataFrame for the cross section data. + + Raises + ------ + ValueError + When this method is called before the multi-group cross section is + computed from tally data. + + """ + + if self.xs_tally is None: + msg = 'Unable to get Pandas DataFrame since the ' \ + 'cross section has not been computed' + raise ValueError(msg) + + if groups != 'all': + cv.check_iterable_type('groups', groups, Integral) + if nuclides != 'all' and nuclides != 'sum': + cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + # Get a Pandas DataFrame from the derived xs tally + if self.by_nuclide and nuclides == 'sum': + + # Use tally summation to sum across all nuclides + query_nuclides = self.get_all_nuclides() + xs_tally = self.xs_tally.summation(nuclides=query_nuclides) + df = xs_tally.get_pandas_dataframe(summary=summary) + + # Remove nuclide column since it is homogeneous and redundant + df.drop('nuclide', axis=1, inplace=True) + + # If the user requested a specific set of nuclides + elif self.by_nuclide and nuclides != 'all': + xs_tally = self.xs_tally.get_slice(nuclides=nuclides) + df = xs_tally.get_pandas_dataframe(summary=summary) + + # If the user requested all nuclides, keep nuclide column in dataframe + else: + df = self.xs_tally.get_pandas_dataframe(summary=summary) + + # Remove the score column since it is homogeneous and redundant + if summary and self.domain_type == 'distribcell': + df = df.drop('score', level=0, axis=1) + else: + df = df.drop('score', axis=1) + + # Override energy groups bounds with indices + all_groups = np.arange(self.num_groups, 0, -1, dtype=np.int) + all_groups = np.repeat(all_groups, self.num_nuclides) + if 'energy [MeV]' in df and 'energyout [MeV]' in df: + df.rename(columns={'energy [MeV]': 'group in'}, inplace=True) + in_groups = np.tile(all_groups, self.num_subdomains) + in_groups = np.repeat(in_groups, self.num_groups) + df['group in'] = in_groups + + df.rename(columns={'energyout [MeV]': 'group out'}, inplace=True) + out_groups = \ + np.tile(all_groups, self.num_subdomains * self.num_groups) + df['group out'] = out_groups + columns = ['group in', 'group out'] + + elif 'energyout [MeV]' in df: + df.rename(columns={'energyout [MeV]': 'group out'}, inplace=True) + in_groups = np.tile(all_groups, self.num_subdomains) + df['group out'] = in_groups + columns = ['group out'] + + elif 'energy [MeV]' in df: + df.rename(columns={'energy [MeV]': 'group in'}, inplace=True) + in_groups = np.tile(all_groups, self.num_subdomains) + df['group in'] = in_groups + columns = ['group in'] + + # Select out those groups the user requested + if groups != 'all': + if 'group in' in df: + df = df[df['group in'].isin(groups)] + if 'group out' in df: + df = df[df['group out'].isin(groups)] + + # If user requested micro cross sections, divide out the atom densities + if xs_type == 'micro': + if self.by_nuclide: + densities = self.get_nuclide_densities(nuclides) + else: + densities = self.get_nuclide_densities('sum') + tile_factor = df.shape[0] / len(densities) + df['mean'] /= np.tile(densities, tile_factor) + df['std. dev.'] /= np.tile(densities, tile_factor) + + # Sort the dataframe by domain type id (e.g., distribcell id) and + # energy groups such that data is from fast to thermal + df.sort([self.domain_type] + columns, inplace=True) + + return df + + +class TotalXS(MGXS): + """A total multi-group cross section.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(TotalXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'total' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs two tracklength tallies to compute the 'flux' + and 'total' reaction rates in the spatial domain and energy groups + of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['flux', 'total'] + estimator = 'tracklength' + keys = scores + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy_filter = openmc.Filter('energy', group_edges) + filters = [[energy_filter], [energy_filter]] + + # Initialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes the multi-group total cross sections using OpenMC + tally arithmetic. + """ + + self._xs_tally = self.tallies['total'] / self.tallies['flux'] + super(TotalXS, self).compute_xs() + + +class TransportXS(MGXS): + """A transport-corrected total multi-group cross section.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(TransportXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'transport' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs three analog tallies to compute the 'flux', + 'total' and 'scatter-P1' reaction rates in the spatial domain and + energy groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['flux', 'total', 'scatter-P1'] + estimator = 'analog' + keys = scores + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy_filter = openmc.Filter('energy', group_edges) + energyout_filter = openmc.Filter('energyout', group_edges) + filters = [[energy_filter], [energy_filter], [energyout_filter]] + + # Initialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes the multi-group transport cross sections using OpenMC + tally arithmetic.""" + + # Use tally slicing to remove scatter-P0 data from scatter-P1 tally + scatter_p1 = self.tallies['scatter-P1'] + self.tallies['scatter-P1'] = scatter_p1.get_slice(scores=['scatter-P1']) + self.tallies['scatter-P1'].filters[-1].type = 'energy' + + self._xs_tally = self.tallies['total'] - self.tallies['scatter-P1'] + self._xs_tally /= self.tallies['flux'] + super(TransportXS, self).compute_xs() + + +class AbsorptionXS(MGXS): + """An absorption multi-group cross section.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(AbsorptionXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'absorption' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs two tracklength tallies to compute the 'flux' + and 'absorption' reaction rates in the spatial domain and energy + groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['flux', 'absorption'] + estimator = 'tracklength' + keys = scores + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy_filter = openmc.Filter('energy', group_edges) + filters = [[energy_filter], [energy_filter]] + + # Initialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes the multi-group absorption cross sections using OpenMC + tally arithmetic.""" + + self._xs_tally = self.tallies['absorption'] / self.tallies['flux'] + super(AbsorptionXS, self).compute_xs() + + +class CaptureXS(MGXS): + """A capture multi-group cross section. + + The Neutron capture reaction rate is defined as the difference between + OpenMC's 'absorption' and 'fission' reaction rate score types. This includes + not only radiative capture, but all forms of neutron disappearance aside + from fission (e.g., MT > 100). + + """ + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(CaptureXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'capture' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs two tracklength tallies to compute the 'flux' + and 'capture' reaction rates in the spatial domain and energy + groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['flux', 'absorption', 'fission'] + estimator = 'tracklength' + keys = scores + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy_filter = openmc.Filter('energy', group_edges) + filters = [[energy_filter], [energy_filter], [energy_filter]] + + # Initialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes the multi-group capture cross sections using OpenMC + tally arithmetic.""" + + self._xs_tally = self.tallies['absorption'] - self.tallies['fission'] + self._xs_tally /= self.tallies['flux'] + super(CaptureXS, self).compute_xs() + + +class FissionXS(MGXS): + """A fission multi-group cross section.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(FissionXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'fission' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs two tracklength tallies to compute the 'flux' + and 'fission' reaction rates in the spatial domain and energy + groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['flux', 'fission'] + estimator = 'tracklength' + keys = scores + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy_filter = openmc.Filter('energy', group_edges) + filters = [[energy_filter], [energy_filter]] + + # Initialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes the multi-group fission cross sections using OpenMC + tally arithmetic.""" + + self._xs_tally = self.tallies['fission'] / self.tallies['flux'] + super(FissionXS, self).compute_xs() + + +class NuFissionXS(MGXS): + """A fission production multi-group cross section.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(NuFissionXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'nu-fission' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs two tracklength tallies to compute the 'flux' + and 'nu-fission' reaction rates in the spatial domain and energy + groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['flux', 'nu-fission'] + estimator = 'tracklength' + keys = scores + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy_filter = openmc.Filter('energy', group_edges) + filters = [[energy_filter], [energy_filter]] + + # Initialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes the multi-group nu-fission cross sections using OpenMC + tally arithmetic.""" + + self._xs_tally = self.tallies['nu-fission'] / self.tallies['flux'] + super(NuFissionXS, self).compute_xs() + + +class ScatterXS(MGXS): + """A scatter multi-group cross section.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(ScatterXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'scatter' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs two tracklength tallies to compute the 'flux' + and 'scatter' reaction rates in the spatial domain and energy + groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['flux', 'scatter'] + estimator = 'tracklength' + keys = scores + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy_filter = openmc.Filter('energy', group_edges) + filters = [[energy_filter], [energy_filter]] + + # Intialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes the scattering multi-group cross sections using + OpenMC tally arithmetic.""" + + self._xs_tally = self.tallies['scatter'] / self.tallies['flux'] + super(ScatterXS, self).compute_xs() + + +class NuScatterXS(MGXS): + """A nu-scatter multi-group cross section.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(NuScatterXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'nu-scatter' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs two analog tallies to compute the 'flux' + and 'nu-scatter' reaction rates in the spatial domain and energy + groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['flux', 'nu-scatter'] + estimator = 'analog' + keys = scores + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy_filter = openmc.Filter('energy', group_edges) + filters = [[energy_filter], [energy_filter]] + + # Initialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes the nu-scattering multi-group cross section using OpenMC + tally arithmetic.""" + + self._xs_tally = self.tallies['nu-scatter'] / self.tallies['flux'] + super(NuScatterXS, self).compute_xs() + + +class ScatterMatrixXS(MGXS): + """A scattering matrix multi-group cross section. + + Attributes + ---------- + correction : 'P0' or None + Apply the P0 correction to scattering matrices if set to 'P0' + + """ + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(ScatterMatrixXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'scatter matrix' + self._correction = 'P0' + + def __deepcopy__(self, memo): + clone = super(ScatterMatrixXS, self).__deepcopy__(memo) + clone._correction = self.correction + return clone + + @property + def correction(self): + return self._correction + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs three analog tallies to compute the 'flux', + 'scatter' and 'scatter-P1' reaction rates in the spatial domain and + energy groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + group_edges = self.energy_groups.group_edges + energy = openmc.Filter('energy', group_edges) + energyout = openmc.Filter('energyout', group_edges) + + # Create a list of scores for each Tally to be created + if self.correction == 'P0': + scores = ['flux', 'scatter', 'scatter-P1'] + filters = [[energy], [energy, energyout], [energyout]] + else: + scores = ['flux', 'scatter'] + filters = [[energy], [energy, energyout]] + + estimator = 'analog' + keys = scores + + # Initialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + @correction.setter + def correction(self, correction): + cv.check_value('correction', correction, ('P0', None)) + self._correction = correction + + def compute_xs(self): + """Computes the multi-group scattering matrix using OpenMC + tally arithmetic.""" + + # If using P0 correction subtract scatter-P1 from the diagonal + if self.correction == 'P0': + scatter_p1 = self.tallies['scatter-P1'] + scatter_p1 = scatter_p1.get_slice(scores=['scatter-P1']) + energy_filter = openmc.Filter(type='energy') + energy_filter.bins = self.energy_groups.group_edges + scatter_p1 = scatter_p1.diagonalize_filter(energy_filter) + rxn_tally = self.tallies['scatter'] - scatter_p1 + else: + rxn_tally = self.tallies['scatter'] + + self._xs_tally = rxn_tally / self.tallies['flux'] + super(ScatterMatrixXS, self).compute_xs() + + def get_xs(self, in_groups='all', out_groups='all', + subdomains='all', nuclides='all', xs_type='macro', + order_groups='increasing', value='mean'): + """Returns an array of multi-group cross sections. + + This method constructs a 2D NumPy array for the requested scattering + matrix data data for one or more energy groups and subdomains. + + Parameters + ---------- + in_groups : Iterable of Integral or 'all' + Incoming energy groups of interest. Defaults to 'all'. + out_groups : Iterable of Integral or 'all' + Outgoing energy groups of interest. Defaults to 'all'. + subdomains : Iterable of Integral or 'all' + Subdomain IDs of interest. Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + A list of nuclide name strings (e.g., ['U-235', 'U-238']). The + special string 'all' will return the cross sections for all nuclides + in the spatial domain. The special string 'sum' will return the + cross section summed over all nuclides. Defaults to 'all'. + xs_type: {'macro', 'micro'} + Return the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + order_groups: {'increasing', 'decreasing'} + Return the cross section indexed according to increasing or + decreasing energy groups (decreasing or increasing energies). + Defaults to 'increasing'. + value : str + A string for the type of value to return - 'mean', 'std_dev', or + 'rel_err' are accepted. Defaults to the empty string. + + Returns + ------- + ndarray + A NumPy array of the multi-group cross section indexed in the order + each group and subdomain is listed in the parameters. + + Raises + ------ + ValueError + When this method is called before the multi-group cross section is + computed from tally data. + + """ + + if self.xs_tally is None: + msg = 'Unable to get cross section since it has not been computed' + raise ValueError(msg) + + cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + filters = [] + filter_bins = [] + + # Construct a collection of the domain filter bins + if subdomains != 'all': + cv.check_iterable_type('subdomains', subdomains, Integral) + for subdomain in subdomains: + filters.append(self.domain_type) + filter_bins.append((subdomain,)) + + # Construct list of energy group bounds tuples for all requested groups + if in_groups != 'all': + cv.check_iterable_type('groups', in_groups, Integral) + for group in in_groups: + filters.append('energy') + filter_bins.append((self.energy_groups.get_group_bounds(group),)) + + # Construct list of energy group bounds tuples for all requested groups + if out_groups != 'all': + cv.check_iterable_type('groups', out_groups, Integral) + for group in out_groups: + filters.append('energyout') + filter_bins.append((self.energy_groups.get_group_bounds(group),)) + + # Construct a collection of the nuclides to retrieve from the xs tally + if self.by_nuclide: + if nuclides == 'all' or nuclides == 'sum' or nuclides == ['sum']: + query_nuclides = self.get_all_nuclides() + else: + query_nuclides = nuclides + else: + query_nuclides = ['total'] + + # Use tally summation if user requested the sum for all nuclides + if nuclides == 'sum' or nuclides == ['sum']: + xs_tally = self.xs_tally.summation(nuclides=query_nuclides) + xs = xs_tally.get_values(filters=filters, + filter_bins=filter_bins, value=value) + else: + xs = self.xs_tally.get_values(filters=filters, + filter_bins=filter_bins, + nuclides=query_nuclides, value=value) + + xs = np.nan_to_num(xs) + + # Divide by atom number densities for microscopic cross sections + if xs_type == 'micro': + if self.by_nuclide: + densities = self.get_nuclide_densities(nuclides) + else: + densities = self.get_nuclide_densities('sum') + if value == 'mean' or value == 'std_dev': + xs /= densities[np.newaxis, :, np.newaxis] + + # Reverse data if user requested increasing energy groups since + # tally data is stored in order of increasing energies + if order_groups == 'increasing': + if in_groups == 'all': + num_in_groups = self.num_groups + else: + num_in_groups = len(in_groups) + if out_groups == 'all': + num_out_groups = self.num_groups + else: + num_out_groups = len(out_groups) + + # Reshape tally data array with separate axes for domain and energy + num_subdomains = int(xs.shape[0] / (num_in_groups * num_out_groups)) + new_shape = (num_subdomains, num_in_groups, num_out_groups) + new_shape += xs.shape[1:] + xs = np.reshape(xs, new_shape) + + # Reverse energies to align with increasing energy groups + xs = xs[:, ::-1, ::-1, :] + + # Eliminate trivial dimensions + xs = np.squeeze(xs) + xs = np.atleast_2d(xs) + + return xs + + def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'): + """Prints a string representation for the multi-group cross section. + + Parameters + ---------- + subdomains : Iterable of Integral or 'all' + The subdomain IDs of the cross sections to include in the report. + Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + The nuclides of the cross-sections to include in the report. This + may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). + The special string 'all' will report the cross sections for all + nuclides in the spatial domain. The special string 'sum' will report + the cross sections summed over all nuclides. Defaults to 'all'. + xs_type: {'macro', 'micro'} + Return the macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + + """ + + # Construct a collection of the subdomains to report + if subdomains != 'all': + cv.check_iterable_type('subdomains', subdomains, Integral) + elif self.domain_type == 'distribcell': + subdomains = np.arange(self.num_subdomains, dtype=np.int) + else: + subdomains = [self.domain.id] + + # Construct a collection of the nuclides to report + if self.by_nuclide: + if nuclides == 'all': + nuclides = self.get_all_nuclides() + if nuclides == 'sum': + nuclides = ['sum'] + else: + cv.check_iterable_type('nuclides', nuclides, basestring) + else: + nuclides = ['sum'] + + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + # Build header for string with type and domain info + string = 'Multi-Group XS\n' + string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) + string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) + string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) + + # If cross section data has not been computed, only print string header + if self.xs_tally is None: + print(string) + return + + string += '{0: <16}\n'.format('\tEnergy Groups:') + template = '{0: <12}Group {1} [{2: <10} - {3: <10}MeV]\n' + + # Loop over energy groups ranges + for group in range(1, self.num_groups+1): + bounds = self.energy_groups.get_group_bounds(group) + string += template.format('', group, bounds[0], bounds[1]) + + if subdomains == 'all': + if self.domain_type == 'distribcell': + subdomains = np.arange(self.num_subdomains, dtype=np.int) + else: + subdomains = [self.domain.id] + + # Loop over all subdomains + for subdomain in subdomains: + + if self.domain_type == 'distribcell': + string += \ + '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain) + + # Loop over all Nuclides + for nuclide in nuclides: + + # Build header for nuclide type + if xs_type != 'sum': + string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide) + + # Build header for cross section type + if xs_type == 'macro': + string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:') + else: + string += '{0: <16}\n'.format('\tCross Sections [barns]:') + + template = '{0: <12}Group {1} -> Group {2}:\t\t' + + # Loop over incoming/outgoing energy groups ranges + for in_group in range(1, self.num_groups+1): + for out_group in range(1, self.num_groups+1): + string += template.format('', in_group, out_group) + average = \ + self.get_xs([in_group], [out_group], + [subdomain], [nuclide], + xs_type=xs_type, value='mean') + rel_err = \ + self.get_xs([in_group], [out_group], + [subdomain], [nuclide], + xs_type=xs_type, value='rel_err') + average = average.flatten()[0] + rel_err = rel_err.flatten()[0] * 100. + string += '{:1.2e} +/- {:1.2e}%'.format(average, rel_err) + string += '\n' + string += '\n' + string += '\n' + string += '\n' + + print(string) + + +class NuScatterMatrixXS(ScatterMatrixXS): + """A scattering production matrix multi-group cross section.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(NuScatterMatrixXS, self).__init__(domain, domain_type, + groups, by_nuclide, name) + self._rxn_type = 'nu-scatter matrix' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs three analog tallies to compute the 'flux', + 'nu-scatter' and 'scatter-P1' reaction rates in the spatial domain and + energy groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energy = openmc.Filter('energy', group_edges) + energyout = openmc.Filter('energyout', group_edges) + + # Create a list of scores for each Tally to be created + if self.correction == 'P0': + scores = ['flux', 'nu-scatter', 'scatter-P1'] + estimator = 'analog' + keys = ['flux', 'scatter', 'scatter-P1'] + filters = [[energy], [energy, energyout], [energyout]] + else: + scores = ['flux', 'nu-scatter'] + estimator = 'analog' + keys = ['flux', 'scatter'] + filters = [[energy], [energy, energyout]] + + # Intialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + +class Chi(MGXS): + """The fission spectrum.""" + + def __init__(self, domain=None, domain_type=None, + groups=None, by_nuclide=False, name=''): + super(Chi, self).__init__(domain, domain_type, groups, by_nuclide, name) + self._rxn_type = 'chi' + + @property + def tallies(self): + """Construct the OpenMC tallies needed to compute this cross section. + + This method constructs two analog tallies to compute 'nu-fission' + reaction rates with 'energy' and 'energyout' filters in the spatial + domain and energy groups of interest. + + """ + + # Instantiate tallies if they do not exist + if self._tallies is None: + + # Create a list of scores for each Tally to be created + scores = ['nu-fission', 'nu-fission'] + estimator = 'analog' + keys = ['nu-fission-in', 'nu-fission-out'] + + # Create the non-domain specific Filters for the Tallies + group_edges = self.energy_groups.group_edges + energyout = openmc.Filter('energyout', group_edges) + energyin = openmc.Filter('energy', [group_edges[0], group_edges[-1]]) + filters = [[energyin], [energyout]] + + # Intialize the Tallies + self._create_tallies(scores, filters, keys, estimator) + + return self._tallies + + def compute_xs(self): + """Computes chi fission spectrum using OpenMC tally arithmetic.""" + + # Retrieve the fission production tallies + nu_fission_in = self.tallies['nu-fission-in'] + nu_fission_out = self.tallies['nu-fission-out'] + + # Remove coarse energy filter to keep it out of tally arithmetic + energy_filter = nu_fission_in.find_filter('energy') + nu_fission_in.remove_filter(energy_filter) + + # Compute chi + self._xs_tally = nu_fission_out / nu_fission_in + + # Add the coarse energy filter back to the nu-fission tally + nu_fission_in.add_filter(energy_filter) + + super(Chi, self).compute_xs() + + def get_xs(self, groups='all', subdomains='all', nuclides='all', + xs_type='macro', order_groups='increasing', value='mean'): + """Returns an array of the fission spectrum. + + This method constructs a 2D NumPy array for the requested multi-group + cross section data data for one or more energy groups and subdomains. + + Parameters + ---------- + groups : Iterable of Integral or 'all' + Energy groups of interest. Defaults to 'all'. + subdomains : Iterable of Integral or 'all' + Subdomain IDs of interest. Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + A list of nuclide name strings (e.g., ['U-235', 'U-238']). The + special string 'all' will return the cross sections for all nuclides + in the spatial domain. The special string 'sum' will return the + cross section summed over all nuclides. Defaults to 'all'. + xs_type: {'macro', 'micro'} + This parameter is not relevant for chi but is included here to + mirror the parent MGXS.get_xs(...) class method + order_groups: {'increasing', 'decreasing'} + Return the cross section indexed according to increasing or + decreasing energy groups (decreasing or increasing energies). + Defaults to 'increasing'. + value : str + A string for the type of value to return - 'mean', 'std_dev', or + 'rel_err' are accepted. Defaults to 'mean'. + + Returns + ------- + ndarray + A NumPy array of the multi-group cross section indexed in the order + each group, subdomain and nuclide is listed in the parameters. + + Raises + ------ + ValueError + When this method is called before the multi-group cross section is + computed from tally data. + + """ + + if self.xs_tally is None: + msg = 'Unable to get cross section since it has not been computed' + raise ValueError(msg) + + cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) + cv.check_value('xs_type', xs_type, ['macro', 'micro']) + + filters = [] + filter_bins = [] + + # Construct a collection of the domain filter bins + if subdomains != 'all': + cv.check_iterable_type('subdomains', subdomains, Integral) + for subdomain in subdomains: + filters.append(self.domain_type) + filter_bins.append((subdomain,)) + + # Construct list of energy group bounds tuples for all requested groups + if groups != 'all': + cv.check_iterable_type('groups', groups, Integral) + for group in groups: + filters.append('energyout') + filter_bins.append((self.energy_groups.get_group_bounds(group),)) + + # If chi was computed for each nuclide in the domain + if self.by_nuclide: + + # Get the sum as the fission source weighted average chi for all + # nuclides in the domain + if nuclides == 'sum' or nuclides == ['sum']: + + # Retrieve the fission production tallies + nu_fission_in = self.tallies['nu-fission-in'] + nu_fission_out = self.tallies['nu-fission-out'] + + # Sum out all nuclides + nuclides = self.get_all_nuclides() + nu_fission_in = nu_fission_in.summation(nuclides=nuclides) + nu_fission_out = nu_fission_out.summation(nuclides=nuclides) + + # Remove coarse energy filter to keep it out of tally arithmetic + energy_filter = nu_fission_in.find_filter('energy') + nu_fission_in.remove_filter(energy_filter) + + # Compute chi and store it as the xs_tally attribute so we can + # use the generic get_xs(...) method + xs_tally = nu_fission_out / nu_fission_in + + # Add the coarse energy filter back to the nu-fission tally + nu_fission_in.add_filter(energy_filter) + + xs = xs_tally.get_values(filters=filters, + filter_bins=filter_bins, value=value) + + # Get chi for all nuclides in the domain + elif nuclides == 'all': + nuclides = self.get_all_nuclides() + xs = self.xs_tally.get_values(filters=filters, + filter_bins=filter_bins, + nuclides=nuclides, value=value) + + # Get chi for user-specified nuclides in the domain + else: + cv.check_iterable_type('nuclides', nuclides, basestring) + xs = self.xs_tally.get_values(filters=filters, + filter_bins=filter_bins, + nuclides=nuclides, value=value) + + # If chi was computed as an average of nuclides in the domain + else: + xs = self.xs_tally.get_values(filters=filters, + filter_bins=filter_bins, value=value) + + # Reverse data if user requested increasing energy groups since + # tally data is stored in order of increasing energies + if order_groups == 'increasing': + + # Reshape tally data array with separate axes for domain and energy + if groups == 'all': + num_groups = self.num_groups + else: + num_groups = len(groups) + num_subdomains = int(xs.shape[0] / num_groups) + new_shape = (num_subdomains, num_groups) + xs.shape[1:] + xs = np.reshape(xs, new_shape) + + # Reverse energies to align with increasing energy groups + xs = xs[:, ::-1, :] + + # Eliminate trivial dimensions + xs = np.squeeze(xs) + xs = np.atleast_1d(xs) + + xs = np.nan_to_num(xs) + return xs + + def get_pandas_dataframe(self, groups='all', nuclides='all', + xs_type='macro', summary=None): + """Build a Pandas DataFrame for the MGXS data. + + This method leverages the Tally.get_pandas_dataframe(...) method, but + renames the columns with terminology appropriate for cross section data. + + Parameters + ---------- + groups : Iterable of Integral or 'all' + Energy groups of interest. Defaults to 'all'. + nuclides : Iterable of str or 'all' or 'sum' + The nuclides of the cross-sections to include in the dataframe. This + may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). + The special string 'all' will include the cross sections for all + nuclides in the spatial domain. The special string 'sum' will + include the cross sections summed over all nuclides. Defaults to + 'all'. + xs_type: {'macro', 'micro'} + Return macro or micro cross section in units of cm^-1 or barns. + Defaults to 'macro'. + summary : None or Summary + An optional Summary object to be used to construct columns for + distribcell tally filters (default is None). The geometric + information in the Summary object is embedded into a multi-index + column with a geometric "path" to each distribcell intance. + NOTE: This option requires the OpenCG Python package. + + Returns + ------- + pandas.DataFrame + A Pandas DataFrame for the cross section data. + + Raises + ------ + ValueError + When this method is called before the multi-group cross section is + computed from tally data. + + """ + + # Build the dataframe using the parent class method + df = super(Chi, self).get_pandas_dataframe(groups, nuclides, + xs_type, summary) + + # If user requested micro cross sections, multiply by the atom + # densities to cancel out division made by the parent class method + if xs_type == 'micro': + if self.by_nuclide: + densities = self.get_nuclide_densities(nuclides) + else: + densities = self.get_nuclide_densities('sum') + tile_factor = df.shape[0] / len(densities) + df['mean'] *= np.tile(densities, tile_factor) + df['std. dev.'] *= np.tile(densities, tile_factor) + + return df diff --git a/openmc/nuclide.py b/openmc/nuclide.py index 7e7cd5af35..01fb2aa459 100644 --- a/openmc/nuclide.py +++ b/openmc/nuclide.py @@ -26,6 +26,8 @@ class Nuclide(object): zaid : int 1000*(atomic number) + mass number. As an example, the zaid of U-235 would be 92235. + scattering : 'data' or 'iso-in-lab' or None + The type of angular scattering distribution to use """ @@ -34,6 +36,7 @@ class Nuclide(object): self._name = '' self._xs = None self._zaid = None + self._scattering = None # Set the Material class attributes self.name = name @@ -41,24 +44,31 @@ class Nuclide(object): if xs is not None: self.xs = xs - def __eq__(self, nuclide2): - # Check type - if not isinstance(nuclide2, Nuclide): - return False - - # Check name - elif self._name != nuclide2._name: - return False - - # Check xs - elif self._xs != nuclide2._xs: - return False - - else: + def __eq__(self, other): + if isinstance(other, Nuclide): + if self._name != other._name: + return False + elif self._xs != other._xs: + return False + else: + return True + elif isinstance(other, basestring) and other == self.name: return True + else: + return False + + def __ne__(self, other): + return not self == other def __hash__(self): - return hash((self._name, self._xs)) + return hash(repr(self)) + + def __repr__(self): + string = 'Nuclide - {0}\n'.format(self._name) + string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs) + if self._zaid is not None: + string += '{0: <16}{1}{2}\n'.format('\tZAID', '=\t', self._zaid) + return string @property def name(self): @@ -72,6 +82,10 @@ class Nuclide(object): def zaid(self): return self._zaid + @property + def scattering(self): + return self._scattering + @name.setter def name(self, name): check_type('name', name, basestring) @@ -87,9 +101,22 @@ class Nuclide(object): check_type('zaid', zaid, Integral) self._zaid = zaid + @scattering.setter + def scattering(self, scattering): + + if not scattering in ['data', 'iso-in-lab']: + msg = 'Unable to set scattering for Nuclide to {0} ' \ + 'which is not "data" or "iso-in-lab"'.format(scattering) + raise ValueError(msg) + + self._scattering = scattering + def __repr__(self): string = 'Nuclide - {0}\n'.format(self._name) - string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs) - if self._zaid is not None: - string += '{0: <16}{1}{2}\n'.format('\tZAID', '=\t', self._zaid) + string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self.xs) + if self.zaid is not None: + string += '{0: <16}{1}{2}\n'.format('\tZAID', '=\t', self.zaid) + if self.scattering is not None: + string += '{0: <16}{1}{2}\n'.format('\tscattering', '=\t', + self.scattering) return string diff --git a/openmc/opencg_compatible.py b/openmc/opencg_compatible.py index 65e980c003..afa57c78d9 100644 --- a/openmc/opencg_compatible.py +++ b/openmc/opencg_compatible.py @@ -9,6 +9,8 @@ except ImportError: raise ImportError(msg) import openmc +from openmc.region import Intersection +from openmc.surface import Halfspace # A dictionary of all OpenMC Materials created @@ -83,14 +85,14 @@ def get_opencg_material(openmc_material): raise ValueError(msg) global OPENCG_MATERIALS - material_id = openmc_material._id + material_id = openmc_material.id # If this Material was already created, use it if material_id in OPENCG_MATERIALS: return OPENCG_MATERIALS[material_id] # Create an OpenCG Material to represent this OpenMC Material - name = openmc_material._name + name = openmc_material.name opencg_material = opencg.Material(material_id=material_id, name=name) # Add the OpenMC Material to the global collection of all OpenMC Materials @@ -123,14 +125,14 @@ def get_openmc_material(opencg_material): raise ValueError(msg) global OPENMC_MATERIALS - material_id = opencg_material._id + material_id = opencg_material.id # If this Material was already created, use it if material_id in OPENMC_MATERIALS: return OPENMC_MATERIALS[material_id] # Create an OpenMC Material to represent this OpenCG Material - name = opencg_material._name + name = opencg_material.name openmc_material = openmc.Material(material_id=material_id, name=name) # Add the OpenMC Material to the global collection of all OpenMC Materials @@ -168,8 +170,8 @@ def is_opencg_surface_compatible(opencg_surface): 'since "{0}" is not a Surface'.format(opencg_surface) raise ValueError(msg) - if opencg_surface._type in ['x-squareprism', - 'y-squareprism', 'z-squareprism']: + if opencg_surface.type in ['x-squareprism', + 'y-squareprism', 'z-squareprism']: return False else: return True @@ -196,59 +198,59 @@ def get_opencg_surface(openmc_surface): raise ValueError(msg) global OPENCG_SURFACES - surface_id = openmc_surface._id + surface_id = openmc_surface.id # If this Material was already created, use it if surface_id in OPENCG_SURFACES: return OPENCG_SURFACES[surface_id] # Create an OpenCG Surface to represent this OpenMC Surface - name = openmc_surface._name + name = openmc_surface.name # Correct for OpenMC's syntax for Surfaces dividing Cells - boundary = openmc_surface._boundary_type + boundary = openmc_surface.boundary_type if boundary == 'transmission': boundary = 'interface' opencg_surface = None - if openmc_surface._type == 'plane': - A = openmc_surface._coeffs['A'] - B = openmc_surface._coeffs['B'] - C = openmc_surface._coeffs['C'] - D = openmc_surface._coeffs['D'] + if openmc_surface.type == 'plane': + A = openmc_surface.a + B = openmc_surface.b + C = openmc_surface.c + D = openmc_surface.d opencg_surface = opencg.Plane(surface_id, name, boundary, A, B, C, D) - elif openmc_surface._type == 'x-plane': - x0 = openmc_surface._coeffs['x0'] + elif openmc_surface.type == 'x-plane': + x0 = openmc_surface.x0 opencg_surface = opencg.XPlane(surface_id, name, boundary, x0) - elif openmc_surface._type == 'y-plane': - y0 = openmc_surface._coeffs['y0'] + elif openmc_surface.type == 'y-plane': + y0 = openmc_surface.y0 opencg_surface = opencg.YPlane(surface_id, name, boundary, y0) - elif openmc_surface._type == 'z-plane': - z0 = openmc_surface._coeffs['z0'] + elif openmc_surface.type == 'z-plane': + z0 = openmc_surface.z0 opencg_surface = opencg.ZPlane(surface_id, name, boundary, z0) - elif openmc_surface._type == 'x-cylinder': - y0 = openmc_surface._coeffs['y0'] - z0 = openmc_surface._coeffs['z0'] - R = openmc_surface._coeffs['R'] + elif openmc_surface.type == 'x-cylinder': + y0 = openmc_surface.y0 + z0 = openmc_surface.z0 + R = openmc_surface.r opencg_surface = opencg.XCylinder(surface_id, name, boundary, y0, z0, R) - elif openmc_surface._type == 'y-cylinder': - x0 = openmc_surface._coeffs['x0'] - z0 = openmc_surface._coeffs['z0'] - R = openmc_surface._coeffs['R'] + elif openmc_surface.type == 'y-cylinder': + x0 = openmc_surface.x0 + z0 = openmc_surface.z0 + R = openmc_surface.r opencg_surface = opencg.YCylinder(surface_id, name, boundary, x0, z0, R) - elif openmc_surface._type == 'z-cylinder': - x0 = openmc_surface._coeffs['x0'] - y0 = openmc_surface._coeffs['y0'] - R = openmc_surface._coeffs['R'] + elif openmc_surface.type == 'z-cylinder': + x0 = openmc_surface.x0 + y0 = openmc_surface.y0 + R = openmc_surface.r opencg_surface = opencg.ZCylinder(surface_id, name, boundary, x0, y0, R) @@ -282,61 +284,61 @@ def get_openmc_surface(opencg_surface): raise ValueError(msg) global openmc_surface - surface_id = opencg_surface._id + surface_id = opencg_surface.id # If this Surface was already created, use it if surface_id in OPENMC_SURFACES: return OPENMC_SURFACES[surface_id] # Create an OpenMC Surface to represent this OpenCG Surface - name = opencg_surface._name + name = opencg_surface.name # Correct for OpenMC's syntax for Surfaces dividing Cells - boundary = opencg_surface._boundary_type + boundary = opencg_surface.boundary_type if boundary == 'interface': boundary = 'transmission' - if opencg_surface._type == 'plane': - A = opencg_surface._coeffs['A'] - B = opencg_surface._coeffs['B'] - C = opencg_surface._coeffs['C'] - D = opencg_surface._coeffs['D'] + if opencg_surface.type == 'plane': + A = opencg_surface.a + B = opencg_surface.b + C = opencg_surface.c + D = opencg_surface.d openmc_surface = openmc.Plane(surface_id, boundary, A, B, C, D, name) - elif opencg_surface._type == 'x-plane': - x0 = opencg_surface._coeffs['x0'] + elif opencg_surface.type == 'x-plane': + x0 = opencg_surface.x0 openmc_surface = openmc.XPlane(surface_id, boundary, x0, name) - elif opencg_surface._type == 'y-plane': - y0 = opencg_surface._coeffs['y0'] + elif opencg_surface.type == 'y-plane': + y0 = opencg_surface.y0 openmc_surface = openmc.YPlane(surface_id, boundary, y0, name) - elif opencg_surface._type == 'z-plane': - z0 = opencg_surface._coeffs['z0'] + elif opencg_surface.type == 'z-plane': + z0 = opencg_surface.z0 openmc_surface = openmc.ZPlane(surface_id, boundary, z0, name) - elif opencg_surface._type == 'x-cylinder': - y0 = opencg_surface._coeffs['y0'] - z0 = opencg_surface._coeffs['z0'] - R = opencg_surface._coeffs['R'] + elif opencg_surface.type == 'x-cylinder': + y0 = opencg_surface.y0 + z0 = opencg_surface.z0 + R = opencg_surface.r openmc_surface = openmc.XCylinder(surface_id, boundary, y0, z0, R, name) - elif opencg_surface._type == 'y-cylinder': - x0 = opencg_surface._coeffs['x0'] - z0 = opencg_surface._coeffs['z0'] - R = opencg_surface._coeffs['R'] + elif opencg_surface.type == 'y-cylinder': + x0 = opencg_surface.x0 + z0 = opencg_surface.z0 + R = opencg_surface.r openmc_surface = openmc.YCylinder(surface_id, boundary, x0, z0, R, name) - elif opencg_surface._type == 'z-cylinder': - x0 = opencg_surface._coeffs['x0'] - y0 = opencg_surface._coeffs['y0'] - R = opencg_surface._coeffs['R'] + elif opencg_surface.type == 'z-cylinder': + x0 = opencg_surface.x0 + y0 = opencg_surface.y0 + R = opencg_surface.r openmc_surface = openmc.ZCylinder(surface_id, boundary, x0, y0, R, name) else: msg = 'Unable to create an OpenMC Surface from an OpenCG ' \ 'Surface of type "{0}" since it is not a compatible ' \ - 'Surface type in OpenMC'.format(opencg_surface._type) + 'Surface type in OpenMC'.format(opencg_surface.type) raise ValueError(msg) # Add the OpenMC Surface to the global collection of all OpenMC Surfaces @@ -373,20 +375,20 @@ def get_compatible_opencg_surfaces(opencg_surface): raise ValueError(msg) global OPENMC_SURFACES - surface_id = opencg_surface._id + surface_id = opencg_surface.id # If this Surface was already created, use it if surface_id in OPENMC_SURFACES: return OPENMC_SURFACES[surface_id] # Create an OpenMC Surface to represent this OpenCG Surface - name = opencg_surface._name - boundary = opencg_surface._boundary_type + name = opencg_surface.name + boundary = opencg_surface.boundary_type - if opencg_surface._type == 'x-squareprism': - y0 = opencg_surface._coeffs['y0'] - z0 = opencg_surface._coeffs['z0'] - R = opencg_surface._coeffs['R'] + if opencg_surface.type == 'x-squareprism': + y0 = opencg_surface.y0 + z0 = opencg_surface.z0 + R = opencg_surface.r # Create a list of the four planes we need left = opencg.YPlane(name=name, boundary=boundary, y0=y0-R) @@ -395,10 +397,10 @@ def get_compatible_opencg_surfaces(opencg_surface): top = opencg.ZPlane(name=name, boundary=boundary, z0=z0+R) surfaces = [left, right, bottom, top] - elif opencg_surface._type == 'y-squareprism': - x0 = opencg_surface._coeffs['x0'] - z0 = opencg_surface._coeffs['z0'] - R = opencg_surface._coeffs['R'] + elif opencg_surface.type == 'y-squareprism': + x0 = opencg_surface.x0 + z0 = opencg_surface.z0 + R = opencg_surface.r # Create a list of the four planes we need left = opencg.XPlane(name=name, boundary=boundary, x0=x0-R) @@ -407,10 +409,10 @@ def get_compatible_opencg_surfaces(opencg_surface): top = opencg.ZPlane(name=name, boundary=boundary, z0=z0+R) surfaces = [left, right, bottom, top] - elif opencg_surface._type == 'z-squareprism': - x0 = opencg_surface._coeffs['x0'] - y0 = opencg_surface._coeffs['y0'] - R = opencg_surface._coeffs['R'] + elif opencg_surface.type == 'z-squareprism': + x0 = opencg_surface.x0['x0'] + y0 = opencg_surface.y0['y0'] + R = opencg_surface.r['R'] # Create a list of the four planes we need left = opencg.XPlane(name=name, boundary=boundary, x0=x0-R) @@ -422,7 +424,7 @@ def get_compatible_opencg_surfaces(opencg_surface): else: msg = 'Unable to create a compatible OpenMC Surface an OpenCG ' \ 'Surface of type "{0}" since it already a compatible ' \ - 'Surface type in OpenMC'.format(opencg_surface._type) + 'Surface type in OpenMC'.format(opencg_surface.type) raise ValueError(msg) # Add the OpenMC Surface(s) to the global collection of all OpenMC Surfaces @@ -455,37 +457,51 @@ def get_opencg_cell(openmc_cell): raise ValueError(msg) global OPENCG_CELLS - cell_id = openmc_cell._id + cell_id = openmc_cell.id # If this Cell was already created, use it if cell_id in OPENCG_CELLS: return OPENCG_CELLS[cell_id] # Create an OpenCG Cell to represent this OpenMC Cell - name = openmc_cell._name + name = openmc_cell.name opencg_cell = opencg.Cell(cell_id, name) - fill = openmc_cell._fill + fill = openmc_cell.fill - if (openmc_cell._type == 'normal'): - opencg_cell.setFill(get_opencg_material(fill)) - elif (openmc_cell._type == 'fill'): - opencg_cell.setFill(get_opencg_universe(fill)) + if (openmc_cell.fill_type == 'material'): + opencg_cell.fill = get_opencg_material(fill) + elif (openmc_cell.fill_type == 'universe'): + opencg_cell.fill = get_opencg_universe(fill) else: - opencg_cell.setFill(get_opencg_lattice(fill)) + opencg_cell.fill = get_opencg_lattice(fill) - if openmc_cell._rotation is not None: - opencg_cell.setRotation(openmc_cell._rotation) + if openmc_cell.rotation is not None: + opencg_cell.rotation = openmc_cell.rotation - if openmc_cell._translation is not None: - opencg_cell.setTranslation(openmc_cell._translation) + if openmc_cell.translation is not None: + opencg_cell.translation = openmc_cell.translation - surfaces = openmc_cell._surfaces - - for surface_id in surfaces: - surface = surfaces[surface_id][0] - halfspace = surfaces[surface_id][1] - opencg_cell.addSurface(get_opencg_surface(surface), halfspace) + # Add surfaces to OpenCG cell from OpenMC cell region. Right now this only + # works if the region is a single half-space or an intersection of + # half-spaces, i.e., no complex cells. + region = openmc_cell.region + if region is not None: + if isinstance(region, Halfspace): + surface = region.surface + halfspace = -1 if region.side == '-' else 1 + opencg_cell.add_surface(get_opencg_surface(surface), halfspace) + elif isinstance(region, Intersection): + for node in region.nodes: + if not isinstance(node, Halfspace): + raise NotImplementedError("Complex cells not yet " + "supported in OpenCG.") + surface = node.surface + halfspace = -1 if node.side == '-' else 1 + opencg_cell.add_surface(get_opencg_surface(surface), halfspace) + else: + raise NotImplementedError("Complex cells not yet supported " + "in OpenCG.") # Add the OpenMC Cell to the global collection of all OpenMC Cells OPENMC_CELLS[cell_id] = openmc_cell @@ -536,8 +552,8 @@ def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace): compatible_cells = [] # SquarePrism Surfaces - if opencg_surface._type in ['x-squareprism', 'y-squareprism', - 'z-squareprism']: + if opencg_surface.type in ['x-squareprism', 'y-squareprism', + 'z-squareprism']: # Get the compatible Surfaces (XPlanes and YPlanes) compatible_surfaces = get_compatible_opencg_surfaces(opencg_surface) @@ -546,10 +562,10 @@ def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace): # If Cell is inside SquarePrism, add "inside" of Surface halfspaces if halfspace == -1: - opencg_cell.addSurface(compatible_surfaces[0], +1) - opencg_cell.addSurface(compatible_surfaces[1], -1) - opencg_cell.addSurface(compatible_surfaces[2], +1) - opencg_cell.addSurface(compatible_surfaces[3], -1) + opencg_cell.add_surface(compatible_surfaces[0], +1) + opencg_cell.add_surface(compatible_surfaces[1], -1) + opencg_cell.add_surface(compatible_surfaces[2], +1) + opencg_cell.add_surface(compatible_surfaces[3], -1) compatible_cells.append(opencg_cell) # If Cell is outside SquarePrism, add "outside" of Surface halfspaces @@ -631,12 +647,12 @@ def make_opencg_cells_compatible(opencg_universe): raise ValueError(msg) # Check all OpenCG Cells in this Universe for compatibility with OpenMC - opencg_cells = opencg_universe._cells + opencg_cells = opencg_universe.cells for cell_id, opencg_cell in opencg_cells.items(): # Check each of the OpenCG Surfaces for OpenMC compatibility - surfaces = opencg_cell._surfaces + surfaces = opencg_cell.surfaces for surface_id in surfaces: surface = surfaces[surface_id][0] @@ -659,7 +675,7 @@ def make_opencg_cells_compatible(opencg_universe): opencg_universe.removeCell(opencg_cell) # Add the compatible OpenCG Cells to the Universe - opencg_universe.addCells(cells) + opencg_universe.add_cells(cells) # Make recursive call to look at the updated state of the # OpenCG Universe and return @@ -690,34 +706,34 @@ def get_openmc_cell(opencg_cell): raise ValueError(msg) global OPENMC_CELLS - cell_id = opencg_cell._id + cell_id = opencg_cell.id # If this Cell was already created, use it if cell_id in OPENMC_CELLS: return OPENMC_CELLS[cell_id] # Create an OpenCG Cell to represent this OpenMC Cell - name = opencg_cell._name + name = opencg_cell.name openmc_cell = openmc.Cell(cell_id, name) - fill = opencg_cell._fill + fill = opencg_cell.fill - if (opencg_cell._type == 'universe'): + if (opencg_cell.type == 'universe'): openmc_cell.fill = get_openmc_universe(fill) - elif (opencg_cell._type == 'lattice'): + elif (opencg_cell.type == 'lattice'): openmc_cell.fill = get_openmc_lattice(fill) else: openmc_cell.fill = get_openmc_material(fill) - if opencg_cell._rotation: - rotation = np.asarray(opencg_cell._rotation, dtype=np.int) + if opencg_cell.rotation: + rotation = np.asarray(opencg_cell.rotation, dtype=np.float64) openmc_cell.rotation = rotation - if opencg_cell._translation: - translation = np.asarray(opencg_cell._translation, dtype=np.float64) - openmc_cell.setTranslation(translation) + if opencg_cell.translation: + translation = np.asarray(opencg_cell.translation, dtype=np.float64) + openmc_cell.translation = translation - surfaces = opencg_cell._surfaces + surfaces = opencg_cell.surfaces for surface_id in surfaces: surface = surfaces[surface_id][0] @@ -754,22 +770,22 @@ def get_opencg_universe(openmc_universe): raise ValueError(msg) global OPENCG_UNIVERSES - universe_id = openmc_universe._id + universe_id = openmc_universe.id # If this Universe was already created, use it if universe_id in OPENCG_UNIVERSES: return OPENCG_UNIVERSES[universe_id] # Create an OpenCG Universe to represent this OpenMC Universe - name = openmc_universe._name + name = openmc_universe.name opencg_universe = opencg.Universe(universe_id, name) # Convert all OpenMC Cells in this Universe to OpenCG Cells - openmc_cells = openmc_universe._cells + openmc_cells = openmc_universe.cells for cell_id, openmc_cell in openmc_cells.items(): opencg_cell = get_opencg_cell(openmc_cell) - opencg_universe.addCell(opencg_cell) + opencg_universe.add_cell(opencg_cell) # Add the OpenMC Universe to the global collection of all OpenMC Universes OPENMC_UNIVERSES[universe_id] = openmc_universe @@ -801,7 +817,7 @@ def get_openmc_universe(opencg_universe): raise ValueError(msg) global OPENMC_UNIVERSES - universe_id = opencg_universe._id + universe_id = opencg_universe.id # If this Universe was already created, use it if universe_id in OPENMC_UNIVERSES: @@ -811,11 +827,11 @@ def get_openmc_universe(opencg_universe): make_opencg_cells_compatible(opencg_universe) # Create an OpenMC Universe to represent this OpenCSg Universe - name = opencg_universe._name + name = opencg_universe.name openmc_universe = openmc.Universe(universe_id, name) # Convert all OpenCG Cells in this Universe to OpenMC Cells - opencg_cells = opencg_universe._cells + opencg_cells = opencg_universe.cells for cell_id, opencg_cell in opencg_cells.items(): openmc_cell = get_openmc_cell(opencg_cell) @@ -851,7 +867,7 @@ def get_opencg_lattice(openmc_lattice): raise ValueError(msg) global OPENCG_LATTICES - lattice_id = openmc_lattice._id + lattice_id = openmc_lattice.id # If this Lattice was already created, use it if lattice_id in OPENCG_LATTICES: @@ -863,9 +879,10 @@ def get_opencg_lattice(openmc_lattice): pitch = openmc_lattice.pitch lower_left = openmc_lattice.lower_left universes = openmc_lattice.universes + outer = openmc_lattice.outer if len(pitch) == 2: - new_pitch = np.ones(3, dtype=np.float64) + new_pitch = np.ones(3, dtype=np.float64) * np.inf new_pitch[:2] = pitch pitch = new_pitch @@ -888,18 +905,20 @@ def get_opencg_lattice(openmc_lattice): for z in range(dimension[2]): for y in range(dimension[1]): for x in range(dimension[0]): - universe_id = universes[x][dimension[1]-y-1][z]._id + universe_id = universes[x][dimension[1]-y-1][z].id universe_array[z][y][x] = unique_universes[universe_id] opencg_lattice = opencg.Lattice(lattice_id, name) - opencg_lattice.setDimension(dimension) - opencg_lattice.setWidth(pitch) - opencg_lattice.setUniverses(universe_array) + opencg_lattice.dimension = dimension + opencg_lattice.width = pitch + opencg_lattice.universes = universe_array + if outer is not None: + opencg_lattice.outside = get_opencg_universe(outer) offset = np.array(lower_left, dtype=np.float64) - \ ((np.array(pitch, dtype=np.float64) * np.array(dimension, dtype=np.float64))) / -2.0 - opencg_lattice.setOffset(offset) + opencg_lattice.offset = offset # Add the OpenMC Lattice to the global collection of all OpenMC Lattices OPENMC_LATTICES[lattice_id] = openmc_lattice @@ -931,23 +950,24 @@ def get_openmc_lattice(opencg_lattice): raise ValueError(msg) global OPENMC_LATTICES - lattice_id = opencg_lattice._id + lattice_id = opencg_lattice.id # If this Lattice was already created, use it if lattice_id in OPENMC_LATTICES: return OPENMC_LATTICES[lattice_id] - dimension = opencg_lattice._dimension - width = opencg_lattice._width - offset = opencg_lattice._offset - universes = opencg_lattice._universes + dimension = opencg_lattice.dimension + width = opencg_lattice.width + offset = opencg_lattice.offset + universes = opencg_lattice.universes + outer = opencg_lattice.outside # Initialize an empty array for the OpenMC nested Universes in this Lattice universe_array = np.ndarray(tuple(np.array(dimension)), dtype=openmc.Universe) # Create OpenMC Universes for each unique nested Universe in this Lattice - unique_universes = opencg_lattice.getUniqueUniverses() + unique_universes = opencg_lattice.get_unique_universes() for universe_id, universe in unique_universes.items(): unique_universes[universe_id] = get_openmc_universe(universe) @@ -956,7 +976,7 @@ def get_openmc_lattice(opencg_lattice): for z in range(dimension[2]): for y in range(dimension[1]): for x in range(dimension[0]): - universe_id = universes[z][y][x]._id + universe_id = universes[z][y][x].id universe_array[x][y][z] = unique_universes[universe_id] # Reverse y-dimension in array to match ordering in OpenCG @@ -971,6 +991,8 @@ def get_openmc_lattice(opencg_lattice): openmc_lattice.pitch = width openmc_lattice.universes = universe_array openmc_lattice.lower_left = lower_left + if outer is not None: + openmc_lattice.outer = get_openmc_universe(outer) # Add the OpenMC Lattice to the global collection of all OpenMC Lattices OPENMC_LATTICES[lattice_id] = openmc_lattice @@ -1011,12 +1033,12 @@ def get_opencg_geometry(openmc_geometry): OPENMC_LATTICES.clear() OPENCG_LATTICES.clear() - openmc_root_universe = openmc_geometry._root_universe + openmc_root_universe = openmc_geometry.root_universe opencg_root_universe = get_opencg_universe(openmc_root_universe) opencg_geometry = opencg.Geometry() - opencg_geometry.setRootUniverse(opencg_root_universe) - opencg_geometry.initializeCellOffsets() + opencg_geometry.root_universe = opencg_root_universe + opencg_geometry.initialize_cell_offsets() return opencg_geometry @@ -1043,11 +1065,11 @@ def get_openmc_geometry(opencg_geometry): # Deep copy the goemetry since it may be modified to make all Surfaces # compatible with OpenMC's specifications - opencg_geometry.assignAutoIds() + opencg_geometry.assign_auto_ids() opencg_geometry = copy.deepcopy(opencg_geometry) # Update Cell bounding boxes in Geometry - opencg_geometry.updateBoundingBoxes() + opencg_geometry.update_bounding_boxes() # Clear dictionaries and auto-generated ID OPENMC_SURFACES.clear() @@ -1060,14 +1082,14 @@ def get_openmc_geometry(opencg_geometry): OPENCG_LATTICES.clear() # Make the entire geometry "compatible" before assigning auto IDs - universes = opencg_geometry.getAllUniverses() + universes = opencg_geometry.get_all_universes() for universe_id, universe in universes.items(): if not isinstance(universe, opencg.Lattice): make_opencg_cells_compatible(universe) - opencg_geometry.assignAutoIds() + opencg_geometry.assign_auto_ids() - opencg_root_universe = opencg_geometry._root_universe + opencg_root_universe = opencg_geometry.root_universe openmc_root_universe = get_openmc_universe(opencg_root_universe) openmc_geometry = openmc.Geometry() diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py index d664de1aee..72bf3ac3de 100644 --- a/openmc/particle_restart.py +++ b/openmc/particle_restart.py @@ -12,10 +12,6 @@ class Particle(object): Attributes ---------- - filetype : int - Integer indicating the file type - revision : int - Revision of the particle restart format current_batch : int The batch containing the particle gen_per_batch : int @@ -40,70 +36,55 @@ 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() + # Ensure filetype and revision are correct + if 'filetype' not in self._f or self._f[ + 'filetype'].value.decode() != 'particle restart': + raise IOError('{} is not a particle restart file.'.format(filename)) + if self._f['revision'].value != 1: + raise IOError('Particle restart file has a file revision of {} ' + 'which is not consistent with the revision this ' + 'version of OpenMC expects ({}).'.format( + self._f['revision'].value, 1)) - def _read_data(self): - # Read filetype - self.filetype = self._get_int(path='filetype')[0] + @property + def current_batch(self): + return self._f['current_batch'].value - # Read statepoint revision - self.revision = self._get_int(path='revision')[0] + @property + def current_gen(self): + return self._f['current_gen'].value - # Read current batch - self.current_batch = self._get_int(path='current_batch')[0] + @property + def energy(self): + return self._f['energy'].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] + @property + def gen_per_batch(self): + return self._f['gen_per_batch'].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') + @property + def id(self): + return self._f['id'].value - def _get_data(self, n, typeCode, size): - return list(struct.unpack('={0}{1}'.format(n, typeCode), - self._f.read(n*size))) + @property + def n_particles(self): + return self._f['n_particles'].value - 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)] + @property + def run_mode(self): + return self._f['run_mode'].value.decode() - 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)] + @property + def uvw(self): + return self._f['uvw'].value - def _get_float(self, n=1, path=None): - if self._hdf5: - return [float(v) for v in self._f[path].value] - else: - return [float(v) for v in self._get_data(n, 'f', 4)] + @property + def weight(self): + return self._f['weight'].value - def _get_double(self, n=1, path=None): - if self._hdf5: - return [float(v) for v in self._f[path].value] - else: - return [float(v) for v in self._get_data(n, 'd', 8)] - - 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]) + @property + def xyz(self): + return self._f['xyz'].value diff --git a/openmc/plots.py b/openmc/plots.py index 66419a6ffc..636ca225cb 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -5,9 +5,9 @@ import sys import numpy as np +import openmc +import openmc.checkvalue as cv from openmc.clean_xml import * -from openmc.checkvalue import (check_type, check_value, check_length, - check_greater_than, check_less_than) if sys.version_info[0] >= 3: basestring = str @@ -143,70 +143,70 @@ class Plot(object): self._id = AUTO_PLOT_ID AUTO_PLOT_ID += 1 else: - check_type('plot ID', plot_id, Integral) - check_greater_than('plot ID', plot_id, 0) + cv.check_type('plot ID', plot_id, Integral) + cv.check_greater_than('plot ID', plot_id, 0, equality=True) self._id = plot_id @name.setter def name(self, name): - check_type('plot name', name, basestring) + cv.check_type('plot name', name, basestring) self._name = name @width.setter def width(self, width): - check_type('plot width', width, Iterable, Real) - check_length('plot width', width, 2, 3) + cv.check_type('plot width', width, Iterable, Real) + cv.check_length('plot width', width, 2, 3) self._width = width @origin.setter def origin(self, origin): - check_type('plot origin', origin, Iterable, Real) - check_length('plot origin', origin, 3) + cv.check_type('plot origin', origin, Iterable, Real) + cv.check_length('plot origin', origin, 3) self._origin = origin @pixels.setter def pixels(self, pixels): - check_type('plot pixels', pixels, Iterable, Integral) - check_length('plot pixels', pixels, 2, 3) + cv.check_type('plot pixels', pixels, Iterable, Integral) + cv.check_length('plot pixels', pixels, 2, 3) for dim in pixels: - check_greater_than('plot pixels', dim, 0) + cv.check_greater_than('plot pixels', dim, 0) self._pixels = pixels @filename.setter def filename(self, filename): - check_type('filename', filename, basestring) + cv.check_type('filename', filename, basestring) self._filename = filename @color.setter def color(self, color): - check_type('plot color', color, basestring) - check_value('plot color', color, ['cell', 'mat']) + cv.check_type('plot color', color, basestring) + cv.check_value('plot color', color, ['cell', 'mat']) self._color = color @type.setter def type(self, plottype): - check_type('plot type', plottype, basestring) - check_value('plot type', plottype, ['slice', 'voxel']) + cv.check_type('plot type', plottype, basestring) + cv.check_value('plot type', plottype, ['slice', 'voxel']) self._type = plottype @basis.setter def basis(self, basis): - check_type('plot basis', basis, basestring) - check_value('plot basis', basis, ['xy', 'xz', 'yz']) + cv.check_type('plot basis', basis, basestring) + cv.check_value('plot basis', basis, ['xy', 'xz', 'yz']) self._basis = basis @background.setter def background(self, background): - check_type('plot background', background, Iterable, Integral) - check_length('plot background', background, 3) + cv.check_type('plot background', background, Iterable, Integral) + cv.check_length('plot background', background, 3) for rgb in background: - check_greater_than('plot background',rgb, 0, True) - check_less_than('plot background', rgb, 256) + cv.check_greater_than('plot background',rgb, 0, True) + cv.check_less_than('plot background', rgb, 256) self._background = background @col_spec.setter def col_spec(self, col_spec): - check_type('plot col_spec parameter', col_spec, dict, Integral) + cv.check_type('plot col_spec parameter', col_spec, dict, Integral) for key in col_spec: if key < 0: @@ -229,18 +229,18 @@ class Plot(object): @mask_componenets.setter def mask_components(self, mask_components): - check_type('plot mask_components', mask_components, Iterable, Integral) + cv.check_type('plot mask_components', mask_components, Iterable, Integral) for component in mask_components: - check_greater_than('plot mask_components', component, 0, True) + cv.check_greater_than('plot mask_components', component, 0, True) self._mask_components = mask_components @mask_background.setter def mask_background(self, mask_background): - check_type('plot mask background', mask_background, Iterable, Integral) - check_length('plot mask background', mask_background, 3) + cv.check_type('plot mask background', mask_background, Iterable, Integral) + cv.check_length('plot mask background', mask_background, 3) for rgb in mask_background: - check_greater_than('plot mask background', rgb, 0, True) - check_less_than('plot mask background', rgb, 256) + cv.check_greater_than('plot mask background', rgb, 0, True) + cv.check_less_than('plot mask background', rgb, 256) self._mask_background = mask_background def __repr__(self): @@ -261,6 +261,97 @@ class Plot(object): string += '{0: <16}{1}{2}\n'.format('\tCol Spec', '=\t', self._col_spec) return string + def colorize(self, geometry, seed=1): + """Generate a color scheme for each domain in the plot. + + This routine may be used to generate random, reproducible color schemes. + The colors generated are based upon cell/material IDs in the geometry. + + Parameters + ---------- + geometry : openmc.Geometry + The geometry for which the plot is defined + seed : Integral + The random number seed used to generate the color scheme + + """ + + cv.check_type('geometry', geometry, openmc.Geometry) + cv.check_type('seed', seed, Integral) + cv.check_greater_than('seed', seed, 1, equality=True) + + # Get collections of the domains which will be plotted + if self.color is 'mat': + domains = geometry.get_all_materials() + else: + domains = geometry.get_all_cells() + + # Set the seed for the random number generator + np.random.seed(seed) + + # Generate random colors for each feature + self.col_spec = {} + for domain in domains: + r = np.random.randint(0, 256) + g = np.random.randint(0, 256) + b = np.random.randint(0, 256) + self.col_spec[domain] = (r, g, b) + + def highlight_domains(self, geometry, domains, seed=1, + alpha=0.5, background='gray'): + """Use alpha compositing to highlight one or more domains in the plot. + + This routine generates a color scheme and applies alpha compositing + to make all domains except the highlighted ones appear partially + transparent. + + Parameters + ---------- + geometry : openmc.Geometry + The geometry for which the plot is defined + domains : Iterable of Integral + A collection of the domain IDs to highlight in the plot + seed : Integral + The random number seed used to generate the color scheme + alpha : Real in [0,1] + The value to apply in alpha compisiting + background : 3-tuple of Integral or 'white' or 'black' or 'gray' + The background color to apply in alpha compisiting + + """ + + cv.check_iterable_type('domains', domains, Integral) + cv.check_type('alpha', alpha, Real) + cv.check_greater_than('alpha', alpha, 0., equality=True) + cv.check_less_than('alpha', alpha, 1., equality=True) + + # Get a background (R,G,B) tuple to apply in alpha compositing + if isinstance(background, basestring): + if background == 'white': + background = (255, 255, 255) + elif background == 'black': + background = (0, 0, 0) + elif background == 'gray': + background = (160, 160, 160) + else: + msg = 'The background "{}" is not defined'.format(background) + raise ValueError(msg) + + cv.check_iterable_type('background', background, Integral) + + # Generate a color scheme + self.colorize(geometry, seed) + + # Apply alpha compositing to the colors for all domains + # other than those the user wishes to highlight + for domain_id in self.col_spec: + if domain_id not in domains: + r, g, b = self.col_spec[domain_id] + r = int(((1-alpha) * background[0]) + (alpha * r)) + g = int(((1-alpha) * background[1]) + (alpha * g)) + b = int(((1-alpha) * background[2]) + (alpha * b)) + self._col_spec[domain_id] = (r, g, b) + def get_plot_xml(self): """Return XML representation of the plot @@ -349,6 +440,51 @@ class PlotsFile(object): self._plots.remove(plot) + def colorize(self, geometry, seed=1): + """Generate a consistent color scheme for each domain in each plot. + + This routine may be used to generate random, reproducible color schemes. + The colors generated are based upon cell/material IDs in the geometry. + The color schemes will be consistent for all plots in "plots.xml". + + Parameters + ---------- + geometry : openmc.Geometry + The geometry for which the plots are defined + seed : Integral + The random number seed used to generate the color scheme + + """ + + for plot in self._plots: + plot.colorize(geometry, seed) + + + def highlight_domains(self, geometry, domains, seed=1, + alpha=0.5, background='gray'): + """Use alpha compositing to highlight one or more domains in the plot. + + This routine generates a color scheme and applies alpha compositing + to make all domains except the highlighted ones partially transparent. + + Parameters + ---------- + geometry : openmc.Geometry + The geometry for which the plot is defined + domains : Iterable of Integral + A collection of the domain IDs to highlight in the plot + seed : Integral + The random number seed used to generate the color scheme + alpha : Real in [0,1] + The value to apply in alpha compisiting + background : 3-tuple of Integral or 'white' or 'black' or 'gray' + The background color to apply in alpha compisiting + + """ + + for plot in self._plots: + plot.highlight_domains(geometry, domains, seed, alpha, background) + def _create_plot_subelements(self): for plot in self._plots: xml_element = plot.get_plot_xml() @@ -363,6 +499,9 @@ class PlotsFile(object): """ + # Reset xml element tree + self._plots_file.clear() + self._create_plot_subelements() # Clean the indentation in the file to be user-readable diff --git a/openmc/region.py b/openmc/region.py new file mode 100644 index 0000000000..7589184aa5 --- /dev/null +++ b/openmc/region.py @@ -0,0 +1,362 @@ +from abc import ABCMeta, abstractmethod +from collections import Iterable + +import numpy as np + +from openmc.checkvalue import check_type + + +class Region(object): + """Region of space that can be assigned to a cell. + + Region is an abstract base class that is inherited by Halfspace, + Intersection, Union, and Complement. Each of those respective classes are + typically not instantiated directly but rather are created through operators + of the Surface and Region classes. + + """ + + __metaclass__ = ABCMeta + + def __and__(self, other): + return Intersection(self, other) + + def __or__(self, other): + return Union(self, other) + + def __invert__(self): + return Complement(self) + + @abstractmethod + def __str__(self): + return '' + + def __eq__(self, other): + if not isinstance(other, type(self)): + return False + elif str(self) != str(other): + return False + else: + return True + + def __ne__(self, other): + return not self == other + + @staticmethod + def from_expression(expression, surfaces): + """Generate a region given an infix expression. + + Parameters + ---------- + expression : str + Boolean expression relating surface half-spaces. The possible + operators are union '|', intersection ' ', and complement '~'. For + example, '(1 -2) | 3 ~(4 -5)'. + surfaces : dict + Dictionary whose keys are suface IDs that appear in the Boolean + expression and whose values are Surface objects. + + """ + + # Strip leading and trailing whitespace + expression = expression.strip() + + # Convert the string expression into a list of tokens, i.e., operators + # and surface half-spaces, representing the expression in infix + # notation. + i = 0 + i_start = -1 + tokens = [] + while i < len(expression): + if expression[i] in '()|~ ': + # If special character appears immediately after a non-operator, + # create a token with the apporpriate half-space + if i_start >= 0: + j = int(expression[i_start:i]) + if j < 0: + tokens.append(-surfaces[abs(j)]) + else: + tokens.append(+surfaces[abs(j)]) + + if expression[i] in '()|~': + # For everything other than intersection, add the operator + # to the list of tokens + tokens.append(expression[i]) + else: + # Find next non-space character + while expression[i+1] == ' ': + i += 1 + + # If previous token is a halfspace or right parenthesis and next token + # is not a left parenthese or union operator, that implies that the + # whitespace is to be interpreted as an intersection operator + if (i_start >= 0 or tokens[-1] == ')') and \ + expression[i+1] not in ')|': + tokens.append(' ') + + i_start = -1 + else: + # Check for invalid characters + if expression[i] not in '-+0123456789': + raise SyntaxError("Invalid character '{}' in expression" + .format(expression[i])) + + # If we haven't yet reached the start of a word, start one + if i_start < 0: + i_start = i + i += 1 + + # If we've reached the end and we're still in a word, create a + # half-space token and add it to the list + if i_start >= 0: + j = int(expression[i_start:]) + if j < 0: + tokens.append(-surfaces[abs(j)]) + else: + tokens.append(+surfaces[abs(j)]) + + # The functions below are used to apply an operator to operands on the + # output queue during the shunting yard algorithm. + def can_be_combined(region): + return isinstance(region, Complement) or hasattr(region, 'surface') + + def apply_operator(output, operator): + r2 = output.pop() + if operator == ' ': + r1 = output.pop() + if isinstance(r1, Intersection) and can_be_combined(r2): + r1.nodes.append(r2) + output.append(r1) + elif isinstance(r2, Intersection) and can_be_combined(r1): + r2.nodes.insert(0, r1) + output.append(r2) + elif isinstance(r1, Intersection) and isinstance(r2, Intersection): + r1.nodes += r2.nodes + output.append(r1) + else: + output.append(Intersection(r1, r2)) + elif operator == '|': + r1 = output.pop() + if isinstance(r1, Union) and can_be_combined(r2): + r1.nodes.append(r2) + output.append(r1) + elif isinstance(r2, Union) and can_be_combined(r1): + r2.nodes.insert(0, r1) + output.append(r2) + elif isinstance(r1, Union) and isinstance(r2, Union): + r1.nodes += r2.nodes + output.append(r1) + else: + output.append(Union(r1, r2)) + elif operator == '~': + output.append(Complement(r2)) + + # The following is an implementation of the shunting yard algorithm to + # generate an abstract syntax tree for the region expression. + output = [] + stack = [] + precedence = {'|': 1, ' ': 2, '~': 3} + associativity = {'|': 'left', ' ': 'left', '~': 'right'} + for token in tokens: + if token in (' ', '|', '~'): + # Normal operators + while stack: + op = stack[-1] + if (op not in ('(', ')') and + ((associativity[token] == 'right' and + precedence[token] < precedence[op]) or + (associativity[token] == 'left' and + precedence[token] <= precedence[op]))): + apply_operator(output, stack.pop()) + else: + break + stack.append(token) + elif token == '(': + # Left parentheses + stack.append(token) + elif token == ')': + # Right parentheses + while stack[-1] != '(': + apply_operator(output, stack.pop()) + if len(stack) == 0: + raise SyntaxError('Mismatched parentheses in ' + 'region specification.') + stack.pop() + else: + # Surface halfspaces + output.append(token) + while stack: + if stack[-1] in '()': + raise SyntaxError('Mismatched parentheses in region ' + 'specification.') + apply_operator(output, stack.pop()) + + # Since we are generating an abstract syntax tree rather than a reverse + # Polish notation expression, the output queue should have a single item + # at the end + return output[0] + + +class Intersection(Region): + """Intersection of two or more regions. + + Instances of Intersection are generally created via the __and__ operator + applied to two instances of Region. This is illustrated in the following + example: + + >>> equator = openmc.surface.ZPlane(z0=0.0) + >>> earth = openmc.surface.Sphere(R=637.1e6) + >>> northern_hemisphere = -earth & +equator + >>> southern_hemisphere = -earth & -equator + >>> type(northern_hemisphere) + + + Parameters + ---------- + *nodes + Regions to take the intersection of + + Attributes + ---------- + nodes : tuple of Region + Regions to take the intersection of + bounding_box : tuple of numpy.array + Lower-left and upper-right coordinates of an axis-aligned bounding box + + """ + + def __init__(self, *nodes): + self.nodes = list(nodes) + + def __str__(self): + return '(' + ' '.join(map(str, self.nodes)) + ')' + + @property + def nodes(self): + return self._nodes + + @property + def bounding_box(self): + lower_left = np.array([-np.inf, -np.inf, -np.inf]) + upper_right = np.array([np.inf, np.inf, np.inf]) + for n in self.nodes: + lower_left_n, upper_right_n = n.bounding_box + lower_left[:] = np.maximum(lower_left, lower_left_n) + upper_right[:] = np.minimum(upper_right, upper_right_n) + return lower_left, upper_right + + @nodes.setter + def nodes(self, nodes): + check_type('nodes', nodes, Iterable, Region) + self._nodes = nodes + + +class Union(Region): + """Union of two or more regions. + + Instances of Union are generally created via the __or__ operator applied to + two instances of Region. This is illustrated in the following example: + + >>> s1 = openmc.surface.ZPlane(z0=0.0) + >>> s2 = openmc.surface.Sphere(R=637.1e6) + >>> type(-s2 | +s1) + + + Parameters + ---------- + *nodes + Regions to take the union of + + Attributes + ---------- + nodes : tuple of Region + Regions to take the union of + bounding_box : tuple of numpy.array + Lower-left and upper-right coordinates of an axis-aligned bounding box + + """ + + def __init__(self, *nodes): + self.nodes = list(nodes) + + def __str__(self): + return '(' + ' | '.join(map(str, self.nodes)) + ')' + + @property + def nodes(self): + return self._nodes + + @property + def bounding_box(self): + lower_left = np.array([np.inf, np.inf, np.inf]) + upper_right = np.array([-np.inf, -np.inf, -np.inf]) + for n in self.nodes: + lower_left_n, upper_right_n = n.bounding_box + lower_left[:] = np.minimum(lower_left, lower_left_n) + upper_right[:] = np.maximum(upper_right, upper_right_n) + return lower_left, upper_right + + @nodes.setter + def nodes(self, nodes): + check_type('nodes', nodes, Iterable, Region) + self._nodes = nodes + + +class Complement(Region): + """Complement of a region. + + The Complement of an existing Region can be created by using the __invert__ + operator as the following example demonstrates: + + >>> xl = openmc.surface.XPlane(x0=-10.0) + >>> xr = openmc.surface.XPlane(x0=10.0) + >>> yl = openmc.surface.YPlane(y0=-10.0) + >>> yr = openmc.surface.YPlane(y0=10.0) + >>> inside_box = +xl & -xr & +yl & -yl + >>> outside_box = ~inside_box + >>> type(outside_box) + + + Parameters + ---------- + node : Region + Region to take the complement of + + Attributes + ---------- + node : Region + Regions to take the complement of + bounding_box : tuple of numpy.array + Lower-left and upper-right coordinates of an axis-aligned bounding box + + """ + + def __init__(self, node): + self.node = node + + def __str__(self): + return '~' + str(self.node) + + @property + def node(self): + return self._node + + @node.setter + def node(self, node): + check_type('node', node, Region) + self._node = node + + @property + def bounding_box(self): + # Use De Morgan's laws to distribute the complement operator so that it + # only applies to surface half-spaces, thus allowing us to calculate the + # bounding box in the usual recursive manner. + if isinstance(self.node, Union): + temp_region = Intersection(*[~n for n in self.node.nodes]) + elif isinstance(self.node, Intersection): + temp_region = Union(*[~n for n in self.node.nodes]) + elif isinstance(self.node, Complement): + temp_region = self.node.node + else: + temp_region = ~self.node + return temp_region.bounding_box diff --git a/openmc/settings.py b/openmc/settings.py index 981166af51..9eb54b9eb6 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -20,6 +20,8 @@ class SettingsFile(object): Attributes ---------- + run_mode : {'eigenvalue' or 'fixed source'} + The type of calculation to perform (default is 'eigenvalue') batches : int Number of batches to simulate generations_per_batch : int @@ -122,7 +124,9 @@ class SettingsFile(object): """ def __init__(self): - # Eigenvalue subelement + + # Run mode subelement (default is 'eigenvalue') + self._run_mode = 'eigenvalue' self._batches = None self._generations_per_batch = None self._inactive = None @@ -196,9 +200,13 @@ class SettingsFile(object): self._dd_count_interactions = False self._settings_file = ET.Element("settings") - self._eigenvalue_subelement = None + self._run_mode_subelement = None self._source_element = None + @property + def run_mode(self): + return self._run_mode + @property def batches(self): return self._batches @@ -399,6 +407,14 @@ class SettingsFile(object): def dd_count_interactions(self): return self._dd_count_interactions + @run_mode.setter + def run_mode(self, run_mode): + if 'run_mode' not in ['eigenvalue', 'fixed source']: + msg = 'Unable to set run mode to "{0}". Only "eigenvalue" ' \ + 'and "fixed source" are supported."'.format(run_mode) + raise ValueError(msg) + self._run_mode = run_mode + @batches.setter def batches(self, batches): check_type('batches', batches, Integral) @@ -861,57 +877,47 @@ class SettingsFile(object): self._dd_count_interactions = interactions - def _create_eigenvalue_subelement(self): - self._create_particles_subelement() - self._create_batches_subelement() - self._create_inactive_subelement() - self._create_generations_per_batch_subelement() - self._create_keff_trigger_subelement() + def _create_run_mode_subelement(self): + + if self.run_mode == 'eigenvalue': + self._run_mode_subelement = \ + ET.SubElement(self._settings_file, "eigenvalue") + self._create_particles_subelement() + self._create_batches_subelement() + self._create_inactive_subelement() + self._create_generations_per_batch_subelement() + self._create_keff_trigger_subelement() + else: + if self._run_mode_subelement is None: + self._run_mode_subelement = \ + ET.SubElement(self._settings_file, "fixed_source") + self._create_particles_subelement() + self._create_batches_subelement() def _create_batches_subelement(self): if self._batches is not None: - if self._eigenvalue_subelement is None: - self._eigenvalue_subelement = ET.SubElement(self._settings_file, - "eigenvalue") - - element = ET.SubElement(self._eigenvalue_subelement, "batches") + element = ET.SubElement(self._run_mode_subelement, "batches") element.text = str(self._batches) def _create_generations_per_batch_subelement(self): if self._generations_per_batch is not None: - if self._eigenvalue_subelement is None: - self._eigenvalue_subelement = ET.SubElement(self._settings_file, - "eigenvalue") - - element = ET.SubElement(self._eigenvalue_subelement, + element = ET.SubElement(self._run_mode_subelement, "generations_per_batch") element.text = str(self._generations_per_batch) def _create_inactive_subelement(self): if self._inactive is not None: - if self._eigenvalue_subelement is None: - self._eigenvalue_subelement = ET.SubElement(self._settings_file, - "eigenvalue") - - element = ET.SubElement(self._eigenvalue_subelement, "inactive") + element = ET.SubElement(self._run_mode_subelement, "inactive") element.text = str(self._inactive) def _create_particles_subelement(self): if self._particles is not None: - if self._eigenvalue_subelement is None: - self._eigenvalue_subelement = ET.SubElement(self._settings_file, - "eigenvalue") - - element = ET.SubElement(self._eigenvalue_subelement, "particles") + element = ET.SubElement(self._run_mode_subelement, "particles") element.text = str(self._particles) def _create_keff_trigger_subelement(self): if self._keff_trigger is not None: - if self._eigenvalue_subelement is None: - self._eigenvalue_subelement = ET.SubElement(self._settings_file, - "eigenvalue") - - element = ET.SubElement(self._eigenvalue_subelement, "keff_trigger") + element = ET.SubElement(self._run_mode_subelement, "keff_trigger") for key in self._keff_trigger: subelement = ET.SubElement(element, key) @@ -1178,7 +1184,14 @@ class SettingsFile(object): """ - self._create_eigenvalue_subelement() + # Reset xml element tree + self._settings_file.clear() + self._source_subelement = None + self._trigger_subelement = None + self._run_mode_subelement = None + self._source_element = None + + self._create_run_mode_subelement() self._create_source_subelement() self._create_output_subelement() self._create_statepoint_subelement() diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 6a4713e91d..2edf9badd4 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -1,64 +1,13 @@ -import copy -import struct import sys - +import re import numpy as np -import scipy.stats import openmc -from openmc.constants import * if sys.version > '3': long = int -class SourceSite(object): - """A single source site produced from fission. - - Attributes - ---------- - weight : float - Weight of the particle arising from the site - xyz : list of float - Cartesian coordinates of the site - uvw : list of float - Directional cosines for particles emerging from the site - E : float - Energy of the emerging particle in MeV - - """ - - def __init__(self): - self._weight = None - self._xyz = None - self._uvw = None - self._E = None - - def __repr__(self): - string = 'SourceSite\n' - string += '{0: <16}{1}{2}\n'.format('\tweight', '=\t', self._weight) - string += '{0: <16}{1}{2}\n'.format('\tE', '=\t', self._E) - string += '{0: <16}{1}{2}\n'.format('\t(x,y,z)', '=\t', self._xyz) - string += '{0: <16}{1}{2}\n'.format('\t(u,v,w)', '=\t', self._uvw) - return string - - @property - def weight(self): - return self._weight - - @property - def xyz(self): - return self._xyz - - @property - def uvw(self): - return self._uvw - - @property - def E(self): - return self._E - - class StatePoint(object): """State information on a simulation at a certain point in time (at the end of a given batch). Statepoints can be used to analyze tally results as well as @@ -66,567 +15,445 @@ class StatePoint(object): Attributes ---------- + cmfd_on : bool + Indicate whether CMFD is active + cmfd_balance : ndarray + Residual neutron balance for each batch + cmfd_dominance + Dominance ratio for each batch + cmfd_entropy : ndarray + Shannon entropy of CMFD fission source for each batch + cmfd_indices : ndarray + Number of CMFD mesh cells and energy groups. The first three indices + correspond to the x-, y-, and z- spatial directions and the fourth index + is the number of energy groups. + cmfd_srccmp : ndarray + Root-mean-square difference between OpenMC and CMFD fission source for + each batch + cmfd_src : ndarray + CMFD fission source distribution over all mesh cells and energy groups. + current_batch : Integral + Number of batches simulated + date_and_time : str + Date and time when simulation began + entropy : ndarray + Shannon entropy of fission source at each batch + gen_per_batch : Integral + Number of fission generations per batch + global_tallies : ndarray of compound datatype + Global tallies for k-effective estimates and leakage. The compound + datatype has fields 'name', 'sum', 'sum_sq', 'mean', and 'std_dev'. k_combined : list Combined estimator for k-effective and its uncertainty - n_particles : int - Number of particles per generation - n_batches : int + k_col_abs : Real + Cross-product of collision and absorption estimates of k-effective + k_col_tra : Real + Cross-product of collision and tracklength estimates of k-effective + k_abs_tra : Real + Cross-product of absorption and tracklength estimates of k-effective + k_generation : ndarray + Estimate of k-effective for each batch/generation + meshes : dict + Dictionary whose keys are mesh IDs and whose values are Mesh objects + n_batches : Integral Number of batches - current_batch : - Number of batches simulated - results : bool - Indicate whether tally results have been read - source : ndarray of SourceSite - Array of source sites - with_summary : bool - Indicate whether statepoint data has been linked against a summary file + n_inactive : Integral + Number of inactive batches + n_particles : Integral + Number of particles per generation + n_realizations : Integral + Number of tally realizations + path : str + Working directory for simulation + run_mode : str + Simulation run mode, e.g. 'k-eigenvalue' + seed : Integral + Pseudorandom number generator seed + source : ndarray of compound datatype + Array of source sites. The compound datatype has fields 'wgt', 'xyz', + 'uvw', and 'E' corresponding to the weight, position, direction, and + energy of the source site. + source_present : bool + Indicate whether source sites are present tallies : dict Dictionary whose keys are tally IDs and whose values are Tally objects tallies_present : bool Indicate whether user-defined tallies are present - global_tallies : ndarray - Global tallies and their uncertainties - n_realizations : int - Number of tally realizations + version: tuple of Integral + Version of OpenMC + summary : None or openmc.summary.Summary + A summary object if the statepoint has been linked with a summary file """ 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') + + # Ensure filetype and revision are correct + try: + if 'filetype' not in self._f or self._f[ + 'filetype'].value.decode() != 'statepoint': + raise IOError('{} is not a statepoint file.'.format(filename)) + except AttributeError: + raise IOError('Could not read statepoint file. This most likely ' + 'means the statepoint file was produced by a different ' + 'version of OpenMC than the one you are using.') + if self._f['revision'].value != 14: + raise IOError('Statepoint file has a file revision of {} ' + 'which is not consistent with the revision this ' + 'version of OpenMC expects ({}).'.format( + self._f['revision'].value, 14)) # Set flags for what data has been read - self._results = False - self._source = False - self._with_summary = False - - # Read all metadata - self._read_metadata() - - # Read information about tally meshes - self._read_meshes() - - # Read tally metadata - self._read_tallies() + self._meshes_read = False + self._tallies_read = False + self._summary = False + self._global_tallies = None def close(self): self._f.close() @property - def k_combined(self): - return self._k_combined + def cmfd_on(self): + return self._f['cmfd_on'].value > 0 @property - def n_particles(self): - return self._n_particles + def cmfd_balance(self): + return self._f['cmfd/cmfd_balance'].value if self.cmfd_on else None @property - def n_batches(self): - return self._n_batches + def cmfd_dominance(self): + return self._f['cmfd/cmfd_dominance'].value if self.cmfd_on else None + + @property + def cmfd_entropy(self): + return self._f['cmfd/cmfd_entropy'].value if self.cmfd_on else None + + @property + def cmfd_indices(self): + return self._f['cmfd/indices'].value if self.cmfd_on else None + + @property + def cmfd_src(self): + if self.cmfd_on: + data = self._f['cmfd/cmfd_src'].value + return np.reshape(data, tuple(self.cmfd_indices), order='F') + else: + return None + + @property + def cmfd_srccmp(self): + return self._f['cmfd/cmfd_srccmp'].value if self.cmfd_on else None @property def current_batch(self): - return self._current_batch + return self._f['current_batch'].value @property - def results(self): - return self._results + def date_and_time(self): + return self._f['date_and_time'].value.decode() + + @property + def entropy(self): + if self.run_mode == 'k-eigenvalue': + return self._f['entropy'].value + else: + return None + + @property + def gen_per_batch(self): + if self.run_mode == 'k-eigenvalue': + return self._f['gen_per_batch'].value + else: + return None + + @property + def global_tallies(self): + if self._global_tallies is None: + data = self._f['global_tallies'].value + gt = np.zeros_like(data, dtype=[ + ('name', 'a14'), ('sum', 'f8'), ('sum_sq', 'f8'), + ('mean', 'f8'), ('std_dev', 'f8')]) + gt['name'] = ['k-collision', 'k-absorption', 'k-tracklength', + 'leakage'] + gt['sum'] = data['sum'] + gt['sum_sq'] = data['sum_sq'] + + # Calculate mean and sample standard deviation of mean + n = self.n_realizations + gt['mean'] = gt['sum']/n + gt['std_dev'] = np.sqrt((gt['sum_sq']/n - gt['mean']**2)/(n - 1)) + + self._global_tallies = gt + + return self._global_tallies + + @property + def k_cmfd(self): + if self.cmfd_on: + return self._f['cmfd/k_cmfd'].value + else: + return None + + @property + def k_generation(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_generation'].value + else: + return None + + @property + def k_combined(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_combined'].value + else: + return None + + @property + def k_col_abs(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_col_abs'].value + else: + return None + + @property + def k_col_tra(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_col_tra'].value + else: + return None + + @property + def k_abs_tra(self): + if self.run_mode == 'k-eigenvalue': + return self._f['k_abs_tra'].value + else: + return None + + @property + def meshes(self): + if not self._meshes_read: + # Initialize dictionaries for the Meshes + # Keys - Mesh IDs + # Values - Mesh objects + self._meshes = {} + + # Read the number of Meshes + n_meshes = self._f['tallies/meshes/n_meshes'].value + + # Read a list of the IDs for each Mesh + if n_meshes > 0: + # User-defined Mesh IDs + mesh_keys = self._f['tallies/meshes/keys'].value + else: + mesh_keys = [] + + # Build dictionary of Meshes + base = 'tallies/meshes/mesh ' + + # Iterate over all Meshes + for mesh_key in mesh_keys: + # Read the mesh type + mesh_type = self._f['{0}{1}/type'.format(base, mesh_key)].value.decode() + + # Read the mesh dimensions, lower-left coordinates, + # upper-right coordinates, and width of each mesh cell + 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_key) + mesh.dimension = dimension + mesh.width = width + mesh.lower_left = lower_left + mesh.upper_right = upper_right + mesh.type = mesh_type + + # Add mesh to the global dictionary of all Meshes + self._meshes[mesh_key] = mesh + + self._meshes_read = True + + return self._meshes + + @property + def n_batches(self): + return self._f['n_batches'].value + + @property + def n_inactive(self): + if self.run_mode == 'k-eigenvalue': + return self._f['n_inactive'].value + else: + return None + + @property + def n_particles(self): + return self._f['n_particles'].value + + @property + def n_realizations(self): + return self._f['n_realizations'].value + + @property + def path(self): + return self._f['path'].value.decode() + + @property + def run_mode(self): + return self._f['run_mode'].value.decode() + + @property + def seed(self): + return self._f['seed'].value @property def source(self): - return self._source + return self._f['source_bank'].value if self.source_present else None @property - def with_summary(self): - return self._with_summary + def source_present(self): + return self._f['source_present'].value > 0 @property def tallies(self): + if not self._tallies_read: + # Initialize dictionary for tallies + self._tallies = {} + + # Read the number of tallies + n_tallies = self._f['tallies/n_tallies'].value + + # Read a list of the IDs for each Tally + if n_tallies > 0: + # OpenMC Tally IDs (redefined internally from user definitions) + tally_keys = self._f['tallies/keys'].value + else: + tally_keys = [] + + base = 'tallies/tally ' + + # Iterate over all Tallies + for tally_key in tally_keys: + + # Read the Tally size specifications + n_realizations = self._f['{0}{1}/n_realizations'.format(base, tally_key)].value + + # Create Tally object and assign basic properties + tally = openmc.Tally(tally_id=tally_key) + tally._sp_filename = self._f.filename + tally.estimator = self._f['{0}{1}/estimator'.format( + base, tally_key)].value.decode() + tally.num_realizations = n_realizations + + # Read the number of Filters + n_filters = self._f['{0}{1}/n_filters'.format(base, tally_key)].value + + subbase = '{0}{1}/filter '.format(base, tally_key) + + # Initialize all Filters + for j in range(1, n_filters+1): + + # Read the Filter type + filter_type = self._f['{0}{1}/type'.format(subbase, j)].value.decode() + + # Read the Filter offset + offset = self._f['{0}{1}/offset'.format(subbase, j)].value + + n_bins = self._f['{0}{1}/n_bins'.format(subbase, j)].value + + # Read the bin values + bins = self._f['{0}{1}/bins'.format(subbase, j)].value + + # Create Filter object + filter = openmc.Filter(filter_type, bins) + filter.offset = offset + filter.num_bins = n_bins + + if filter_type == 'mesh': + mesh_ids = self._f['tallies/meshes/ids'].value + mesh_keys = self._f['tallies/meshes/keys'].value + + key = mesh_keys[mesh_ids == bins][0] + filter.mesh = self.meshes[key] + + # Add Filter to the Tally + tally.add_filter(filter) + + # Read Nuclide bins + nuclide_names = self._f['{0}{1}/nuclides'.format(base, tally_key)].value + + # Add all Nuclides to the Tally + for name in nuclide_names: + nuclide = openmc.Nuclide(name.decode().strip()) + tally.add_nuclide(nuclide) + + # Read score bins + n_score_bins = self._f['{0}{1}/n_score_bins'.format(base, tally_key)].value + + tally.num_score_bins = n_score_bins + + scores = self._f['{0}{1}/score_bins'.format( + base, tally_key)].value + n_user_scores = self._f['{0}{1}/n_user_score_bins' + .format(base, tally_key)].value + + # Compute and set the filter strides + for i in range(n_filters): + filter = tally.filters[i] + filter.stride = n_score_bins * len(nuclide_names) + + for j in range(i+1, n_filters): + filter.stride *= tally.filters[j].num_bins + + # Read scattering moment order strings (e.g., P3, Y-1,2, etc.) + moments = self._f['{0}{1}/moment_orders'.format( + base, tally_key)].value + + # Add the scores to the Tally + for j, score in enumerate(scores): + score = score.decode() + + # If this is a moment, use generic moment order + pattern = r'-n$|-pn$|-yn$' + score = re.sub(pattern, '-' + moments[j].decode(), score) + + tally.add_score(score) + + # Add Tally to the global dictionary of all Tallies + self._tallies[tally_key] = tally + + self._tallies_read = True + return self._tallies @property def tallies_present(self): - return self._tallies_present + return self._f['tallies/tallies_present'].value @property - def global_tallies(self): - return self._global_tallies + def version(self): + return (self._f['version_major'].value, + self._f['version_minor'].value, + self._f['version_release'].value) @property - def n_realizations(self): - return self._n_realizations + def summary(self): + return self._summary - def _read_metadata(self): - # Read filetype - self._filetype = self._get_int(path='filetype')[0] - - # Read statepoint revision - self._revision = self._get_int(path='revision')[0] - 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) - - # Read date and time - self._date_and_time = self._get_string(19, path='date_and_time') - - # Read path - self._path = self._get_string(255, path='path').strip() - - # Read random number seed - self._seed = self._get_long(path='seed')[0] - - # 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] - - # Read current batch - self._current_batch = self._get_int(path='current_batch')[0] - - # Read whether or not the source site distribution is present - self._source_present = self._get_int(path='source_present')[0] - - # Read criticality information - if self._run_mode == 2: - self._read_criticality() - - def _read_criticality(self): - # Read criticality information - if self._run_mode == 2: - - self._n_inactive = self._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._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') - - # Read CMFD information (if used) - self._read_cmfd() - - def _read_cmfd(self): - base = 'cmfd' - - # Read CMFD information - self._cmfd_on = self._get_int(path='cmfd_on')[0] - - 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_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)) - - def _read_meshes(self): - # Initialize dictionaries for the Meshes - # Keys - Mesh IDs - # Values - Mesh objects - self._meshes = {} - - # Read the number of Meshes - self._n_meshes = self._get_int(path='tallies/meshes/n_meshes')[0] - - # 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') - - # User-defined Mesh IDs - self._mesh_keys = self._get_int(self._n_meshes, - path='tallies/meshes/keys') - - else: - self._mesh_keys = [] - self._mesh_ids = [] - - # Build dictionary of Meshes - base = 'tallies/meshes/mesh ' - - # Iterate over all Meshes - for mesh_key in self._mesh_keys: - - # Read the user-specified Mesh ID and type - mesh_id = self._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] - - # Get the Mesh dimension - n_dimension = self._get_int( - path='{0}{1}/n_dimension'.format(base, mesh_key))[0] - - # 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)) - - # Create the Mesh and assign properties to it - mesh = openmc.Mesh(mesh_id) - - mesh.dimension = dimension - mesh.width = width - mesh.lower_left = lower_left - mesh.upper_right = upper_right - - #FIXME: Set the mesh type to 'rectangular' by default - mesh.type = 'rectangular' - - # Add mesh to the global dictionary of all Meshes - self._meshes[mesh_id] = mesh - - def _read_tallies(self): - # Initialize dictionaries for the Tallies - # Keys - Tally IDs - # Values - Tally objects - self._tallies = {} - - # Read the number of tallies - self._n_tallies = self._get_int(path='/tallies/n_tallies')[0] - - # 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') - - # User-defined Tally IDs - self._tally_keys = self._get_int( - self._n_tallies, path='tallies/keys') - - else: - self._tally_keys = [] - self._tally_ids = [] - - base = 'tallies/tally ' - - # Iterate over all Tallies - for tally_key in self._tally_keys: - - # Read integer Tally estimator type code (analog or tracklength) - estimator_type = self._get_int( - path='{0}{1}/estimator'.format(base, tally_key))[0] - - # Read the Tally size specifications - n_realizations = self._get_int( - path='{0}{1}/n_realizations'.format(base, tally_key))[0] - - # Create Tally object and assign basic properties - tally = openmc.Tally(tally_key) - tally.estimator = ESTIMATOR_TYPES[estimator_type] - tally.num_realizations = n_realizations - - # Read the number of Filters - n_filters = self._get_int( - path='{0}{1}/n_filters'.format(base, tally_key))[0] - - subbase = '{0}{1}/filter '.format(base, tally_key) - - # Initialize all Filters - for j in range(1, n_filters+1): - - # Read the integer Filter type code - filter_type = self._get_int( - path='{0}{1}/type'.format(subbase, j))[0] - - # Read the Filter offset - offset = self._get_int( - path='{0}{1}/offset'.format(subbase, j))[0] - - n_bins = self._get_int( - path='{0}{1}/n_bins'.format(subbase, j))[0] - - if n_bins <= 0: - msg = 'Unable to create Filter "{0}" for Tally ID="{1}" ' \ - 'since no bins were specified'.format(j, tally_key) - raise ValueError(msg) - - # Read the bin values - if FILTER_TYPES[filter_type] in ['energy', 'energyout']: - bins = self._get_double( - n_bins+1, path='{0}{1}/bins'.format(subbase, j)) - - elif FILTER_TYPES[filter_type] in ['mesh', 'distribcell']: - bins = self._get_int( - path='{0}{1}/bins'.format(subbase, j))[0] - - else: - bins = self._get_int( - n_bins, path='{0}{1}/bins'.format(subbase, j)) - - # Create Filter object - filter = openmc.Filter(FILTER_TYPES[filter_type], bins) - filter.offset = offset - filter.num_bins = n_bins - - if FILTER_TYPES[filter_type] == 'mesh': - key = self._mesh_keys[self._mesh_ids.index(bins)] - filter.mesh = self._meshes[key] - - # Add Filter to the Tally - tally.add_filter(filter) - - # Read Nuclide bins - n_nuclides = self._get_int( - path='{0}{1}/n_nuclides'.format(base, tally_key))[0] - - nuclide_zaids = self._get_int( - n_nuclides, path='{0}{1}/nuclides'.format(base, tally_key)) - - # 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] - - 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] - - # Compute and set the filter strides - for i in range(n_filters): - filter = tally.filters[i] - filter.stride = n_score_bins * n_nuclides - - for j in range(i+1, n_filters): - filter.stride *= tally.filters[j].num_bins - - # Read scattering moment order strings (e.g., P3, Y-1,2, etc.) - moments = [] - subbase = '{0}{1}/moments/'.format(base, tally_key) - - # 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 = moment.lstrip('[\'') - moment = moment.rstrip('\']') - - # Remove extra whitespace - moment.replace(" ", "") - moments.append(moment) - - # Add the scores to the Tally - for j, score in enumerate(scores): - # If this is a scattering moment, insert the scattering order - if '-n' in score: - score = score.replace('-n', '-' + str(moments[j])) - elif '-pn' in score: - score = score.replace('-pn', '-' + str(moments[j])) - elif '-yn' in score: - score = score.replace('-yn', '-' + str(moments[j])) - - tally.add_score(score) - - # Add Tally to the global dictionary of all Tallies - self.tallies[tally_key] = tally - - def read_results(self): - """Read tally results and store them in the ``tallies`` attribute. No results - are read when the statepoint is instantiated. - - """ - - # Number of realizations for global Tallies - self._n_realizations = self._get_int(path='n_realizations')[0] - - # Read global Tallies - n_global_tallies = self._get_int(path='n_global_tallies')[0] - - if self._hdf5: - data = self._f['global_tallies'].value - self._global_tallies = np.column_stack((data['sum'], data['sum_sq'])) - - else: - self._global_tallies = np.array(self._get_double(2*n_global_tallies)) - self._global_tallies.shape = (n_global_tallies, 2) - - # Flag indicating if Tallies are present - self._tallies_present = self._get_int(path='tallies/tallies_present')[0] - - base = 'tallies/tally ' - - # Read Tally results - if self._tallies_present: - - # Iterate over and extract the results for all Tallies - for tally_key in self._tally_keys: - - # Get this Tally - tally = self._tallies[tally_key] - - # Compute the total number of bins for this Tally - 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] - - # Define a routine to convert 0 to 1 - def nonzero(val): - return 1 if not val else val - - # Reshape the results arrays - new_shape = (nonzero(tally.num_filter_bins), - nonzero(tally.num_nuclides), - nonzero(tally.num_score_bins)) - - sum = np.reshape(sum, new_shape) - sum_sq = np.reshape(sum_sq, new_shape) - - # Set the data for this Tally - tally.sum = sum - tally.sum_sq = sum_sq - - # Indicate that Tally results have been read - self._results = True - - def read_source(self): - """Read and store source sites from the statepoint file. By default, source - sites are not loaded upon initialization. - - """ - - # Check whether Tally results have been read - if not self._results: - self.read_results() - - # Check if source bank is in statepoint - if not self._source_present: - print('Unable to read source since it is not in statepoint file') - return - - # Initialize a NumPy array for the source sites - self._source = np.empty(self._n_particles, dtype=SourceSite) - - # For HDF5 state points, copy entire bank - if self._hdf5: - source_sites = self._f['source_bank'].value - - # Initialize SourceSite object for each particle - for i in range(self._n_particles): - # Initialize new source site - site = SourceSite() - - # Read position, angle, and energy - 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] - - # Store the source site in the NumPy array - self._source[i] = site - - def compute_ci(self, confidence=0.95): - """Computes confidence intervals for each Tally bin. - - This method is equivalent to calling compute_stdev(...) when the - confidence is known as opposed to its corresponding t value. - - Parameters - ---------- - confidence : float, optional - Confidence level. Defaults to 0.95. - - """ - - # Determine significance level and percentile for two-sided CI - alpha = 1 - confidence - percentile = 1 - alpha/2 - - # Calculate t-value - t_value = scipy.stats.t.ppf(percentile, self._n_realizations - 1) - self.compute_stdev(t_value) - - def compute_stdev(self, t_value=1.0): - """Computes the sample mean and the standard deviation of the mean - for each Tally bin. - - Parameters - ---------- - t_value : float, optional - Student's t-value applied to the uncertainty. Defaults to 1.0, - meaning the reported value is the sample standard deviation. - - """ - - # Determine number of realizations - n = self._n_realizations - - # Calculate the standard deviation for each global tally - for i in range(len(self._global_tallies)): - - # Get sum and sum of squares - s, s2 = self._global_tallies[i] - - # Calculate sample mean and replace value - s /= n - self._global_tallies[i, 0] = s - - # Calculate standard deviation - if s != 0.0: - self._global_tallies[i, 1] = t_value * np.sqrt((s2 / n - s**2) / (n-1)) - - # Calculate sample mean and standard deviation for user-defined Tallies - for tally_id, tally in self.tallies.items(): - tally.compute_std_dev(t_value) + @property + def with_summary(self): + return False if self.summary is None else True def get_tally(self, scores=[], filters=[], nuclides=[], name=None, id=None, estimator=None): """Finds and returns a Tally object with certain properties. This routine searches the list of Tallies and returns the first Tally - found it finds which satisfies all of the input parameters. + found which satisfies all of the input parameters. NOTE: The input parameters do not need to match the complete Tally specification and may only represent a subset of the Tally's properties. @@ -640,7 +467,7 @@ class StatePoint(object): A list of Nuclide objects (default is []). name : str, optional The name specified for the Tally (default is None). - id : int, optional + id : Integral, optional The id specified for the Tally (default is None). estimator: str, optional The type of estimator ('tracklength', 'analog'; default is None). @@ -694,8 +521,16 @@ class StatePoint(object): # Iterate over the Filters requested by the user for filter in filters: - if filter not in test_tally.filters: - contains_filters = False + contains_filters = False + + # Test if requested filter is a subset of any of the test + # tally's filters and if so continue to next filter + for test_filter in test_tally.filters: + if test_filter.is_subset(filter): + contains_filters = True + break + + if not contains_filters: break if not contains_filters: @@ -757,15 +592,6 @@ class StatePoint(object): tally.name = summary.tallies[tally_id].name tally.with_summary = True - nuclide_zaids = copy.deepcopy(tally.nuclides) - - for nuclide_zaid in nuclide_zaids: - tally.remove_nuclide(nuclide_zaid) - if nuclide_zaid == -1: - tally.add_nuclide(openmc.Nuclide('total')) - else: - tally.add_nuclide(summary.nuclides[nuclide_zaid]) - for filter in tally.filters: if filter.type == 'surface': surface_ids = [] @@ -791,44 +617,4 @@ class StatePoint(object): material_ids.append(summary.materials[bin].id) 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]) + self._summary = summary diff --git a/openmc/summary.py b/openmc/summary.py index 7f9d5387e9..4b1088e827 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -1,12 +1,22 @@ import numpy as np import openmc +from openmc.region import Region class Summary(object): """Information summarizing the geometry, materials, and tallies used in a simulation. + Attributes + ---------- + openmc_geometry : openmc.Geometry + An OpenMC geometry object reconstructed from the summary file + opencg_geometry : opencg.Geometry + An OpenCG geometry object equivalent to the OpenMC geometry + encapsulated by the summary file. Use of this attribute requires + installation of the OpenCG Python module. + """ def __init__(self, filename): @@ -22,31 +32,41 @@ class Summary(object): raise ValueError(msg) self._f = h5py.File(filename, 'r') - self.openmc_geometry = None - self.opencg_geometry = None + self._openmc_geometry = None + self._opencg_geometry = None self._read_metadata() self._read_geometry() self._read_tallies() + @property + def openmc_geometry(self): + return self._openmc_geometry + + @property + def opencg_geometry(self): + if self._opencg_geometry is None: + from openmc.opencg_compatible import get_opencg_geometry + self._opencg_geometry = get_opencg_geometry(self.openmc_geometry) + return self._opencg_geometry + def _read_metadata(self): # Read OpenMC version - self.version = [self._f['version_major'][0], - self._f['version_minor'][0], - self._f['version_release'][0]] + self.version = [self._f['version_major'].value, + self._f['version_minor'].value, + self._f['version_release'].value] # Read date and time self.date_and_time = self._f['date_and_time'][...] - self.n_batches = self._f['n_batches'][0] - self.n_particles = self._f['n_particles'][0] - self.n_active = self._f['n_active'][0] - self.n_inactive = self._f['n_inactive'][0] - self.gen_per_batch = self._f['gen_per_batch'][0] - self.n_procs = self._f['n_procs'][0] + self.n_batches = self._f['n_batches'].value + self.n_particles = self._f['n_particles'].value + self.n_active = self._f['n_active'].value + self.n_inactive = self._f['n_inactive'].value + self.gen_per_batch = self._f['gen_per_batch'].value + self.n_procs = self._f['n_procs'].value def _read_geometry(self): # Read in and initialize the Materials and Geometry - self._read_nuclides() self._read_materials() self._read_surfaces() self._read_cells() @@ -54,37 +74,8 @@ class Summary(object): self._read_lattices() self._finalize_geometry() - def _read_nuclides(self): - self.n_nuclides = self._f['nuclides/n_nuclides'][0] - - # Initialize dictionary for each Nuclide - # Keys - Nuclide ZAIDs - # Values - Nuclide objects - self.nuclides = {} - - for key in self._f['nuclides'].keys(): - if key == 'n_nuclides': - continue - - index = self._f['nuclides'][key]['index'][0] - alias = self._f['nuclides'][key]['alias'][0] - zaid = self._f['nuclides'][key]['zaid'][0] - - # Read the Nuclide's name (e.g., 'H-1' or 'U-235') - name = alias.split('.')[0] - - # Read the Nuclide's cross-section identifier (e.g., '70c') - xs = alias.split('.')[1] - - # Initialize this Nuclide and add to global dictionary of Nuclides - if 'nat' in name: - self.nuclides[zaid] = openmc.Element(name=name, xs=xs) - else: - self.nuclides[zaid] = openmc.Nuclide(name=name, xs=xs) - self.nuclides[zaid].zaid = zaid - def _read_materials(self): - self.n_materials = self._f['materials/n_materials'][0] + self.n_materials = self._f['n_materials'].value # Initialize dictionary for each Material # Keys - Material keys @@ -96,51 +87,42 @@ class Summary(object): continue material_id = int(key.lstrip('material ')) - index = self._f['materials'][key]['index'][0] - name = self._f['materials'][key]['name'][0] - density = self._f['materials'][key]['atom_density'][0] + index = self._f['materials'][key]['index'].value + name = self._f['materials'][key]['name'].value.decode() + density = self._f['materials'][key]['atom_density'].value nuc_densities = self._f['materials'][key]['nuclide_densities'][...] - nuclides = self._f['materials'][key]['nuclides'][...] - n_sab = self._f['materials'][key]['n_sab'][0] - - sab_names = [] - sab_xs = [] - - # Read the names of the S(a,b) tables for this Material - for i in range(1, n_sab+1): - sab_table = self._f['materials'][key]['sab_tables'][str(i)][0] - - # Read the cross-section identifiers for each S(a,b) table - sab_names.append(sab_table.split('.')[0]) - sab_xs.append(sab_table.split('.')[1]) + nuclides = self._f['materials'][key]['nuclides'].value # Create the Material material = openmc.Material(material_id=material_id, name=name) - # Set the Material's density to g/cm3 - this is what is used in OpenMC - material.set_density(density=density, units='g/cm3') + # Read the names of the S(a,b) tables for this Material and add them + if 'sab_names' in self._f['materials'][key]: + sab_tables = self._f['materials'][key]['sab_names'].value + for sab_table in sab_tables: + name, xs = sab_table.decode().split('.') + material.add_s_alpha_beta(name, xs) - # Add all Nuclides to the Material - for i, zaid in enumerate(nuclides): - nuclide = self.get_nuclide_by_zaid(zaid) - density = nuc_densities[i] + # Set the Material's density to atom/b-cm as used by OpenMC + material.set_density(density=density, units='atom/b-cm') - if isinstance(nuclide, openmc.Nuclide): - material.add_nuclide(nuclide, percent=density, percent_type='ao') - elif isinstance(nuclide, openmc.Element): - material.add_element(nuclide, percent=density, percent_type='ao') + # Add all nuclides to the Material + for fullname, density in zip(nuclides, nuc_densities): + fullname = fullname.decode().strip() + name, xs = fullname.split('.') - # Add S(a,b) table(s?) to the Material - for i in range(n_sab): - name = sab_names[i] - xs = sab_xs[i] - material.add_s_alpha_beta(name, xs) + if 'nat' in name: + material.add_element(openmc.Element(name=name, xs=xs), + percent=density, percent_type='ao') + else: + material.add_nuclide(openmc.Nuclide(name=name, xs=xs), + percent=density, percent_type='ao') # Add the Material to the global dictionary of all Materials self.materials[index] = material def _read_surfaces(self): - self.n_surfaces = self._f['geometry/n_surfaces'][0] + self.n_surfaces = self._f['geometry/n_surfaces'].value # Initialize dictionary for each Surface # Keys - Surface keys @@ -152,75 +134,80 @@ class Summary(object): continue surface_id = int(key.lstrip('surface ')) - index = self._f['geometry/surfaces'][key]['index'][0] - name = self._f['geometry/surfaces'][key]['name'][0] - surf_type = self._f['geometry/surfaces'][key]['type'][...][0] - bc = self._f['geometry/surfaces'][key]['boundary_condition'][...][0] + index = self._f['geometry/surfaces'][key]['index'].value + name = self._f['geometry/surfaces'][key]['name'].value.decode() + surf_type = self._f['geometry/surfaces'][key]['type'].value.decode() + bc = self._f['geometry/surfaces'][key]['boundary_condition'].value.decode() coeffs = self._f['geometry/surfaces'][key]['coefficients'][...] # Create the Surface based on its type - if surf_type == 'X Plane': + if surf_type == 'x-plane': x0 = coeffs[0] surface = openmc.XPlane(surface_id, bc, x0, name) - elif surf_type == 'Y Plane': + elif surf_type == 'y-plane': y0 = coeffs[0] surface = openmc.YPlane(surface_id, bc, y0, name) - elif surf_type == 'Z Plane': + elif surf_type == 'z-plane': z0 = coeffs[0] surface = openmc.ZPlane(surface_id, bc, z0, name) - elif surf_type == 'Plane': + elif surf_type == 'plane': A = coeffs[0] B = coeffs[1] C = coeffs[2] D = coeffs[3] surface = openmc.Plane(surface_id, bc, A, B, C, D, name) - elif surf_type == 'X Cylinder': + elif surf_type == 'x-cylinder': y0 = coeffs[0] z0 = coeffs[1] R = coeffs[2] surface = openmc.XCylinder(surface_id, bc, y0, z0, R, name) - elif surf_type == 'Y Cylinder': + elif surf_type == 'y-cylinder': x0 = coeffs[0] z0 = coeffs[1] R = coeffs[2] surface = openmc.YCylinder(surface_id, bc, x0, z0, R, name) - elif surf_type == 'Z Cylinder': + elif surf_type == 'z-cylinder': x0 = coeffs[0] y0 = coeffs[1] R = coeffs[2] surface = openmc.ZCylinder(surface_id, bc, x0, y0, R, name) - elif surf_type == 'Sphere': + elif surf_type == 'sphere': x0 = coeffs[0] y0 = coeffs[1] z0 = coeffs[2] R = coeffs[3] surface = openmc.Sphere(surface_id, bc, x0, y0, z0, R, name) - elif surf_type in ['X Cone', 'Y Cone', 'Z Cone']: + elif surf_type in ['x-cone', 'y-cone', 'z-cone']: x0 = coeffs[0] y0 = coeffs[1] z0 = coeffs[2] R2 = coeffs[3] - if surf_type == 'X Cone': + if surf_type == 'x-cone': surface = openmc.XCone(surface_id, bc, x0, y0, z0, R2, name) - if surf_type == 'Y Cone': + if surf_type == 'y-cone': surface = openmc.YCone(surface_id, bc, x0, y0, z0, R2, name) - if surf_type == 'Z Cone': + if surf_type == 'z-cone': surface = openmc.ZCone(surface_id, bc, x0, y0, z0, R2, name) + elif surf_type == 'quadric': + a, b, c, d, e, f, g, h, j, k = coeffs + surface = openmc.Quadric(surface_id, bc, a, b, c, d, e, f, + g, h, j, k, name) + # Add Surface to global dictionary of all Surfaces self.surfaces[index] = surface def _read_cells(self): - self.n_cells = self._f['geometry/n_cells'][0] + self.n_cells = self._f['geometry/n_cells'].value # Initialize dictionary for each Cell # Keys - Cell keys @@ -240,41 +227,37 @@ class Summary(object): continue cell_id = int(key.lstrip('cell ')) - index = self._f['geometry/cells'][key]['index'][0] - name = self._f['geometry/cells'][key]['name'][0] - fill_type = self._f['geometry/cells'][key]['fill_type'][...][0] + index = self._f['geometry/cells'][key]['index'].value + name = self._f['geometry/cells'][key]['name'].value.decode() + fill_type = self._f['geometry/cells'][key]['fill_type'].value.decode() if fill_type == 'normal': - fill = self._f['geometry/cells'][key]['material'][0] + fill = self._f['geometry/cells'][key]['material'].value elif fill_type == 'universe': - fill = self._f['geometry/cells'][key]['fill'][0] + fill = self._f['geometry/cells'][key]['fill'].value else: - fill = self._f['geometry/cells'][key]['lattice'][0] + fill = self._f['geometry/cells'][key]['lattice'].value - if 'surfaces' in self._f['geometry/cells'][key].keys(): - surfaces = self._f['geometry/cells'][key]['surfaces'][...] + if 'region' in self._f['geometry/cells'][key].keys(): + region = self._f['geometry/cells'][key]['region'].value.decode() else: - surfaces = [] + region = [] # Create this Cell cell = openmc.Cell(cell_id=cell_id, name=name) if fill_type == 'universe': - maps = self._f['geometry/cells'][key]['maps'][0] - - if maps > 0: + if 'offset' in self._f['geometry/cells'][key]: offset = self._f['geometry/cells'][key]['offset'][...] - cell.set_offset(offset) + cell.offsets = offset - translated = self._f['geometry/cells'][key]['translated'][0] - if translated: + if 'translation' in self._f['geometry/cells'][key]: translation = \ self._f['geometry/cells'][key]['translation'][...] translation = np.asarray(translation, dtype=np.float64) cell.translation = translation - rotated = self._f['geometry/cells'][key]['rotated'][0] - if rotated: + if 'rotation' in self._f['geometry/cells'][key]: rotation = \ self._f['geometry/cells'][key]['rotation'][...] rotation = np.asarray(rotation, dtype=np.int) @@ -283,19 +266,16 @@ class Summary(object): # Store Cell fill information for after Universe/Lattice creation self._cell_fills[index] = (fill_type, fill) - # Iterate over all Surfaces and add them to the Cell - for surface_halfspace in surfaces: - - halfspace = np.sign(surface_halfspace) - surface_id = np.abs(surface_halfspace) - surface = self.surfaces[surface_id] - cell.add_surface(surface, halfspace) + # Generate Region object given infix expression + if region: + cell.region = Region.from_expression( + region, {s.id: s for s in self.surfaces.values()}) # Add the Cell to the global dictionary of all Cells self.cells[index] = cell def _read_universes(self): - self.n_universes = self._f['geometry/n_universes'][0] + self.n_universes = self._f['geometry/n_universes'].value # Initialize dictionary for each Universe # Keys - Universe keys @@ -307,7 +287,7 @@ class Summary(object): continue universe_id = int(key.lstrip('universe ')) - index = self._f['geometry/universes'][key]['index'][0] + index = self._f['geometry/universes'][key]['index'].value cells = self._f['geometry/universes'][key]['cells'][...] # Create this Universe @@ -322,7 +302,7 @@ class Summary(object): self.universes[index] = universe def _read_lattices(self): - self.n_lattices = self._f['geometry/n_lattices'][0] + self.n_lattices = self._f['geometry/n_lattices'].value # Initialize lattices for each Lattice # Keys - Lattice keys @@ -334,21 +314,21 @@ class Summary(object): continue lattice_id = int(key.lstrip('lattice ')) - index = self._f['geometry/lattices'][key]['index'][0] - name = self._f['geometry/lattices'][key]['name'][0] - lattice_type = self._f['geometry/lattices'][key]['type'][...][0] - maps = self._f['geometry/lattices'][key]['maps'][0] - offset_size = self._f['geometry/lattices'][key]['offset_size'][0] + index = self._f['geometry/lattices'][key]['index'].value + name = self._f['geometry/lattices'][key]['name'].value.decode() + lattice_type = self._f['geometry/lattices'][key]['type'].value.decode() - if offset_size > 0: + if 'offsets' in self._f['geometry/lattices'][key]: offsets = self._f['geometry/lattices'][key]['offsets'][...] + else: + offsets = None if lattice_type == 'rectangular': dimension = self._f['geometry/lattices'][key]['dimension'][...] lower_left = \ self._f['geometry/lattices'][key]['lower_left'][...] pitch = self._f['geometry/lattices'][key]['pitch'][...] - outer = self._f['geometry/lattices'][key]['outer'][0] + outer = self._f['geometry/lattices'][key]['outer'].value universe_ids = \ self._f['geometry/lattices'][key]['universes'][...] @@ -382,7 +362,7 @@ class Summary(object): universes = universes[:, ::-1, :] lattice.universes = universes - if offset_size > 0: + if offsets is not None: offsets = np.swapaxes(offsets, 0, 1) offsets = np.swapaxes(offsets, 1, 2) lattice.offsets = offsets @@ -476,7 +456,7 @@ class Summary(object): # Lattice is 2D; extract the only axial level lattice.universes = universes[0] - if offset_size > 0: + if offsets is not None: lattice.offsets = offsets # Add the Lattice to the global dictionary of all Lattices @@ -484,7 +464,7 @@ class Summary(object): def _finalize_geometry(self): # Initialize Geometry object - self.openmc_geometry = openmc.Geometry() + self._openmc_geometry = openmc.Geometry() # Iterate over all Cells and add fill Materials, Universes and Lattices for cell_key in self._cell_fills.keys(): @@ -521,7 +501,7 @@ class Summary(object): self.n_tallies = 0 return - self.n_tallies = self._f['tallies/n_tallies'][0] + self.n_tallies = self._f['tallies/n_tallies'].value # OpenMC Tally keys all_keys = self._f['tallies/'].keys() @@ -531,43 +511,34 @@ class Summary(object): # Iterate over all Tallies for tally_key in tally_keys: - tally_id = int(tally_key.strip('tally ')) subbase = '{0}{1}'.format(base, tally_id) # Read Tally name metadata - name_size = self._f['{0}/name_size'.format(subbase)][0] - if (name_size > 0): - tally_name = self._f['{0}/name'.format(subbase)][0] - tally_name = tally_name.lstrip('[\'') - tally_name = tally_name.rstrip('\']') - else: - tally_name = '' + tally_name = self._f['{0}/name'.format(subbase)].value.decode() # Create Tally object and assign basic properties tally = openmc.Tally(tally_id, tally_name) # Read score metadata - score_bins = self._f['{0}/score_bins'.format(subbase)][...] - for score_bin in score_bins: - tally.add_score(openmc.SCORE_TYPES[score_bin]) + scores = self._f['{0}/score_bins'.format(subbase)].value + for score in scores: + tally.add_score(score.decode()) num_score_bins = self._f['{0}/n_score_bins'.format(subbase)][...] tally.num_score_bins = num_score_bins # Read filter metadata - num_filters = self._f['{0}/n_filters'.format(subbase)][0] + num_filters = self._f['{0}/n_filters'.format(subbase)].value # Initialize all Filters for j in range(1, num_filters+1): - subsubbase = '{0}/filter {1}'.format(subbase, j) # Read filter type (e.g., "cell", "energy", etc.) - filter_type_code = self._f['{0}/type'.format(subsubbase)][0] - filter_type = openmc.FILTER_TYPES[filter_type_code] + filter_type = self._f['{0}/type'.format(subsubbase)].value.decode() # Read the filter bins - num_bins = self._f['{0}/n_bins'.format(subsubbase)][0] + num_bins = self._f['{0}/n_bins'.format(subsubbase)].value bins = self._f['{0}/bins'.format(subsubbase)][...] # Create Filter object @@ -580,45 +551,6 @@ class Summary(object): # Add Tally to the global dictionary of all Tallies self.tallies[tally_id] = tally - def make_opencg_geometry(self): - """Create OpenCG geometry based on the information contained in the summary - file. The geometry is stored as the 'opencg_geometry' attribute. - - """ - - try: - from openmc.opencg_compatible import get_opencg_geometry - except ImportError: - msg = 'Unable to import opencg which is needed ' \ - 'by Summary.make_opencg_geometry()' - raise ImportError(msg) - - if self.opencg_geometry is None: - self.opencg_geometry = get_opencg_geometry(self.openmc_geometry) - - def get_nuclide_by_zaid(self, zaid): - """Return a Nuclide object given the 'zaid' identifier for the nuclide. - - Parameters - ---------- - zaid : int - 1000*Z + A, where Z is the atomic number of the nuclide and A is the - mass number. For example, the zaid for U-235 is 92235. - - Returns - ------- - nuclide : openmc.nuclide.Nuclide or None - Nuclide matching the specified zaid, or None if no matching object - is found. - - """ - - for index, nuclide in self.nuclides.items(): - if nuclide._zaid == zaid: - return nuclide - - return None - def get_material_by_id(self, material_id): """Return a Material object given the material id diff --git a/openmc/surface.py b/openmc/surface.py index d5d258fa7a..8dc45209be 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -3,8 +3,10 @@ from numbers import Real, Integral from xml.etree import ElementTree as ET import sys +import numpy as np + from openmc.checkvalue import check_type, check_value, check_greater_than -from openmc.constants import BC_TYPES +from openmc.region import Region if sys.version_info[0] >= 3: basestring = str @@ -12,6 +14,8 @@ if sys.version_info[0] >= 3: # A static variable for auto-generated Surface IDs AUTO_SURFACE_ID = 10000 +_BC_TYPES = ['transmission', 'vacuum', 'reflective', 'periodic'] + def reset_auto_surface_id(): global AUTO_SURFACE_ID @@ -37,17 +41,17 @@ class Surface(object): Attributes ---------- + boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic'} + Boundary condition that defines the behavior for particles hitting the + surface. + coeffs : dict + Dictionary of surface coefficients id : int Unique identifier for the surface name : str Name of the surface type : str Type of the surface, e.g. 'x-plane' - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic'} - Boundary condition that defines the behavior for particles hitting the - surface. - coeffs : dict - Dictionary of surface coefficients """ @@ -67,6 +71,28 @@ class Surface(object): # proper order self._coeff_keys = [] + def __neg__(self): + return Halfspace(self, '-') + + def __pos__(self): + return Halfspace(self, '+') + + def __repr__(self): + string = 'Surface\n' + string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) + string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) + string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type) + string += '{0: <16}{1}{2}\n'.format('\tBoundary', '=\t', self._boundary_type) + + coeffs = '{0: <16}'.format('\tCoefficients') + '\n' + + for coeff in self._coeffs: + coeffs += '{0: <16}{1}{2}\n'.format(coeff, '=\t', self._coeffs[coeff]) + + string += coeffs + + return string + @property def id(self): return self._id @@ -95,35 +121,49 @@ class Surface(object): AUTO_SURFACE_ID += 1 else: check_type('surface ID', surface_id, Integral) - check_greater_than('surface ID', surface_id, 0) + check_greater_than('surface ID', surface_id, 0, equality=True) self._id = surface_id @name.setter def name(self, name): - check_type('surface name', name, basestring) - self._name = name + if name is not None: + check_type('surface name', name, basestring) + self._name = name + else: + self._name = '' @boundary_type.setter def boundary_type(self, boundary_type): check_type('boundary type', boundary_type, basestring) - check_value('boundary type', boundary_type, BC_TYPES.values()) + check_value('boundary type', boundary_type, _BC_TYPES) self._boundary_type = boundary_type - def __repr__(self): - string = 'Surface\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type) - string += '{0: <16}{1}{2}\n'.format('\tBoundary', '=\t', self._boundary_type) + def bounding_box(self, side): + """Determine an axis-aligned bounding box. - coeffs = '{0: <16}'.format('\tCoefficients') + '\n' + An axis-aligned bounding box for surface half-spaces is represented by + its lower-left and upper-right coordinates. If the half-space is + unbounded in a particular direction, numpy.inf is used to represent + infinity. - for coeff in self._coeffs: - coeffs += '{0: <16}{1}{2}\n'.format(coeff, '=\t', self._coeffs[coeff]) + Parameters + ---------- + side : {'+', '-'} + Indicates the negative or positive half-space - string += coeffs + Returns + ------- + numpy.array + Lower-left coordinates of the axis-aligned bounding box for the + desired half-space + numpy.array + Upper-right coordinates of the axis-aligned bounding box for the + desired half-space - return string + """ + + return (np.array([-np.inf, -np.inf, -np.inf]), + np.array([np.inf, np.inf, np.inf])) def create_xml_subelement(self): element = ET.Element("surface") @@ -134,7 +174,7 @@ class Surface(object): element.set("type", self._type) element.set("boundary", self._boundary_type) - element.set("coeffs", ' '.join([str(self._coeffs[key]) + element.set("coeffs", ' '.join([str(self._coeffs.setdefault(key, 0.0)) for key in self._coeff_keys])) return element @@ -183,6 +223,10 @@ class Plane(Surface): self._type = 'plane' self._coeff_keys = ['A', 'B', 'C', 'D'] + self._coeffs['A'] = 1. + self._coeffs['B'] = 0. + self._coeffs['C'] = 0. + self._coeffs['D'] = 0. if A is not None: self.a = A @@ -265,19 +309,51 @@ class XPlane(Plane): self._type = 'x-plane' self._coeff_keys = ['x0'] + self._coeffs['x0'] = 0. if x0 is not None: self.x0 = x0 @property def x0(self): - return self.coeff['x0'] + return self.coeffs['x0'] @x0.setter def x0(self, x0): check_type('x0 coefficient', x0, Real) self._coeffs['x0'] = x0 + def bounding_box(self, side): + """Determine an axis-aligned bounding box. + + An axis-aligned bounding box for surface half-spaces is represented by + its lower-left and upper-right coordinates. For the x-plane surface, the + half-spaces are unbounded in their y- and z- directions. To represent + infinity, numpy.inf is used. + + Parameters + ---------- + side : {'+', '-'} + Indicates the negative or positive half-space + + Returns + ------- + numpy.array + Lower-left coordinates of the axis-aligned bounding box for the + desired half-space + numpy.array + Upper-right coordinates of the axis-aligned bounding box for the + desired half-space + + """ + + if side == '-': + return (np.array([-np.inf, -np.inf, -np.inf]), + np.array([self.x0, np.inf, np.inf])) + elif side == '+': + return (np.array([self.x0, -np.inf, -np.inf]), + np.array([np.inf, np.inf, np.inf])) + class YPlane(Plane): """A plane perpendicular to the y axis, i.e. a surface of the form :math:`y - @@ -311,6 +387,7 @@ class YPlane(Plane): self._type = 'y-plane' self._coeff_keys = ['y0'] + self._coeffs['y0'] = 0. if y0 is not None: self.y0 = y0 @@ -324,6 +401,37 @@ class YPlane(Plane): check_type('y0 coefficient', y0, Real) self._coeffs['y0'] = y0 + def bounding_box(self, side): + """Determine an axis-aligned bounding box. + + An axis-aligned bounding box for surface half-spaces is represented by + its lower-left and upper-right coordinates. For the y-plane surface, the + half-spaces are unbounded in their x- and z- directions. To represent + infinity, numpy.inf is used. + + Parameters + ---------- + side : {'+', '-'} + Indicates the negative or positive half-space + + Returns + ------- + numpy.array + Lower-left coordinates of the axis-aligned bounding box for the + desired half-space + numpy.array + Upper-right coordinates of the axis-aligned bounding box for the + desired half-space + + """ + + if side == '-': + return (np.array([-np.inf, -np.inf, -np.inf]), + np.array([np.inf, self.y0, np.inf])) + elif side == '+': + return (np.array([-np.inf, self.y0, -np.inf]), + np.array([np.inf, np.inf, np.inf])) + class ZPlane(Plane): """A plane perpendicular to the z axis, i.e. a surface of the form :math:`z - @@ -357,6 +465,7 @@ class ZPlane(Plane): self._type = 'z-plane' self._coeff_keys = ['z0'] + self._coeffs['z0'] = 0. if z0 is not None: self.z0 = z0 @@ -370,6 +479,37 @@ class ZPlane(Plane): check_type('z0 coefficient', z0, Real) self._coeffs['z0'] = z0 + def bounding_box(self, side): + """Determine an axis-aligned bounding box. + + An axis-aligned bounding box for surface half-spaces is represented by + its lower-left and upper-right coordinates. For the z-plane surface, the + half-spaces are unbounded in their x- and y- directions. To represent + infinity, numpy.inf is used. + + Parameters + ---------- + side : {'+', '-'} + Indicates the negative or positive half-space + + Returns + ------- + numpy.array + Lower-left coordinates of the axis-aligned bounding box for the + desired half-space + numpy.array + Upper-right coordinates of the axis-aligned bounding box for the + desired half-space + + """ + + if side == '-': + return (np.array([-np.inf, -np.inf, -np.inf]), + np.array([np.inf, np.inf, self.z0])) + elif side == '+': + return (np.array([-np.inf, -np.inf, self.z0]), + np.array([np.inf, np.inf, np.inf])) + class Cylinder(Surface): """A cylinder whose length is parallel to the x-, y-, or z-axis. @@ -404,6 +544,7 @@ class Cylinder(Surface): super(Cylinder, self).__init__(surface_id, boundary_type, name=name) self._coeff_keys = ['R'] + self._coeffs['R'] = 1. if R is not None: self.r = R @@ -457,6 +598,8 @@ class XCylinder(Cylinder): self._type = 'x-cylinder' self._coeff_keys = ['y0', 'z0', 'R'] + self._coeffs['y0'] = 0. + self._coeffs['z0'] = 0. if y0 is not None: self.y0 = y0 @@ -482,6 +625,38 @@ class XCylinder(Cylinder): check_type('z0 coefficient', z0, Real) self._coeffs['z0'] = z0 + def bounding_box(self, side): + """Determine an axis-aligned bounding box. + + An axis-aligned bounding box for surface half-spaces is represented by + its lower-left and upper-right coordinates. For the x-cylinder surface, + the negative half-space is unbounded in the x- direction and the + positive half-space is unbounded in all directions. To represent + infinity, numpy.inf is used. + + Parameters + ---------- + side : {'+', '-'} + Indicates the negative or positive half-space + + Returns + ------- + numpy.array + Lower-left coordinates of the axis-aligned bounding box for the + desired half-space + numpy.array + Upper-right coordinates of the axis-aligned bounding box for the + desired half-space + + """ + + if side == '-': + return (np.array([-np.inf, self.y0 - self.r, self.z0 - self.r]), + np.array([np.inf, self.y0 + self.r, self.z0 + self.r])) + elif side == '+': + return (np.array([-np.inf, -np.inf, -np.inf]), + np.array([np.inf, np.inf, np.inf])) + class YCylinder(Cylinder): """An infinite cylinder whose length is parallel to the y-axis. This is a @@ -522,6 +697,8 @@ class YCylinder(Cylinder): self._type = 'y-cylinder' self._coeff_keys = ['x0', 'z0', 'R'] + self._coeffs['x0'] = 0. + self._coeffs['z0'] = 0. if x0 is not None: self.x0 = x0 @@ -547,6 +724,38 @@ class YCylinder(Cylinder): check_type('z0 coefficient', z0, Real) self._coeffs['z0'] = z0 + def bounding_box(self, side): + """Determine an axis-aligned bounding box. + + An axis-aligned bounding box for surface half-spaces is represented by + its lower-left and upper-right coordinates. For the y-cylinder surface, + the negative half-space is unbounded in the y- direction and the + positive half-space is unbounded in all directions. To represent + infinity, numpy.inf is used. + + Parameters + ---------- + side : {'+', '-'} + Indicates the negative or positive half-space + + Returns + ------- + numpy.array + Lower-left coordinates of the axis-aligned bounding box for the + desired half-space + numpy.array + Upper-right coordinates of the axis-aligned bounding box for the + desired half-space + + """ + + if side == '-': + return (np.array([self.x0 - self.r, -np.inf, self.z0 - self.r]), + np.array([self.x0 + self.r, np.inf, self.z0 + self.r])) + elif side == '+': + return (np.array([-np.inf, -np.inf, -np.inf]), + np.array([np.inf, np.inf, np.inf])) + class ZCylinder(Cylinder): """An infinite cylinder whose length is parallel to the z-axis. This is a @@ -587,6 +796,8 @@ class ZCylinder(Cylinder): self._type = 'z-cylinder' self._coeff_keys = ['x0', 'y0', 'R'] + self._coeffs['x0'] = 0. + self._coeffs['y0'] = 0. if x0 is not None: self.x0 = x0 @@ -612,6 +823,38 @@ class ZCylinder(Cylinder): check_type('y0 coefficient', y0, Real) self._coeffs['y0'] = y0 + def bounding_box(self, side): + """Determine an axis-aligned bounding box. + + An axis-aligned bounding box for surface half-spaces is represented by + its lower-left and upper-right coordinates. For the z-cylinder surface, + the negative half-space is unbounded in the z- direction and the + positive half-space is unbounded in all directions. To represent + infinity, numpy.inf is used. + + Parameters + ---------- + side : {'+', '-'} + Indicates the negative or positive half-space + + Returns + ------- + numpy.array + Lower-left coordinates of the axis-aligned bounding box for the + desired half-space + numpy.array + Upper-right coordinates of the axis-aligned bounding box for the + desired half-space + + """ + + if side == '-': + return (np.array([self.x0 - self.r, self.y0 - self.r, -np.inf]), + np.array([self.x0 + self.r, self.y0 + self.r, np.inf])) + elif side == '+': + return (np.array([-np.inf, -np.inf, -np.inf]), + np.array([np.inf, np.inf, np.inf])) + class Sphere(Surface): """A sphere of the form :math:`(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 = R^2`. @@ -656,6 +899,10 @@ class Sphere(Surface): self._type = 'sphere' self._coeff_keys = ['x0', 'y0', 'z0', 'R'] + self._coeffs['x0'] = 0. + self._coeffs['y0'] = 0. + self._coeffs['z0'] = 0. + self._coeffs['R'] = 1. if x0 is not None: self.x0 = x0 @@ -705,6 +952,39 @@ class Sphere(Surface): check_type('R coefficient', R, Real) self._coeffs['R'] = R + def bounding_box(self, side): + """Determine an axis-aligned bounding box. + + An axis-aligned bounding box for surface half-spaces is represented by + its lower-left and upper-right coordinates. The positive half-space of a + sphere is unbounded in all directions. To represent infinity, numpy.inf + is used. + + Parameters + ---------- + side : {'+', '-'} + Indicates the negative or positive half-space + + Returns + ------- + numpy.array + Lower-left coordinates of the axis-aligned bounding box for the + desired half-space + numpy.array + Upper-right coordinates of the axis-aligned bounding box for the + desired half-space + + """ + + if side == '-': + return (np.array([self.x0 - self.r, self.y0 - self.r, + self.z0 - self.r]), + np.array([self.x0 + self.r, self.y0 + self.r, + self.z0 + self.r])) + elif side == '+': + return (np.array([-np.inf, -np.inf, -np.inf]), + np.array([np.inf, np.inf, np.inf])) + class Cone(Surface): """A conical surface parallel to the x-, y-, or z-axis. @@ -750,6 +1030,10 @@ class Cone(Surface): super(Cone, self).__init__(surface_id, boundary_type, name=name) self._coeff_keys = ['x0', 'y0', 'z0', 'R2'] + self._coeffs['x0'] = 0. + self._coeffs['y0'] = 0. + self._coeffs['z0'] = 0. + self._coeffs['R2'] = 1. if x0 is not None: self.x0 = x0 @@ -936,3 +1220,222 @@ class ZCone(Cone): R2, name=name) self._type = 'z-cone' + + +class Quadric(Surface): + """A sphere of the form :math:`Ax^2 + By^2 + Cz^2 + Dxy + Eyz + Fxz + Gx + Hy + + Jz + K`. + + Parameters + ---------- + surface_id : int + Unique identifier for the surface. If not specified, an identifier will + automatically be assigned. + boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic'} + Boundary condition that defines the behavior for particles hitting the + surface. Defaults to transmissive boundary condition where particles + freely pass through the surface. + a, b, c, d, e, f, g, h, j, k : float + coefficients for the surface + name : str + Name of the sphere. If not specified, the name will be the empty string. + + Attributes + ---------- + a, b, c, d, e, f, g, h, j, k : float + coefficients for the surface + + """ + + def __init__(self, surface_id=None, boundary_type='transmission', + a=None, b=None, c=None, d=None, e=None, f=None, g=None, + h=None, j=None, k=None, name=''): + # Initialize Quadric class attributes + super(Quadric, self).__init__(surface_id, boundary_type, name=name) + + self._type = 'quadric' + self._coeff_keys = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k'] + for key in self._coeff_keys: + self._coeffs[key] = 0. + + if a is not None: + self.a = a + if b is not None: + self.b = b + if c is not None: + self.c = c + if d is not None: + self.d = d + if e is not None: + self.e = e + if f is not None: + self.f = f + if g is not None: + self.g = g + if h is not None: + self.h = h + if j is not None: + self.j = j + if k is not None: + self.k = k + + @property + def a(self): + return self.coeffs['a'] + + @property + def b(self): + return self.coeffs['b'] + + @property + def c(self): + return self.coeffs['c'] + + @property + def d(self): + return self.coeffs['d'] + + @property + def e(self): + return self.coeffs['e'] + + @property + def f(self): + return self.coeffs['f'] + + @property + def g(self): + return self.coeffs['g'] + + @property + def h(self): + return self.coeffs['h'] + + @property + def j(self): + return self.coeffs['j'] + + @property + def k(self): + return self.coeffs['k'] + + @a.setter + def a(self, a): + check_type('a coefficient', a, Real) + self._coeffs['a'] = a + + @b.setter + def b(self, b): + check_type('b coefficient', b, Real) + self._coeffs['b'] = b + + @c.setter + def c(self, c): + check_type('c coefficient', c, Real) + self._coeffs['c'] = c + + @d.setter + def d(self, d): + check_type('d coefficient', d, Real) + self._coeffs['d'] = d + + @e.setter + def e(self, e): + check_type('e coefficient', e, Real) + self._coeffs['e'] = e + + @f.setter + def f(self, f): + check_type('f coefficient', f, Real) + self._coeffs['f'] = f + + @g.setter + def g(self, g): + check_type('g coefficient', g, Real) + self._coeffs['g'] = g + + @h.setter + def h(self, h): + check_type('h coefficient', h, Real) + self._coeffs['h'] = h + + @j.setter + def j(self, j): + check_type('j coefficient', j, Real) + self._coeffs['j'] = j + + @k.setter + def k(self, k): + check_type('k coefficient', k, Real) + self._coeffs['k'] = k + + +class Halfspace(Region): + """A positive or negative half-space region. + + A half-space is either of the two parts into which a two-dimension surface + divides the three-dimensional Euclidean space. If the equation of the + surface is :math:`f(x,y,z) = 0`, the region for which :math:`f(x,y,z) < 0` + is referred to as the negative half-space and the region for which + :math:`f(x,y,z) > 0` is referred to as the positive half-space. + + Instances of Halfspace are generally not instantiated directly. Rather, they + can be created from an existing Surface through the __neg__ and __pos__ + operators, as the following example demonstrates: + + >>> sphere = openmc.surface.Sphere(surface_id=1, R=10.0) + >>> inside_sphere = -sphere + >>> outside_sphere = +sphere + >>> type(inside_sphere) + + + Parameters + ---------- + surface : Surface + Surface which divides Euclidean space. + side : {'+', '-'} + Indicates whether the positive or negative half-space is used. + + Attributes + ---------- + surface : Surface + Surface which divides Euclidean space. + side : {'+', '-'} + Indicates whether the positive or negative half-space is used. + bounding_box : tuple of numpy.array + Lower-left and upper-right coordinates of an axis-aligned bounding box + + """ + + def __init__(self, surface, side): + self.surface = surface + self.side = side + + def __invert__(self): + return -self.surface if self.side == '+' else +self.surface + + @property + def surface(self): + return self._surface + + @surface.setter + def surface(self, surface): + check_type('surface', surface, Surface) + self._surface = surface + + @property + def side(self): + return self._side + + @side.setter + def side(self, side): + check_value('side', side, ('+', '-')) + self._side = side + + @property + def bounding_box(self): + return self.surface.bounding_box(self.side) + + def __str__(self): + return '-' + str(self.surface.id) if self.side == '-' \ + else str(self.surface.id) diff --git a/openmc/tallies.py b/openmc/tallies.py index 6e418a2be4..13a219dedd 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1,4 +1,6 @@ -from collections import Iterable +from __future__ import division + +from collections import Iterable, defaultdict import copy import os import pickle @@ -11,8 +13,8 @@ import numpy as np from openmc import Mesh, Filter, Trigger, Nuclide from openmc.cross import CrossScore, CrossNuclide, CrossFilter -from openmc.summary import Summary -from openmc.checkvalue import check_type, check_value, check_greater_than +from openmc.filter import _FILTER_TYPES +import openmc.checkvalue as cv from openmc.clean_xml import * @@ -34,7 +36,7 @@ class Tally(object): Parameters ---------- - tally_id : int, optional + tally_id : Integral, optional Unique identifier for the tally. If none is specified, an identifier will automatically be assigned name : str, optional @@ -42,7 +44,7 @@ class Tally(object): Attributes ---------- - id : int + id : Integral Unique identifier for the tally name : str Name of the tally @@ -52,21 +54,21 @@ class Tally(object): List of nuclides to score results for scores : list of str List of defined scores, e.g. 'flux', 'fission', etc. - estimator : {'analog', 'tracklength'} + estimator : {'analog', 'tracklength', 'collision'} Type of estimator for the tally triggers : list of openmc.trigger.Trigger List of tally triggers - num_score_bins : int + num_score_bins : Integral Total number of scores, accounting for the fact that a single user-specified score, e.g. scatter-P3 or flux-Y2,2, might have multiple bins - num_scores : int + num_scores : Integral Total number of user-specified scores - num_filter_bins : int + num_filter_bins : Integral Total number of filter bins accounting for all filters - num_bins : int + num_bins : Integral Total number of bins for the tally - num_realizations : int + num_realizations : Integral Total number of realizations with_summary : bool Whether or not a Summary has been linked @@ -103,6 +105,9 @@ class Tally(object): self._with_batch_statistics = False self._derived = False + self._sp_filename = None + self._results_read = False + def __deepcopy__(self, memo): existing = memo.get(id(self)) @@ -114,13 +119,15 @@ class Tally(object): clone.estimator = self.estimator clone.num_score_bins = self.num_score_bins clone.num_realizations = self.num_realizations - clone._sum = copy.deepcopy(self.sum, memo) - clone._sum_sq = copy.deepcopy(self.sum_sq, memo) - clone._mean = copy.deepcopy(self.mean, memo) - clone._std_dev = copy.deepcopy(self.std_dev, memo) + clone._sum = copy.deepcopy(self._sum, memo) + clone._sum_sq = copy.deepcopy(self._sum_sq, memo) + clone._mean = copy.deepcopy(self._mean, memo) + clone._std_dev = copy.deepcopy(self._std_dev, memo) clone._with_summary = self.with_summary clone._with_batch_statistics = self.with_batch_statistics clone._derived = self.derived + clone._sp_filename = self._sp_filename + clone._results_read = self._results_read clone._filters = [] for filter in self.filters: @@ -146,52 +153,70 @@ class Tally(object): else: return existing - def __eq__(self, tally2): + def __eq__(self, other): + if not isinstance(other, Tally): + return False + # Check all filters - if len(self.filters) != len(tally2.filters): + if len(self.filters) != len(other.filters): return False for filter in self.filters: - if filter not in tally2.filters: + if filter not in other.filters: return False # Check all nuclides - if len(self.nuclides) != len(tally2.nuclides): + if len(self.nuclides) != len(other.nuclides): return False for nuclide in self.nuclides: - if nuclide not in tally2.nuclides: + if nuclide not in other.nuclides: return False # Check all scores - if len(self.scores) != len(tally2.scores): + if len(self.scores) != len(other.scores): return False for score in self.scores: - if score not in tally2.scores: + if score not in other.scores: return False - if self.estimator != tally2.estimator: + if self.estimator != other.estimator: return False return True + def __ne__(self, other): + return not self == other + def __hash__(self): - hashable = [] + return hash(repr(self)) + + def __repr__(self): + string = 'Tally\n' + string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self.id) + string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self.name) + + string += '{0: <16}{1}\n'.format('\tFilters', '=\t') for filter in self.filters: - hashable.append((filter.type, tuple(filter.bins))) + string += '{0: <16}\t\t{1}\t{2}\n'.format('', filter.type, + filter.bins) + + string += '{0: <16}{1}'.format('\tNuclides', '=\t') for nuclide in self.nuclides: - hashable.append(nuclide.name) + if isinstance(nuclide, Nuclide): + string += '{0} '.format(nuclide.name) + else: + string += '{0} '.format(nuclide) - for score in self.scores: - hashable.append(score) + string += '\n' - hashable.append(self.estimator) - hashable.append(self.name) + string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self.scores) + string += '{0: <16}{1}{2}\n'.format('\tEstimator', '=\t', self.estimator) - return hash(tuple(hashable)) + return string @property def id(self): @@ -229,7 +254,7 @@ class Tally(object): def num_filter_bins(self): num_bins = 1 - for filter in self._filters: + for filter in self.filters: num_bins *= filter.num_bins return num_bins @@ -259,24 +284,77 @@ class Tally(object): @property def sum(self): + if not self._sp_filename: + return None + + if not self._results_read: + import h5py + + # Open the HDF5 statepoint file + f = h5py.File(self._sp_filename, 'r') + + # Extract Tally data from the file + data = f['tallies/tally {0}/results'.format( + self.id)].value + sum = data['sum'] + sum_sq = data['sum_sq'] + + # Define a routine to convert 0 to 1 + def nonzero(val): + return 1 if not val else val + + # Reshape the results arrays + new_shape = (nonzero(self.num_filter_bins), + nonzero(self.num_nuclides), + nonzero(self.num_score_bins)) + + sum = np.reshape(sum, new_shape) + sum_sq = np.reshape(sum_sq, new_shape) + + # Set the data for this Tally + self._sum = sum + self._sum_sq = sum_sq + + # Indicate that Tally results have been read + self._results_read = True + + # Close the HDF5 statepoint file + f.close() + return self._sum @property def sum_sq(self): + if not self._sp_filename: + return None + + if not self._results_read: + # Force reading of sum and sum_sq + self.sum + return self._sum_sq @property def mean(self): - # Compute the mean if needed if self._mean is None: - self.compute_mean() + if not self._sp_filename: + return None + + self._mean = self.sum / self.num_realizations return self._mean @property def std_dev(self): - # Compute the standard deviation if needed if self._std_dev is None: - self.compute_std_dev() + if not self._sp_filename: + return None + + n = self.num_realizations + nonzero = np.abs(self.mean) > 0 + self._std_dev = np.zeros_like(self.mean) + self._std_dev[nonzero] = np.sqrt((self.sum_sq[nonzero]/n - + self.mean[nonzero]**2)/(n - 1)) + self.with_batch_statistics = True return self._std_dev @property @@ -289,7 +367,8 @@ class Tally(object): @estimator.setter def estimator(self, estimator): - check_value('estimator', estimator, ['analog', 'tracklength']) + cv.check_value('estimator', estimator, + ['analog', 'tracklength', 'collision']) self._estimator = estimator def add_trigger(self, trigger): @@ -307,7 +386,8 @@ class Tally(object): 'since "{1}" is not a Trigger'.format(self.id, trigger) raise ValueError(msg) - self._triggers.append(trigger) + if trigger not in self.triggers: + self.triggers.append(trigger) @id.setter def id(self, tally_id): @@ -316,14 +396,17 @@ class Tally(object): self._id = AUTO_TALLY_ID AUTO_TALLY_ID += 1 else: - check_type('tally ID', tally_id, Integral) - check_greater_than('tally ID', tally_id, 0) + cv.check_type('tally ID', tally_id, Integral) + cv.check_greater_than('tally ID', tally_id, 0, equality=True) self._id = tally_id @name.setter def name(self, name): - check_type('tally name', name, basestring) - self._name = name + if name is not None: + cv.check_type('tally name', name, basestring) + self._name = name + else: + self._name = '' def add_filter(self, filter): """Add a filter to the tally @@ -372,6 +455,10 @@ class Tally(object): # If the score is already in the Tally, don't add it again if score in self.scores: return + # Normal score strings + if isinstance(score, basestring): + self._scores.append(score.strip()) + # CrossScores else: self._scores.append(score) @@ -381,28 +468,28 @@ class Tally(object): @num_realizations.setter def num_realizations(self, num_realizations): - check_type('number of realizations', num_realizations, Integral) - check_greater_than('number of realizations', num_realizations, 0, True) + cv.check_type('number of realizations', num_realizations, Integral) + cv.check_greater_than('number of realizations', num_realizations, 0, True) self._num_realizations = num_realizations @with_summary.setter def with_summary(self, with_summary): - check_type('with_summary', with_summary, bool) + cv.check_type('with_summary', with_summary, bool) self._with_summary = with_summary @with_batch_statistics.setter def with_batch_statistics(self, with_batch_statistics): - check_type('with_batch_statistics', with_batch_statistics, bool) + cv.check_type('with_batch_statistics', with_batch_statistics, bool) self._with_batch_statistics = with_batch_statistics @sum.setter def sum(self, sum): - check_type('sum', sum, Iterable) + cv.check_type('sum', sum, Iterable) self._sum = sum @sum_sq.setter def sum_sq(self, sum_sq): - check_type('sum_sq', sum_sq, Iterable) + cv.check_type('sum_sq', sum_sq, Iterable) self._sum_sq = sum_sq def remove_score(self, score): @@ -456,56 +543,6 @@ class Tally(object): self._nuclides.remove(nuclide) - def compute_mean(self): - """Compute the sample mean for each bin in the tally""" - - # Calculate sample mean - self._mean = self.sum / self.num_realizations - - def compute_std_dev(self, t_value=1.0): - """Compute the sample standard deviation for each bin in the tally - - Parameters - ---------- - t_value : float, optional - Student's t-value applied to the uncertainty. Defaults to 1.0, - meaning the reported value is the sample standard deviation. - - """ - - # Calculate sample standard deviation - self.compute_mean() - self._std_dev = np.sqrt((self.sum_sq / self.num_realizations - - self.mean**2) / (self.num_realizations - 1)) - self._std_dev *= t_value - self.with_batch_statistics = True - - def __repr__(self): - string = 'Tally\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self.id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self.name) - - string += '{0: <16}{1}\n'.format('\tFilters', '=\t') - - for filter in self.filters: - string += '{0: <16}\t\t{1}\t{2}\n'.format('', filter.type, - filter.bins) - - string += '{0: <16}{1}'.format('\tNuclides', '=\t') - - for nuclide in self.nuclides: - if isinstance(nuclide, Nuclide): - string += '{0} '.format(nuclide.name) - else: - string += '{0} '.format(nuclide) - - string += '\n' - - string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self.scores) - string += '{0: <16}{1}{2}\n'.format('\tEstimator', '=\t', self.estimator) - - return string - def can_merge(self, tally): """Determine if another tally can be merged with this one @@ -535,6 +572,21 @@ class Tally(object): if len(self.filters) != len(tally.filters): return False + # Check if only one tally contains a delayed group filter + tally1_dg = False + for filter1 in self.filters: + if filter1.type == 'delayedgroup': + tally1_dg = True + + tally2_dg = False + for filter2 in tally.filters: + if filter2.type == 'delayedgroup': + tally2_dg = True + + # Return False if only one tally has a delayed group filter + if (tally1_dg or tally2_dg) and not (tally1_dg and tally2_dg): + return False + # Look to see if all filters are the same, or one or more can be merged for filter1 in self.filters: mergeable_filter = False @@ -706,8 +758,7 @@ class Tally(object): ---------- filter_type : str The type of Filter (e.g., 'cell', 'energy', etc.) - - filter_bin : int, list + filter_bin : Integral or tuple The bin is an integer ID for 'material', 'surface', 'cell', 'cellborn', and 'universe' Filters. The bin is an integer for the cell instance ID for 'distribcell' Filters. The bin is a 2-tuple of @@ -805,40 +856,199 @@ class Tally(object): return score_index - def get_values(self, scores=[], filters=[], filter_bins=[], - nuclides=[], value='mean'): - """Returns a tally score value given a list of filters to satisfy. + def get_filter_indices(self, filters=[], filter_bins=[]): + """Get indices into the filter axis of this tally's data arrays. - This method constructs a 3D NumPy array for the requested Tally data - indexed by filter bin, nuclide bin, and score index. The method will - order the data in the array as specified in the parameter lists + This is a helper method for the Tally.get_values(...) method to + extract tally data. This method returns the indices into the filter + axis of the tally's data array (axis=0) for particular combinations + of filters and their corresponding bins. Parameters ---------- - scores : list - A list of one or more score strings - (e.g., ['absorption', 'nu-fission']; default is []) - - filters : list + filters : list of str A list of filter type strings (e.g., ['mesh', 'energy']; default is []) - - filter_bins : list + filter_bins : list of Iterables A list of the filter bins corresponding to the filter_types - parameter (e.g., [1, (0., 0.625e-6)]; default is []). Each bin in - the list is the integer ID for 'material', 'surface', 'cell', + parameter (e.g., [(1,), (0., 0.625e-6)]; default is []). Each bin + in the list is the integer ID for 'material', 'surface', 'cell', 'cellborn', and 'universe' Filters. Each bin is an integer for the - cell instance ID for 'distribcell Filters. Each bin is a 2-tuple of + cell instance ID for 'distribcell' Filters. Each bin is a 2-tuple of floats for 'energy' and 'energyout' filters corresponding to the energy boundaries of the bin of interest. The bin is a (x,y,z) 3-tuple for 'mesh' filters corresponding to the mesh cell of - interest. The order of the bins in the list must correspond of the + interest. The order of the bins in the list must correspond to the filter_types parameter. - nuclides : list + Returns + ------- + ndarray + A NumPy array of the filter indices + + """ + + cv.check_iterable_type('filters', filters, basestring) + cv.check_iterable_type('filter_bins', filter_bins, tuple) + + # Determine the score indices from any of the requested scores + if filters: + # Initialize empty list of indices for each bin in each Filter + filter_indices = [] + + # Loop over all of the Tally's Filters + for i, filter in enumerate(self.filters): + user_filter = False + + # If a user-requested Filter, get the user-requested bins + for j, test_filter in enumerate(filters): + if filter.type == test_filter: + bins = filter_bins[j] + user_filter = True + break + + # If not a user-requested Filter, get all bins + if not user_filter: + # Create list of 2- or 3-tuples tuples for mesh cell bins + if filter.type == 'mesh': + dimension = filter.mesh.dimension + xyz = map(lambda x: np.arange(1, x+1), dimension) + bins = list(itertools.product(*xyz)) + + # Create list of 2-tuples for energy boundary bins + elif filter.type in ['energy', 'energyout']: + bins = [] + for k in range(filter.num_bins): + bins.append((filter.bins[k], filter.bins[k+1])) + + # Create list of cell instance IDs for distribcell Filters + elif filter.type == 'distribcell': + bins = np.arange(filter.num_bins) + + # Create list of IDs for bins for all other filter types + else: + bins = filter.bins + + # Initialize a NumPy array for the Filter bin indices + filter_indices.append(np.zeros(len(bins), dtype=np.int)) + + # Add indices for each bin in this Filter to the list + for j, bin in enumerate(bins): + filter_index = self.get_filter_index(filter.type, bin) + filter_indices[i][j] = filter_index + + # Account for stride in each of the previous filters + for indices in filter_indices[:i]: + indices *= filter.num_bins + + # Apply outer product sum between all filter bin indices + filter_indices = list(map(sum, itertools.product(*filter_indices))) + + # If user did not specify any specific Filters, use them all + else: + filter_indices = np.arange(self.num_filter_bins) + + return filter_indices + + def get_nuclide_indices(self, nuclides): + """Get indices into the nuclide axis of this tally's data arrays. + + This is a helper method for the Tally.get_values(...) method to + extract tally data. This method returns the indices into the nuclide + axis of the tally's data array (axis=1) for one or more nuclides. + + Parameters + ---------- + nuclides : list of str A list of nuclide name strings (e.g., ['U-235', 'U-238']; default is []) + Returns + ------- + ndarray + A NumPy array of the nuclide indices + + """ + + cv.check_iterable_type('nuclides', nuclides, basestring) + + # Determine the score indices from any of the requested scores + if nuclides: + nuclide_indices = np.zeros(len(nuclides), dtype=np.int) + for i, nuclide in enumerate(nuclides): + nuclide_indices[i] = self.get_nuclide_index(nuclide) + + # If user did not specify any specific Nuclides, use them all + else: + nuclide_indices = np.arange(self.num_nuclides) + + return nuclide_indices + + def get_score_indices(self, scores): + """Get indices into the score axis of this tally's data arrays. + + This is a helper method for the Tally.get_values(...) method to + extract tally data. This method returns the indices into the score + axis of the tally's data array (axis=2) for one or more scores. + + Parameters + ---------- + scores : list of str + A list of one or more score strings + (e.g., ['absorption', 'nu-fission']; default is []) + + Returns + ------- + ndarray + A NumPy array of the score indices + + """ + + cv.check_iterable_type('scores', scores, basestring) + + # Determine the score indices from any of the requested scores + if scores: + score_indices = np.zeros(len(scores), dtype=np.int) + for i, score in enumerate(scores): + score_indices[i] = self.get_score_index(score) + + # If user did not specify any specific scores, use them all + else: + score_indices = np.arange(self.num_scores) + + return score_indices + + def get_values(self, scores=[], filters=[], filter_bins=[], + nuclides=[], value='mean'): + """Returns one or more tallied values given a list of scores, filters, + filter bins and nuclides. + + This method constructs a 3D NumPy array for the requested Tally data + indexed by filter bin, nuclide bin, and score index. The method will + order the data in the array as specified in the parameter lists. + + Parameters + ---------- + scores : list of str + A list of one or more score strings + (e.g., ['absorption', 'nu-fission']; default is []) + filters : list of str + A list of filter type strings + (e.g., ['mesh', 'energy']; default is []) + filter_bins : list of Iterables + A list of the filter bins corresponding to the filter_types + parameter (e.g., [(1,), (0., 0.625e-6)]; default is []). Each bin + in the list is the integer ID for 'material', 'surface', 'cell', + 'cellborn', and 'universe' Filters. Each bin is an integer for the + cell instance ID for 'distribcell' Filters. Each bin is a 2-tuple of + floats for 'energy' and 'energyout' filters corresponding to the + energy boundaries of the bin of interest. The bin is a (x,y,z) + 3-tuple for 'mesh' filters corresponding to the mesh cell of + interest. The order of the bins in the list must correspond to the + filter_types parameter. + nuclides : list of str + A list of nuclide name strings + (e.g., ['U-235', 'U-238']; default is []) value : str A string for the type of value to return - 'mean' (default), 'std_dev', 'rel_err', 'sum', or 'sum_sq' are accepted @@ -870,81 +1080,10 @@ class Tally(object): 'Tally.get_values(...)'.format(self.id) raise ValueError(msg) - ############################ FILTERS ######################### - # Determine the score indices from any of the requested scores - if filters: - # Initialize empty list of indices for each bin in each Filter - filter_indices = [] - - # Loop over all of the Tally's Filters - for i, filter in enumerate(self.filters): - user_filter = False - - # If a user-requested Filter, get the user-requested bins - for j, test_filter in enumerate(filters): - if filter.type == test_filter: - bins = filter_bins[j] - user_filter = True - break - - # If not a user-requested Filter, get all bins - if not user_filter: - # Create list of 2- or 3-tuples tuples for mesh cell bins - if filter.type == 'mesh': - dimension = filter.mesh.dimension - xyz = map(lambda x: np.arange(1, x+1), dimension) - bins = list(itertools.product(*xyz)) - - # Create list of 2-tuples for energy boundary bins - elif filter.type in ['energy', 'energyout']: - bins = [] - for k in range(filter.num_bins): - bins.append((filter.bins[k], filter.bins[k+1])) - - # Create list of IDs for bins for all other Filter types - else: - bins = filter.bins - - # Initialize a NumPy array for the Filter bin indices - filter_indices.append(np.zeros(len(bins), dtype=np.int)) - - # Add indices for each bin in this Filter to the list - for j, bin in enumerate(bins): - filter_index = self.get_filter_index(filter.type, bin) - filter_indices[i][j] = filter_index - - # Account for stride in each of the previous filters - for indices in filter_indices[:i]: - indices *= filter.num_bins - - # Apply outer product sum between all filter bin indices - filter_indices = list(map(sum, itertools.product(*filter_indices))) - - # If user did not specify any specific Filters, use them all - else: - filter_indices = np.arange(self.num_filter_bins) - - ############################ NUCLIDES ######################## - # Determine the score indices from any of the requested scores - if nuclides: - nuclide_indices = np.zeros(len(nuclides), dtype=np.int) - for i, nuclide in enumerate(nuclides): - nuclide_indices[i] = self.get_nuclide_index(nuclide) - - # If user did not specify any specific Nuclides, use them all - else: - nuclide_indices = np.arange(self.num_nuclides) - - ############################# SCORES ######################### - # Determine the score indices from any of the requested scores - if scores: - score_indices = np.zeros(len(scores), dtype=np.int) - for i, score in enumerate(scores): - score_indices[i] = self.get_score_index(score) - - # If user did not specify any specific scores, use them all - else: - score_indices = np.arange(self.num_scores) + # Get filter, nuclide and score indices + filter_indices = self.get_filter_indices(filters, filter_bins) + nuclide_indices = self.get_nuclide_indices(nuclides) + score_indices = self.get_score_indices(scores) # Construct outer product of all three index types with each other indices = np.ix_(filter_indices, nuclide_indices, score_indices) @@ -963,7 +1102,7 @@ class Tally(object): else: msg = 'Unable to return results from Tally ID="{0}" since the ' \ 'the requested value "{1}" is not \'mean\', \'std_dev\', ' \ - '\rel_err\', \'sum\', or \'sum_sq\''.format(self.id, value) + '\'rel_err\', \'sum\', or \'sum_sq\''.format(self.id, value) raise LookupError(msg) return data @@ -974,21 +1113,19 @@ class Tally(object): This method constructs a Pandas DataFrame object for the Tally data with columns annotated by filter, nuclide and score bin information. - This capability has been tested for Pandas >=v0.13.1. However, if - possible, it is recommended to use the v0.16 or newer versions of - Pandas since this this method uses the Multi-index Pandas feature. + + This capability has been tested for Pandas >=0.13.1. However, it is + recommended to use v0.16 or newer versions of Pandas since this method + uses the Multi-index Pandas feature. Parameters ---------- filters : bool Include columns with filter bin information (default is True). - nuclides : bool Include columns with nuclide bin information (default is True). - scores : bool Include columns with score bin information (default is True). - summary : None or Summary An optional Summary object to be used to construct columns for distribcell tally filters (default is None). The geometric @@ -1008,6 +1145,8 @@ class Tally(object): KeyError When this method is called before the Tally is populated with data by the StatePoint.read_results() method. + ImportError + When Pandas can not be found on the caller's system """ @@ -1026,11 +1165,11 @@ class Tally(object): 'Summary info'.format(self.id) raise KeyError(msg) - # Attempt to import the pandas package + # Attempt to import Pandas try: import pandas as pd except ImportError: - msg = 'The pandas Python package must be installed on your system' + msg = 'The Pandas Python package must be installed on your system' raise ImportError(msg) # Initialize a pandas dataframe for the tally data @@ -1039,224 +1178,13 @@ class Tally(object): # Find the total length of the tally data array data_size = self.mean.size - # Split CrossFilters into separate filters - split_filters = [] - for filter in self.filters: - if isinstance(filter, CrossFilter): - split_filters.extend(filter.split_filters()) - else: - split_filters.append(filter) - # Build DataFrame columns for filters if user requested them if filters: - for filter in split_filters: - - # mesh filters - if filter.type == 'mesh': - - # Initialize dictionary to build Pandas Multi-index column - filter_dict = {} - - # Append Mesh ID as outermost index of mult-index - mesh_id = filter.mesh.id - mesh_key = 'mesh {0}'.format(mesh_id) - - # Find mesh dimensions - use 3D indices for simplicity - if (len(filter.mesh.dimension) == 3): - nx, ny, nz = filter.mesh.dimension - else: - nx, ny = filter.mesh.dimension - nz = 1 - - # Generate multi-index sub-column for x-axis - filter_bins = np.arange(1, nx+1) - repeat_factor = ny * nz * filter.stride - filter_bins = np.repeat(filter_bins, repeat_factor) - tile_factor = data_size / len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'x')] = filter_bins - - # Generate multi-index sub-column for y-axis - filter_bins = np.arange(1, ny+1) - repeat_factor = nz * filter.stride - filter_bins = np.repeat(filter_bins, repeat_factor) - tile_factor = data_size / len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'y')] = filter_bins - - # Generate multi-index sub-column for z-axis - filter_bins = np.arange(1, nz+1) - repeat_factor = filter.stride - filter_bins = np.repeat(filter_bins, repeat_factor) - tile_factor = data_size / len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'z')] = filter_bins - - # Append the multi-index column to the DataFrame - df = pd.concat([df, pd.DataFrame(filter_dict)], axis=1) - - # distribcell filters - elif filter.type == 'distribcell': - if isinstance(summary, Summary): - # Attempt to import the OpenCG package - try: - import opencg - except ImportError: - msg = 'The OpenCG package must be installed ' \ - 'to use a Summary for distribcell dataframes' - raise ImportError(msg) - - # Create and extract the OpenCG geometry the Summary - summary.make_opencg_geometry() - opencg_geometry = summary.opencg_geometry - openmc_geometry = summary.openmc_geometry - - # Use OpenCG to compute the number of regions - opencg_geometry.initializeCellOffsets() - num_regions = opencg_geometry._num_regions - - # Initialize a dictionary mapping OpenMC distribcell - # offsets to OpenCG LocalCoords linked lists - offsets_to_coords = {} - - # Use OpenCG to compute LocalCoords linked list for - # each region and store in dictionary - for region in range(num_regions): - coords = opencg_geometry.findRegion(region) - path = opencg.get_path(coords) - cell_id = path[-1] - - # If this region is in Cell corresponding to the - # distribcell filter bin, store it in dictionary - if cell_id == filter.bins[0]: - offset = openmc_geometry.get_offset(path, - filter.offset) - offsets_to_coords[offset] = coords - - # Each distribcell offset is a DataFrame bin - # Unravel the paths into DataFrame columns - num_offsets = len(offsets_to_coords) - - # Initialize termination condition for while loop - levels_remain = True - counter = 0 - - # Iterate over each level in the CSG tree hierarchy - while levels_remain: - levels_remain = False - - # Initialize dictionary to build Pandas Multi-index - # column for this level in the CSG tree hierarchy - level_dict = {} - - # Initialize prefix Multi-index keys - counter += 1 - level_key = 'level {0}'.format(counter) - univ_key = (level_key, 'univ', 'id') - cell_key = (level_key, 'cell', 'id') - lat_id_key = (level_key, 'lat', 'id') - lat_x_key = (level_key, 'lat', 'x') - lat_y_key = (level_key, 'lat', 'y') - lat_z_key = (level_key, 'lat', 'z') - - # Allocate NumPy arrays for each CSG level and - # each Multi-index column in the DataFrame - level_dict[univ_key] = np.empty(num_offsets) - level_dict[cell_key] = np.empty(num_offsets) - level_dict[lat_id_key] = np.empty(num_offsets) - level_dict[lat_x_key] = np.empty(num_offsets) - level_dict[lat_y_key] = np.empty(num_offsets) - level_dict[lat_z_key] = np.empty(num_offsets) - - # Initialize Multi-index columns to NaN - this is - # necessary since some distribcell instances may - # have very different LocalCoords linked lists - level_dict[univ_key][:] = np.nan - level_dict[cell_key][:] = np.nan - level_dict[lat_id_key][:] = np.nan - level_dict[lat_x_key][:] = np.nan - level_dict[lat_y_key][:] = np.nan - level_dict[lat_z_key][:] = np.nan - - # Iterate over all regions (distribcell instances) - for offset in range(num_offsets): - coords = offsets_to_coords[offset] - - # If entire LocalCoords has been unraveled into - # Multi-index columns already, continue - if coords is None: - continue - - # Assign entry to Universe Multi-index column - if coords._type == 'universe': - univ_id = coords._universe._id - cell_id = coords._cell._id - level_dict[univ_key][offset] = univ_id - level_dict[cell_key][offset] = cell_id - - # Assign entry to Lattice Multi-index column - else: - lat_id = coords._lattice._id - lat_x = coords._lat_x - lat_y = coords._lat_y - lat_z = coords._lat_z - level_dict[lat_id_key][offset] = lat_id - level_dict[lat_x_key][offset] = lat_x - level_dict[lat_y_key][offset] = lat_y - level_dict[lat_z_key][offset] = lat_z - - # Move to next node in LocalCoords linked list - if coords._next is None: - offsets_to_coords[offset] = None - else: - offsets_to_coords[offset] = coords._next - levels_remain = True - - # Tile the Multi-index columns - for level_key, level_bins in level_dict.items(): - level_bins = \ - np.repeat(level_bins, filter.stride) - tile_factor = data_size / len(level_bins) - level_bins = np.tile(level_bins, tile_factor) - level_dict[level_key] = level_bins - - # Append the multi-index column to the DataFrame - df = pd.concat([df, pd.DataFrame(level_dict)], - axis=1) - - # Create DataFrame column for distribcell instances IDs - # NOTE: This is performed regardless of whether the user - # requests Summary geomeric information - filter_bins = np.arange(filter.num_bins) - filter_bins = np.repeat(filter_bins, filter.stride) - tile_factor = data_size / len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - df[filter.type] = filter_bins - - # energy, energyout filters - elif 'energy' in filter.type: - bins = filter.bins - num_bins = filter.num_bins - - # Create strings for - template = '{0:.1e} - {1:.1e}' - filter_bins = [] - for i in range(num_bins): - filter_bins.append(template.format(bins[i], bins[i+1])) - - # Tile the energy bins into a DataFrame column - filter_bins = np.repeat(filter_bins, filter.stride) - tile_factor = data_size / len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - df[filter.type + ' [MeV]'] = filter_bins - - # universe, material, surface, cell, and cellborn filters - else: - filter_bins = np.repeat(filter.bins, filter.stride) - tile_factor = data_size / len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - df[filter.type] = filter_bins + # Append each Filter's DataFrame to the overall DataFrame + for filter in self.filters: + filter_df = filter.get_pandas_dataframe(data_size, summary) + df = pd.concat([df, filter_df], axis=1) # Include DataFrame column for nuclides if user requested it if nuclides: @@ -1283,10 +1211,76 @@ class Tally(object): df['mean'] = self.mean.ravel() df['std. dev.'] = self.std_dev.ravel() - df.index.name = 'bin' df = df.dropna(axis=1) + + # Expand the columns into Pandas MultiIndices for readability + if pd.__version__ >= '0.16': + columns = copy.deepcopy(df.columns.values) + + # Convert all elements in columns list to tuples + for i, column in enumerate(columns): + if not isinstance(column, tuple): + columns[i] = (column,) + + # Make each tuple the same length + max_len_column = len(max(columns, key=len)) + for i, column in enumerate(columns): + delta_len = max_len_column - len(column) + if delta_len > 0: + new_column = list(column) + new_column.extend(['']*delta_len) + columns[i] = tuple(new_column) + + # Create and set a MultiIndex for the DataFrame's columns + df.columns = pd.MultiIndex.from_tuples(columns) + return df + def get_reshaped_data(self, value='mean'): + """Returns an array of tally data with one dimension per filter. + + The tally data in OpenMC is stored as a 3D array with the dimensions + corresponding to filters, nuclides and scores. As a result, tally data + can be opaque for a user to directly index (i.e., without use of the + Tally.get_values(...) method) since one must know how to properly use + the number of bins and strides for each filter to index into the first + (filter) dimension. + + This builds and returns a reshaped version of the tally data array with + unique dimensions corresponding to each tally filter. For example, + suppose this tally has arrays of data with shape (8,5,5) corresponding + to two filters (2 and 4 bins, respectively), five nuclides and five + scores. This method will return a version of the data array with the + with a new shape of (2,4,5,5) such that the first two dimensions + correspond directly to the two filters with two and four bins. + + Parameters + ---------- + value : str + A string for the type of value to return - 'mean' (default), + 'std_dev', 'rel_err', 'sum', or 'sum_sq' are accepted + + Returns + ------- + ndarray + The tally data array indexed by filters, nuclides and scores. + + """ + + # Get the 3D array of data in filters, nuclides and scores + data = self.get_values(value=value) + + # Build a new array shape with one dimension per filter + new_shape = () + for filter in self.filters: + new_shape += (filter.num_bins, ) + new_shape += (self.num_nuclides,) + new_shape += (self.num_score_bins,) + + # Reshape the data with one dimension for each filter + data = np.reshape(data, new_shape) + return data + def export_results(self, filename='tally-results', directory='.', format='hdf5', append=True): """Exports tallly results to an HDF5 or Python pickle binary file. @@ -1295,14 +1289,11 @@ class Tally(object): ---------- filename : str The name of the file for the results (default is 'tally-results') - directory : str The name of the directory for the results (default is '.') - format : str The format for the exported file - HDF5 ('hdf5', default) and Python pickle ('pkl') files are supported - append : bool Whether or not to append the results to the file (default is True) @@ -1315,9 +1306,9 @@ class Tally(object): """ # Ensure that StatePoint.read_results() was called first - if self._sum is None or self._sum_sq is None: + if self._sum is None or self._sum_sq is None and not self.derived: msg = 'The Tally ID="{0}" has no data to export. Call the ' \ - 'StatePoint.read_results() routine before using ' \ + 'StatePoint.read_results() method before using ' \ 'Tally.export_results(...)'.format(self.id) raise KeyError(msg) @@ -1452,7 +1443,7 @@ class Tally(object): Returns ------- Tally - A new Tally outer that is the outer product with this one. + A new Tally that is the outer product with this one. Raises ------ @@ -1468,38 +1459,62 @@ class Tally(object): 'since it does not contain any results.'.format(other.id) raise ValueError(msg) - new_name = '({0} {1} {2})'.format(self.name, binary_op, other.name) - new_tally = Tally(name=new_name) + new_tally = Tally() new_tally.with_batch_statistics = True new_tally._derived = True - data = self._align_tally_data(other) + # Construct a combined derived name from the two tally operands + if self.name != '' and other.name != '': + new_name = '({0} {1} {2})'.format(self.name, binary_op, other.name) + new_tally.name = new_name + + # Create copies of self and other tallies to rearrange for tally + # arithmetic + self_copy = copy.deepcopy(self) + other_copy = copy.deepcopy(other) + + # Find any shared filters between the two tallies + filter_intersect = [] + for filter in self_copy.filters: + if filter in other_copy.filters: + filter_intersect.append(filter) + + # Align the shared filters in successive order + for i, filter in enumerate(filter_intersect): + self_index = self_copy.filters.index(filter) + other_index = other_copy.filters.index(filter) + + # If necessary, swap self filter + if self_index != i: + self_copy.swap_filters(filter, self_copy.filters[i], inplace=True) + + # If necessary, swap other filter + if other_index != i: + other_copy.swap_filters(filter, other_copy.filters[i], inplace=True) + + data = self_copy._align_tally_data(other_copy) if binary_op == '+': new_tally._mean = data['self']['mean'] + data['other']['mean'] new_tally._std_dev = np.sqrt(data['self']['std. dev.']**2 + data['other']['std. dev.']**2) elif binary_op == '-': - data = self._align_tally_data(other) new_tally._mean = data['self']['mean'] - data['other']['mean'] new_tally._std_dev = np.sqrt(data['self']['std. dev.']**2 + data['other']['std. dev.']**2) elif binary_op == '*': - data = self._align_tally_data(other) self_rel_err = data['self']['std. dev.'] / data['self']['mean'] other_rel_err = data['other']['std. dev.'] / data['other']['mean'] new_tally._mean = data['self']['mean'] * data['other']['mean'] new_tally._std_dev = np.abs(new_tally.mean) * \ np.sqrt(self_rel_err**2 + other_rel_err**2) elif binary_op == '/': - data = self._align_tally_data(other) self_rel_err = data['self']['std. dev.'] / data['self']['mean'] other_rel_err = data['other']['std. dev.'] / data['other']['mean'] new_tally._mean = data['self']['mean'] / data['other']['mean'] new_tally._std_dev = np.abs(new_tally.mean) * \ np.sqrt(self_rel_err**2 + other_rel_err**2) elif binary_op == '^': - data = self._align_tally_data(other) mean_ratio = data['other']['mean'] / data['self']['mean'] first_term = mean_ratio * data['self']['std. dev.'] second_term = \ @@ -1508,44 +1523,76 @@ class Tally(object): new_tally._std_dev = np.abs(new_tally.mean) * \ np.sqrt(first_term**2 + second_term**2) - if self.estimator == other.estimator: - new_tally.estimator = self.estimator - if self.with_summary and other.with_summary: - new_tally.with_summary = self.with_summary - if self.num_realizations == other.num_realizations: - new_tally.num_realizations = self.num_realizations - new_tally.num_score_bins = self.num_score_bins * other.num_score_bins + if self_copy.estimator == other_copy.estimator: + new_tally.estimator = self_copy.estimator + if self_copy.with_summary and other_copy.with_summary: + new_tally.with_summary = self_copy.with_summary + if self_copy.num_realizations == other_copy.num_realizations: + new_tally.num_realizations = self_copy.num_realizations - # Generate filter "outer products" - if self.filters == other.filters: - for self_filter in self.filters: + # If filters are identical, simply reuse them in derived tally + if self_copy.filters == other_copy.filters: + for self_filter in self_copy.filters: new_tally.add_filter(self_filter) + + # Generate filter "outer products" for non-identical filters else: - all_filters = [self.filters, other.filters] - for self_filter, other_filter in itertools.product(*all_filters): - new_filter = CrossFilter(self_filter, other_filter, binary_op) - new_tally.add_filter(new_filter) + + # Find the common longest sequence of shared filters + match = 0 + for self_filter, other_filter in zip(self_copy.filters, other_copy.filters): + if self_filter == other_filter: + match += 1 + else: + break + + match_filters = self_copy.filters[:match] + cross_filters = [self_copy.filters[match:], other_copy.filters[match:]] + + # Simply reuse shared filters in derived tally + for filter in match_filters: + new_tally.add_filter(filter) + + # Use cross filters to combine non-shared filters in derived tally + if len(self_copy.filters) != match and len(other_copy.filters) == match: + for filter in cross_filters[0]: + new_tally.add_filter(filter) + elif len(self_copy.filters) == match and len(other_copy.filters) != match: + for filter in cross_filters[1]: + new_tally.add_filter(filter) + else: + for self_filter, other_filter in itertools.product(*cross_filters): + new_filter = CrossFilter(self_filter, other_filter, binary_op) + new_tally.add_filter(new_filter) # Generate score "outer products" - if self.scores == other.scores: - for self_score in self.scores: + if self_copy.scores == other_copy.scores: + new_tally.num_score_bins = self_copy.num_score_bins + for self_score in self_copy.scores: new_tally.add_score(self_score) else: - all_scores = [self.scores, other.scores] + new_tally.num_score_bins = self_copy.num_score_bins * other_copy.num_score_bins + all_scores = [self_copy.scores, other_copy.scores] for self_score, other_score in itertools.product(*all_scores): new_score = CrossScore(self_score, other_score, binary_op) new_tally.add_score(new_score) # Generate nuclide "outer products" - if self.nuclides == other.nuclides: - for self_nuclide in self.nuclides: + if self_copy.nuclides == other_copy.nuclides: + for self_nuclide in self_copy.nuclides: new_tally.nuclides.append(self_nuclide) else: - all_nuclides = [self.nuclides, other.nuclides] + all_nuclides = [self_copy.nuclides, other_copy.nuclides] for self_nuclide, other_nuclide in itertools.product(*all_nuclides): new_nuclide = CrossNuclide(self_nuclide, other_nuclide, binary_op) new_tally.add_nuclide(new_nuclide) + # Correct each Filter's stride + stride = new_tally.num_nuclides * new_tally.num_score_bins + for filter in reversed(new_tally.filters): + filter.stride = stride + stride *= filter.num_bins + return new_tally def _align_tally_data(self, other): @@ -1571,7 +1618,6 @@ class Tally(object): A dictionary of dictionaries to "aligned" 'mean' and 'std. dev' NumPy arrays for each tally's data. - """ self_mean = copy.deepcopy(self.mean) @@ -1583,14 +1629,40 @@ class Tally(object): # Determine the number of paired combinations of filter bins # between the two tallies and repeat arrays along filter axes - self_repeat_factor = other.num_filter_bins - other_tile_factor = self.num_filter_bins + diff1 = list(set(self.filters).difference(set(other.filters))) + diff2 = list(set(other.filters).difference(set(self.filters))) - # Replicate the data - self_mean = np.repeat(self_mean, self_repeat_factor, axis=0) - other_mean = np.tile(other_mean, (other_tile_factor, 1, 1)) - self_std_dev = np.repeat(self_std_dev, self_repeat_factor, axis=0) - other_std_dev = np.tile(other_std_dev, (other_tile_factor, 1, 1)) + # Determine the factors by which each tally operands' data arrays + # must be tiled or repeated for the tally outer product + other_tile_factor = 1 + self_repeat_factor = 1 + for filter in diff1: + other_tile_factor *= filter.num_bins + for filter in diff2: + self_repeat_factor *= filter.num_bins + + # Tile / repeat the tally data for the tally outer product + self_shape = list(self_mean.shape) + other_shape = list(other_mean.shape) + self_shape[0] *= self_repeat_factor + self_mean = np.repeat(self_mean, self_repeat_factor) + self_std_dev = np.repeat(self_std_dev, self_repeat_factor) + + if self_repeat_factor == 1: + other_shape[0] *= other_tile_factor + other_mean = np.repeat(other_mean, other_tile_factor, axis=0) + other_std_dev = np.repeat(other_std_dev, other_tile_factor, + axis=0) + else: + other_mean = np.tile(other_mean, (other_tile_factor, 1, 1)) + other_std_dev = np.tile(other_std_dev, (other_tile_factor, 1, 1)) + + # NumPy repeat and tile routines return 1D flattened arrays + # Reshape arrays as 3D with filters, nuclides and scores axes + self_mean.shape = tuple(self_shape) + self_std_dev.shape = tuple(self_shape) + other_mean.shape = tuple(other_shape) + other_std_dev.shape = tuple(other_shape) if self.nuclides != other.nuclides: @@ -1599,12 +1671,23 @@ class Tally(object): self_repeat_factor = other.num_nuclides other_tile_factor = self.num_nuclides - # Replicate the data + # Tile / repeat the tally data for the tally outer product + self_shape = list(self_mean.shape) + other_shape = list(other_mean.shape) + self_shape[1] *= self_repeat_factor + other_shape[1] *= other_tile_factor self_mean = np.repeat(self_mean, self_repeat_factor, axis=1) other_mean = np.tile(other_mean, (1, other_tile_factor, 1)) self_std_dev = np.repeat(self_std_dev, self_repeat_factor, axis=1) other_std_dev = np.tile(other_std_dev, (1, other_tile_factor, 1)) + # NumPy repeat and tile routines return 1D flattened arrays + # Reshape arrays as 3D with filters, nuclides and scores axes + self_mean.shape = tuple(self_shape) + self_std_dev.shape = tuple(self_shape) + other_mean.shape = tuple(other_shape) + other_std_dev.shape = tuple(other_shape) + if self.scores != other.scores: # Determine the number of paired combinations of score bins @@ -1612,12 +1695,23 @@ class Tally(object): self_repeat_factor = other.num_score_bins other_tile_factor = self.num_score_bins - # Replicate the data + # Tile / repeat the tally data for the tally outer product + self_shape = list(self_mean.shape) + other_shape = list(other_mean.shape) + self_shape[2] *= self_repeat_factor + other_shape[2] *= other_tile_factor self_mean = np.repeat(self_mean, self_repeat_factor, axis=2) other_mean = np.tile(other_mean, (1, 1, other_tile_factor)) self_std_dev = np.repeat(self_std_dev, self_repeat_factor, axis=2) other_std_dev = np.tile(other_std_dev, (1, 1, other_tile_factor)) + # NumPy repeat and tile routines return 1D flattened arrays + # Reshape arrays as 3D with filters, nuclides and scores axes + self_mean.shape = tuple(self_shape) + self_std_dev.shape = tuple(self_shape) + other_mean.shape = tuple(other_shape) + other_std_dev.shape = tuple(other_shape) + data = {} data['self'] = {} data['other'] = {} @@ -1627,6 +1721,133 @@ class Tally(object): data['other']['std. dev.'] = other_std_dev return data + def swap_filters(self, filter1, filter2, inplace=False): + """Reverse the ordering of two filters in this tally + + This is a helper method for tally arithmetic which helps align the data + in two tallies with shared filters. This method copies this tally and + reverses the order of the two filters. + + Parameters + ---------- + filter1 : Filter + The filter to swap with filter2 + + filter2 : Filter + The filter to swap with filter1 + + inplace : bool, optional + Whether to perform operation inplace or return new tally with the + filters swapped. + + Returns + ------- + swap_tally + If inplace is false, a copy of this tally with the filters swapped. + Otherwise, nothing is returned. + + Raises + ------ + ValueError + If this is a derived tally or this method is called before the tally + is populated with data by the StatePoint.read_results() method. + + """ + + # Check that results have been read + if not self.derived and self.sum is None: + msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ + 'since it does not contain any results.'.format(self.id) + raise ValueError(msg) + + cv.check_type('filter1', filter1, Filter) + cv.check_type('filter2', filter2, Filter) + + if filter1 == filter2: + msg = 'Unable to swap a filter with itself' + raise ValueError(msg) + elif filter1 not in self.filters: + msg = 'Unable to swap "{0}" filter1 in Tally ID="{1}" since it ' \ + 'does not contain such a filter'.format(filter1.type, self.id) + raise ValueError(msg) + elif filter2 not in self.filters: + msg = 'Unable to swap "{0}" filter2 in Tally ID="{1}" since it ' \ + 'does not contain such a filter'.format(filter2.type, self.id) + raise ValueError(msg) + + # Create a copy of the tally that preserves the original data formatting + # throughout swapping process + tally_copy = copy.deepcopy(self) + + # Set the swap tally + if inplace: + swap_tally = self + else: + swap_tally = copy.deepcopy(self) + + # Swap the filters in the copied version of this Tally + filter1_index = swap_tally.filters.index(filter1) + filter2_index = swap_tally.filters.index(filter2) + swap_tally.filters[filter1_index] = filter2 + swap_tally.filters[filter2_index] = filter1 + + # Update the strides for each of the filters + stride = swap_tally.num_nuclides * swap_tally.num_score_bins + for filter in reversed(swap_tally.filters): + filter.stride = stride + stride *= filter.num_bins + + # Construct lists of tuples for the bins in each of the two filters + filters = [filter1.type, filter2.type] + if filter1.type == 'distribcell': + filter1_bins = np.arange(filter.num_bins) + else: + filter1_bins = [(filter1.get_bin(i)) for i in range(filter1.num_bins)] + + if filter1.type == 'distribcell': + filter2_bins = np.arange(filter2.num_bins) + else: + filter2_bins = [filter2.get_bin(i) for i in range(filter2.num_bins)] + + # Adjust the sum data array to relect the new filter order + if swap_tally.sum is not None: + for bin1, bin2 in itertools.product(filter1_bins, filter2_bins): + filter_bins = [(bin1,), (bin2,)] + data = tally_copy.get_values( + filters=filters, filter_bins=filter_bins, value='sum') + indices = swap_tally.get_filter_indices(filters, filter_bins) + swap_tally.sum[indices, :, :] = data + + # Adjust the sum_sq data array to relect the new filter order + if swap_tally.sum_sq is not None: + for bin1, bin2 in itertools.product(filter1_bins, filter2_bins): + filter_bins = [(bin1,), (bin2,)] + data = tally_copy.get_values( + filters=filters, filter_bins=filter_bins, value='sum_sq') + indices = swap_tally.get_filter_indices(filters, filter_bins) + swap_tally.sum_sq[indices, :, :] = data + + # Adjust the mean data array to relect the new filter order + if swap_tally.mean is not None: + for bin1, bin2 in itertools.product(filter1_bins, filter2_bins): + filter_bins = [(bin1,), (bin2,)] + data = tally_copy.get_values( + filters=filters, filter_bins=filter_bins, value='mean') + indices = swap_tally.get_filter_indices(filters, filter_bins) + swap_tally._mean[indices, :, :] = data + + # Adjust the std_dev data array to relect the new filter order + if swap_tally.std_dev is not None: + for bin1, bin2 in itertools.product(filter1_bins, filter2_bins): + filter_bins = [(bin1,), (bin2,)] + data = tally_copy.get_values( + filters=filters, filter_bins=filter_bins, value='std_dev') + indices = swap_tally.get_filter_indices(filters, filter_bins) + swap_tally._std_dev[indices, :, :] = data + + if not inplace: + return swap_tally + def __add__(self, other): """Adds this tally to another tally or scalar value. @@ -1677,8 +1898,8 @@ class Tally(object): new_tally._derived = True new_tally.with_batch_statistics = True new_tally.name = self.name - new_tally._mean = self._mean + other - new_tally._std_dev = self._std_dev + new_tally._mean = self.mean + other + new_tally._std_dev = self.std_dev new_tally.estimator = self.estimator new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations @@ -1746,8 +1967,8 @@ class Tally(object): new_tally = Tally(name='derived') new_tally._derived = True new_tally.name = self.name - new_tally._mean = self._mean - other - new_tally._std_dev = self._std_dev + new_tally._mean = self.mean - other + new_tally._std_dev = self.std_dev new_tally.estimator = self.estimator new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations @@ -1816,8 +2037,8 @@ class Tally(object): new_tally = Tally(name='derived') new_tally._derived = True new_tally.name = self.name - new_tally._mean = self._mean * other - new_tally._std_dev = self._std_dev * np.abs(other) + new_tally._mean = self.mean * other + new_tally._std_dev = self.std_dev * np.abs(other) new_tally.estimator = self.estimator new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations @@ -1837,7 +2058,7 @@ class Tally(object): return new_tally - def __div__(self, other): + def __truediv__(self, other): """Divides this tally by another tally or scalar value. This method builds a new tally with data that is the dividend of @@ -1886,8 +2107,8 @@ class Tally(object): new_tally = Tally(name='derived') new_tally._derived = True new_tally.name = self.name - new_tally._mean = self._mean / other - new_tally._std_dev = self._std_dev * np.abs(1. / other) + new_tally._mean = self.mean / other + new_tally._std_dev = self.std_dev * np.abs(1. / other) new_tally.estimator = self.estimator new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations @@ -1907,6 +2128,9 @@ class Tally(object): return new_tally + def __div__(self, other): + return self.__truediv__(other) + def __pow__(self, power): """Raises this tally to another tally or scalar value power. @@ -2085,33 +2309,30 @@ class Tally(object): """Build a sliced tally for the specified filters, scores and nuclides. This method constructs a new tally to encapsulate a subset of the data - represented by this tally. The subset of data to included in the tally + represented by this tally. The subset of data to include in the tally slice is determined by the scores, filters and nuclides specified in the input parameters. Parameters ---------- - scores : list + scores : list of str A list of one or more score strings (e.g., ['absorption', 'nu-fission']; default is []) - - filters : list + filters : list of str A list of filter type strings (e.g., ['mesh', 'energy']; default is []) - - filter_bins : list + filter_bins : list of Iterables A list of the filter bins corresponding to the filter_types - parameter (e.g., [1, (0., 0.625e-6)]; default is []). Each bin in - the list is the integer ID for 'material', 'surface', 'cell', + parameter (e.g., [(1,), (0., 0.625e-6)]; default is []). Each bin + in the list is the integer ID for 'material', 'surface', 'cell', 'cellborn', and 'universe' Filters. Each bin is an integer for the cell instance ID for 'distribcell Filters. Each bin is a 2-tuple of floats for 'energy' and 'energyout' filters corresponding to the energy boundaries of the bin of interest. The bin is a (x,y,z) 3-tuple for 'mesh' filters corresponding to the mesh cell of - interest. The order of the bins in the list must correspond of the + interest. The order of the bins in the list must correspond to the filter_types parameter. - - nuclides : list + nuclides : list of str A list of nuclide name strings (e.g., ['U-235', 'U-238']; default is []) @@ -2130,21 +2351,29 @@ class Tally(object): """ # Ensure that StatePoint.read_results() was called first - if self.sum is None: + if not self.derived and self.sum is None: msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ 'since it does not contain any results.'.format(self.id) raise ValueError(msg) new_tally = copy.deepcopy(self) - new_sum = self.get_values(scores, filters, filter_bins, - nuclides, 'sum') - new_sum_sq = self.get_values(scores, filters, filter_bins, - nuclides, 'sum_sq') - new_tally.sum = new_sum - new_tally.sum_sq = new_sum_sq - new_tally._mean = None - new_tally._std_dev = None + if self.sum is not None: + new_sum = self.get_values(scores, filters, filter_bins, + nuclides, 'sum') + new_tally.sum = new_sum + if self.sum_sq is not None: + new_sum_sq = self.get_values(scores, filters, filter_bins, + nuclides, 'sum_sq') + new_tally.sum_sq = new_sum_sq + if self.mean is not None: + new_mean = self.get_values(scores, filters, filter_bins, + nuclides, 'mean') + new_tally._mean = new_mean + if self.std_dev is not None: + new_std_dev = self.get_values(scores, filters, filter_bins, + nuclides, 'std_dev') + new_tally._std_dev = new_std_dev # SCORES if scores: @@ -2187,10 +2416,193 @@ class Tally(object): for filter_bin in filter_bins[i]: bin_index = filter.get_bin_index(filter_bin) - bin_indices.append(bin_index) + if filter_type in ['energy', 'energyout']: + bin_indices.extend([bin_index, bin_index+1]) + elif filter_type == 'distribcell': + indices = [(bin,) for bin in range(filter.num_bins)] + bin_indices.extend(indices) + else: + bin_indices.append(bin_index) - new_bins = filter.bins[bin_indices] - filter.bins = new_bins + filter.bins = filter.bins[bin_indices] + filter.num_bins = len(filter_bins[i]) + + # Correct each Filter's stride + stride = new_tally.num_nuclides * new_tally.num_score_bins + for filter in reversed(new_tally.filters): + filter.stride = stride + stride *= filter.num_bins + + return new_tally + + def summation(self, scores=[], filter_type=None, + filter_bins=[], nuclides=[], remove_filter=False): + """Vectorized sum of tally data across scores, filter bins and/or + nuclides using tally addition. + + This method constructs a new tally to encapsulate the sum of the data + represented by the summation of the data in this tally. The tally data + sum is determined by the scores, filter bins and nuclides specified + in the input parameters. + + Parameters + ---------- + scores : list of str + A list of one or more score strings to sum across + (e.g., ['absorption', 'nu-fission']; default is []) + filter_type : str + A filter type string (e.g., 'cell', 'energy') corresponding to the + filter bins to sum across + filter_bins : Iterable of Integral or tuple + A list of the filter bins corresponding to the filter_type parameter + Each bin in the list is the integer ID for 'material', 'surface', + 'cell', 'cellborn', and 'universe' Filters. Each bin is an integer + for the cell instance ID for 'distribcell Filters. Each bin is a + 2-tuple of floats for 'energy' and 'energyout' filters corresponding + to the energy boundaries of the bin of interest. Each bin is an + (x,y,z) 3-tuple for 'mesh' filters corresponding to the mesh cell of + interest. + nuclides : list of str + A list of nuclide name strings to sum across + (e.g., ['U-235', 'U-238']; default is []) + remove_filter : bool + If a filter is being summed over, this bool indicates whether to + remove that filter in the returned tally. Default is False. + + Returns + ------- + Tally + A new tally which encapsulates the sum of data requested. + """ + + # If user did not specify any scores, do not sum across scores + if len(scores) == 0: + scores = [[]] + # Sum across any scores specified by the user + else: + scores = [[score] for score in scores] + + # If user did not specify any nuclides, do not sum across nuclides + if len(nuclides) == 0: + nuclides = [[]] + # Sum across any nuclides specified by the user + else: + nuclides = [[nuclide] for nuclide in nuclides] + + # Sum across any filter bins specified by the user + if filter_type in _FILTER_TYPES: + + # If user did not specify filter bins, sum across all bins + if len(filter_bins) == 0: + filter = self.find_filter(filter_type) + filter_bins = [[(filter.get_bin(i),)] for i in range(filter.num_bins)] + else: + filter_bins = [[(filter_bin,)] for filter_bin in filter_bins] + + filters = [[filter_type]] + # If user did not specify a filter type, do not sum across filter bins + else: + filter_bins = [[]] + filters = [[]] + + # Initialize Tally sum + tally_sum = 0 + + # Iterate over all Tally slice operands in summation + prod = [scores, filters, filter_bins, nuclides] + summed_filters = defaultdict(list) + for scores, filters, filter_bins, nuclides in itertools.product(*prod): + tally_slice = self.get_slice(scores, filters, filter_bins, nuclides) + + # Remove filters summed across to avoid bulky CrossFilters + if filter_type: + filter = tally_slice.find_filter(filter_type) + tally_slice.remove_filter(filter) + summed_filters[filter_type].append(filter) + + # Accumulate this Tally slice into the Tally sum + tally_sum += tally_slice + + # Add back the filter(s) which were summed across to derived tally, + # if filter bins were input; otherwise, leave out summed filter(s) + if remove_filter and filter_type is not None: + # Rename tally sum indicating a summation over a particular filter + tally_sum.name = 'sum({0}, {1})'.format(self.name, filter_type) + else: + for summed_filter_type in summed_filters: + filters = summed_filters[summed_filter_type] + for i in range(1, len(filters)): + filters[i] = CrossFilter(filters[i-1], filters[i], '+') + tally_sum.add_filter(filters[-1]) + + return tally_sum + + def diagonalize_filter(self, new_filter): + """Diagonalize the tally data array along a new axis of filter bins. + + This is a helper method for the tally arithmetic methods. This method + adds the new filter to a derived tally constructed copied from this one. + The data in the derived tally arrays is "diagonalized" along the bins in + the new filter. This functionality is used by the openmc.mgxs module; to + transport-correct scattering matrices by subtracting a 'scatter-P1' + reaction rate tally with an energy filter from an 'scatter' reaction + rate tally with both energy and energyout filters. + + Parameters + ---------- + new_filter : Filter + The filter along which to diagonalize the data in the new + + Returns + ------- + Tally + A new derived Tally with data diagaonalized along the new filter. + + """ + + cv.check_type('new_filter', new_filter, Filter) + + if new_filter in self.filters: + msg = 'Unable to diagonalize Tally ID="{0}" which already ' \ + 'contains a "{1}" filter'.format(self.id, new_filter.type) + raise ValueError(msg) + + # Add the new filter to a copy of this Tally + new_tally = copy.deepcopy(self) + new_tally.add_filter(new_filter) + + # Determine the shape of data in the new diagonalized Tally + num_filter_bins = new_tally.num_filter_bins + num_nuclides = new_tally.num_nuclides + num_score_bins = new_tally.num_score_bins + new_shape = (num_filter_bins, num_nuclides, num_score_bins) + + # Determine "base" indices along the new "diagonal", and the factor + # by which the "base" indices should be repeated to account for all + # other filter bins in the diagonalized tally + indices = np.arange(0, new_filter.num_bins**2, new_filter.num_bins+1) + diag_factor = int(self.num_filter_bins / new_filter.num_bins) + diag_indices = np.zeros(self.num_filter_bins, dtype=np.int) + + # Determine the filter indices along the new "diagonal" + for i in range(diag_factor): + start = i * new_filter.num_bins + end = (i+1) * new_filter.num_bins + diag_indices[start:end] = indices + (i * new_filter.num_bins**2) + + # Inject this Tally's data along the diagonal of the diagonalized Tally + if self.sum is not None: + new_tally._sum = np.zeros(new_shape, dtype=np.float64) + new_tally._sum[diag_indices, :, :] = self.sum + if self.sum_sq is not None: + new_tally._sum_sq = np.zeros(new_shape, dtype=np.float64) + new_tally._sum_sq[diag_indices, :, :] = self.sum_sq + if self.mean is not None: + new_tally._mean = np.zeros(new_shape, dtype=np.float64) + new_tally._mean[diag_indices, :, :] = self.mean + if self.std_dev is not None: + new_tally._std_dev = np.zeros(new_shape, dtype=np.float64) + new_tally._std_dev[diag_indices, :, :] = self.std_dev # Correct each Filter's stride stride = new_tally.num_nuclides * new_tally.num_score_bins @@ -2213,6 +2625,14 @@ class TalliesFile(object): self._meshes = [] self._tallies_file = ET.Element("tallies") + @property + def tallies(self): + return self._tallies + + @property + def meshes(self): + return self._meshes + def add_tally(self, tally, merge=False): """Add a tally to the file @@ -2220,6 +2640,7 @@ class TalliesFile(object): ---------- tally : Tally Tally to add to file + merge : bool Indicate whether the tally should be merged with an existing tally, if possible. Defaults to False. @@ -2333,6 +2754,9 @@ class TalliesFile(object): """ + # Reset xml element tree + self._tallies_file.clear() + self._create_mesh_subelements() self._create_tally_subelements() diff --git a/openmc/temp.py b/openmc/temp.py deleted file mode 100644 index 91f6082996..0000000000 --- a/openmc/temp.py +++ /dev/null @@ -1,12 +0,0 @@ -from checkvalue import * -from checkvalue import _isinstance - -import numpy as np - -zs = np.zeros((2,)) - -print _isinstance(zs[0], Integral) -print _isinstance(zs[0], Real) -print _isinstance(zs[0], (Integral, Real)) - -print check_iterable_type('thing', zs, (Real, Integral)) diff --git a/openmc/trigger.py b/openmc/trigger.py index e695defde2..bcac8c31c6 100644 --- a/openmc/trigger.py +++ b/openmc/trigger.py @@ -58,6 +58,22 @@ class Trigger(object): else: return existing + def __eq__(self, other): + if str(self) == str(other): + return True + else: + return False + + def __ne__(self, other): + return not self == other + + def __repr__(self): + string = 'Trigger\n' + string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type) + string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold) + string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores) + return string + @property def trigger_type(self): return self._trigger_type @@ -102,13 +118,6 @@ class Trigger(object): else: self._scores.append(score) - def __repr__(self): - string = 'Trigger\n' - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type) - string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold) - string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores) - return string - def get_trigger_xml(self, element): """Return XML representation of the trigger diff --git a/openmc/universe.py b/openmc/universe.py index bab10f5df7..98367c381b 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -3,15 +3,22 @@ from collections import OrderedDict, Iterable from numbers import Real, Integral from xml.etree import ElementTree as ET import sys +import warnings import numpy as np import openmc import openmc.checkvalue as cv +from openmc.surface import Halfspace +from openmc.region import Region, Intersection, Complement if sys.version_info[0] >= 3: basestring = str + +# DeprecationWarning filter for the Cell.add_surface(...) method +warnings.simplefilter('always', DeprecationWarning) + # A static variable for auto-generated Cell IDs AUTO_CELL_ID = 10000 @@ -45,10 +52,8 @@ class Cell(object): Name of the cell fill : Material or Universe or Lattice or 'void' Indicates what the region of space is filled with - surfaces : dict - Dictionary whose keys are surface IDs and values are 2-tuples of a - Surface object and an integer identify whether the positive or negative - half-space is to be used + region : openmc.region.Region + Region of space that is assigned to the cell. rotation : ndarray If the cell is filled with a universe, this array specifies the angles in degrees about the x, y, and z axes that the filled universe should be @@ -67,11 +72,59 @@ class Cell(object): self.name = name self._fill = None self._type = None - self._surfaces = {} + self._region = None self._rotation = None self._translation = None self._offsets = None + def __eq__(self, other): + if not isinstance(other, Cell): + return False + elif self.id != other.id: + return False + elif self.name != other.name: + return False + elif self.fill != other.fill: + return False + elif self.region != other.region: + return False + elif self.rotation != other.rotation: + return False + elif self.translation != other.translation: + return False + else: + return True + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(repr(self)) + + def __repr__(self): + string = 'Cell\n' + string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) + string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) + + if isinstance(self._fill, openmc.Material): + string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t', + self._fill._id) + elif isinstance(self._fill, (Universe, Lattice)): + string += '{0: <16}{1}{2}\n'.format('\tFill', '=\t', + self._fill._id) + else: + string += '{0: <16}{1}{2}\n'.format('\tFill', '=\t', self._fill) + + string += '{0: <16}{1}{2}\n'.format('\tRegion', '=\t', self._region) + + string += '{0: <16}{1}{2}\n'.format('\tRotation', '=\t', + self._rotation) + string += '{0: <16}{1}{2}\n'.format('\tTranslation', '=\t', + self._translation) + string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self._offsets) + + return string + @property def id(self): return self._id @@ -85,12 +138,19 @@ class Cell(object): return self._fill @property - def type(self): - return self._fill + def fill_type(self): + if isinstance(self.fill, openmc.Material): + return 'material' + elif isinstance(self.fill, openmc.Universe): + return 'universe' + elif isinstance(self.fill, openmc.Lattice): + return 'lattice' + else: + return None @property - def surfaces(self): - return self._surfaces + def region(self): + return self._region @property def rotation(self): @@ -112,13 +172,16 @@ class Cell(object): AUTO_CELL_ID += 1 else: cv.check_type('cell ID', cell_id, Integral) - cv.check_greater_than('cell ID', cell_id, 0) + cv.check_greater_than('cell ID', cell_id, 0, equality=True) self._id = cell_id @name.setter def name(self, name): - cv.check_type('cell name', name, basestring) - self._name = name + if name is not None: + cv.check_type('cell name', name, basestring) + self._name = name + else: + self._name = '' @fill.setter def fill(self, fill): @@ -163,6 +226,11 @@ class Cell(object): cv.check_type('cell offsets', offsets, Iterable) self._offsets = offsets + @region.setter + def region(self, region): + cv.check_type('cell region', region, Region) + self._region = region + def add_surface(self, surface, halfspace): """Add a half-space to the list of half-spaces whose intersection defines the cell. @@ -176,6 +244,11 @@ class Cell(object): """ + warnings.warn("Cell.add_surface(...) has been deprecated and may be " + "removed in a future version. The region for a Cell " + "should be defined using the region property directly.", + DeprecationWarning) + if not isinstance(surface, openmc.Surface): msg = 'Unable to add Surface "{0}" to Cell ID="{1}" since it is ' \ 'not a Surface object'.format(surface, self._id) @@ -186,28 +259,17 @@ class Cell(object): '"{2}" since it is not +/-1'.format(surface, self._id, halfspace) raise ValueError(msg) - # If the Cell does not already contain the Surface, add it - if surface._id not in self._surfaces: - self._surfaces[surface._id] = (surface, halfspace) - - def remove_surface(self, surface): - """Remove the half-space associated with a particular surface. - - Parameters - ---------- - surface : openmc.surface.Surface - Surface to remove from definition - - """ - - if not isinstance(surface, openmc.Surface): - msg = 'Unable to remove Surface "{0}" from Cell ID="{1}" since it is ' \ - 'not a Surface object'.format(surface, self._id) - raise ValueError(msg) - - # If the Cell contains the Surface, delete it - if surface._id in self._surfaces: - del self._surfaces[surface._id] + # If no region has been assigned, simply use the half-space. Otherwise, + # take the intersection of the current region and the half-space + # specified + region = +surface if halfspace == 1 else -surface + if self.region is None: + self.region = region + else: + if isinstance(self.region, Intersection): + self.region.nodes.append(region) + else: + self.region = Intersection(self.region, region) def get_offset(self, path, filter_offset): # Get the current element and remove it from the list @@ -240,7 +302,7 @@ class Cell(object): """ - nuclides = {} + nuclides = OrderedDict() if self._type != 'void': nuclides.update(self._fill.get_all_nuclides()) @@ -258,13 +320,34 @@ class Cell(object): """ - cells = {} + cells = OrderedDict() if self._type == 'fill' or self._type == 'lattice': cells.update(self._fill.get_all_cells()) return cells + def get_all_materials(self): + """Return all materials that are contained within the cell + + Returns + ------- + materials : dict + Dictionary whose keys are material IDs and values are Material instances + + """ + + materials = OrderedDict() + if self.fill_type == 'material': + materials[self.fill.id] = self.fill + + # Append all Cells in each Cell in the Universe to the dictionary + cells = self.get_all_cells() + for cell_id, cell in cells.items(): + materials.update(cell.get_all_materials()) + + return materials + def get_all_universes(self): """Return all universes that are contained within this one if any of its cells are filled with a universe or lattice. @@ -277,7 +360,7 @@ class Cell(object): """ - universes = {} + universes = OrderedDict() if self._type == 'fill': universes[self._fill._id] = self._fill @@ -287,36 +370,6 @@ class Cell(object): return universes - def __repr__(self): - string = 'Cell\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - - if isinstance(self._fill, openmc.Material): - string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t', - self._fill._id) - elif isinstance(self._fill, (Universe, Lattice)): - string += '{0: <16}{1}{2}\n'.format('\tFill', '=\t', - self._fill._id) - else: - string += '{0: <16}{1}{2}\n'.format('\tFill', '=\t', self._fill) - - string += '{0: <16}{1}\n'.format('\tSurfaces', '=\t') - - for surface_id in self._surfaces: - halfspace = self._surfaces[surface_id][1] - string += '{0} '.format(halfspace * surface_id) - - string = string.rstrip(' ') + '\n' - - string += '{0: <16}{1}{2}\n'.format('\tRotation', '=\t', - self._rotation) - string += '{0: <16}{1}{2}\n'.format('\tTranslation', '=\t', - self._translation) - string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self._offsets) - - return string - def create_xml_subelement(self, xml_element): element = ET.Element("cell") element.set("id", str(self._id)) @@ -338,26 +391,30 @@ class Cell(object): element.set("fill", str(self._fill)) self._fill.create_xml_subelement(xml_element) - if self._surfaces is not None: - surfaces = '' + if self.region is not None: + # Set the region attribute with the region specification + element.set("region", str(self.region)) - for surface_id in self._surfaces: - # Determine if XML element already includes this Surface - path = './surface[@id=\'{0}\']'.format(surface_id) - test = xml_element.find(path) + # Only surfaces that appear in a region are added to the geometry + # file, so the appropriate check is performed here. First we create + # a function which is called recursively to navigate through the CSG + # tree. When it reaches a leaf (a Halfspace), it creates a + # element for the corresponding surface if none has been created + # thus far. + def create_surface_elements(node, element): + if isinstance(node, Halfspace): + path = './surface[@id=\'{0}\']'.format(node.surface.id) + if xml_element.find(path) is None: + surface_subelement = node.surface.create_xml_subelement() + xml_element.append(surface_subelement) + elif isinstance(node, Complement): + create_surface_elements(node.node, element) + else: + for subnode in node.nodes: + create_surface_elements(subnode, element) - # If the element does not contain the Surface subelement - if test is None: - # Create the XML subelement for this Surface - surface = self._surfaces[surface_id][0] - surface_subelement = surface.create_xml_subelement() - xml_element.append(surface_subelement) - - # Append the halfspace and Surface ID - halfspace = self._surfaces[surface_id][1] - surfaces += '{0} '.format(halfspace * surface_id) - - element.set("surfaces", surfaces.rstrip(' ')) + # Call the recursive function from the top node + create_surface_elements(self.region, xml_element) if self._translation is not None: element.set("translation", ' '.join(map(str, self._translation))) @@ -406,13 +463,41 @@ class Universe(object): # Keys - Cell IDs # Values - Cells - self._cells = {} + self._cells = OrderedDict() # Keys - Cell IDs # Values - Offsets self._cell_offsets = OrderedDict() self._num_regions = 0 + def __eq__(self, other): + if not isinstance(other, Universe): + return False + elif self.id != other.id: + return False + elif self.name != other.name: + return False + elif self.cells != other.cells: + return False + else: + return True + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(repr(self)) + + def __repr__(self): + string = 'Universe\n' + string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) + string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) + string += '{0: <16}{1}{2}\n'.format('\tCells', '=\t', + list(self._cells.keys())) + string += '{0: <16}{1}{2}\n'.format('\t# Regions', '=\t', + self._num_regions) + return string + @property def id(self): return self._id @@ -433,13 +518,16 @@ class Universe(object): AUTO_UNIVERSE_ID += 1 else: cv.check_type('universe ID', universe_id, Integral) - cv.check_greater_than('universe ID', universe_id, 0, True) + cv.check_greater_than('universe ID', universe_id, 0, equality=True) self._id = universe_id @name.setter def name(self, name): - cv.check_type('universe name', name, basestring) - self._name = name + if name is not None: + cv.check_type('universe name', name, basestring) + self._name = name + else: + self._name = '' def add_cell(self, cell): """Add a cell to the universe. @@ -494,11 +582,9 @@ class Universe(object): 'not a Cell'.format(self._id, cell) raise ValueError(msg) - cell_id = cell.getId() - # If the Cell is in the Universe's list of Cells, delete it - if cell_id in self._cells: - del self._cells[cell_id] + if cell.id in self._cells: + del self._cells[cell.id] def clear_cells(self): """Remove all cells from the universe.""" @@ -529,7 +615,7 @@ class Universe(object): """ - nuclides = {} + nuclides = OrderedDict() # Append all Nuclides in each Cell in the Universe to the dictionary for cell_id, cell in self._cells.items(): @@ -547,7 +633,7 @@ class Universe(object): """ - cells = {} + cells = OrderedDict() # Add this Universe's cells to the dictionary cells.update(self._cells) @@ -558,6 +644,25 @@ class Universe(object): return cells + def get_all_materials(self): + """Return all materials that are contained within the universe + + Returns + ------- + materials : dict + Dictionary whose keys are material IDs and values are Material instances + + """ + + materials = OrderedDict() + + # Append all Cells in each Cell in the Universe to the dictionary + cells = self.get_all_cells() + for cell_id, cell in cells.items(): + materials.update(cell.get_all_materials()) + + return materials + def get_all_universes(self): """Return all universes that are contained within this one. @@ -572,7 +677,7 @@ class Universe(object): # Get all Cells in this Universe cells = self.get_all_cells() - universes = {} + universes = OrderedDict() # Append all Universes containing each Cell to the dictionary for cell_id, cell in cells.items(): @@ -580,17 +685,8 @@ class Universe(object): return universes - def __repr__(self): - string = 'Universe\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tCells', '=\t', - list(self._cells.keys())) - string += '{0: <16}{1}{2}\n'.format('\t# Regions', '=\t', - self._num_regions) - return string - def create_xml_subelement(self, xml_element): + # Iterate over all Cells for cell_id, cell in self._cells.items(): @@ -644,6 +740,25 @@ class Lattice(object): self._outer = None self._universes = None + def __eq__(self, other): + if not isinstance(other, Lattice): + return False + elif self.id != other.id: + return False + elif self.name != other.name: + return False + elif self.pitch != other.pitch: + return False + elif self.outer != other.outer: + return False + elif self.universes != other.universes: + return False + else: + return True + + def __ne__(self, other): + return not self == other + @property def id(self): return self._id @@ -672,13 +787,16 @@ class Lattice(object): AUTO_UNIVERSE_ID += 1 else: cv.check_type('lattice ID', lattice_id, Integral) - cv.check_greater_than('lattice ID', lattice_id, 0) + cv.check_greater_than('lattice ID', lattice_id, 0, equality=True) self._id = lattice_id @name.setter def name(self, name): - cv.check_type('lattice name', name, basestring) - self._name = name + if name is not None: + cv.check_type('lattice name', name, basestring) + self._name = name + else: + self._name = '' @outer.setter def outer(self, outer): @@ -702,7 +820,7 @@ class Lattice(object): """ - univs = dict() + univs = OrderedDict() for k in range(len(self._universes)): for j in range(len(self._universes[k])): if isinstance(self._universes[k][j], Universe): @@ -730,7 +848,7 @@ class Lattice(object): """ - nuclides = {} + nuclides = OrderedDict() # Get all unique Universes contained in each of the lattice cells unique_universes = self.get_unique_universes() @@ -751,7 +869,7 @@ class Lattice(object): """ - cells = {} + cells = OrderedDict() unique_universes = self.get_unique_universes() for universe_id, universe in unique_universes.items(): @@ -759,6 +877,25 @@ class Lattice(object): return cells + def get_all_materials(self): + """Return all materials that are contained within the lattice + + Returns + ------- + materials : dict + Dictionary whose keys are material IDs and values are Material instances + + """ + + materials = OrderedDict() + + # Append all Cells in each Cell in the Universe to the dictionary + cells = self.get_all_cells() + for cell_id, cell in cells.items(): + materials.update(cell.get_all_materials()) + + return materials + def get_all_universes(self): """Return all universes that are contained within the lattice @@ -772,7 +909,7 @@ class Lattice(object): # Initialize a dictionary of all Universes contained by the Lattice # in each nested Universe level - all_universes = {} + all_universes = OrderedDict() # Get all unique Universes contained in each of the lattice cells unique_universes = self.get_unique_universes() @@ -821,6 +958,68 @@ class RectLattice(Lattice): self._lower_left = None self._offsets = None + def __eq__(self, other): + if not isinstance(other, RectLattice): + return False + elif not super(RectLattice, self).__eq__(other): + return False + elif self.dimension != other.dimension: + return False + elif self.lower_left != other.lower_left: + return False + else: + return True + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(repr(self)) + + def __repr__(self): + string = 'RectLattice\n' + string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) + string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) + string += '{0: <16}{1}{2}\n'.format('\tDimension', '=\t', + self._dimension) + string += '{0: <16}{1}{2}\n'.format('\tLower Left', '=\t', + self._lower_left) + string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch) + + if self._outer is not None: + string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', + self._outer._id) + else: + string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', + self._outer) + + string += '{0: <16}\n'.format('\tUniverses') + + # Lattice nested Universe IDs - column major for Fortran + for i, universe in enumerate(np.ravel(self._universes)): + string += '{0} '.format(universe._id) + + # Add a newline character every time we reach end of row of cells + if (i+1) % self._dimension[-1] == 0: + string += '\n' + + string = string.rstrip('\n') + + if self._offsets is not None: + string += '{0: <16}\n'.format('\tOffsets') + + # Lattice cell offsets + for i, offset in enumerate(np.ravel(self._offsets)): + string += '{0} '.format(offset) + + # Add a newline character when we reach end of row of cells + if (i+1) % self._dimension[-1] == 0: + string += '\n' + + string = string.rstrip('\n') + + return string + @property def dimension(self): return self._dimension @@ -878,51 +1077,8 @@ class RectLattice(Lattice): return offset - def __repr__(self): - string = 'RectLattice\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tDimension', '=\t', - self._dimension) - string += '{0: <16}{1}{2}\n'.format('\tLower Left', '=\t', - self._lower_left) - string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch) - - if self._outer is not None: - string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', - self._outer._id) - else: - string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', - self._outer) - - string += '{0: <16}\n'.format('\tUniverses') - - # Lattice nested Universe IDs - column major for Fortran - for i, universe in enumerate(np.ravel(self._universes)): - string += '{0} '.format(universe._id) - - # Add a newline character every time we reach end of row of cells - if (i+1) % self._dimension[-1] == 0: - string += '\n' - - string = string.rstrip('\n') - - if self._offsets is not None: - string += '{0: <16}\n'.format('\tOffsets') - - # Lattice cell offsets - for i, offset in enumerate(np.ravel(self._offsets)): - string += '{0} '.format(offset) - - # Add a newline character when we reach end of row of cells - if (i+1) % self._dimension[-1] == 0: - string += '\n' - - string = string.rstrip('\n') - - return string - def create_xml_subelement(self, xml_element): + # Determine if XML element already contains subelement for this Lattice path = './lattice[@id=\'{0}\']'.format(self._id) test = xml_element.find(path) @@ -1037,6 +1193,54 @@ class HexLattice(Lattice): self._num_axial = None self._center = None + def __eq__(self, other): + if not isinstance(other, HexLattice): + return False + elif not super(HexLattice, self).__eq__(other): + return False + elif self.num_rings != other.num_rings: + return False + elif self.num_axial != other.num_axial: + return False + elif self.center != other.center: + return False + else: + return True + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(repr(self)) + + def __repr__(self): + string = 'HexLattice\n' + string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) + string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) + string += '{0: <16}{1}{2}\n'.format('\t# Rings', '=\t', self._num_rings) + string += '{0: <16}{1}{2}\n'.format('\t# Axial', '=\t', self._num_axial) + string += '{0: <16}{1}{2}\n'.format('\tCenter', '=\t', + self._center) + string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch) + + if self._outer is not None: + string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', + self._outer._id) + else: + string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', + self._outer) + + string += '{0: <16}\n'.format('\tUniverses') + + if self._num_axial is not None: + slices = [self._repr_axial_slice(x) for x in self._universes] + string += '\n'.join(slices) + + else: + string += self._repr_axial_slice(self._universes) + + return string + @property def num_rings(self): return self._num_rings @@ -1157,34 +1361,6 @@ class HexLattice(Lattice): 6*(self._num_rings - 1 - r)) raise ValueError(msg) - def __repr__(self): - string = 'HexLattice\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\t# Rings', '=\t', self._num_rings) - string += '{0: <16}{1}{2}\n'.format('\t# Axial', '=\t', self._num_axial) - string += '{0: <16}{1}{2}\n'.format('\tCenter', '=\t', - self._center) - string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch) - - if self._outer is not None: - string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', - self._outer._id) - else: - string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', - self._outer) - - string += '{0: <16}\n'.format('\tUniverses') - - if self._num_axial is not None: - slices = [self._repr_axial_slice(x) for x in self._universes] - string += '\n'.join(slices) - - else: - string += self._repr_axial_slice(self._universes) - - return string - def create_xml_subelement(self, xml_element): # Determine if XML element already contains subelement for this Lattice path = './hex_lattice[@id=\'{0}\']'.format(self._id) diff --git a/scripts/openmc-plot-mesh-tally b/scripts/openmc-plot-mesh-tally index 5c46d927c0..04f1f06c6c 100755 --- a/scripts/openmc-plot-mesh-tally +++ b/scripts/openmc-plot-mesh-tally @@ -33,7 +33,7 @@ class MeshPlotter(tk.Frame): self.labels = {'cell': 'Cell:', 'cellborn': 'Cell born:', 'surface': 'Surface:', 'material': 'Material:', - 'universe': 'Universe:', 'energyin': 'Energy in:', + 'universe': 'Universe:', 'energy': 'Energy in:', 'energyout': 'Energy out:'} self.filterBoxes = {} @@ -133,7 +133,11 @@ class MeshPlotter(tk.Frame): self.mesh = selectedTally.filters_by_name['mesh'].mesh # Get mesh dimensions - self.nx, self.ny, self.nz = self.mesh.dimension + if len(self.mesh.dimension) == 2: + self.nx, self.ny = self.mesh.dimension + self.nz = 1 + else: + self.nx, self.ny, self.nz = self.mesh.dimension # Repopulate comboboxes baesd on current basis selection text = self.basisBox.get() @@ -176,9 +180,9 @@ class MeshPlotter(tk.Frame): self.filterBoxes[filterType] = combobox # Set combobox items - if filterType in ['energyin', 'energyout']: + if filterType in ['energy', 'energyout']: combobox['values'] = ['{0} to {1}'.format(*f.bins[i:i+2]) - for i in range(f.length)] + for i in range(len(f.bins) - 1)] else: combobox['values'] = [str(i) for i in f.bins] @@ -209,8 +213,13 @@ class MeshPlotter(tk.Frame): if f.type == 'mesh': mesh_filter = f continue - index = self.filterBoxes[f.type].current() - spec_list.append((f, index)) + elif f.type in ['energy', 'energyout']: + index = self.filterBoxes[f.type].current() + ebin = (f.bins[index], f.bins[index + 1]) + spec_list.append((f.type, (ebin,))) + else: + index = self.filterBoxes[f.type].current() + spec_list.append((f.type, (index,))) text = self.basisBox.get() if text == 'xy': @@ -229,11 +238,11 @@ class MeshPlotter(tk.Frame): else: meshtuple = (i + 1, axial_level, j + 1) filters, filter_bins = zip(*spec_list + [ - (mesh_filter, meshtuple)]) - mean = selectedTally.get_value( - self.scoreBox.get(), filters, filter_bins) - stdev = selectedTally.get_value( - self.scoreBox.get(), filters, filter_bins, + (mesh_filter.type, (meshtuple,))]) + mean = selectedTally.get_values( + [self.scoreBox.get()], filters, filter_bins) + stdev = selectedTally.get_values( + [self.scoreBox.get()], filters, filter_bins, value='std_dev') if mbvalue == 'Mean': matrix[i, j] = mean @@ -264,8 +273,6 @@ class MeshPlotter(tk.Frame): def get_file_data(self, filename): # Create StatePoint object and read in data self.datafile = StatePoint(filename) - self.datafile.read_results() - self.datafile.compute_stdev() # Find which tallies are mesh tallies self.meshTallies = [] diff --git a/scripts/openmc-statepoint-3d b/scripts/openmc-statepoint-3d index 30205c7692..e667ad0bbd 100755 --- a/scripts/openmc-statepoint-3d +++ b/scripts/openmc-statepoint-3d @@ -219,7 +219,7 @@ def main(file_, o): for y in range(1,ny+1): for z in range(1,nz+1): filterspec[0][1] = (x,y,z) - val = sp.get_value(tally.id-1, filterspec, sid)[o.valerr] + val = sp.get_values(tally.id-1, filterspec, sid)[o.valerr] if o.vtk: # vtk cells go z, y, x, so we store it now and enter it later i = (z-1)*nx*ny + (y-1)*nx + x-1 diff --git a/scripts/openmc-statepoint-histogram b/scripts/openmc-statepoint-histogram deleted file mode 100755 index 26e8bdae60..0000000000 --- a/scripts/openmc-statepoint-histogram +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python - -from __future__ import print_function -from sys import argv -from math import sqrt - -import numpy as np -import scipy.stats -import matplotlib.pyplot as plt - -from openmc.statepoint import StatePoint - -# Get filename -filename = argv[1] - -# Create StatePoint object -sp = StatePoint(filename) -sp.read_results() -sp.compute_ci() - -# Check if tallies are present -if not sp.tallies_present: - raise Exception("No tally data in state point!") - -# Loop over all tallies -for i, t in sp.tallies.items(): - # Determine relative error and fraction of bins with less than 1% half-width - # of CI - n_bins = t.mean.size - relative_error = t.std_dev[t.mean > 0.] / t.mean[t.mean > 0.] - fraction = float(sum(relative_error < 0.01))/n_bins - - # Display results - print("Tally " + str(i)) - print(" Fraction under 1% = {0}".format(fraction)) - print(" Min relative error = {0}".format(min(relative_error))) - print(" Max relative error = {0}".format(max(relative_error))) - print(" Non-scoring bins = {0}".format( - 1.0 - float(relative_error.size)/n_bins)) - - # Plot histogram - plt.hist(relative_error, 100) - plt.show() diff --git a/scripts/openmc-tally-convergence b/scripts/openmc-tally-convergence deleted file mode 100755 index 81f45fd717..0000000000 --- a/scripts/openmc-tally-convergence +++ /dev/null @@ -1,375 +0,0 @@ -#!/usr/bin/env python - -# This program takes OpenMC statepoint binary files and creates a variety of -# outputs from them which should provide the user with an idea of the -# convergence behavior of all the tallies and filters defined by the user in -# tallies.xml. The program can directly plot the value and errors of each -# tally, filter, score combination; it can save these plots to a file; and -# it can also save the data used in these plots to a CSV file for importing in -# to other plotting packages such as Excel, gnuplot, MathGL, or Veusz. - -# To use the program, run this program from the working directory of the openMC -# problem to analyze. - -# The USER OPTIONS block below provides four options for the user to set: -# fileType, printxs, showImg, and savetoCSV. See the options block for more -# information. - -from __future__ import print_function -from math import sqrt, pow -from glob import glob - -import numpy as np -import scipy.stats -import matplotlib.pyplot as plt - -from openmc.statepoint import StatePoint - -##################################### USER OPTIONS - -# Set filetype (the file extension desired, without the period.) -# Options are backend dependent, but most backends support png, pdf, ps, eps -# and svg. Write "none" if no saved files are desired. -fileType = "none" - -# Set if cross-sections or reaction rates are desired printxs = True means X/S -printxs = False - -# Set if the figures should be displayed to screen or not (True means show) -showImg = False - -# Save to CSV for use in more advanced plotting programs like GNUPlot, MathGL -savetoCSV = True - -##################################### END USER OPTIONS - -## Find if tallies.xml exists. -#if glob('./tallies.xml') != None: -# # It exists -# tallyData = talliesXML('tallies.xml') -#else: -# # It does not exist. -# tallyData = None - -# Find all statepoints in this directory. -files = glob('./statepoint.*.binary') -fileNums = [] -begin = 13 -# Arrange the file list in increasing batch order -for i in range(len(files)): - end = files[i].find(".binary") - fileNums.append(int(files[i][begin:end])) -fileNums.sort() -# Re-make filenames -files = [] -for i in range(len(fileNums)): - files.append("./statepoint." + str(fileNums[i]) + ".binary") - -# Initialize arrays as needed -mean = [None for x in range(len(files))] -uncert = [None for x in range(len(files))] -scoreType = [None for x in range(len(files))] -active_batches = [None for x in range(len(files))] - -for i_batch in range(len(files)): - - # Get filename - batch_filename = files[i_batch] - - # Create StatePoint object - sp = StatePoint(batch_filename) - - # Read number of realizations for global tallies - sp.n_realizations = sp._get_int()[0] - - # Read global tallies - n_global_tallies = sp._get_int()[0] - sp.global_tallies = np.array(sp._get_double(2*n_global_tallies)) - sp.global_tallies.shape = (n_global_tallies, 2) - - # Flag indicating if tallies are present - tallies_present = sp._get_int()[0] - - # Check if tallies are present - if not tallies_present: - raise Exception("No tally data in state point!") - - # Increase the dimensionality of our main variables - mean[i_batch] = [None for x in range(len(sp.tallies))] - uncert[i_batch] = [None for x in range(len(sp.tallies))] - scoreType[i_batch] = [None for x in range(len(sp.tallies))] - - # Loop over all tallies - for i_tally, t in enumerate(sp.tallies): - # Calculate t-value for 95% two-sided CI - n = t.n_realizations - t_value = scipy.stats.t.ppf(0.975, n - 1) - - # Store the batch count - active_batches[i_batch] = n - - # Resize the 2nd dimension - mean[i_batch][i_tally] = [None for x in range(t.total_filter_bins)] - uncert[i_batch][i_tally] = [None for x in range(t.total_filter_bins)] - scoreType[i_batch][i_tally] = [None for x in range(t.total_filter_bins)] - - for i_filter in range(t.total_filter_bins): - # Resize the 3rd dimension - mean[i_batch][i_tally][i_filter] = [None for x in range(t.n_nuclides)] - uncert[i_batch][i_tally][i_filter] = [None for x in range(t.n_nuclides)] - scoreType[i_batch][i_tally][i_filter] = [None for x in range(t.n_nuclides)] - print(t.total_filter_bins,t.n_nuclides) - for i_nuclide in range(t.n_nuclides): - mean[i_batch][i_tally][i_filter][i_nuclide] = \ - [None for x in range(t.n_scores)] - uncert[i_batch][i_tally][i_filter][i_nuclide] = \ - [None for x in range(t.n_scores)] - scoreType[i_batch][i_tally][i_filter][i_nuclide] = \ - [None for x in range(t.n_scores)] - for i_score in range(t.n_scores): - scoreType[i_batch][i_tally][i_filter][i_nuclide][i_score] = \ - t.scores[i_score] - s, s2 = sp._get_double(2) - s /= n - mean[i_batch][i_tally][i_filter][i_nuclide][i_score] = s - if s != 0.0: - relative_error = t_value*sqrt((s2/n - s*s)/(n-1))/s - else: - relative_error = 0.0 - uncert[i_batch][i_tally][i_filter][i_nuclide][i_score] = relative_error - -# Reorder the data lists in to a list order more conducive for plotting: -# The indexing should be: [tally][filter][score][batch] -meanPlot = [None for x in range(len(mean[0]))] # Set to the number of tallies -uncertPlot = [None for x in range(len(mean[0]))] # Set to the number of tallies -absUncertPlot = [None for x in range(len(mean[0]))] # Set to number of tallies -filterLabel = [None for x in range(len(mean[0]))] #Set to the number of tallies -fluxLoc = [None for x in range(len(mean[0]))] # Set to the number of tallies -printxs = [False for x in range(len(mean[0]))] # Set to the number of tallies - -# Get and set the correct sizes for the rest of the dimensions -for i_tally in range(len(meanPlot)): - # Set 2nd (score) dimension - meanPlot[i_tally] = [None for x in range(len(mean[0][i_tally]))] - uncertPlot[i_tally] = [None for x in range(len(mean[0][i_tally]))] - absUncertPlot[i_tally] = [None for x in range(len(mean[0][i_tally]))] - filterLabel[i_tally] = [None for x in range(len(mean[0][i_tally]))] - - # Initialize flux location so it will be -1 if not found - fluxLoc[i_tally] = -1 - - for i_filter in range(len(meanPlot[i_tally])): - # Set 3rd (filter) dimension - meanPlot[i_tally][i_filter] = \ - [None for x in range(len(mean[0][i_tally][i_filter]))] - uncertPlot[i_tally][i_filter] = \ - [None for x in range(len(mean[0][i_tally][i_filter]))] - absUncertPlot[i_tally][i_filter] = \ - [None for x in range(len(mean[0][i_tally][i_filter]))] - filterLabel[i_tally][i_filter] = \ - [None for x in range(len(mean[0][i_tally][i_filter]))] - - for i_nuclide in range(len(meanPlot[i_tally][i_filter])): - # Set 4th (nuclide)) dimension - meanPlot[i_tally][i_filter][i_nuclide] = \ - [None for x in range(len(mean[0][i_tally][i_filter][i_nuclide]))] - uncertPlot[i_tally][i_filter][i_nuclide] = \ - [None for x in range(len(mean[0][i_tally][i_filter][i_nuclide]))] - absUncertPlot[i_tally][i_filter][i_nuclide] = \ - [None for x in range(len(mean[0][i_tally][i_filter][i_nuclide]))] - - for i_score in range(len(meanPlot[i_tally][i_filter][i_nuclide])): - # Set 5th (batch) dimension - meanPlot[i_tally][i_filter][i_nuclide][i_score] = \ - [None for x in range(len(mean))] - uncertPlot[i_tally][i_filter][i_nuclide][i_score] = \ - [None for x in range(len(mean))] - absUncertPlot[i_tally][i_filter][i_nuclide][i_score] = \ - [None for x in range(len(mean))] - - # Get filterLabel (this should be moved to its own function) - #??? How to do? - - # Set flux location if found - # all batches and all tallies will have the same score ordering, hence - # the 0's in the 1st, 3rd, and 4th dimensions. - if scoreType[0][i_tally][0][0][i_score] == 'flux': - fluxLoc[i_tally] = i_score - -# Set printxs array according to the printxs input -if printxs: - for i_tally in range(len(fluxLoc)): - if fluxLoc[i_tally] != -1: - printxs[i_tally] = True - -# Now rearrange the data as suitable, and perform xs conversion if necessary -for i_batch in range(len(mean)): - for i_tally in range(len(mean[i_batch])): - for i_filter in range(len(mean[i_batch][i_tally])): - for i_nuclide in range(len(mean[i_batch][i_tally][i_filter])): - for i_score in range(len(mean[i_batch][i_tally][i_filter][i_nuclide])): - if (printxs[i_tally] and \ - ((scoreType[0][i_tally][i_filter][i_nuclide][i_score] != 'flux') and \ - (scoreType[0][i_tally][i_filter][i_nuclide][i_score] != 'current'))): - - # Perform rate to xs conversion - # mean is mean/fluxmean - meanPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - mean[i_batch][i_tally][i_filter][i_nuclide][i_score] / \ - mean[i_batch][i_tally][i_filter][i_nuclide][fluxLoc[i_tally]] - - # Update the relative uncertainty via error propagation - uncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - sqrt(pow(uncert[i_batch][i_tally][i_filter][i_nuclide][i_score],2) \ - + pow(uncert[i_batch][i_tally][i_filter][i_nuclide][fluxLoc[i_tally]],2)) - else: - - # Do not perform rate to xs conversion - meanPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - mean[i_batch][i_tally][i_filter][i_nuclide][i_score] - uncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - uncert[i_batch][i_tally][i_filter][i_nuclide][i_score] - - # Both have the same absolute uncertainty calculation - absUncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch] = \ - uncert[i_batch][i_tally][i_filter][i_nuclide][i_score] * \ - mean[i_batch][i_tally][i_filter][i_nuclide][i_score] - -# Set plotting constants -xLabel = "Batches" -xLabel = xLabel.title() # not necessary for now, but is left in to handle if -# the previous line changes - -# Begin plotting -for i_tally in range(len(meanPlot)): - # Set tally string (placeholder until I put tally labels in statePoint) - tallyStr = "Tally " + str(i_tally + 1) - - for i_filter in range(len(meanPlot[i_tally])): - - # Set filter string - filterStr = "Filter " + str(i_filter + 1) - - for i_nuclide in range(len(meanPlot[i_tally][i_filter])): - - nuclideStr = "Nuclide " + str(i_nuclide + 1) - - for i_score in range(len(meanPlot[i_tally][i_filter][i_nuclide])): - - # Set score string - scoreStr = scoreType[i_batch][i_tally][i_filter][i_nuclide][i_score] - scoreStr = scoreStr.title() - if (printxs[i_tally] and ((scoreStr != 'Flux') and \ - (scoreStr != 'Current'))): - scoreStr = scoreStr + "-XS" - - # set Title - title = "Convergence of " + scoreStr + " in " + tallyStr + " for "\ - + filterStr + " and " + nuclideStr - - # set yLabel - yLabel = scoreStr - yLabel = yLabel.title() - - # Set saving filename - fileName = "tally_" + str(i_tally + 1) + "_" + scoreStr + \ - "_filter_" + str(i_filter+1) + "_nuclide_" + str(i_nuclide+1) \ - + "." + fileType - REfileName = "tally_" + str(i_tally + 1) + "_" + scoreStr + \ - "RE_filter_" + str(i_filter+1) + "_nuclide_" + str(i_nuclide+1) \ - + "." + fileType - - # Plot mean with absolute error bars - plt.errorbar(active_batches, \ - meanPlot[i_tally][i_filter][i_nuclide][i_score][:], \ - absUncertPlot[i_tally][i_filter][i_nuclide][i_score][:],fmt='o-',aa=True) - plt.xlabel(xLabel) - plt.ylabel(yLabel) - plt.title(title) - if (fileType != 'none'): - plt.savefig(fileName) - if showImg: - plt.show() - plt.clf() - - # Plot relative uncertainty - plt.plot(active_batches, \ - uncertPlot[i_tally][i_filter][i_nuclide][i_score][:],'o-',aa=True) - plt.xlabel(xLabel) - plt.ylabel("Relative Error of " + yLabel) - plt.title("Relative Error of " + title) - if (fileType != 'none'): - plt.savefig(REfileName) - if showImg: - plt.show() - plt.clf() - -if savetoCSV: - # This block loops through each tally, and for each tally: - # Creates a new file - # Writes the scores and filters for that tally in csv format. - # The columns will be: batches,then for each filter: all the scores - # The rows, of course, are the data points per batch. - - for i_tally in range(len(meanPlot)): - # Set tally string (placeholder until I put tally labels in statePoint) - tallyStr = "Tally " + str(i_tally + 1) - CSV_filename = "./tally" + str(i_tally+1)+".csv" - # Open the file - f = open(CSV_filename, 'w') - - # Write the header line - - lineText = "Batches" - - for i_filter in range(len(meanPlot[i_tally])): - - # Set filter string - filterStr = "Filter " + str(i_filter + 1) - - for i_nuclide in range(len(meanPlot[i_tally][i_filter])): - - nuclideStr = "Nuclide " + str(i_nuclide + 1) - - for i_score in range(len(meanPlot[i_tally][i_filter][i_nuclide])): - - # Set the title - scoreStr = scoreType[i_batch][i_tally][i_filter][i_nuclide][i_score] - scoreStr = scoreStr.title() - if (printxs[i_tally] and ((scoreStr != 'Flux') and \ - (scoreStr != 'Current'))): - scoreStr = scoreStr + "-XS" - - # set header - headerText = scoreStr + " for " + filterStr + " for " + nuclideStr - - lineText = lineText + "," + headerText + \ - ",Abs Unc of " + headerText + \ - ",Rel Unc of " + headerText - - f.write(lineText + "\n") - - # Write the data lines, each row is a different batch - - for i_batch in range(len(meanPlot[i_tally][0][0][0])): - - lineText = repr(active_batches[i_batch]) - - for i_filter in range(len(meanPlot[i_tally])): - - for i_nuclide in range(len(meanPlot[i_tally][i_filter])): - - for i_score in range(len(meanPlot[i_tally][i_filter][i_nuclide])): - - fieldText = \ - repr(meanPlot[i_tally][i_filter][i_nuclide][i_score][i_batch]) + \ - "," + \ - repr(absUncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch]) +\ - "," + \ - repr(uncertPlot[i_tally][i_filter][i_nuclide][i_score][i_batch]) - - lineText = lineText + "," + fieldText - - f.write(lineText + "\n") - - diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk index 8db57e2a3f..e22a22dea3 100755 --- a/scripts/openmc-track-to-vtk +++ b/scripts/openmc-track-to-vtk @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python """Convert binary particle track to VTK poly data. Usage information can be obtained by running 'track.py --help': @@ -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,51 +40,38 @@ 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').read() - coords = [struct.unpack("ddd", track[24*i : 24*(i+1)]) - for i in range(len(track)/24)] - n_points = len(coords) - for triplet in coords: - points.InsertNextPoint(triplet) - else: - coords = h5py.File(fname).get('coordinates') - n_points = coords.shape[0] - for i in range(n_points): - points.InsertNextPoint(coords[i, :]) + 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,:]) - # Create VTK line and assign points to line. - line = vtk.vtkPolyLine() - line.GetPointIds().SetNumberOfIds(n_points) - for i in range(n_points): - line.GetPointIds().SetId(i, point_offset+i) + for i in range(n_particles): + # Create VTK line and assign points to line. + line = vtk.vtkPolyLine() + line.GetPointIds().SetNumberOfIds(n_coords[i]) + for j in range(n_coords[i]): + line.GetPointIds().SetId(j, point_offset + j) + + # Add line to cell array + cells.InsertNextCell(line) + point_offset += n_coords[i] - cells.InsertNextCell(line) - point_offset += n_points data = vtk.vtkPolyData() data.SetPoints(points) data.SetLines(cells) diff --git a/scripts/openmc-update-inputs b/scripts/openmc-update-inputs index f2e5308d02..2a8097854d 100755 --- a/scripts/openmc-update-inputs +++ b/scripts/openmc-update-inputs @@ -1,14 +1,15 @@ #!/usr/bin/env python """Update OpenMC's input XML files to the latest format. -Usage information can be obtained by running 'update_inputs.py --help': +Usage information can be obtained by running 'openmc-update-inputs --help': -usage: update_lattices.py [-h] IN [IN ...] +usage: openmc-update-inputs [-h] IN [IN ...] -Update lattices in geometry.xml files to the latest format. This will remove -'outside' attributes/elements and replace them with 'outer' attributes. Note -that this script will not delete the given files; it will append '.original' -to the given files and write new ones. +Update geometry.xml files to the latest format. This will remove 'outside' +attributes/elements from lattices and replace them with 'outer' attributes. For +'cell' elements, any 'surfaces' attributes/elements will be renamed +'region'. Note that this script will not delete the given files; it will append +'.original' to the given files and write new ones. positional arguments: IN Input geometry.xml file(s). @@ -35,9 +36,10 @@ they will be moved to a new file with '.original' appended to their name. Formatting changes that will be made: -geometry.xml: Lattices containing 'outside' attributes/tags will be replaced +geometry.xml: Lattices containing 'outside' attributes/tags will be replaced with lattices containing 'outer' attributes, and the appropriate - cells/universes will be added. + cells/universes will be added. Any 'surfaces' attributes/elements on a cell + will be renamed 'region'. """ @@ -173,9 +175,6 @@ def update_geometry(geometry_root): root = geometry_root was_updated = False - # Ignore files that do not contain lattices. - if all([child.tag != 'lattice' for child in root]): return False - # Get a set of already-used universe and cell ids. uids = get_universe_ids(root) cids = get_cell_ids(root) @@ -233,6 +232,17 @@ def update_geometry(geometry_root): del lat.attrib['width'] was_updated = True + # Change 'surfaces' to 'region' in cell definitions + for cell in root.iter('cell'): + elem = cell.find('surfaces') + if elem is not None: + elem.tag = 'region' + was_updated = True + if 'surfaces' in cell.attrib: + cell.attrib['region'] = cell.attrib['surfaces'] + del cell.attrib['surfaces'] + was_updated = True + return was_updated diff --git a/scripts/openmc-voxel-to-silovtk b/scripts/openmc-voxel-to-silovtk index eb052c75fa..1329b6b6c7 100755 --- a/scripts/openmc-voxel-to-silovtk +++ b/scripts/openmc-voxel-to-silovtk @@ -1,9 +1,11 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python from __future__ import division, print_function import struct import sys +import numpy as np +import h5py def parse_options(): """Process command line arguments""" @@ -22,14 +24,16 @@ def parse_options(): return parsed -def main(file_, o): - print(file_) - fh = open(file_, 'rb') - header = get_header(fh) - meshparms = (header['dimension'] + header['lower_left'] + - header['upper_right']) - nx, ny, nz = meshparms[:3] - ll = header['lower_left'] +def main(filename, o): + # Read data from voxel file + fh = h5py.File(filename, 'r') + dimension = fh['num_voxels'].value + width = fh['voxel_width'].value + lower_left = fh['lower_left'].value + voxel_data = fh['data'].value + + nx, ny, nz = dimension + upper_right = lower_left + width*dimension if o.vtk: try: @@ -40,13 +44,10 @@ def main(file_, o): 'See: http://www.vtk.org/') return - origin = [(l + w*n/2.) for n, l, w in - zip((nx, ny, nz), ll, header['width'])] - grid = vtk.vtkImageData() grid.SetDimensions(nx+1, ny+1, nz+1) - grid.SetOrigin(*ll) - grid.SetSpacing(*header['width']) + grid.SetOrigin(*lower_left) + grid.SetSpacing(*width) data = vtk.vtkDoubleArray() data.SetName("id") @@ -57,8 +58,7 @@ def main(file_, o): for y in range(ny): for z in range(nz): i = z*nx*ny + y*nx + x - id_ = get_int(fh)[0] - data.SetValue(i, id_) + data.SetValue(i, voxel_data[x,y,z]) grid.GetCellData().AddArray(data) writer = vtk.vtkXMLImageDataWriter() @@ -81,44 +81,23 @@ def main(file_, o): if not o.output.endswith(".silo"): o.output += ".silo" silomesh.init_silo(o.output) - silomesh.init_mesh('plot', *meshparms) + meshparams = list(map(int, dimension)) + list(map(float, lower_left)) + \ + list(map(float, upper_right)) + silomesh.init_mesh('plot', *meshparams) silomesh.init_var("id") - for x in range(1, nx+1): + for x in range(nx): sys.stdout.write(" {0}%\r".format(int(x/nx*100))) sys.stdout.flush() - for y in range(1, ny+1): - for z in range(1, nz+1): - id_ = get_int(fh)[0] - silomesh.set_value(float(id_), x, y, z) + for y in range(ny): + for z in range(nz): + silomesh.set_value(float(voxel_data[x,y,z]), + x + 1, y + 1, z + 1) print() silomesh.finalize_var() silomesh.finalize_mesh() silomesh.finalize_silo() -def get_header(file_): - nx, ny, nz = get_int(file_, 3) - wx, wy, wz = get_double(file_, 3) - lx, ly, lz = get_double(file_, 3) - header = {'dimension': [nx, ny, nz], 'width': [wx, wy, wz], - 'lower_left': [lx, ly, lz], - 'upper_right': [lx+wx*nx, ly+wy*ny, lz+wz*nz]} - return header - - -def get_data(file_, n, typeCode, size): - return list(struct.unpack('={0}{1}'.format(n, typeCode), - file_.read(n*size))) - - -def get_int(file_, n=1, path=None): - return get_data(file_, n, 'i', 4) - - -def get_double(file_, n=1, path=None): - return get_data(file_, n, 'd', 8) - - if __name__ == '__main__': (options, args) = parse_options() if args: diff --git a/setup.py b/setup.py index 655e38e3a4..907d80e31b 100644 --- a/setup.py +++ b/setup.py @@ -10,8 +10,8 @@ except ImportError: have_setuptools = False kwargs = {'name': 'openmc', - 'version': '0.7.0', - 'packages': ['openmc'], + 'version': '0.7.1', + 'packages': ['openmc', 'openmc.mgxs'], 'scripts': glob.glob('scripts/openmc-*'), # Metadata @@ -32,7 +32,7 @@ kwargs = {'name': 'openmc', if have_setuptools: kwargs.update({ # Required dependencies - 'install_requires': ['numpy', 'scipy', 'h5py', 'matplotlib'], + 'install_requires': ['numpy', 'h5py', 'matplotlib'], # Optional dependencies 'extras_require': { diff --git a/src/ace.F90 b/src/ace.F90 index 0dd92ea2c7..e97338b558 100644 --- a/src/ace.F90 +++ b/src/ace.F90 @@ -45,9 +45,9 @@ contains integer :: temp_table ! temporary value for sorting character(12) :: name ! name of isotope, e.g. 92235.03c character(12) :: alias ! alias of nuclide, e.g. U-235.03c - type(Material), pointer :: mat => null() - type(Nuclide), pointer :: nuc => null() - type(SAlphaBeta), pointer :: sab => null() + type(Material), pointer :: mat + type(Nuclide), pointer :: nuc + type(SAlphaBeta), pointer :: sab type(SetChar) :: already_read ! allocate arrays for ACE table storage and cross section cache @@ -215,6 +215,16 @@ contains end do MATERIAL_LOOP3 + ! Show which nuclide results in lowest energy for neutron transport + do i = 1, n_nuclides_total + if (nuclides(i)%energy(nuclides(i)%n_grid) == energy_max_neutron) then + call write_message("Maximum neutron transport energy: " // & + trim(to_str(energy_max_neutron)) // " MeV for " // & + trim(adjustl(nuclides(i)%name)), 6) + exit + end if + end do + end subroutine read_xs !=============================================================================== @@ -224,7 +234,6 @@ contains !=============================================================================== subroutine read_ace_table(i_table, i_listing) - integer, intent(in) :: i_table ! index in nuclides/sab_tables integer, intent(in) :: i_listing ! index in xs_listings @@ -234,7 +243,7 @@ contains integer :: location ! location of ACE table integer :: entries ! number of entries on each record integer :: length ! length of ACE table - integer :: in = 7 ! file unit + integer :: unit_ace ! file unit integer :: zaids(16) ! list of ZAIDs (only used for S(a,b)) integer :: filetype ! filetype (ASCII or BINARY) real(8) :: kT ! temperature of table @@ -248,9 +257,9 @@ contains character(10) :: mat ! material identifier character(70) :: comment ! comment for ACE table character(MAX_FILE_LEN) :: filename ! path to ACE cross section library - type(Nuclide), pointer :: nuc => null() - type(SAlphaBeta), pointer :: sab => null() - type(XsListing), pointer :: listing => null() + type(Nuclide), pointer :: nuc + type(SAlphaBeta), pointer :: sab + type(XsListing), pointer :: listing ! determine path, record length, and location of table listing => xs_listings(i_listing) @@ -277,14 +286,14 @@ contains ! READ ACE TABLE IN ASCII FORMAT ! Find location of table - open(UNIT=in, FILE=filename, STATUS='old', ACTION='read') - rewind(UNIT=in) + open(NEWUNIT=unit_ace, FILE=filename, STATUS='old', ACTION='read') + rewind(UNIT=unit_ace) do i = 1, location - 1 - read(UNIT=in, FMT=*) + read(UNIT=unit_ace, FMT=*) end do ! Read first line of header - read(UNIT=in, FMT='(A10,2G12.0,1X,A10)') name, awr, kT, date_ + read(UNIT=unit_ace, FMT='(A10,2G12.0,1X,A10)') name, awr, kT, date_ ! Check that correct xs was found -- if cross_sections.xml is broken, the ! location of the table may be wrong @@ -294,7 +303,7 @@ contains end if ! Read more header and NXS and JXS - read(UNIT=in, FMT=100) comment, mat, & + read(UNIT=unit_ace, FMT=100) comment, mat, & (zaids(i), awrs(i), i=1,16), NXS, JXS 100 format(A70,A10/4(I7,F11.0)/4(I7,F11.0)/4(I7,F11.0)/4(I7,F11.0)/& ,8I9/8I9/8I9/8I9/8I9/8I9) @@ -304,21 +313,21 @@ contains allocate(XSS(length)) ! Read XSS array - read(UNIT=in, FMT='(4G20.0)') XSS + read(UNIT=unit_ace, FMT='(4G20.0)') XSS ! Close ACE file - close(UNIT=in) + close(UNIT=unit_ace) elseif (filetype == BINARY) then ! ======================================================================= ! READ ACE TABLE IN BINARY FORMAT ! Open ACE file - open(UNIT=in, FILE=filename, STATUS='old', ACTION='read', & + open(NEWUNIT=unit_ace, FILE=filename, STATUS='old', ACTION='read', & ACCESS='direct', RECL=record_length) ! Read all header information - read(UNIT=in, REC=location) name, awr, kT, date_, & + read(UNIT=unit_ace, REC=location) name, awr, kT, date_, & comment, mat, (zaids(i), awrs(i), i=1,16), NXS, JXS ! determine table length @@ -329,11 +338,11 @@ contains do i = 1, (length + entries - 1)/entries j1 = 1 + (i-1)*entries j2 = min(length, j1 + entries - 1) - read(UNIT=IN, REC=location + i) (XSS(j), j=j1,j2) + read(UNIT=UNIT_ACE, REC=location + i) (XSS(j), j=j1,j2) end do ! Close ACE file - close(UNIT=in) + close(UNIT=unit_ace) end if ! ========================================================================== @@ -396,8 +405,6 @@ contains end select deallocate(XSS) - if(associated(nuc)) nullify(nuc) - if(associated(sab)) nullify(sab) end subroutine read_ace_table @@ -407,10 +414,8 @@ contains !=============================================================================== subroutine read_esz(nuc, data_0K) - - type(Nuclide), pointer :: nuc - - logical :: data_0K ! are we reading 0K data? + type(Nuclide), intent(inout) :: nuc + logical, intent(in) :: data_0K ! are we reading 0K data? integer :: NE ! number of energy points for total and elastic cross sections integer :: i ! index in 0K elastic xs array for this nuclide @@ -482,6 +487,10 @@ contains ! Continue reading elastic scattering and heating nuc % elastic = get_real(NE) + ! Determine if minimum/maximum energy for this nuclide is greater/less + ! than the previous + energy_min_neutron = max(energy_min_neutron, nuc%energy(1)) + energy_max_neutron = min(energy_max_neutron, nuc%energy(NE)) end if end subroutine read_esz @@ -493,8 +502,7 @@ contains !=============================================================================== subroutine read_nu_data(nuc) - - type(Nuclide), pointer :: nuc + type(Nuclide), intent(inout) :: nuc integer :: i ! loop index integer :: JXS2 ! location for fission nu data @@ -510,7 +518,7 @@ contains integer :: LOCC ! location of energy distributions for given MT integer :: lc ! locator integer :: length ! length of data to allocate - type(DistEnergy), pointer :: edist => null() + type(DistEnergy), pointer :: edist JXS2 = JXS(2) JXS24 = JXS(24) @@ -635,6 +643,15 @@ contains ! Allocate space for secondary energy distribution NPCR = NXS(8) + + ! Check to make sure nuclide does not have more than the maximum number + ! of delayed groups + if (NPCR > MAX_DELAYED_GROUPS) then + call fatal_error("Encountered nuclide with " // trim(to_str(NPCR)) & + // " delayed groups while the maximum number of delayed groups & + &set in constants.F90 is " // trim(to_str(MAX_DELAYED_GROUPS))) + end if + nuc % n_precursor = NPCR allocate(nuc % nu_d_edist(NPCR)) @@ -672,6 +689,7 @@ contains else nuc % nu_d_type = NU_NONE + nuc % n_precursor = 0 end if end subroutine read_nu_data @@ -683,8 +701,7 @@ contains !=============================================================================== subroutine read_reactions(nuc) - - type(Nuclide), pointer :: nuc + type(Nuclide), intent(inout) :: nuc integer :: i ! loop indices integer :: i_fission ! index in nuc % index_fission @@ -698,7 +715,6 @@ contains integer :: IE ! reaction's starting index on energy grid integer :: NE ! number of energies integer :: NR ! number of interpolation regions - type(Reaction), pointer :: rxn => null() type(ListInt) :: MTs LMT = JXS(3) @@ -716,14 +732,15 @@ contains ! Store elastic scattering cross-section on reaction one -- note that the ! sigma array is not allocated or stored for elastic scattering since it is ! already stored in nuc % elastic - rxn => nuc % reactions(1) - rxn % MT = 2 - rxn % Q_value = ZERO - rxn % multiplicity = 1 - rxn % threshold = 1 - rxn % scatter_in_cm = .true. - rxn % has_angle_dist = .false. - rxn % has_energy_dist = .false. + associate (rxn => nuc % reactions(1)) + rxn%MT = 2 + rxn%Q_value = ZERO + rxn%multiplicity = 1 + rxn%threshold = 1 + rxn%scatter_in_cm = .true. + rxn%has_angle_dist = .false. + rxn%has_energy_dist = .false. + end associate ! Add contribution of elastic scattering to total cross section nuc % total = nuc % total + nuc % elastic @@ -736,123 +753,125 @@ contains i_fission = 0 do i = 1, NMT - rxn => nuc % reactions(i+1) + associate (rxn => nuc % reactions(i+1)) + ! set defaults + rxn % has_angle_dist = .false. + rxn % has_energy_dist = .false. - ! set defaults - rxn % has_angle_dist = .false. - rxn % has_energy_dist = .false. + ! read MT number, Q-value, and neutrons produced + rxn % MT = int(XSS(LMT + i - 1)) + rxn % Q_value = XSS(JXS4 + i - 1) + rxn % multiplicity = abs(nint(XSS(JXS5 + i - 1))) + rxn % scatter_in_cm = (nint(XSS(JXS5 + i - 1)) < 0) - ! read MT number, Q-value, and neutrons produced - rxn % MT = int(XSS(LMT + i - 1)) - rxn % Q_value = XSS(JXS4 + i - 1) - rxn % multiplicity = abs(nint(XSS(JXS5 + i - 1))) - rxn % scatter_in_cm = (nint(XSS(JXS5 + i - 1)) < 0) + ! Read energy-dependent multiplicities + if (rxn % multiplicity > 100) then + ! Set flag and allocate space for Tab1 to store yield + rxn % multiplicity_with_E = .true. + allocate(rxn % multiplicity_E) - ! Read energy-dependent multiplicities - if (rxn % multiplicity > 100) then - ! Set flag and allocate space for Tab1 to store yield - rxn % multiplicity_with_E = .true. - allocate(rxn % multiplicity_E) + XSS_index = JXS(11) + rxn % multiplicity - 101 + NR = nint(XSS(XSS_index)) + rxn % multiplicity_E % n_regions = NR - XSS_index = JXS(11) + rxn % multiplicity - 101 - NR = nint(XSS(XSS_index)) - rxn % multiplicity_E % n_regions = NR + ! allocate space for ENDF interpolation parameters + if (NR > 0) then + allocate(rxn % multiplicity_E % nbt(NR)) + allocate(rxn % multiplicity_E % int(NR)) + end if - ! allocate space for ENDF interpolation parameters - if (NR > 0) then - allocate(rxn % multiplicity_E % nbt(NR)) - allocate(rxn % multiplicity_E % int(NR)) + ! read ENDF interpolation parameters + XSS_index = XSS_index + 1 + if (NR > 0) then + rxn % multiplicity_E % nbt = get_int(NR) + rxn % multiplicity_E % int = get_int(NR) + end if + + ! allocate space for yield data + XSS_index = XSS_index + 2*NR + NE = nint(XSS(XSS_index)) + rxn % multiplicity_E % n_pairs = NE + allocate(rxn % multiplicity_E % x(NE)) + allocate(rxn % multiplicity_E % y(NE)) + + ! read yield data + XSS_index = XSS_index + 1 + rxn % multiplicity_E % x = get_real(NE) + rxn % multiplicity_E % y = get_real(NE) end if - ! read ENDF interpolation parameters - XSS_index = XSS_index + 1 - if (NR > 0) then - rxn % multiplicity_E % nbt = get_int(NR) - rxn % multiplicity_E % int = get_int(NR) - end if + ! read starting energy index + LOCA = int(XSS(LXS + i - 1)) + IE = int(XSS(JXS7 + LOCA - 1)) + rxn % threshold = IE - ! allocate space for yield data - XSS_index = XSS_index + 2*NR - NE = nint(XSS(XSS_index)) - rxn % multiplicity_E % n_pairs = NE - allocate(rxn % multiplicity_E % x(NE)) - allocate(rxn % multiplicity_E % y(NE)) - - ! read yield data - XSS_index = XSS_index + 1 - rxn % multiplicity_E % x = get_real(NE) - rxn % multiplicity_E % y = get_real(NE) - end if - - ! read starting energy index - LOCA = int(XSS(LXS + i - 1)) - IE = int(XSS(JXS7 + LOCA - 1)) - rxn % threshold = IE - - ! read number of energies cross section values - NE = int(XSS(JXS7 + LOCA)) - allocate(rxn % sigma(NE)) - XSS_index = JXS7 + LOCA + 1 - rxn % sigma = get_real(NE) + ! read number of energies cross section values + NE = int(XSS(JXS7 + LOCA)) + allocate(rxn % sigma(NE)) + XSS_index = JXS7 + LOCA + 1 + rxn % sigma = get_real(NE) + end associate end do ! Create set of MT values do i = 1, size(nuc % reactions) call MTs % append(nuc % reactions(i) % MT) + call nuc%reaction_index%add_key(nuc%reactions(i)%MT, i) end do ! Create total, absorption, and fission cross sections do i = 2, size(nuc % reactions) - rxn => nuc % reactions(i) - IE = rxn % threshold - NE = size(rxn % sigma) + associate (rxn => nuc % reactions(i)) + IE = rxn % threshold + NE = size(rxn % sigma) - ! Skip total inelastic level scattering, gas production cross sections - ! (MT=200+), etc. - if (rxn % MT == N_LEVEL) cycle - if (rxn % MT > N_5N2P .and. rxn % MT < N_P0) cycle + ! Skip total inelastic level scattering, gas production cross sections + ! (MT=200+), etc. + if (rxn % MT == N_LEVEL) cycle + if (rxn % MT > N_5N2P .and. rxn % MT < N_P0) cycle - ! Skip level cross sections if total is available - if (rxn % MT >= N_P0 .and. rxn % MT <= N_PC .and. MTs % contains(N_P)) cycle - if (rxn % MT >= N_D0 .and. rxn % MT <= N_DC .and. MTs % contains(N_D)) cycle - if (rxn % MT >= N_T0 .and. rxn % MT <= N_TC .and. MTs % contains(N_T)) cycle - if (rxn % MT >= N_3HE0 .and. rxn % MT <= N_3HEC .and. MTs % contains(N_3HE)) cycle - if (rxn % MT >= N_A0 .and. rxn % MT <= N_AC .and. MTs % contains(N_A)) cycle - if (rxn % MT >= N_2N0 .and. rxn % MT <= N_2NC .and. MTs % contains(N_2N)) cycle + ! Skip level cross sections if total is available + if (rxn % MT >= N_P0 .and. rxn % MT <= N_PC .and. MTs % contains(N_P)) cycle + if (rxn % MT >= N_D0 .and. rxn % MT <= N_DC .and. MTs % contains(N_D)) cycle + if (rxn % MT >= N_T0 .and. rxn % MT <= N_TC .and. MTs % contains(N_T)) cycle + if (rxn % MT >= N_3HE0 .and. rxn % MT <= N_3HEC .and. MTs % contains(N_3HE)) cycle + if (rxn % MT >= N_A0 .and. rxn % MT <= N_AC .and. MTs % contains(N_A)) cycle + if (rxn % MT >= N_2N0 .and. rxn % MT <= N_2NC .and. MTs % contains(N_2N)) cycle - ! Add contribution to total cross section - nuc % total(IE:IE+NE-1) = nuc % total(IE:IE+NE-1) + rxn % sigma + ! Add contribution to total cross section + nuc % total(IE:IE+NE-1) = nuc % total(IE:IE+NE-1) + rxn % sigma - ! Add contribution to absorption cross section - if (is_disappearance(rxn % MT)) then - nuc % absorption(IE:IE+NE-1) = nuc % absorption(IE:IE+NE-1) + rxn % sigma - end if + ! Add contribution to absorption cross section + if (is_disappearance(rxn % MT)) then + nuc % absorption(IE:IE+NE-1) = nuc % absorption(IE:IE+NE-1) + rxn % sigma + end if - ! Information about fission reactions - if (rxn % MT == N_FISSION) then - allocate(nuc % index_fission(1)) - elseif (rxn % MT == N_F) then - allocate(nuc % index_fission(PARTIAL_FISSION_MAX)) - nuc % has_partial_fission = .true. - end if + ! Information about fission reactions + if (rxn % MT == N_FISSION) then + allocate(nuc % index_fission(1)) + elseif (rxn % MT == N_F) then + allocate(nuc % index_fission(PARTIAL_FISSION_MAX)) + nuc % has_partial_fission = .true. + end if - ! Add contribution to fission cross section - if (is_fission(rxn % MT)) then - nuc % fissionable = .true. - nuc % fission(IE:IE+NE-1) = nuc % fission(IE:IE+NE-1) + rxn % sigma + ! Add contribution to fission cross section + if (is_fission(rxn % MT)) then + nuc % fissionable = .true. + nuc % fission(IE:IE+NE-1) = nuc % fission(IE:IE+NE-1) + rxn % sigma - ! Also need to add fission cross sections to absorption - nuc % absorption(IE:IE+NE-1) = nuc % absorption(IE:IE+NE-1) + rxn % sigma + ! Also need to add fission cross sections to absorption + nuc % absorption(IE:IE+NE-1) = nuc % absorption(IE:IE+NE-1) + rxn % sigma - ! If total fission reaction is present, there's no need to store the - ! reaction cross-section since it was copied to nuc % fission - if (rxn % MT == N_FISSION) deallocate(rxn % sigma) + ! If total fission reaction is present, there's no need to store the + ! reaction cross-section since it was copied to nuc % fission + if (rxn % MT == N_FISSION) deallocate(rxn % sigma) - ! Keep track of this reaction for easy searching later - i_fission = i_fission + 1 - nuc % index_fission(i_fission) = i - nuc % n_fission = nuc % n_fission + 1 - end if + ! Keep track of this reaction for easy searching later + i_fission = i_fission + 1 + nuc % index_fission(i_fission) = i + nuc % n_fission = nuc % n_fission + 1 + end if + end associate end do ! Clear MTs set @@ -866,8 +885,7 @@ contains !=============================================================================== subroutine read_angular_dist(nuc) - - type(Nuclide), pointer :: nuc + type(Nuclide), intent(inout) :: nuc integer :: JXS8 ! location of angular distribution locators integer :: JXS9 ! location of angular distributions @@ -878,7 +896,6 @@ contains integer :: i ! index in reactions array integer :: j ! index over incoming energies integer :: length ! length of data array to allocate - type(Reaction), pointer :: rxn => null() JXS8 = JXS(8) JXS9 = JXS(9) @@ -886,71 +903,72 @@ contains ! loop over all reactions with secondary neutrons -- NXS(5) does not include ! elastic scattering do i = 1, NXS(5) + 1 - rxn => nuc%reactions(i) + associate (rxn => nuc%reactions(i)) - ! find location of angular distribution - LOCB = int(XSS(JXS8 + i - 1)) - if (LOCB == -1) then - ! Angular distribution data are specified through LAWi = 44 in the DLW - ! block - cycle - elseif (LOCB == 0) then - ! No angular distribution data are given for this reaction, isotropic - ! scattering is asssumed (in CM if TY < 0 and in LAB if TY > 0) - cycle - end if - rxn % has_angle_dist = .true. - - ! allocate space for incoming energies and locations - NE = int(XSS(JXS9 + LOCB - 1)) - rxn % adist % n_energy = NE - allocate(rxn % adist % energy(NE)) - allocate(rxn % adist % type(NE)) - allocate(rxn % adist % location(NE)) - - ! read incoming energy grid and location of nucs - XSS_index = JXS9 + LOCB - rxn % adist % energy = get_real(NE) - rxn % adist % location = get_int(NE) - - ! determine dize of data block - length = 0 - do j = 1, NE - LC = rxn % adist % location(j) - if (LC == 0) then - ! isotropic - rxn % adist % type(j) = ANGLE_ISOTROPIC - elseif (LC > 0) then - ! 32 equiprobable bins - rxn % adist % type(j) = ANGLE_32_EQUI - length = length + 33 - elseif (LC < 0) then - ! tabular distribution - rxn % adist % type(j) = ANGLE_TABULAR - NP = int(XSS(JXS9 + abs(LC))) - length = length + 2 + 3*NP + ! find location of angular distribution + LOCB = int(XSS(JXS8 + i - 1)) + if (LOCB == -1) then + ! Angular distribution data are specified through LAWi = 44 in the DLW + ! block + cycle + elseif (LOCB == 0) then + ! No angular distribution data are given for this reaction, isotropic + ! scattering is assumed (in CM if TY < 0 and in LAB if TY > 0) + cycle end if - end do + rxn % has_angle_dist = .true. - ! allocate angular distribution data and read - allocate(rxn % adist % data(length)) + ! allocate space for incoming energies and locations + NE = int(XSS(JXS9 + LOCB - 1)) + rxn % adist % n_energy = NE + allocate(rxn % adist % energy(NE)) + allocate(rxn % adist % type(NE)) + allocate(rxn % adist % location(NE)) - ! read angular distribution -- currently this does not actually parse the - ! angular distribution tables for each incoming energy, that must be done - ! on-the-fly - XSS_index = JXS9 + LOCB + 2 * NE - rxn % adist % data = get_real(length) + ! read incoming energy grid and location of nucs + XSS_index = JXS9 + LOCB + rxn % adist % energy = get_real(NE) + rxn % adist % location = get_int(NE) - ! change location pointers since they are currently relative to JXS(9) - LC = LOCB + 2 * NE + 1 - do j = 1, NE - ! For consistency, leave location as 0 if type is isotropic. - ! This is not necessary for current correctness, but can avoid - ! future issues - if (rxn % adist % location(j) /= 0) then - rxn % adist % location(j) = abs(rxn % adist % location(j)) - LC - end if - end do + ! determine dize of data block + length = 0 + do j = 1, NE + LC = rxn % adist % location(j) + if (LC == 0) then + ! isotropic + rxn % adist % type(j) = ANGLE_ISOTROPIC + elseif (LC > 0) then + ! 32 equiprobable bins + rxn % adist % type(j) = ANGLE_32_EQUI + length = length + 33 + elseif (LC < 0) then + ! tabular distribution + rxn % adist % type(j) = ANGLE_TABULAR + NP = int(XSS(JXS9 + abs(LC))) + length = length + 2 + 3*NP + end if + end do + + ! allocate angular distribution data and read + allocate(rxn % adist % data(length)) + + ! read angular distribution -- currently this does not actually parse the + ! angular distribution tables for each incoming energy, that must be done + ! on-the-fly + XSS_index = JXS9 + LOCB + 2 * NE + rxn % adist % data = get_real(length) + + ! change location pointers since they are currently relative to JXS(9) + LC = LOCB + 2 * NE + 1 + do j = 1, NE + ! For consistency, leave location as 0 if type is isotropic. + ! This is not necessary for current correctness, but can avoid + ! future issues + if (rxn % adist % location(j) /= 0) then + rxn % adist % location(j) = abs(rxn % adist % location(j)) - LC + end if + end do + end associate end do end subroutine read_angular_dist @@ -961,29 +979,28 @@ contains !=============================================================================== subroutine read_energy_dist(nuc) - - type(Nuclide), pointer :: nuc + type(Nuclide), intent(inout) :: nuc integer :: LED ! location of energy distribution locators integer :: LOCC ! location of energy distributions for given MT integer :: i ! loop index - type(Reaction), pointer :: rxn => null() LED = JXS(10) ! Loop over all reactions do i = 1, NXS(5) - rxn => nuc % reactions(i+1) ! skip over elastic scattering - rxn % has_energy_dist = .true. + associate (rxn => nuc % reactions(i+1)) ! skip over elastic scattering + rxn % has_energy_dist = .true. - ! find location of energy distribution data - LOCC = int(XSS(LED + i - 1)) + ! find location of energy distribution data + LOCC = int(XSS(LED + i - 1)) - ! allocate energy distribution - allocate(rxn % edist) + ! allocate energy distribution + allocate(rxn % edist) - ! read data for energy distribution - call get_energy_dist(rxn % edist, LOCC) + ! read data for energy distribution + call get_energy_dist(rxn % edist, LOCC) + end associate end do end subroutine read_energy_dist @@ -995,10 +1012,9 @@ contains !=============================================================================== recursive subroutine get_energy_dist(edist, loc_law, delayed_n) - - type(DistEnergy), pointer :: edist ! energy distribution - integer, intent(in) :: loc_law ! locator for data - logical, optional :: delayed_n ! is this for delayed neutrons? + type(DistEnergy), intent(inout) :: edist ! energy distribution + integer, intent(in) :: loc_law ! locator for data + logical, intent(in), optional :: delayed_n ! is this for delayed neutrons? integer :: LDIS ! location of all energy distributions integer :: LNW ! location of next energy distribution if multiple @@ -1078,7 +1094,6 @@ contains !=============================================================================== function length_energy_dist(lc, law, LOCC, lid) result(length) - integer, intent(in) :: lc ! location in XSS array integer, intent(in) :: law ! energy distribution law integer, intent(in) :: LOCC ! location of energy distribution @@ -1122,7 +1137,7 @@ contains NR = int(XSS(lc + 1)) NE = int(XSS(lc + 2 + 2*NR)) allocate(L(NE)) - L = int(XSS(lc + 3 + 2*NR + NE: lc + 3 + 2*NR + 2*NE - 1)) + L(:) = int(XSS(lc + 3 + 2*NR + NE: lc + 3 + 2*NR + 2*NE - 1)) ! Continue with finding data length length = length + 2 + 2*NR + 2*NE @@ -1180,7 +1195,7 @@ contains NR = int(XSS(lc + 1)) NE = int(XSS(lc + 2 + 2*NR)) allocate(L(NE)) - L = int(XSS(lc + 3 + 2*NR + NE: lc + 3 + 2*NR + 2*NE - 1)) + L(:) = int(XSS(lc + 3 + 2*NR + NE: lc + 3 + 2*NR + 2*NE - 1)) ! Continue with finding data length length = length + 2 + 2*NR + 2*NE @@ -1210,7 +1225,7 @@ contains NR = int(XSS(lc + 1)) NE = int(XSS(lc + 2 + 2*NR)) allocate(L(NE)) - L = int(XSS(lc + 3 + 2*NR + NE: lc + 3 + 2*NR + 2*NE - 1)) + L(:) = int(XSS(lc + 3 + 2*NR + NE: lc + 3 + 2*NR + 2*NE - 1)) ! Continue with finding data length length = length + 2 + 2*NR + 2*NE @@ -1261,7 +1276,7 @@ contains ! in a way inconsistent with the current form of the ACE Format Guide ! (MCNP5 Manual, Vol 3) allocate(L(NE)) - L = int(XSS(lc + 3 + 2*NR + NE: lc + 3 + 2*NR + 2*NE - 1)) + L(:) = int(XSS(lc + 3 + 2*NR + NE: lc + 3 + 2*NR + 2*NE - 1)) ! Don't currently do anything with L deallocate(L) ! Continue with finding data length @@ -1277,8 +1292,7 @@ contains !=============================================================================== subroutine read_unr_res(nuc) - - type(Nuclide), pointer :: nuc + type(Nuclide), intent(inout) :: nuc integer :: JXS23 ! location of URR data integer :: lc ! locator @@ -1366,8 +1380,7 @@ contains !=============================================================================== subroutine generate_nu_fission(nuc) - - type(Nuclide), pointer :: nuc + type(Nuclide), intent(inout) :: nuc integer :: i ! index on nuclide energy grid real(8) :: E ! energy @@ -1393,8 +1406,7 @@ contains !=============================================================================== subroutine read_thermal_data(table) - - type(SAlphaBeta), pointer :: table + type(SAlphaBeta), intent(inout) :: table integer :: i ! index for incoming energies integer :: j ! index for outgoing energies @@ -1576,7 +1588,7 @@ contains do i = 1, n_nuclides_total do j = 1, n_nuclides_total if (nuclides(i) % zaid == nuclides(j) % zaid) then - call nuclides(i) % nuc_list % append(j) + call nuclides(i) % nuc_list % push_back(j) end if end do end do diff --git a/src/ace_header.F90 b/src/ace_header.F90 index 209b752bf8..985371ff18 100644 --- a/src/ace_header.F90 +++ b/src/ace_header.F90 @@ -1,8 +1,9 @@ module ace_header use constants, only: MAX_FILE_LEN, ZERO + use dict_header, only: DictIntInt use endf_header, only: Tab1 - use list_header, only: ListInt + use stl_vector, only: VectorInt implicit none @@ -17,10 +18,6 @@ module ace_header integer, allocatable :: type(:) ! type of distribution integer, allocatable :: location(:) ! location of each table real(8), allocatable :: data(:) ! angular distribution data - - ! Type-Bound procedures - contains - procedure :: clear => distangle_clear ! Deallocates DistAngle end type DistAngle !=============================================================================== @@ -51,7 +48,7 @@ module ace_header integer :: MT ! ENDF MT value real(8) :: Q_value ! Reaction Q value integer :: multiplicity ! Number of secondary particles released - type(Tab1), pointer :: multiplicity_E => null() ! Energy-dependent neutron yield + type(Tab1), allocatable :: multiplicity_E ! Energy-dependent neutron yield integer :: threshold ! Energy grid index of threshold logical :: scatter_in_cm ! scattering system in center-of-mass? logical :: multiplicity_with_E = .false. ! Flag to indicate E-dependent multiplicity @@ -79,10 +76,6 @@ module ace_header logical :: multiply_smooth ! multiply by smooth cross section? real(8), allocatable :: energy(:) ! incident energies real(8), allocatable :: prob(:,:,:) ! actual probabibility tables - - ! Type-Bound procedures - contains - procedure :: clear => urrdata_clear ! Deallocates UrrData end type UrrData !=============================================================================== @@ -99,7 +92,7 @@ module ace_header real(8) :: kT ! temperature in MeV (k*T) ! Linked list of indices in nuclides array of instances of this same nuclide - type(ListInt) :: nuc_list + type(VectorInt) :: nuc_list ! Energy grid information integer :: n_grid ! # of nuclide grid points @@ -153,7 +146,9 @@ module ace_header ! Reactions integer :: n_reaction ! # of reactions - type(Reaction), pointer :: reactions(:) => null() + type(Reaction), allocatable :: reactions(:) + type(DictIntInt) :: reaction_index ! map MT values to index in reactions + ! array; used at tally-time ! Type-Bound procedures contains @@ -166,14 +161,12 @@ module ace_header !=============================================================================== type Nuclide0K - character(10) :: nuclide ! name of nuclide, e.g. U-238 character(16) :: scheme = 'ares' ! target velocity sampling scheme character(10) :: name ! name of nuclide, e.g. 92235.03c character(10) :: name_0K ! name of 0K nuclide, e.g. 92235.00c real(8) :: E_min = 0.01e-6_8 ! lower cutoff energy for res scattering real(8) :: E_max = 1000.0e-6_8 ! upper cutoff energy for res scattering - end type Nuclide0K !=============================================================================== @@ -265,7 +258,6 @@ module ace_header real(8) :: absorption ! microscopic absorption xs real(8) :: fission ! microscopic fission xs real(8) :: nu_fission ! microscopic production xs - real(8) :: kappa_fission ! microscopic energy-released from fission ! Information for S(a,b) use integer :: index_sab ! index in sab_tables (zero means no table) @@ -288,24 +280,10 @@ module ace_header real(8) :: absorption ! macroscopic absorption xs real(8) :: fission ! macroscopic fission xs real(8) :: nu_fission ! macroscopic production xs - real(8) :: kappa_fission ! macroscopic energy-released from fission end type MaterialMacroXS contains -!=============================================================================== -! DISTANGLE_CLEAR resets and deallocates data in Reaction. -!=============================================================================== - - subroutine distangle_clear(this) - - class(DistAngle), intent(inout) :: this ! The DistAngle object to clear - - if (allocated(this % energy)) & - deallocate(this % energy, this % type, this % location, this % data) - - end subroutine distangle_clear - !=============================================================================== ! DISTENERGY_CLEAR resets and deallocates data in DistEnergy. !=============================================================================== @@ -314,12 +292,6 @@ module ace_header class(DistEnergy), intent(inout) :: this ! The DistEnergy object to clear - ! Clear p_valid - call this % p_valid % clear() - - if (allocated(this % data)) & - deallocate(this % data) - if (associated(this % next)) then ! recursively clear this item call this % next % clear() @@ -336,32 +308,13 @@ module ace_header class(Reaction), intent(inout) :: this ! The Reaction object to clear - if (allocated(this % sigma)) deallocate(this % sigma) - - if (associated(this % multiplicity_E)) deallocate(this % multiplicity_E) - if (associated(this % edist)) then call this % edist % clear() deallocate(this % edist) end if - call this % adist % clear() - end subroutine reaction_clear -!=============================================================================== -! URRDATA_CLEAR resets and deallocates data in Reaction. -!=============================================================================== - - subroutine urrdata_clear(this) - - class(UrrData), intent(inout) :: this ! The UrrData object to clear - - if (allocated(this % energy)) & - deallocate(this % energy, this % prob) - - end subroutine urrdata_clear - !=============================================================================== ! NUCLIDE_CLEAR resets and deallocates data in Nuclide. !=============================================================================== @@ -372,31 +325,6 @@ module ace_header integer :: i ! Loop counter - if (allocated(this % energy)) & - deallocate(this % energy, this % total, this % elastic, & - & this % fission, this % nu_fission, this % absorption) - - if (allocated(this % energy_0K)) & - deallocate(this % energy_0K) - - if (allocated(this % elastic_0K)) & - deallocate(this % elastic_0K) - - if (allocated(this % xs_cdf)) & - deallocate(this % xs_cdf) - - if (allocated(this % heating)) & - deallocate(this % heating) - - if (allocated(this % index_fission)) deallocate(this % index_fission) - - if (allocated(this % nu_t_data)) deallocate(this % nu_t_data) - if (allocated(this % nu_p_data)) deallocate(this % nu_p_data) - if (allocated(this % nu_d_data)) deallocate(this % nu_d_data) - - if (allocated(this % nu_d_precursor_data)) & - deallocate(this % nu_d_precursor_data) - if (associated(this % nu_d_edist)) then do i = 1, size(this % nu_d_edist) call this % nu_d_edist(i) % clear() @@ -405,18 +333,16 @@ module ace_header end if if (associated(this % urr_data)) then - call this % urr_data % clear() deallocate(this % urr_data) end if - if (associated(this % reactions)) then + if (allocated(this % reactions)) then do i = 1, size(this % reactions) call this % reactions(i) % clear() end do - deallocate(this % reactions) end if - call this % nuc_list % clear() + call this % reaction_index % clear() end subroutine nuclide_clear diff --git a/src/bank_header.F90 b/src/bank_header.F90 index 1a91f86f7a..0cb49af35d 100644 --- a/src/bank_header.F90 +++ b/src/bank_header.F90 @@ -1,5 +1,7 @@ module bank_header + use, intrinsic :: ISO_C_BINDING + implicit none !=============================================================================== @@ -8,16 +10,12 @@ 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 + integer(C_INT) :: delayed_group ! delayed group end type Bank end module bank_header diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index 2b17784196..19fe395728 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -57,7 +57,7 @@ contains use global, only: cmfd, n_cmfd_tallies, cmfd_tallies, meshes,& matching_bins use mesh, only: mesh_indices_to_bin - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use string, only: to_str use tally_header, only: TallyObject @@ -79,8 +79,8 @@ contains integer :: i_filter_eout ! index for outgoing energy filter integer :: i_filter_surf ! index for surface filter real(8) :: flux ! temp variable for flux - type(TallyObject), pointer :: t => null() ! pointer for tally object - type(StructuredMesh), pointer :: m => null() ! pointer for mesh object + type(TallyObject), pointer :: t ! pointer for tally object + type(RegularMesh), pointer :: m ! pointer for mesh object ! Extract spatial and energy indices from object nx = cmfd % indices(1) diff --git a/src/cmfd_execute.F90 b/src/cmfd_execute.F90 index c55d206cbc..4dfe99d770 100644 --- a/src/cmfd_execute.F90 +++ b/src/cmfd_execute.F90 @@ -217,7 +217,7 @@ contains use error, only: warning, fatal_error use global, only: meshes, source_bank, work, n_user_meshes, cmfd, & master - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use mesh, only: count_bank_sites, get_mesh_indices use search, only: binary_search use string, only: to_str @@ -239,8 +239,7 @@ contains integer :: n_groups ! number of energy groups logical :: outside ! any source sites outside mesh logical :: in_mesh ! source site is inside mesh - - type(StructuredMesh), pointer :: m ! point to mesh + type(RegularMesh), pointer :: m ! point to mesh ! Associate pointer m => meshes(n_user_meshes + 1) diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 2d44d3e9bc..dac74c9c39 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -247,7 +247,7 @@ contains use constants, only: MAX_LINE_LEN use error, only: fatal_error, warning - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use string use tally, only: setup_active_cmfdtallies use tally_header, only: TallyObject, TallyFilter @@ -264,10 +264,10 @@ contains integer :: i_filter_mesh ! index for mesh filter integer :: iarray3(3) ! temp integer array real(8) :: rarray3(3) ! temp double array - type(TallyObject), pointer :: t => null() - type(StructuredMesh), pointer :: m => null() + type(TallyObject), pointer :: t + type(RegularMesh), pointer :: m type(TallyFilter) :: filters(N_FILTER_TYPES) ! temporary filters - type(Node), pointer :: node_mesh => null() + type(Node), pointer :: node_mesh ! Set global variables if they are 0 (this can happen if there is no tally ! file) diff --git a/src/constants.F90 b/src/constants.F90 index 3aaf08f0eb..ba77f35aba 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -8,17 +8,13 @@ module constants ! OpenMC major, minor, and release numbers integer, parameter :: VERSION_MAJOR = 0 integer, parameter :: VERSION_MINOR = 7 - integer, parameter :: VERSION_RELEASE = 0 + integer, parameter :: VERSION_RELEASE = 1 ! Revision numbers for binary files - integer, parameter :: REVISION_STATEPOINT = 13 + integer, parameter :: REVISION_STATEPOINT = 14 integer, parameter :: REVISION_PARTICLE_RESTART = 1 - - ! Binary file types - integer, parameter :: & - FILETYPE_STATEPOINT = -1, & - FILETYPE_PARTICLE_RESTART = -2, & - FILETYPE_SOURCE = -3 + integer, parameter :: REVISION_TRACK = 1 + integer, parameter :: REVISION_SUMMARY = 1 ! ============================================================================ ! ADJUSTABLE PARAMETERS @@ -44,6 +40,9 @@ module constants integer, parameter :: MAX_EVENTS = 10000 integer, parameter :: MAX_SAMPLE = 100000 + ! Maximum number of secondary particles created + integer, parameter :: MAX_SECONDARY = 1000 + ! Maximum number of words in a single line, length of line, and length of ! single word integer, parameter :: MAX_WORDS = 500 @@ -61,20 +60,22 @@ module constants ! Values here are from the Committee on Data for Science and Technology ! (CODATA) 2010 recommendation (doi:10.1103/RevModPhys.84.1527). - real(8), parameter :: & - PI = 3.1415926535898_8, & ! pi - MASS_NEUTRON = 1.008664916_8, & ! mass of a neutron in amu - MASS_PROTON = 1.007276466812_8, & ! mass of a proton in amu - AMU = 1.660538921e-27_8, & ! 1 amu in kg - N_AVOGADRO = 0.602214129_8, & ! Avogadro's number in 10^24/mol - K_BOLTZMANN = 8.6173324e-11_8, & ! Boltzmann constant in MeV/K - INFINITY = huge(0.0_8), & ! positive infinity - ZERO = 0.0_8, & - HALF = 0.5_8, & - ONE = 1.0_8, & - TWO = 2.0_8, & - THREE = 3.0_8, & - FOUR = 4.0_8 + real(8), parameter :: & + PI = 3.1415926535898_8, & ! pi + MASS_NEUTRON = 1.008664916_8, & ! mass of a neutron in amu + MASS_NEUTRON_MEV = 939.565379_8, & ! mass of a neutron in MeV/c^2 + MASS_PROTON = 1.007276466812_8, & ! mass of a proton in amu + AMU = 1.660538921e-27_8, & ! 1 amu in kg + C_LIGHT = 2.99792458e8_8, & ! speed of light in m/s + N_AVOGADRO = 0.602214129_8, & ! Avogadro's number in 10^24/mol + K_BOLTZMANN = 8.6173324e-11_8, & ! Boltzmann constant in MeV/K + INFINITY = huge(0.0_8), & ! positive infinity + ZERO = 0.0_8, & + HALF = 0.5_8, & + ONE = 1.0_8, & + TWO = 2.0_8, & + THREE = 3.0_8, & + FOUR = 4.0_8 ! ============================================================================ ! GEOMETRY-RELATED CONSTANTS @@ -88,10 +89,11 @@ module constants ! Logical operators for cell definitions integer, parameter :: & - OP_LEFT_PAREN = huge(0), & ! Left parentheses - OP_RIGHT_PAREN = huge(0) - 1, & ! Right parentheses - OP_UNION = huge(0) - 2, & ! Union operator - OP_DIFFERENCE = huge(0) - 3 ! Difference operator + OP_LEFT_PAREN = huge(0), & ! Left parentheses + OP_RIGHT_PAREN = huge(0) - 1, & ! Right parentheses + OP_COMPLEMENT = huge(0) - 2, & ! Complement operator (~) + OP_INTERSECTION = huge(0) - 3, & ! Intersection operator + OP_UNION = huge(0) - 4 ! Union operator (^) ! Cell types integer, parameter :: & @@ -246,7 +248,8 @@ module constants ! Tally estimator types integer, parameter :: & ESTIMATOR_ANALOG = 1, & - ESTIMATOR_TRACKLENGTH = 2 + ESTIMATOR_TRACKLENGTH = 2, & + ESTIMATOR_COLLISION = 3 ! Event types for tallies integer, parameter :: & @@ -256,28 +259,30 @@ module constants EVENT_ABSORB = 2 ! Tally score type - integer, parameter :: N_SCORE_TYPES = 20 + integer, parameter :: N_SCORE_TYPES = 22 integer, parameter :: & - SCORE_FLUX = -1, & ! flux - SCORE_TOTAL = -2, & ! total reaction rate - SCORE_SCATTER = -3, & ! scattering rate - SCORE_NU_SCATTER = -4, & ! scattering production rate - SCORE_SCATTER_N = -5, & ! arbitrary scattering moment - SCORE_SCATTER_PN = -6, & ! system for scoring 0th through nth moment - SCORE_NU_SCATTER_N = -7, & ! arbitrary nu-scattering moment - SCORE_NU_SCATTER_PN = -8, & ! system for scoring 0th through nth nu-scatter moment - SCORE_TRANSPORT = -9, & ! transport reaction rate - SCORE_N_1N = -10, & ! (n,1n) rate - SCORE_ABSORPTION = -11, & ! absorption rate - SCORE_FISSION = -12, & ! fission rate - SCORE_NU_FISSION = -13, & ! neutron production rate - SCORE_KAPPA_FISSION = -14, & ! fission energy production rate - SCORE_CURRENT = -15, & ! partial current - SCORE_FLUX_YN = -16, & ! angular moment of flux - SCORE_TOTAL_YN = -17, & ! angular moment of total reaction rate - SCORE_SCATTER_YN = -18, & ! angular flux-weighted scattering moment (0:N) - SCORE_NU_SCATTER_YN = -19, & ! angular flux-weighted nu-scattering moment (0:N) - SCORE_EVENTS = -20 ! number of events + SCORE_FLUX = -1, & ! flux + SCORE_TOTAL = -2, & ! total reaction rate + SCORE_SCATTER = -3, & ! scattering rate + SCORE_NU_SCATTER = -4, & ! scattering production rate + SCORE_SCATTER_N = -5, & ! arbitrary scattering moment + SCORE_SCATTER_PN = -6, & ! system for scoring 0th through nth moment + SCORE_NU_SCATTER_N = -7, & ! arbitrary nu-scattering moment + SCORE_NU_SCATTER_PN = -8, & ! system for scoring 0th through nth nu-scatter moment + SCORE_TRANSPORT = -9, & ! transport reaction rate + SCORE_N_1N = -10, & ! (n,1n) rate + SCORE_ABSORPTION = -11, & ! absorption rate + SCORE_FISSION = -12, & ! fission rate + SCORE_NU_FISSION = -13, & ! neutron production rate + SCORE_KAPPA_FISSION = -14, & ! fission energy production rate + SCORE_CURRENT = -15, & ! partial current + SCORE_FLUX_YN = -16, & ! angular moment of flux + SCORE_TOTAL_YN = -17, & ! angular moment of total reaction rate + SCORE_SCATTER_YN = -18, & ! angular flux-weighted scattering moment (0:N) + SCORE_NU_SCATTER_YN = -19, & ! angular flux-weighted nu-scattering moment (0:N) + SCORE_EVENTS = -20, & ! number of events + SCORE_DELAYED_NU_FISSION = -21, & ! delayed neutron production rate + SCORE_INVERSE_VELOCITY = -22 ! flux-weighted inverse velocity ! Maximum scattering order supported integer, parameter :: MAX_ANG_ORDER = 10 @@ -300,17 +305,25 @@ module constants integer, parameter :: NO_BIN_FOUND = -1 ! Tally filter and map types - integer, parameter :: N_FILTER_TYPES = 9 + integer, parameter :: N_FILTER_TYPES = 13 integer, parameter :: & - FILTER_UNIVERSE = 1, & - FILTER_MATERIAL = 2, & - FILTER_CELL = 3, & - FILTER_CELLBORN = 4, & - FILTER_SURFACE = 5, & - FILTER_MESH = 6, & - FILTER_ENERGYIN = 7, & - FILTER_ENERGYOUT = 8, & - FILTER_DISTRIBCELL = 9 + FILTER_UNIVERSE = 1, & + FILTER_MATERIAL = 2, & + FILTER_CELL = 3, & + FILTER_CELLBORN = 4, & + FILTER_SURFACE = 5, & + FILTER_MESH = 6, & + FILTER_ENERGYIN = 7, & + FILTER_ENERGYOUT = 8, & + FILTER_DISTRIBCELL = 9, & + FILTER_MU = 10, & + FILTER_POLAR = 11, & + FILTER_AZIMUTHAL = 12, & + FILTER_DELAYEDGROUP = 13 + + ! Mesh types + integer, parameter :: & + MESH_REGULAR = 1 ! Tally surface current directions integer, parameter :: & @@ -327,7 +340,7 @@ module constants RELATIVE_ERROR = 2, & STANDARD_DEVIATION = 3 - ! Global tallY parameters + ! Global tally parameters integer, parameter :: N_GLOBAL_TALLIES = 4 integer, parameter :: & K_COLLISION = 1, & @@ -389,14 +402,6 @@ module constants MODE_PLOTTING = 3, & ! Plotting mode MODE_PARTICLE = 4 ! Particle restart mode - ! Unit numbers - integer, parameter :: UNIT_SUMMARY = 11 ! unit # for writing summary file - integer, parameter :: UNIT_TALLY = 12 ! unit # for writing tally file - integer, parameter :: UNIT_PLOT = 13 ! unit # for writing plot file - integer, parameter :: UNIT_XS = 14 ! unit # for writing xs summary file - integer, parameter :: UNIT_PARTICLE = 15 ! unit # for writing particle restart - integer, parameter :: UNIT_OUTPUT = 16 ! unit # for writing output - !============================================================================= ! CMFD CONSTANTS @@ -409,4 +414,14 @@ module constants ! constant for writing out no residual real(8), parameter :: CMFD_NORES = 99999.0_8 + !============================================================================= + ! DELAYED NEUTRON PRECURSOR CONSTANTS + + ! Since cross section libraries come with different numbers of delayed groups + ! (e.g. ENDF/B-VII.1 has 6 and JEFF 3.1.1 has 8 delayed groups) and we don't + ! yet know what cross section library is being used when the tallies.xml file + ! is read in, we want to have an upper bound on the size of the array we + ! use to store the bins for delayed group tallies. + integer, parameter :: MAX_DELAYED_GROUPS = 8 + end module constants diff --git a/src/cross_section.F90 b/src/cross_section.F90 index b937b03a15..f874eb2a74 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -13,10 +13,6 @@ module cross_section use search, only: binary_search implicit none - save - - integer :: union_grid_index -!$omp threadprivate(union_grid_index) contains @@ -33,6 +29,8 @@ contains integer :: i_nuclide ! index into nuclides array integer :: i_sab ! index into sab_tables array integer :: j ! index in mat % i_sab_nuclides + integer :: i_grid ! index into logarithmic mapping array or material + ! union grid real(8) :: atom_density ! atom density of a nuclide logical :: check_sab ! should we check for S(a,b) table? type(Material), pointer :: mat ! current material @@ -43,16 +41,18 @@ contains material_xs % absorption = ZERO material_xs % fission = ZERO material_xs % nu_fission = ZERO - material_xs % kappa_fission = ZERO ! Exit subroutine if material is void if (p % material == MATERIAL_VOID) return mat => materials(p % material) - ! Find energy index on global or material unionized grid - if (grid_method == GRID_MAT_UNION) & - call find_energy_index(p % E, p % material) + ! Find energy index on energy grid + if (grid_method == GRID_MAT_UNION) then + i_grid = find_energy_index(mat, p % E) + else if (grid_method == GRID_LOGARITHM) then + i_grid = int(log(p % E/energy_min_neutron)/log_spacing) + end if ! Determine if this material has S(a,b) tables check_sab = (mat % n_sab > 0) @@ -94,9 +94,9 @@ contains ! Calculate microscopic cross section for this nuclide if (p % E /= micro_xs(i_nuclide) % last_E) then - call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i) + call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i, i_grid) else if (i_sab /= micro_xs(i_nuclide) % last_index_sab) then - call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i) + call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i, i_grid) end if ! ======================================================================== @@ -124,10 +124,6 @@ contains ! Add contributions to material macroscopic nu-fission cross section material_xs % nu_fission = material_xs % nu_fission + & atom_density * micro_xs(i_nuclide) % nu_fission - - ! Add contributions to material macroscopic energy release from fission - material_xs % kappa_fission = material_xs % kappa_fission + & - atom_density * micro_xs(i_nuclide) % kappa_fission end do end subroutine calculate_xs @@ -137,18 +133,19 @@ contains ! given index in the nuclides array at the energy of the given particle !=============================================================================== - subroutine calculate_nuclide_xs(i_nuclide, i_sab, E, i_mat, i_nuc_mat) - + subroutine calculate_nuclide_xs(i_nuclide, i_sab, E, i_mat, i_nuc_mat, i_log_union) integer, intent(in) :: i_nuclide ! index into nuclides array integer, intent(in) :: i_sab ! index into sab_tables array + real(8), intent(in) :: E ! energy integer, intent(in) :: i_mat ! index into materials array integer, intent(in) :: i_nuc_mat ! index into nuclides array for a material + integer, intent(in) :: i_log_union ! index into logarithmic mapping array or + ! material union energy grid + integer :: i_grid ! index on nuclide energy grid integer :: i_low ! lower logarithmic mapping index integer :: i_high ! upper logarithmic mapping index - integer :: u ! index into logarithmic mapping array - real(8), intent(in) :: E ! energy - real(8) :: f ! interp factor on nuclide energy grid + real(8) :: f ! interp factor on nuclide energy grid type(Nuclide), pointer :: nuc type(Material), pointer :: mat @@ -160,7 +157,7 @@ contains select case (grid_method) case (GRID_MAT_UNION) - i_grid = mat % nuclide_grid_index(i_nuc_mat, union_grid_index) + i_grid = mat % nuclide_grid_index(i_nuc_mat, i_log_union) case (GRID_LOGARITHM) ! Determine the energy grid index using a logarithmic mapping to reduce @@ -173,9 +170,8 @@ contains else ! Determine bounding indices based on which equal log-spaced interval ! the energy is in - u = int(log(E/1.0e-11_8)/log_spacing) - i_low = nuc % grid_index(u) - i_high = nuc % grid_index(u + 1) + 1 + i_low = nuc % grid_index(i_log_union) + i_high = nuc % grid_index(i_log_union + 1) + 1 ! Perform binary search over reduced range i_grid = binary_search(nuc % energy(i_low:i_high), & @@ -215,7 +211,6 @@ contains ! Initialize nuclide cross-sections to zero micro_xs(i_nuclide) % fission = ZERO micro_xs(i_nuclide) % nu_fission = ZERO - micro_xs(i_nuclide) % kappa_fission = ZERO ! Calculate microscopic nuclide total cross section micro_xs(i_nuclide) % total = (ONE - f) * nuc % total(i_grid) & @@ -237,13 +232,6 @@ contains ! Calculate microscopic nuclide nu-fission cross section micro_xs(i_nuclide) % nu_fission = (ONE - f) * nuc % nu_fission( & i_grid) + f * nuc % nu_fission(i_grid+1) - - ! Calculate microscopic nuclide kappa-fission cross section - ! The ENDF standard (ENDF-102) states that MT 18 stores - ! the fission energy as the Q_value (fission(1)) - micro_xs(i_nuclide) % kappa_fission = & - nuc % reactions(nuc % index_fission(1)) % Q_value * & - micro_xs(i_nuclide) % fission end if ! If there is S(a,b) data for this nuclide, we need to do a few @@ -378,7 +366,6 @@ contains logical :: same_nuc ! do we know the xs for this nuclide at this energy? type(UrrData), pointer :: urr type(Nuclide), pointer :: nuc - type(Reaction), pointer :: rxn micro_xs(i_nuclide) % use_ptable = .true. @@ -404,7 +391,7 @@ contains ! preserve correlation of temperature in probability tables same_nuc = .false. do i = 1, nuc % nuc_list % size() - if (E /= ZERO .and. E == micro_xs(nuc % nuc_list % get_item(i)) % last_E) then + if (E /= ZERO .and. E == micro_xs(nuc % nuc_list % data(i)) % last_E) then same_nuc = .true. same_nuc_idx = i exit @@ -412,7 +399,7 @@ contains end do if (same_nuc) then - r = micro_xs(nuc % nuc_list % get_item(same_nuc_idx)) % last_prn + r = micro_xs(nuc % nuc_list % data(same_nuc_idx)) % last_prn else r = prn() micro_xs(i_nuclide) % last_prn = r @@ -474,18 +461,17 @@ contains ! Determine treatment of inelastic scattering inelastic = ZERO if (urr % inelastic_flag > 0) then - ! Get pointer to inelastic scattering reaction - rxn => nuc % reactions(nuc % urr_inelastic) - ! Get index on energy grid and interpolation factor i_energy = micro_xs(i_nuclide) % index_grid f = micro_xs(i_nuclide) % interp_factor ! Determine inelastic scattering cross section - if (i_energy >= rxn % threshold) then - inelastic = (ONE - f) * rxn % sigma(i_energy - rxn%threshold + 1) + & - f * rxn % sigma(i_energy - rxn%threshold + 2) - end if + associate (rxn => nuc % reactions(nuc % urr_inelastic)) + if (i_energy >= rxn % threshold) then + inelastic = (ONE - f) * rxn % sigma(i_energy - rxn%threshold + 1) + & + f * rxn % sigma(i_energy - rxn%threshold + 2) + end if + end associate end if ! Multiply by smooth cross-section if needed @@ -522,38 +508,35 @@ contains ! energy !=============================================================================== - subroutine find_energy_index(E, i_mat) - - real(8), intent(in) :: E ! energy of particle - integer, intent(in) :: i_mat ! material index - type(Material), pointer :: mat ! pointer to current material - - mat => materials(i_mat) + pure function find_energy_index(mat, E) result(i) + type(Material), intent(in) :: mat ! pointer to current material + real(8), intent(in) :: E ! energy of particle + integer :: i ! energy grid index ! if the energy is outside of energy grid range, set to first or last ! index. Otherwise, do a binary search through the union energy grid. if (E <= mat % e_grid(1)) then - union_grid_index = 1 + i = 1 elseif (E > mat % e_grid(mat % n_grid)) then - union_grid_index = mat % n_grid - 1 + i = mat % n_grid - 1 else - union_grid_index = binary_search(mat % e_grid, mat % n_grid, E) + i = binary_search(mat % e_grid, mat % n_grid, E) end if - end subroutine find_energy_index + end function find_energy_index !=============================================================================== ! 0K_ELASTIC_XS determines the microscopic 0K elastic cross section ! for a given nuclide at the trial relative energy used in resonance scattering !=============================================================================== - function elastic_xs_0K(E, nuc) result(xs_out) + pure function elastic_xs_0K(E, nuc) result(xs_out) + real(8), intent(in) :: E ! trial energy + type(Nuclide), intent(in) :: nuc ! target nuclide at temperature + real(8) :: xs_out ! 0K xs at trial energy - type(Nuclide), pointer :: nuc ! target nuclide at temperature - integer :: i_grid ! index on nuclide energy grid - real(8) :: f ! interp factor on nuclide energy grid - real(8), intent(inout) :: E ! trial energy - real(8) :: xs_out ! 0K xs at trial energy + integer :: i_grid ! index on nuclide energy grid + real(8) :: f ! interp factor on nuclide energy grid ! Determine index on nuclide energy grid if (E < nuc % energy_0K(1)) then diff --git a/src/eigenvalue.F90 b/src/eigenvalue.F90 index c4b9b9a678..403347caa1 100644 --- a/src/eigenvalue.F90 +++ b/src/eigenvalue.F90 @@ -4,273 +4,24 @@ module eigenvalue use message_passing #endif - use cmfd_execute, only: cmfd_init_batch, execute_cmfd use constants, only: ZERO use error, only: fatal_error, warning use global use math, only: t_percentile use mesh, only: count_bank_sites - use mesh_header, only: StructuredMesh - use output, only: write_message, header, print_columns, & - print_batch_keff, print_generation + use mesh_header, only: RegularMesh use particle_header, only: Particle use random_lcg, only: prn, set_particle_seed, prn_skip use search, only: binary_search - use source, only: get_source_particle - use state_point, only: write_state_point, write_source_point use string, only: to_str - use tally, only: synchronize_tallies, setup_active_usertallies, & - reset_result - use trigger, only: check_triggers - use tracking, only: transport implicit none - private - public :: run_eigenvalue - real(8) :: keff_generation ! Single-generation k on each - ! processor - real(8) :: k_sum(2) = ZERO ! Used to reduce sum and sum_sq + real(8) :: keff_generation ! Single-generation k on each processor + real(8) :: k_sum(2) = ZERO ! Used to reduce sum and sum_sq contains -!=============================================================================== -! RUN_EIGENVALUE encompasses all the main logic where iterations are performed -! over the batches, generations, and histories in a k-eigenvalue calculation. -!=============================================================================== - - subroutine run_eigenvalue() - - type(Particle) :: p - integer(8) :: i_work - - if (master) call header("K EIGENVALUE SIMULATION", level=1) - - ! Display column titles - if(master) call print_columns() - - ! Turn on inactive timer - call time_inactive % start() - - ! ========================================================================== - ! LOOP OVER BATCHES - BATCH_LOOP: do current_batch = 1, n_max_batches - - call initialize_batch() - - ! Handle restart runs - if (restart_run .and. current_batch <= restart_batch) then - call replay_batch_history() - cycle BATCH_LOOP - end if - - ! ======================================================================= - ! LOOP OVER GENERATIONS - GENERATION_LOOP: do current_gen = 1, gen_per_batch - - call initialize_generation() - - ! Start timer for transport - call time_transport % start() - - ! ==================================================================== - ! LOOP OVER PARTICLES -!$omp parallel do schedule(static) firstprivate(p) - PARTICLE_LOOP: do i_work = 1, work - current_work = i_work - - ! grab source particle from bank - call get_source_particle(p, current_work) - - ! transport particle - call transport(p) - - end do PARTICLE_LOOP -!$omp end parallel do - - ! Accumulate time for transport - call time_transport % stop() - - call finalize_generation() - - end do GENERATION_LOOP - - call finalize_batch() - - if (satisfy_triggers) exit BATCH_LOOP - - end do BATCH_LOOP - - call time_active % stop() - - ! ========================================================================== - ! END OF RUN WRAPUP - - if (master) call header("SIMULATION FINISHED", level=1) - - ! Clear particle - call p % clear() - - end subroutine run_eigenvalue - -!=============================================================================== -! INITIALIZE_BATCH -!=============================================================================== - - subroutine initialize_batch() - - call write_message("Simulating batch " // trim(to_str(current_batch)) & - &// "...", 8) - - ! Reset total starting particle weight used for normalizing tallies - total_weight = ZERO - - if (current_batch == n_inactive + 1) then - ! Switch from inactive batch timer to active batch timer - call time_inactive % stop() - call time_active % start() - - ! Enable active batches (and tallies_on if it hasn't been enabled) - active_batches = .true. - tallies_on = .true. - - ! Add user tallies to active tallies list -!$omp parallel - call setup_active_usertallies() -!$omp end parallel - end if - - ! check CMFD initialize batch - if (cmfd_run) call cmfd_init_batch() - - end subroutine initialize_batch - -!=============================================================================== -! INITIALIZE_GENERATION -!=============================================================================== - - subroutine initialize_generation() - - ! set overall generation number - overall_gen = gen_per_batch*(current_batch - 1) + current_gen - - ! Reset number of fission bank sites - n_bank = 0 - - ! Count source sites if using uniform fission source weighting - if (ufs) call count_source_for_ufs() - - ! Store current value of tracklength k - keff_generation = global_tallies(K_TRACKLENGTH) % value - - end subroutine initialize_generation - -!=============================================================================== -! FINALIZE_GENERATION -!=============================================================================== - - subroutine finalize_generation() - - ! Update global tallies with the omp private accumulation variables -!$omp parallel -!$omp critical - global_tallies(K_TRACKLENGTH) % value = & - global_tallies(K_TRACKLENGTH) % value + global_tally_tracklength - global_tallies(K_COLLISION) % value = & - global_tallies(K_COLLISION) % value + global_tally_collision - global_tallies(LEAKAGE) % value = & - global_tallies(LEAKAGE) % value + global_tally_leakage - global_tallies(K_ABSORPTION) % value = & - global_tallies(K_ABSORPTION) % value + global_tally_absorption -!$omp end critical - - ! reset private tallies - global_tally_tracklength = ZERO - global_tally_collision = ZERO - global_tally_leakage = ZERO - global_tally_absorption = ZERO -!$omp end parallel - -#ifdef _OPENMP - ! Join the fission bank from each thread into one global fission bank - call join_bank_from_threads() -#endif - - ! Distribute fission bank across processors evenly - call time_bank % start() - call synchronize_bank() - call time_bank % stop() - - ! Calculate shannon entropy - if (entropy_on) call shannon_entropy() - - ! Collect results and statistics - call calculate_generation_keff() - call calculate_average_keff() - - ! Write generation output - if (master .and. current_gen /= gen_per_batch) call print_generation() - - end subroutine finalize_generation - -!=============================================================================== -! FINALIZE_BATCH handles synchronization and accumulation of tallies, -! calculation of Shannon entropy, getting single-batch estimate of keff, and -! turning on tallies when appropriate -!=============================================================================== - - subroutine finalize_batch() - - ! Collect tallies - call time_tallies % start() - call synchronize_tallies() - call time_tallies % stop() - - ! Reset global tally results - if (.not. active_batches) then - call reset_result(global_tallies) - n_realizations = 0 - end if - - ! Perform CMFD calculation if on - if (cmfd_on) call execute_cmfd() - - ! Display output - if (master) call print_batch_keff() - - ! Calculate combined estimate of k-effective - if (master) call calculate_combined_keff() - - ! Check_triggers - if (master) call check_triggers() -#ifdef MPI - call MPI_BCAST(satisfy_triggers, 1, MPI_LOGICAL, 0, & - MPI_COMM_WORLD, mpi_err) -#endif - if (satisfy_triggers .or. & - (trigger_on .and. current_batch == n_max_batches)) then - call statepoint_batch % add(current_batch) - end if - - ! Write out state point if it's been specified for this batch - if (statepoint_batch % contains(current_batch)) then - call write_state_point() - end if - - ! Write out source point if it's been specified for this batch - if ((sourcepoint_batch % contains(current_batch) .or. source_latest) .and. & - source_write) then - call write_source_point() - end if - - if (master .and. current_batch == n_max_batches) then - ! Make sure combined estimate of k-effective is calculated at the last - ! batch in case no state point is written - call calculate_combined_keff() - end if - - end subroutine finalize_batch - !=============================================================================== ! SYNCHRONIZE_BANK samples source sites from the fission sites that were ! accumulated during the generation. This routine is what allows this Monte @@ -553,7 +304,7 @@ contains integer :: i, j, k ! index for bank sites integer :: n ! # of boxes in each dimension logical :: sites_outside ! were there sites outside entropy box? - type(StructuredMesh), pointer :: m => null() + type(RegularMesh), pointer :: m ! Get pointer to entropy mesh m => entropy_mesh @@ -830,40 +581,11 @@ contains end subroutine count_source_for_ufs -!=============================================================================== -! REPLAY_BATCH_HISTORY displays keff and entropy for each generation within a -! batch using data read from a state point file -!=============================================================================== - - subroutine replay_batch_history - - ! Write message at beginning - if (current_batch == 1) then - call write_message("Replaying history from state point...", 1) - end if - - do current_gen = 1, gen_per_batch - overall_gen = overall_gen + 1 - call calculate_average_keff() - - ! print out batch keff - if (current_gen < gen_per_batch) then - if (master) call print_generation() - else - if (master) call print_batch_keff() - end if - end do - - ! Write message at end - if (current_batch == restart_batch) then - call write_message("Resuming simulation...", 1) - end if - - end subroutine replay_batch_history - #ifdef _OPENMP !=============================================================================== -! JOIN_BANK_FROM_THREADS +! JOIN_BANK_FROM_THREADS joins threadprivate fission banks into a single fission +! bank that can be sampled. Note that this operation is necessarily sequential +! to preserve the order of the bank when using varying numbers of threads. !=============================================================================== subroutine join_bank_from_threads() diff --git a/src/endf.F90 b/src/endf.F90 index fb85262b20..ba324722c3 100644 --- a/src/endf.F90 +++ b/src/endf.F90 @@ -11,7 +11,7 @@ contains ! REACTION_NAME gives the name of the reaction for a given MT value !=============================================================================== - function reaction_name(MT) result(string) + pure function reaction_name(MT) result(string) integer, intent(in) :: MT character(20) :: string diff --git a/src/endf_header.F90 b/src/endf_header.F90 index 54af0f7383..af62231a5d 100644 --- a/src/endf_header.F90 +++ b/src/endf_header.F90 @@ -13,28 +13,6 @@ module endf_header integer :: n_pairs ! # of pairs of (x,y) values real(8), allocatable :: x(:) ! values of abscissa real(8), allocatable :: y(:) ! values of ordinate - - ! Type-Bound procedures - contains - procedure :: clear => tab1_clear ! deallocates a Tab1 Object. end type Tab1 - contains - -!=============================================================================== -! TAB1_CLEAR deallocates the items in Tab1 -!=============================================================================== - - subroutine tab1_clear(this) - - class(Tab1), intent(inout) :: this ! The Tab1 to clear - - if (allocated(this % nbt)) & - deallocate(this % nbt, this % int) - - if (allocated(this % x)) & - deallocate(this % x, this % y) - - end subroutine tab1_clear - end module endf_header diff --git a/src/energy_grid.F90 b/src/energy_grid.F90 index 1473e52105..66419f83cc 100644 --- a/src/energy_grid.F90 +++ b/src/energy_grid.F90 @@ -73,8 +73,8 @@ contains type(Nuclide), pointer :: nuc ! Set minimum/maximum energies - E_max = 20.0_8 - E_min = 1.0e-11_8 + E_max = energy_max_neutron + E_min = energy_min_neutron ! Determine equal-logarithmic energy spacing M = n_log_bins diff --git a/src/finalize.F90 b/src/finalize.F90 index aa11f47690..86100d1950 100644 --- a/src/finalize.F90 +++ b/src/finalize.F90 @@ -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 diff --git a/src/fission.F90 b/src/fission.F90 index 27143bf386..a005d9f5bc 100644 --- a/src/fission.F90 +++ b/src/fission.F90 @@ -15,18 +15,17 @@ contains ! given nuclide and incoming neutron energy !=============================================================================== - function nu_total(nuc, E) result(nu) - - type(Nuclide), pointer :: nuc ! nuclide from which to find nu - real(8), intent(in) :: E ! energy of incoming neutron - real(8) :: nu ! number of total neutrons emitted per fission + pure function nu_total(nuc, E) result(nu) + type(Nuclide), intent(in) :: nuc ! nuclide from which to find nu + real(8), intent(in) :: E ! energy of incoming neutron + real(8) :: nu ! number of total neutrons emitted per fission integer :: i ! loop index integer :: NC ! number of polynomial coefficients real(8) :: c ! polynomial coefficient if (nuc % nu_t_type == NU_NONE) then - call fatal_error("No neutron emission data for table: " // nuc % name) + nu = ERROR_REAL elseif (nuc % nu_t_type == NU_POLYNOMIAL) then ! determine number of coefficients NC = int(nuc % nu_t_data(1)) @@ -49,11 +48,10 @@ contains ! for a given nuclide and incoming neutron energy !=============================================================================== - function nu_prompt(nuc, E) result(nu) - - type(Nuclide), pointer :: nuc ! nuclide from which to find nu - real(8), intent(in) :: E ! energy of incoming neutron - real(8) :: nu ! number of prompt neutrons emitted per fission + pure function nu_prompt(nuc, E) result(nu) + type(Nuclide), intent(in) :: nuc ! nuclide from which to find nu + real(8), intent(in) :: E ! energy of incoming neutron + real(8) :: nu ! number of prompt neutrons emitted per fission integer :: i ! loop index integer :: NC ! number of polynomial coefficients @@ -63,7 +61,7 @@ contains ! since no prompt or delayed data is present, this means all neutron ! emission is prompt -- WARNING: This currently returns zero. The calling ! routine needs to know this situation is occurring since we don't want - ! to call nu_total unnecessarily if it's already been called + ! to call nu_total unnecessarily if it has already been called. nu = ZERO elseif (nuc % nu_p_type == NU_POLYNOMIAL) then ! determine number of coefficients @@ -87,13 +85,16 @@ contains ! for a given nuclide and incoming neutron energy !=============================================================================== - function nu_delayed(nuc, E) result(nu) - - type(Nuclide), pointer :: nuc ! nuclide from which to find nu - real(8), intent(in) :: E ! energy of incoming neutron - real(8) :: nu ! number of delayed neutrons emitted per fission + pure function nu_delayed(nuc, E) result(nu) + type(Nuclide), intent(in) :: nuc ! nuclide from which to find nu + real(8), intent(in) :: E ! energy of incoming neutron + real(8) :: nu ! number of delayed neutrons emitted per fission if (nuc % nu_d_type == NU_NONE) then + ! since no prompt or delayed data is present, this means all neutron + ! emission is prompt -- WARNING: This currently returns zero. The calling + ! routine needs to know this situation is occurring since we don't want + ! to call nu_delayed unnecessarily if it has already been called. nu = ZERO elseif (nuc % nu_d_type == NU_TABULAR) then ! use ENDF interpolation laws to determine nu @@ -102,4 +103,59 @@ contains end function nu_delayed +!=============================================================================== +! YIELD_DELAYED calculates the fractional yield of delayed neutrons emitted for +! a given nuclide and incoming neutron energy in a given delayed group. +!=============================================================================== + + pure function yield_delayed(nuc, E, g) result(yield) + type(Nuclide), intent(in) :: nuc ! nuclide from which to find nu + real(8), intent(in) :: E ! energy of incoming neutron + real(8) :: yield ! delayed neutron precursor yield + integer, intent(in) :: g ! the delayed neutron precursor group + integer :: d ! precursor group + integer :: lc ! index before start of energies/nu values + integer :: NR ! number of interpolation regions + integer :: NE ! number of energies tabulated + + yield = ZERO + + if (g > nuc % n_precursor .or. g < 1) then + ! if the precursor group is outside the range of precursor groups for + ! the input nuclide, return ZERO. + yield = ZERO + else if (nuc % nu_d_type == NU_NONE) then + ! since no prompt or delayed data is present, this means all neutron + ! emission is prompt -- WARNING: This currently returns zero. The calling + ! routine needs to know this situation is occurring since we don't want + ! to call yield_delayed unnecessarily if it has already been called. + yield = ZERO + else if (nuc % nu_d_type == NU_TABULAR) then + + lc = 1 + + ! loop over delayed groups and determine the yield for the desired group + do d = 1, nuc % n_precursor + + ! determine number of interpolation regions and energies + NR = int(nuc % nu_d_precursor_data(lc + 1)) + NE = int(nuc % nu_d_precursor_data(lc + 2 + 2*NR)) + + ! check if this is the desired group + if (d == g) then + + ! determine delayed neutron precursor yield for group g + yield = interpolate_tab1(nuc % nu_d_precursor_data( & + lc+1:lc+2+2*NR+2*NE), E) + + exit + end if + + ! advance pointer + lc = lc + 2 + 2*NR + 2*NE + 1 + end do + end if + + end function yield_delayed + end module fission diff --git a/src/fixed_source.F90 b/src/fixed_source.F90 deleted file mode 100644 index 9dbd57324f..0000000000 --- a/src/fixed_source.F90 +++ /dev/null @@ -1,176 +0,0 @@ -module fixed_source - -#ifdef MPI - use message_passing -#endif - - use constants, only: ZERO, MAX_LINE_LEN - use global - use output, only: write_message, header - use particle_header, only: Particle - use random_lcg, only: set_particle_seed - use source, only: sample_external_source, copy_source_attributes - use state_point, only: write_state_point - use string, only: to_str - use tally, only: synchronize_tallies, setup_active_usertallies - use trigger, only: check_triggers - use tracking, only: transport - - implicit none - -contains - - subroutine run_fixedsource() - - integer(8) :: i ! index over histories in single cycle - type(Particle) :: p - - if (master) call header("FIXED SOURCE TRANSPORT SIMULATION", level=1) - - ! Allocate particle and dummy source site -!$omp parallel - allocate(source_site) -!$omp end parallel - - ! Turn timer and tallies on - tallies_on = .true. -!$omp parallel - call setup_active_usertallies() -!$omp end parallel - call time_active % start() - - ! ========================================================================== - ! LOOP OVER BATCHES - BATCH_LOOP: do current_batch = 1, n_max_batches - - ! In a restart run, skip any batches that have already been simulated - if (restart_run .and. current_batch <= restart_batch) then - if (current_batch > n_inactive) n_realizations = n_realizations + 1 - cycle BATCH_LOOP - end if - - call initialize_batch() - - ! Start timer for transport - call time_transport % start() - - ! ======================================================================= - ! LOOP OVER PARTICLES -!$omp parallel do schedule(static) firstprivate(p) - PARTICLE_LOOP: do i = 1, work - - ! Set unique particle ID - p % id = (current_batch - 1)*n_particles + work_index(rank) + i - - ! set particle trace - trace = .false. - if (current_batch == trace_batch .and. current_gen == trace_gen .and. & - work_index(rank) + i == trace_particle) trace = .true. - - ! set random number seed - call set_particle_seed(p % id) - - ! grab source particle from bank - call sample_source_particle(p) - - ! transport particle - call transport(p) - - end do PARTICLE_LOOP -!$omp end parallel do - - ! Accumulate time for transport - call time_transport % stop() - - call finalize_batch() - - if (satisfy_triggers) exit BATCH_LOOP - - end do BATCH_LOOP - - call time_active % stop() - - ! ========================================================================== - ! END OF RUN WRAPUP - - if (master) call header("SIMULATION FINISHED", level=1) - - end subroutine run_fixedsource - -!=============================================================================== -! INITIALIZE_BATCH -!=============================================================================== - - subroutine initialize_batch() - - call write_message("Simulating batch " // trim(to_str(current_batch)) & - &// "...", 1) - - ! Reset total starting particle weight used for normalizing tallies - total_weight = ZERO - - end subroutine initialize_batch - -!=============================================================================== -! FINALIZE_BATCH -!=============================================================================== - - subroutine finalize_batch() - -! Update global tallies with the omp private accumulation variables -!$omp parallel -!$omp critical - global_tallies(LEAKAGE) % value = & - global_tallies(LEAKAGE) % value + global_tally_leakage -!$omp end critical - - ! reset private tallies - global_tally_leakage = ZERO -!$omp end parallel - - ! Collect and accumulate tallies - call time_tallies % start() - call synchronize_tallies() - call time_tallies % stop() - - ! Check_triggers - if (master) call check_triggers() -#ifdef MPI - call MPI_BCAST(satisfy_triggers, 1, MPI_LOGICAL, 0, & - MPI_COMM_WORLD, mpi_err) -#endif - if (satisfy_triggers .or. & - (trigger_on .and. current_batch == n_max_batches)) then - call statepoint_batch % add(current_batch) - end if - - ! Write out state point if it's been specified for this batch - if (statepoint_batch % contains(current_batch)) then - call write_state_point() - end if - - end subroutine finalize_batch - -!=============================================================================== -! SAMPLE_SOURCE_PARTICLE -!=============================================================================== - - subroutine sample_source_particle(p) - - type(Particle), intent(inout) :: p - - ! Set particle - call p % initialize() - - ! Sample the external source distribution - call sample_external_source(source_site) - - ! Copy source attributes to the particle - call copy_source_attributes(p, source_site) - - ! Determine whether to create track file - if (write_all_tracks) p % write_track = .true. - - end subroutine sample_source_particle - -end module fixed_source diff --git a/src/geometry.F90 b/src/geometry.F90 index 39d95817ba..9a084a77cb 100644 --- a/src/geometry.F90 +++ b/src/geometry.F90 @@ -2,12 +2,14 @@ module geometry use constants use error, only: fatal_error, warning - use geometry_header, only: Cell, Surface, Universe, Lattice, & + use geometry_header, only: Cell, Universe, Lattice, & &RectLattice, HexLattice use global use output, only: write_message use particle_header, only: LocalCoord, Particle use particle_restart_write, only: write_particle_restart + use surface_header + use stl_vector, only: VectorInt use string, only: to_str use tally, only: score_surface_current @@ -16,59 +18,125 @@ module geometry contains !=============================================================================== -! SIMPLE_CELL_CONTAINS determines whether a given the current coordinates of the -! particle are inside a cell defined as the intersection of a series of surfaces +! CELL_CONTAINS determines if a cell contains the particle at a given +! location. The bounds of the cell are detemined by a logical expression +! involving surface half-spaces. At initialization, the expression was converted +! to RPN notation. +! +! The function is split into two cases, one for simple cells (those involving +! only the intersection of half-spaces) and one for complex cells. Simple cells +! can be evaluated with short circuit evaluation, i.e., as soon as we know that +! one half-space is not satisfied, we can exit. This provides a performance +! benefit for the common case. In complex_cell_contains, we evaluate the RPN +! expression using a stack, similar to how a RPN calculator would work. !=============================================================================== - function simple_cell_contains(c, p) result(in_cell) + pure function cell_contains(c, p) result(in_cell) + type(Cell), intent(in) :: c + type(Particle), intent(in) :: p + logical :: in_cell - type(Cell), pointer :: c - type(Particle), intent(inout) :: p - logical :: in_cell + if (c%simple) then + in_cell = simple_cell_contains(c, p) + else + in_cell = complex_cell_contains(c, p) + end if + end function cell_contains - integer :: i ! index of surfaces in cell - integer :: i_surface ! index in surfaces array (with sign) - logical :: specified_sense ! specified sense of surface in list + pure function simple_cell_contains(c, p) result(in_cell) + type(Cell), intent(in) :: c + type(Particle), intent(in) :: p + logical :: in_cell + + integer :: i + integer :: token logical :: actual_sense ! sense of particle wrt surface - type(Surface), pointer :: s - SURFACE_LOOP: do i = 1, c % n_surfaces - ! Lookup surface - i_surface = c % surfaces(i) - - ! Check if the particle is currently on the specified surface - if (i_surface == p % surface) then - ! Particle is heading into the cell - cycle - elseif (i_surface == -p % surface) then - ! Particle is heading out of the cell - in_cell = .false. - return - end if - - ! Determine the specified sense of the surface in the cell and the actual - ! sense of the particle with respect to the surface - s => surfaces(abs(i_surface)) - actual_sense = sense(p, s) - specified_sense = (c % surfaces(i) > 0) - - ! Compare sense of point to specified sense - if (actual_sense .neqv. specified_sense) then - in_cell = .false. - return - end if - end do SURFACE_LOOP - - ! If we've reached here, then the sense matched on every surface or there - ! are no surfaces. in_cell = .true. - + do i = 1, size(c%rpn) + token = c%rpn(i) + if (token < OP_UNION) then + ! If the token is not an operator, evaluate the sense of particle with + ! respect to the surface and see if the token matches the sense. If the + ! particle's surface attribute is set and matches the token, that + ! overrides the determination based on sense(). + if (token == p%surface) then + cycle + elseif (-token == p%surface) then + in_cell = .false. + exit + else + actual_sense = surfaces(abs(token))%obj%sense(& + p%coord(p%n_coord)%xyz, p%coord(p%n_coord)%uvw) + if (actual_sense .neqv. (token > 0)) then + in_cell = .false. + exit + end if + end if + end if + end do end function simple_cell_contains + pure function complex_cell_contains(c, p) result(in_cell) + type(Cell), intent(in) :: c + type(Particle), intent(in) :: p + logical :: in_cell + + integer :: i + integer :: token + integer :: i_stack + logical :: actual_sense ! sense of particle wrt surface + logical :: stack(size(c%rpn)) + + i_stack = 0 + do i = 1, size(c%rpn) + token = c%rpn(i) + + ! If the token is a binary operator (intersection/union), apply it to + ! the last two items on the stack. If the token is a unary operator + ! (complement), apply it to the last item on the stack. + select case (token) + case (OP_UNION) + stack(i_stack - 1) = stack(i_stack - 1) .or. stack(i_stack) + i_stack = i_stack - 1 + case (OP_INTERSECTION) + stack(i_stack - 1) = stack(i_stack - 1) .and. stack(i_stack) + i_stack = i_stack - 1 + case (OP_COMPLEMENT) + stack(i_stack) = .not. stack(i_stack) + case default + ! If the token is not an operator, evaluate the sense of particle with + ! respect to the surface and see if the token matches the sense. If the + ! particle's surface attribute is set and matches the token, that + ! overrides the determination based on sense(). + i_stack = i_stack + 1 + if (token == p%surface) then + stack(i_stack) = .true. + elseif (-token == p%surface) then + stack(i_stack) = .false. + else + actual_sense = surfaces(abs(token))%obj%sense(& + p%coord(p%n_coord)%xyz, p%coord(p%n_coord)%uvw) + stack(i_stack) = (actual_sense .eqv. (token > 0)) + end if + end select + + end do + + if (i_stack == 1) then + ! The one remaining logical on the stack indicates whether the particle is + ! in the cell. + in_cell = stack(i_stack) + else + ! This case occurs if there is no region specification since i_stack will + ! still be zero. + in_cell = .true. + end if + end function complex_cell_contains !=============================================================================== ! CHECK_CELL_OVERLAP checks for overlapping cells at the current particle's -! position using simple_cell_contains and the LocalCoord's built up by find_cell +! position using cell_contains and the LocalCoord's built up by find_cell !=============================================================================== subroutine check_cell_overlap(p) @@ -95,7 +163,7 @@ contains index_cell = univ % cells(i) c => cells(index_cell) - if (simple_cell_contains(c, p)) then + if (cell_contains(c, p)) then ! the particle should only be contained in one cell per level if (index_cell /= p % coord(j) % cell) then call fatal_error("Overlapping cells detected: " & @@ -164,7 +232,7 @@ contains c => cells(index_cell) ! Move on to the next cell if the particle is not inside this cell - if (.not. simple_cell_contains(c, p)) cycle + if (.not. cell_contains(c, p)) cycle ! Set cell on this level p % coord(j) % cell = index_cell @@ -273,28 +341,19 @@ contains !=============================================================================== subroutine cross_surface(p, last_cell) - type(Particle), intent(inout) :: p integer, intent(in) :: last_cell ! last cell particle was in - real(8) :: x ! x-x0 for sphere - real(8) :: y ! y-y0 for sphere - real(8) :: z ! z-z0 for sphere - real(8) :: R ! radius of sphere real(8) :: u ! x-component of direction real(8) :: v ! y-component of direction real(8) :: w ! z-component of direction - real(8) :: n1 ! x-component of surface normal - real(8) :: n2 ! y-component of surface normal - real(8) :: n3 ! z-component of surface normal - real(8) :: dot_prod ! dot product of direction and normal real(8) :: norm ! "norm" of surface normal integer :: i_surface ! index in surfaces logical :: found ! particle found in universe? - type(Surface), pointer :: surf + class(Surface), pointer :: surf i_surface = abs(p % surface) - surf => surfaces(i_surface) + surf => surfaces(i_surface)%obj if (verbosity >= 10 .or. trace) then call write_message(" Crossing surface " // trim(to_str(surf % id))) end if @@ -351,131 +410,15 @@ contains p % coord(1) % xyz = p % coord(1) % xyz + TINY_BIT * p % coord(1) % uvw end if - ! Copy particle's direction cosines - u = p % coord(1) % uvw(1) - v = p % coord(1) % uvw(2) - w = p % coord(1) % uvw(3) + ! Reflect particle off surface + call surf%reflect(p%coord(1)%xyz, p%coord(1)%uvw) - select case (surf%type) - case (SURF_PX) - u = -u - - case (SURF_PY) - v = -v - - case (SURF_PZ) - w = -w - - case (SURF_PLANE) - ! Find surface coefficients and norm of vector normal to surface - n1 = surf % coeffs(1) - n2 = surf % coeffs(2) - n3 = surf % coeffs(3) - norm = n1*n1 + n2*n2 + n3*n3 - dot_prod = u*n1 + v*n2 + w*n3 - - ! Reflect direction according to normal - u = u - 2*dot_prod*n1/norm - v = v - 2*dot_prod*n2/norm - w = w - 2*dot_prod*n3/norm - - case (SURF_CYL_X) - ! Find y-y0, z-z0 and dot product of direction and surface normal - y = p % coord(1) % xyz(2) - surf % coeffs(1) - z = p % coord(1) % xyz(3) - surf % coeffs(2) - R = surf % coeffs(3) - dot_prod = v*y + w*z - - ! Reflect direction according to normal - v = v - 2*dot_prod*y/(R*R) - w = w - 2*dot_prod*z/(R*R) - - case (SURF_CYL_Y) - ! Find x-x0, z-z0 and dot product of direction and surface normal - x = p % coord(1) % xyz(1) - surf % coeffs(1) - z = p % coord(1) % xyz(3) - surf % coeffs(2) - R = surf % coeffs(3) - dot_prod = u*x + w*z - - ! Reflect direction according to normal - u = u - 2*dot_prod*x/(R*R) - w = w - 2*dot_prod*z/(R*R) - - case (SURF_CYL_Z) - ! Find x-x0, y-y0 and dot product of direction and surface normal - x = p % coord(1) % xyz(1) - surf % coeffs(1) - y = p % coord(1) % xyz(2) - surf % coeffs(2) - R = surf % coeffs(3) - dot_prod = u*x + v*y - - ! Reflect direction according to normal - u = u - 2*dot_prod*x/(R*R) - v = v - 2*dot_prod*y/(R*R) - - case (SURF_SPHERE) - ! Find x-x0, y-y0, z-z0 and dot product of direction and surface - ! normal - x = p % coord(1) % xyz(1) - surf % coeffs(1) - y = p % coord(1) % xyz(2) - surf % coeffs(2) - z = p % coord(1) % xyz(3) - surf % coeffs(3) - R = surf % coeffs(4) - dot_prod = u*x + v*y + w*z - - ! Reflect direction according to normal - u = u - 2*dot_prod*x/(R*R) - v = v - 2*dot_prod*y/(R*R) - w = w - 2*dot_prod*z/(R*R) - - case (SURF_CONE_X) - ! Find x-x0, y-y0, z-z0 and dot product of direction and surface - ! normal - x = p % coord(1) % xyz(1) - surf % coeffs(1) - y = p % coord(1) % xyz(2) - surf % coeffs(2) - z = p % coord(1) % xyz(3) - surf % coeffs(3) - R = surf % coeffs(4) - dot_prod = (v*y + w*z - R*u*x)/((R + ONE)*R*x*x) - - ! Reflect direction according to normal - u = u + 2*dot_prod*R*x - v = v - 2*dot_prod*y - w = w - 2*dot_prod*z - - case (SURF_CONE_Y) - ! Find x-x0, y-y0, z-z0 and dot product of direction and surface - ! normal - x = p % coord(1) % xyz(1) - surf % coeffs(1) - y = p % coord(1) % xyz(2) - surf % coeffs(2) - z = p % coord(1) % xyz(3) - surf % coeffs(3) - R = surf % coeffs(4) - dot_prod = (u*x + w*z - R*v*y)/((R + ONE)*R*y*y) - - ! Reflect direction according to normal - u = u - 2*dot_prod*x - v = v + 2*dot_prod*R*y - w = w - 2*dot_prod*z - - case (SURF_CONE_Z) - ! Find x-x0, y-y0, z-z0 and dot product of direction and surface - ! normal - x = p % coord(1) % xyz(1) - surf % coeffs(1) - y = p % coord(1) % xyz(2) - surf % coeffs(2) - z = p % coord(1) % xyz(3) - surf % coeffs(3) - R = surf % coeffs(4) - dot_prod = (u*x + v*y - R*w*z)/((R + ONE)*R*z*z) - - ! Reflect direction according to normal - u = u - 2*dot_prod*x - v = v - 2*dot_prod*y - w = w + 2*dot_prod*R*z - - case default - call fatal_error("Reflection not supported for surface " & - &// trim(to_str(surf % id))) - end select - - ! Set new particle direction + ! Make sure new particle direction is normalized + u = p%coord(1)%uvw(1) + v = p%coord(1)%uvw(2) + w = p%coord(1)%uvw(3) norm = sqrt(u*u + v*v + w*w) - p % coord(1) % uvw = [u, v, w] / norm + p%coord(1)%uvw(:) = [u, v, w] / norm ! Reassign particle's cell and surface p % coord(1) % cell = last_cell @@ -489,7 +432,7 @@ contains call find_cell(p, found) if (.not. found) then call handle_lost_particle(p, "Couldn't find particle after reflecting& - & from surface.") + & from surface " // trim(to_str(surf%id)) // ".") return end if @@ -507,18 +450,18 @@ contains ! ========================================================================== ! SEARCH NEIGHBOR LISTS FOR NEXT CELL - if (p % surface > 0 .and. allocated(surf % neighbor_pos)) then + if (p % surface > 0 .and. allocated(surf%neighbor_pos)) then ! If coming from negative side of surface, search all the neighboring ! cells on the positive side - call find_cell(p, found, surf % neighbor_pos) + call find_cell(p, found, surf%neighbor_pos) if (found) return - elseif (p % surface < 0 .and. allocated(surf % neighbor_neg)) then + elseif (p % surface < 0 .and. allocated(surf%neighbor_neg)) then ! If coming from positive side of surface, search all the neighboring ! cells on the negative side - call find_cell(p, found, surf % neighbor_neg) + call find_cell(p, found, surf%neighbor_neg) if (found) return end if @@ -546,8 +489,8 @@ contains if (.not. found) then call handle_lost_particle(p, "After particle " // trim(to_str(p % id)) & - &// " crossed surface " // trim(to_str(surfaces(i_surface) % id)) & - &// " it could not be located in any cell and it did not leak.") + // " crossed surface " // trim(to_str(surf%id)) & + // " it could not be located in any cell and it did not leak.") return end if end if @@ -633,7 +576,6 @@ contains subroutine distance_to_boundary(p, dist, surface_crossed, lattice_translation, & next_level) - type(Particle), intent(inout) :: p real(8), intent(out) :: dist integer, intent(out) :: surface_crossed @@ -657,13 +599,10 @@ contains real(8) :: d_lat ! distance to lattice boundary real(8) :: d_surf ! distance to surface real(8) :: x0,y0,z0 ! coefficients for surface - real(8) :: r ! radius for quadratic surfaces - real(8) :: tmp ! dot product of surface normal with direction - real(8) :: a,b,c,k ! quadratic equation coefficients - real(8) :: quad ! discriminant of quadratic equation - logical :: on_surface ! is particle on surface? - type(Cell), pointer :: cl - type(Surface), pointer :: surf + real(8) :: xyz_cross(3) ! coordinates at projected surface crossing + logical :: coincident ! is particle on surface? + type(Cell), pointer :: c + class(Surface), pointer :: surf class(Lattice), pointer :: lat ! inialize distance to infinity (huge) @@ -678,7 +617,7 @@ contains LEVEL_LOOP: do j = 1, p % n_coord ! get pointer to cell on this level - cl => cells(p % coord(j) % cell) + c => cells(p % coord(j) % cell) ! copy directional cosines u = p % coord(j) % uvw(1) @@ -688,427 +627,26 @@ contains ! ======================================================================= ! FIND MINIMUM DISTANCE TO SURFACE IN THIS CELL - SURFACE_LOOP: do i = 1, cl % n_surfaces + SURFACE_LOOP: do i = 1, size(c % region) + index_surf = c % region(i) + coincident = (index_surf == p % surface) - ! copy local coordinates of particle - x = p % coord(j) % xyz(1) - y = p % coord(j) % xyz(2) - z = p % coord(j) % xyz(3) - - ! check for coincident surface -- note that we can't skip the - ! calculation in general because a particle could be on one side of a - ! cylinder and still have a positive distance to the other - - index_surf = cl % surfaces(i) - if (index_surf == p % surface) then - on_surface = .true. - else - on_surface = .false. - end if - - ! check for operators + ! ignore this token if it corresponds to an operator rather than a + ! region. index_surf = abs(index_surf) - if (index_surf >= OP_DIFFERENCE) cycle + if (index_surf >= OP_UNION) cycle - ! get pointer to surface - surf => surfaces(index_surf) + ! Calculate distance to surface + surf => surfaces(index_surf) % obj + d = surf % distance(p % coord(j) % xyz, p % coord(j) % uvw, coincident) - ! TODO: Can probably combines a lot of the cases to reduce repetition - ! since the algorithm is the same for (x-plane, y-plane, z-plane), - ! (x-cylinder, y-cylinder, z-cylinder), etc. - - select case (surf % type) - case (SURF_PX) - if (on_surface .or. u == ZERO) then - d = INFINITY - else - x0 = surf % coeffs(1) - d = (x0 - x)/u - if (d < ZERO) d = INFINITY - end if - - case (SURF_PY) - if (on_surface .or. v == ZERO) then - d = INFINITY - else - y0 = surf % coeffs(1) - d = (y0 - y)/v - if (d < ZERO) d = INFINITY - end if - - case (SURF_PZ) - if (on_surface .or. w == ZERO) then - d = INFINITY - else - z0 = surf % coeffs(1) - d = (z0 - z)/w - if (d < ZERO) d = INFINITY - end if - - case (SURF_PLANE) - A = surf % coeffs(1) - B = surf % coeffs(2) - C = surf % coeffs(3) - D = surf % coeffs(4) - - tmp = A*u + B*v + C*w - if (on_surface .or. tmp == ZERO) then - d = INFINITY - else - d = -(A*x + B*y + C*z - D)/tmp - if (d < ZERO) d = INFINITY - end if - - case (SURF_CYL_X) - a = ONE - u*u ! v^2 + w^2 - if (a == ZERO) then - d = INFINITY - else - y0 = surf % coeffs(1) - z0 = surf % coeffs(2) - r = surf % coeffs(3) - - y = y - y0 - z = z - z0 - k = y*v + z*w - c = y*y + z*z - r*r - quad = k*k - a*c - - if (quad < ZERO) then - ! no intersection with cylinder - - d = INFINITY - - elseif (on_surface) then - ! particle is on the cylinder, thus one distance is - ! positive/negative and the other is zero. The sign of k - ! determines if we are facing in or out - - if (k >= ZERO) then - d = INFINITY - else - d = (-k + sqrt(quad))/a - end if - - elseif (c < ZERO) then - ! particle is inside the cylinder, thus one distance must be - ! negative and one must be positive. The positive distance - ! will be the one with negative sign on sqrt(quad) - - d = (-k + sqrt(quad))/a - - else - ! particle is outside the cylinder, thus both distances are - ! either positive or negative. If positive, the smaller - ! distance is the one with positive sign on sqrt(quad) - - d = (-k - sqrt(quad))/a - if (d < ZERO) d = INFINITY - - end if - end if - - case (SURF_CYL_Y) - a = ONE - v*v ! u^2 + w^2 - if (a == ZERO) then - d = INFINITY - else - x0 = surf % coeffs(1) - z0 = surf % coeffs(2) - r = surf % coeffs(3) - - x = x - x0 - z = z - z0 - k = x*u + z*w - c = x*x + z*z - r*r - quad = k*k - a*c - - if (quad < ZERO) then - ! no intersection with cylinder - - d = INFINITY - - elseif (on_surface) then - ! particle is on the cylinder, thus one distance is - ! positive/negative and the other is zero. The sign of k - ! determines if we are facing in or out - - if (k >= ZERO) then - d = INFINITY - else - d = (-k + sqrt(quad))/a - end if - - elseif (c < ZERO) then - ! particle is inside the cylinder, thus one distance must be - ! negative and one must be positive. The positive distance - ! will be the one with negative sign on sqrt(quad) - - d = (-k + sqrt(quad))/a - - else - ! particle is outside the cylinder, thus both distances are - ! either positive or negative. If positive, the smaller - ! distance is the one with positive sign on sqrt(quad) - - d = (-k - sqrt(quad))/a - if (d < ZERO) d = INFINITY - - end if - end if - - case (SURF_CYL_Z) - a = ONE - w*w ! u^2 + v^2 - if (a == ZERO) then - d = INFINITY - else - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - r = surf % coeffs(3) - - x = x - x0 - y = y - y0 - k = x*u + y*v - c = x*x + y*y - r*r - quad = k*k - a*c - - if (quad < ZERO) then - ! no intersection with cylinder - - d = INFINITY - - elseif (on_surface) then - ! particle is on the cylinder, thus one distance is - ! positive/negative and the other is zero. The sign of k - ! determines if we are facing in or out - - if (k >= ZERO) then - d = INFINITY - else - d = (-k + sqrt(quad))/a - end if - - elseif (c < ZERO) then - ! particle is inside the cylinder, thus one distance must be - ! negative and one must be positive. The positive distance - ! will be the one with negative sign on sqrt(quad) - - d = (-k + sqrt(quad))/a - - else - ! particle is outside the cylinder, thus both distances are - ! either positive or negative. If positive, the smaller - ! distance is the one with positive sign on sqrt(quad) - - d = (-k - sqrt(quad))/a - if (d <= ZERO) d = INFINITY - - end if - end if - - case (SURF_SPHERE) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - z0 = surf % coeffs(3) - r = surf % coeffs(4) - - x = x - x0 - y = y - y0 - z = z - z0 - k = x*u + y*v + z*w - c = x*x + y*y + z*z - r*r - quad = k*k - c - - if (quad < ZERO) then - ! no intersection with sphere - - d = INFINITY - - elseif (on_surface) then - ! particle is on the sphere, thus one distance is - ! positive/negative and the other is zero. The sign of k - ! determines if we are facing in or out - - if (k >= ZERO) then - d = INFINITY - else - d = -k + sqrt(quad) - end if - - elseif (c < ZERO) then - ! particle is inside the sphere, thus one distance must be - ! negative and one must be positive. The positive distance will - ! be the one with negative sign on sqrt(quad) - - d = -k + sqrt(quad) - - else - ! particle is outside the sphere, thus both distances are either - ! positive or negative. If positive, the smaller distance is the - ! one with positive sign on sqrt(quad) - - d = -k - sqrt(quad) - if (d < ZERO) d = INFINITY - - end if - - case (SURF_CONE_X) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - z0 = surf % coeffs(3) - r = surf % coeffs(4) - - x = x - x0 - y = y - y0 - z = z - z0 - a = v*v + w*w - r*u*u - k = y*v + z*w - r*x*u - c = y*y + z*z - r*x*x - quad = k*k - a*c - - if (quad < ZERO) then - ! no intersection with cone - - d = INFINITY - - elseif (on_surface) then - ! particle is on the cone, thus one distance is positive/negative - ! and the other is zero. The sign of k determines which distance is - ! zero and which is not. - - if (k >= ZERO) then - d = (-k - sqrt(quad))/a - else - d = (-k + sqrt(quad))/a - end if - - else - ! calculate both solutions to the quadratic - quad = sqrt(quad) - d = (-k - quad)/a - b = (-k + quad)/a - - ! determine the smallest positive solution - if (d < ZERO) then - if (b > ZERO) then - d = b - end if - else - if (b > ZERO) d = min(d, b) - end if - end if - - ! If the distance was negative, set boundary distance to infinity - if (d <= ZERO) d = INFINITY - - case (SURF_CONE_Y) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - z0 = surf % coeffs(3) - r = surf % coeffs(4) - - x = x - x0 - y = y - y0 - z = z - z0 - a = u*u + w*w - r*v*v - k = x*u + z*w - r*y*v - c = x*x + z*z - r*y*y - quad = k*k - a*c - - if (quad < ZERO) then - ! no intersection with cone - - d = INFINITY - - elseif (on_surface) then - ! particle is on the cone, thus one distance is positive/negative - ! and the other is zero. The sign of k determines which distance is - ! zero and which is not. - - if (k >= ZERO) then - d = (-k - sqrt(quad))/a - else - d = (-k + sqrt(quad))/a - end if - - else - ! calculate both solutions to the quadratic - quad = sqrt(quad) - d = (-k - quad)/a - b = (-k + quad)/a - - ! determine the smallest positive solution - if (d < ZERO) then - if (b > ZERO) then - d = b - end if - else - if (b > ZERO) d = min(d, b) - end if - end if - - ! If the distance was negative, set boundary distance to infinity - if (d <= ZERO) d = INFINITY - - case (SURF_CONE_Z) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - z0 = surf % coeffs(3) - r = surf % coeffs(4) - - x = x - x0 - y = y - y0 - z = z - z0 - a = u*u + v*v - r*w*w - k = x*u + y*v - r*z*w - c = x*x + y*y - r*z*z - quad = k*k - a*c - - if (quad < ZERO) then - ! no intersection with cone - - d = INFINITY - - elseif (on_surface) then - ! particle is on the cone, thus one distance is positive/negative - ! and the other is zero. The sign of k determines which distance is - ! zero and which is not. - - if (k >= ZERO) then - d = (-k - sqrt(quad))/a - else - d = (-k + sqrt(quad))/a - end if - - else - ! calculate both solutions to the quadratic - quad = sqrt(quad) - d = (-k - quad)/a - b = (-k + quad)/a - - ! determine the smallest positive solution - if (d < ZERO) then - if (b > ZERO) then - d = b - end if - else - if (b > ZERO) d = min(d, b) - end if - end if - - ! If the distance was negative, set boundary distance to infinity - if (d <= ZERO) d = INFINITY - - end select - - ! Check is calculated distance is new minimum + ! Check if calculated distance is new minimum if (d < d_surf) then if (abs(d - d_surf)/d_surf >= FP_PRECISION) then d_surf = d - level_surf_cross = -cl % surfaces(i) + level_surf_cross = -c % region(i) end if end if - end do SURFACE_LOOP ! ======================================================================= @@ -1312,14 +850,31 @@ contains if (d_surf < d_lat) then if ((dist - d_surf)/dist >= FP_REL_PRECISION) then dist = d_surf - surface_crossed = level_surf_cross + + ! If the cell is not simple, it is possible that both the negative and + ! positive half-space were given in the region specification. Thus, we + ! have to explicitly check which half-space the particle would be + ! traveling into if the surface is crossed + if (.not. c % simple) then + xyz_cross(:) = p % coord(j) % xyz + d_surf*p % coord(j) % uvw + surf => surfaces(abs(level_surf_cross)) % obj + if (dot_product(p % coord(j) % uvw, & + surf % normal(xyz_cross)) > ZERO) then + surface_crossed = abs(level_surf_cross) + else + surface_crossed = -abs(level_surf_cross) + end if + else + surface_crossed = level_surf_cross + end if + lattice_translation(:) = [0, 0, 0] next_level = j end if else if ((dist - d_lat)/dist >= FP_REL_PRECISION) then dist = d_lat - surface_crossed = None + surface_crossed = NONE lattice_translation(:) = level_lat_trans next_level = j end if @@ -1329,133 +884,6 @@ contains end subroutine distance_to_boundary -!=============================================================================== -! SENSE determines whether a point is on the 'positive' or 'negative' side of a -! surface. This routine is crucial for determining what cell a particular point -! is in. -!=============================================================================== - - recursive function sense(p, surf) result(s) - - type(Particle), intent(inout) :: p - type(Surface), pointer :: surf ! surface - logical :: s ! sense of particle - - integer :: j - real(8) :: x,y,z ! coordinates of particle - real(8) :: func ! surface function evaluated at point - real(8) :: A ! coefficient on x for plane - real(8) :: B ! coefficient on y for plane - real(8) :: C ! coefficient on z for plane - real(8) :: D ! coefficient for plane - real(8) :: x0,y0,z0 ! coefficients for quadratic surfaces / box - real(8) :: r ! radius for quadratic surfaces - - j = p % n_coord - x = p % coord(j) % xyz(1) - y = p % coord(j) % xyz(2) - z = p % coord(j) % xyz(3) - - select case (surf % type) - case (SURF_PX) - x0 = surf % coeffs(1) - func = x - x0 - - case (SURF_PY) - y0 = surf % coeffs(1) - func = y - y0 - - case (SURF_PZ) - z0 = surf % coeffs(1) - func = z - z0 - - case (SURF_PLANE) - A = surf % coeffs(1) - B = surf % coeffs(2) - C = surf % coeffs(3) - D = surf % coeffs(4) - func = A*x + B*y + C*z - D - - case (SURF_CYL_X) - y0 = surf % coeffs(1) - z0 = surf % coeffs(2) - r = surf % coeffs(3) - y = y - y0 - z = z - z0 - func = y*y + z*z - r*r - - case (SURF_CYL_Y) - x0 = surf % coeffs(1) - z0 = surf % coeffs(2) - r = surf % coeffs(3) - x = x - x0 - z = z - z0 - func = x*x + z*z - r*r - - case (SURF_CYL_Z) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - r = surf % coeffs(3) - x = x - x0 - y = y - y0 - func = x*x + y*y - r*r - - case (SURF_SPHERE) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - z0 = surf % coeffs(3) - r = surf % coeffs(4) - x = x - x0 - y = y - y0 - z = z - z0 - func = x*x + y*y + z*z - r*r - - case (SURF_CONE_X) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - z0 = surf % coeffs(3) - r = surf % coeffs(4) - x = x - x0 - y = y - y0 - z = z - z0 - func = y*y + z*z - r*x*x - - case (SURF_CONE_Y) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - z0 = surf % coeffs(3) - r = surf % coeffs(4) - x = x - x0 - y = y - y0 - z = z - z0 - func = x*x + z*z - r*y*y - - case (SURF_CONE_Z) - x0 = surf % coeffs(1) - y0 = surf % coeffs(2) - z0 = surf % coeffs(3) - r = surf % coeffs(4) - x = x - x0 - y = y - y0 - z = z - z0 - func = x*x + y*y - r*z*z - - end select - - ! Check which side of surface the point is on - if (abs(func) < FP_COINCIDENT) then - ! Particle may be coincident with this surface. Artifically move the - ! particle forward a tiny bit. - p % coord(j) % xyz = p % coord(j) % xyz + TINY_BIT * p % coord(j) % uvw - s = sense(p, surf) - elseif (func > 0) then - s = .true. - else - s = .false. - end if - - end function sense - !=============================================================================== ! NEIGHBOR_LISTS builds a list of neighboring cells to each surface to speed up ! searches when a cell boundary is crossed. @@ -1463,77 +891,51 @@ contains subroutine neighbor_lists() - integer :: i ! index in cells/surfaces array - integer :: j ! index of surface in cell - integer :: i_surface ! index in count arrays - integer, allocatable :: count_positive(:) ! # of cells on positive side - integer, allocatable :: count_negative(:) ! # of cells on negative side - logical :: positive ! positive side specified in surface list - type(Cell), pointer :: c - type(Surface), pointer :: surf + integer :: i ! index in cells/surfaces array + integer :: j ! index in region specification + integer :: k ! surface half-space spec + integer :: n ! size of vector + type(VectorInt), allocatable :: neighbor_pos(:) + type(VectorInt), allocatable :: neighbor_neg(:) call write_message("Building neighboring cells lists for each surface...", & - &4) + 4) - allocate(count_positive(n_surfaces)) - allocate(count_negative(n_surfaces)) - count_positive = 0 - count_negative = 0 + allocate(neighbor_pos(n_surfaces)) + allocate(neighbor_neg(n_surfaces)) do i = 1, n_cells - c => cells(i) + do j = 1, size(cells(i)%region) + ! Get token from region specification and skip any tokens that + ! correspond to operators rather than regions + k = cells(i)%region(j) + if (abs(k) >= OP_UNION) cycle - ! loop over each surface specification - do j = 1, c % n_surfaces - i_surface = c % surfaces(j) - positive = (i_surface > 0) - i_surface = abs(i_surface) - if (positive) then - count_positive(i_surface) = count_positive(i_surface) + 1 + ! Add this cell ID to neighbor list for k-th surface + if (k > 0) then + call neighbor_pos(abs(k))%push_back(i) else - count_negative(i_surface) = count_negative(i_surface) + 1 + call neighbor_neg(abs(k))%push_back(i) end if end do end do - ! allocate neighbor lists for each surface do i = 1, n_surfaces - surf => surfaces(i) - if (count_positive(i) > 0) then - allocate(surf%neighbor_pos(count_positive(i))) + ! Copy positive neighbors to Surface instance + n = neighbor_pos(i)%size() + if (n > 0) then + allocate(surfaces(i)%obj%neighbor_pos(n)) + surfaces(i)%obj%neighbor_pos(:) = neighbor_pos(i)%data(1:n) end if - if (count_negative(i) > 0) then - allocate(surf%neighbor_neg(count_negative(i))) + + ! Copy negative neighbors to Surface instance + n = neighbor_neg(i)%size() + if (n > 0) then + allocate(surfaces(i)%obj%neighbor_neg(n)) + surfaces(i)%obj%neighbor_neg(:) = neighbor_neg(i)%data(1:n) end if end do - count_positive = 0 - count_negative = 0 - - ! loop over all cells - do i = 1, n_cells - c => cells(i) - - ! loop over each surface specification - do j = 1, c % n_surfaces - i_surface = c % surfaces(j) - positive = (i_surface > 0) - i_surface = abs(i_surface) - - surf => surfaces(i_surface) - if (positive) then - count_positive(i_surface) = count_positive(i_surface) + 1 - surf%neighbor_pos(count_positive(i_surface)) = i - else - count_negative(i_surface) = count_negative(i_surface) + 1 - surf%neighbor_neg(count_negative(i_surface)) = i - end if - end do - end do - - deallocate(count_positive) - deallocate(count_negative) - end subroutine neighbor_lists !=============================================================================== diff --git a/src/geometry_header.F90 b/src/geometry_header.F90 index 93e5dd1fdb..6ca13740ba 100644 --- a/src/geometry_header.F90 +++ b/src/geometry_header.F90 @@ -24,7 +24,7 @@ module geometry_header type, abstract :: Lattice integer :: id ! Universe number for lattice - character(len=52) :: name = "" ! User-defined name + character(len=104) :: name = "" ! User-defined name real(8), allocatable :: pitch(:) ! Pitch along each axis integer, allocatable :: universes(:,:,:) ! Specified universes integer :: outside ! Material to fill area outside @@ -113,29 +113,13 @@ module geometry_header class(Lattice), allocatable :: obj end type LatticeContainer -!=============================================================================== -! SURFACE type defines a first- or second-order surface that can be used to -! construct closed volumes (cells) -!=============================================================================== - - type Surface - integer :: id ! Unique ID - character(len=52) :: name = "" ! User-defined name - integer :: type ! Type of surface - real(8), allocatable :: coeffs(:) ! Definition of surface - integer, allocatable :: & - neighbor_pos(:), & ! List of cells on positive side - neighbor_neg(:) ! List of cells on negative side - integer :: bc ! Boundary condition - end type Surface - !=============================================================================== ! CELL defines a closed volume by its bounding surfaces !=============================================================================== type Cell integer :: id ! Unique ID - character(len=52) :: name = "" ! User-defined name + character(len=104) :: name = "" ! User-defined name integer :: type ! Type of cell (normal, universe, ! lattice) integer :: universe ! universe # this cell is in @@ -144,14 +128,13 @@ module geometry_header ! the geom integer :: material ! Material within cell (0 for ! universe) - integer :: n_surfaces ! Number of surfaces within integer, allocatable :: offset (:) ! Distribcell offset for tally ! counter - integer, allocatable :: & - & surfaces(:) ! List of surfaces bounding cell - ! -- note that parentheses, union, - ! etc operators will be listed here - ! too + integer, allocatable :: region(:) ! Definition of spatial region as + ! Boolean expression of half-spaces + integer, allocatable :: rpn(:) ! Reverse Polish notation for region + ! expression + logical :: simple ! Is the region simple (intersections only) ! Rotation matrix and translation vector real(8), allocatable :: translation(:) diff --git a/src/global.F90 b/src/global.F90 index a5ff7453ea..88ace73b6d 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -6,19 +6,17 @@ module global use cmfd_header use constants use dict_header, only: DictCharInt, DictIntInt - use geometry_header, only: Cell, Universe, Lattice, LatticeContainer, Surface + use geometry_header, only: Cell, Universe, Lattice, LatticeContainer use material_header, only: Material - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use plot_header, only: ObjectPlot use set_header, only: SetInt + use surface_header, only: SurfaceContainer use source_header, only: ExtSource use tally_header, only: TallyObject, TallyMap, TallyResult 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 @@ -30,12 +28,12 @@ module global ! GEOMETRY-RELATED VARIABLES ! Main arrays - type(Cell), allocatable, target :: cells(:) - type(Universe), allocatable, target :: universes(:) - type(LatticeContainer), allocatable, target :: lattices(:) - type(Surface), allocatable, target :: surfaces(:) - type(Material), allocatable, target :: materials(:) - type(ObjectPlot), allocatable, target :: plots(:) + type(Cell), allocatable, target :: cells(:) + type(Universe), allocatable, target :: universes(:) + type(LatticeContainer), allocatable, target :: lattices(:) + type(SurfaceContainer), allocatable, target :: surfaces(:) + type(Material), allocatable, target :: materials(:) + type(ObjectPlot), allocatable, target :: plots(:) ! Size of main arrays integer :: n_cells ! # of cells @@ -76,6 +74,10 @@ module global integer :: n_sab_tables ! Number of S(a,b) thermal scattering tables integer :: n_listings ! Number of listings in cross_sections.xml + ! Minimum/maximum energies + real(8) :: energy_min_neutron = ZERO + real(8) :: energy_max_neutron = INFINITY + ! Dictionaries to look up cross sections and listings type(DictCharInt) :: nuclide_dict type(DictCharInt) :: sab_dict @@ -93,7 +95,7 @@ module global ! ============================================================================ ! TALLY-RELATED VARIABLES - type(StructuredMesh), allocatable, target :: meshes(:) + type(RegularMesh), allocatable, target :: meshes(:) type(TallyObject), allocatable, target :: tallies(:) integer, allocatable :: matching_bins(:) @@ -109,9 +111,11 @@ module global type(SetInt) :: active_analog_tallies type(SetInt) :: active_tracklength_tallies type(SetInt) :: active_current_tallies + type(SetInt) :: active_collision_tallies type(SetInt) :: active_tallies !$omp threadprivate(active_analog_tallies, active_tracklength_tallies, & -!$omp& active_current_tallies, active_tallies) +!$omp& active_current_tallies, active_collision_tallies, & +!$omp& active_tallies) ! Global tallies ! 1) collision estimate of k-eff @@ -204,11 +208,11 @@ module global logical :: entropy_on = .false. real(8), allocatable :: entropy(:) ! shannon entropy at each generation real(8), allocatable :: entropy_p(:,:,:,:) ! % of source sites in each cell - type(StructuredMesh), pointer :: entropy_mesh + type(RegularMesh), pointer :: entropy_mesh ! Uniform fission source weighting logical :: ufs = .false. - type(StructuredMesh), pointer :: ufs_mesh => null() + type(RegularMesh), pointer :: ufs_mesh => null() real(8), allocatable :: source_frac(:,:,:,:) ! Write source at end of simulation @@ -267,26 +271,12 @@ 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 ! Mode to run in (fixed source, eigenvalue, plotting, etc) integer :: run_mode = NONE - ! Fixed source particle bank - type(Bank), pointer :: source_site => null() -!$omp threadprivate(source_site) - ! Restart run logical :: restart_run = .false. integer :: restart_batch @@ -446,7 +436,12 @@ contains do i = 1, size(nuclides) call nuclides(i) % clear() end do - deallocate(nuclides) + + ! WARNING: The following statement should work but doesn't under gfortran + ! 4.6 because of a bug. Technically, commenting this out leaves a memory + ! leak. + + ! deallocate(nuclides) end if if (allocated(nuclides_0K)) then @@ -473,14 +468,7 @@ contains ! Deallocate tally-related arrays if (allocated(global_tallies)) deallocate(global_tallies) if (allocated(meshes)) deallocate(meshes) - if (allocated(tallies)) then - ! First call the clear routines - do i = 1, size(tallies) - call tallies(i) % clear() - end do - ! Now deallocate the tally array - deallocate(tallies) - end if + if (allocated(tallies)) deallocate(tallies) if (allocated(matching_bins)) deallocate(matching_bins) if (allocated(tally_maps)) deallocate(tally_maps) @@ -504,6 +492,7 @@ contains call active_analog_tallies % clear() call active_tracklength_tallies % clear() call active_current_tallies % clear() + call active_collision_tallies % clear() call active_tallies % clear() ! Deallocate track_identifiers diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 34b72196ee..fc7a462e6a 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1,1816 +1,1924 @@ module hdf5_interface -#ifdef HDF5 +!============================================================================== +! HDF5_INTERFACE -- This module provides the high-level procedures which greatly +! simplify writing/reading different types of data to HDF5 files. In order to +! get it to work with gfotran 4.6, all the write__ND subroutines had to be +! split into two procedures, one accepting an assumed-shape array and another +! one with an explicit-shape array since in gfortran 4.6 C_LOC does not work +! with an assumed-shape array. When we move to gfortran 4.9+, these procedures +! can be combined into one simply accepting an assumed-shape array. +!============================================================================== + + use error, only: fatal_error + use tally_header, only: TallyResult use hdf5 use h5lt use, intrinsic :: ISO_C_BINDING -#ifdef MPI +#ifdef PHDF5 use message_passing, only: MPI_COMM_WORLD, MPI_INFO_NULL #endif implicit none + private - integer :: hdf5_err ! HDF5 error code - integer :: hdf5_rank ! rank of data - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - integer(HID_T) :: memspace ! data space handle for individual procs - integer(HID_T) :: plist ! property list handle - integer(HSIZE_T) :: dims1(1) ! dims type for 1-D array - integer(HSIZE_T) :: dims2(2) ! dims type for 2-D array - integer(HSIZE_T) :: dims3(3) ! dims type for 3-D array - integer(HSIZE_T) :: dims4(4) ! dims type for 4-D array - type(c_ptr) :: f_ptr ! pointer to data + integer(HID_T), public :: hdf5_tallyresult_t ! Compound type for TallyResult + integer(HID_T), public :: hdf5_bank_t ! Compound type for Bank + integer(HID_T), public :: hdf5_integer8_t ! type for integer(8) - ! Generic HDF5 write procedure interface - interface hdf5_write_data - module procedure hdf5_write_double - module procedure hdf5_write_double_1Darray - module procedure hdf5_write_double_2Darray - module procedure hdf5_write_double_3Darray - module procedure hdf5_write_double_4Darray - module procedure hdf5_write_integer - module procedure hdf5_write_integer_1Darray - module procedure hdf5_write_integer_2Darray - module procedure hdf5_write_integer_3Darray - module procedure hdf5_write_integer_4Darray - module procedure hdf5_write_long - module procedure hdf5_write_string -#ifdef MPI - module procedure hdf5_write_double_parallel - module procedure hdf5_write_double_1Darray_parallel - module procedure hdf5_write_double_2Darray_parallel - module procedure hdf5_write_double_3Darray_parallel - module procedure hdf5_write_double_4Darray_parallel - module procedure hdf5_write_integer_parallel - module procedure hdf5_write_integer_1Darray_parallel - module procedure hdf5_write_integer_2Darray_parallel - module procedure hdf5_write_integer_3Darray_parallel - module procedure hdf5_write_integer_4Darray_parallel - module procedure hdf5_write_long_parallel - module procedure hdf5_write_string_parallel -#endif - end interface hdf5_write_data + interface write_dataset + module procedure write_double + module procedure write_double_1D + module procedure write_double_2D + module procedure write_double_3D + module procedure write_double_4D + module procedure write_integer + module procedure write_integer_1D + module procedure write_integer_2D + module procedure write_integer_3D + module procedure write_integer_4D + module procedure write_long + module procedure write_string + module procedure write_string_1D + module procedure write_tally_result_1D + module procedure write_tally_result_2D + end interface write_dataset - ! Generic HDF5 read procedure interface - interface hdf5_read_data - module procedure hdf5_read_double - module procedure hdf5_read_double_1Darray - module procedure hdf5_read_double_2Darray - module procedure hdf5_read_double_3Darray - module procedure hdf5_read_double_4Darray - module procedure hdf5_read_integer - module procedure hdf5_read_integer_1Darray - module procedure hdf5_read_integer_2Darray - module procedure hdf5_read_integer_3Darray - module procedure hdf5_read_integer_4Darray - module procedure hdf5_read_long - module procedure hdf5_read_string -#ifdef MPI - module procedure hdf5_read_double_parallel - module procedure hdf5_read_double_1Darray_parallel - module procedure hdf5_read_double_2Darray_parallel - module procedure hdf5_read_double_3Darray_parallel - module procedure hdf5_read_double_4Darray_parallel - module procedure hdf5_read_integer_parallel - module procedure hdf5_read_integer_1Darray_parallel - module procedure hdf5_read_integer_2Darray_parallel - module procedure hdf5_read_integer_3Darray_parallel - module procedure hdf5_read_integer_4Darray_parallel - module procedure hdf5_read_long_parallel - module procedure hdf5_read_string_parallel -#endif - end interface hdf5_read_data + interface read_dataset + module procedure read_double + module procedure read_double_1D + module procedure read_double_2D + module procedure read_double_3D + module procedure read_double_4D + module procedure read_integer + module procedure read_integer_1D + module procedure read_integer_2D + module procedure read_integer_3D + module procedure read_integer_4D + module procedure read_long + module procedure read_string + module procedure read_string_1D + module procedure read_tally_result_1D + module procedure read_tally_result_2D + end interface read_dataset + + public :: write_dataset + public :: read_dataset + public :: file_create + public :: file_open + public :: file_close + public :: create_group + public :: open_group + public :: close_group + public :: write_attribute_string contains !=============================================================================== -! HDF5_FILE_CREATE creates HDF5 file +! FILE_CREATE creates HDF5 file !=============================================================================== - subroutine hdf5_file_create(filename, file_id) + function file_create(filename, parallel) result(file_id) + character(*), intent(in) :: filename ! name of file + logical, optional, intent(in) :: parallel ! whether to write in serial + integer(HID_T) :: file_id - character(*), intent(in) :: filename ! name of file - integer(HID_T), intent(inout) :: file_id ! file handle + integer(HID_T) :: plist ! property list handle + integer :: hdf5_err ! HDF5 error code + logical :: parallel_ - ! Create the file - call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err) + ! Check for serial option + parallel_ = .false. +#ifdef PHDF5 + if (present(parallel)) parallel_ = parallel +#endif - end subroutine hdf5_file_create + if (parallel_) then + ! Setup file access property list with parallel I/O access + call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) +#ifdef PHDF5 +#ifdef MPIF08 + call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD%MPI_VAL, & + MPI_INFO_NULL%MPI_VAL, hdf5_err) +#else + call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD, MPI_INFO_NULL, hdf5_err) +#endif +#endif + + ! Create the file collectively + call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err, & + access_prp = plist) + + ! Close the property list + call h5pclose_f(plist, hdf5_err) + else + ! Create the file + call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err) + end if + + end function file_create !=============================================================================== -! HDF5_FILE_OPEN opens HDF5 file +! FILE_OPEN opens HDF5 file !=============================================================================== - subroutine hdf5_file_open(filename, file_id, mode) + function file_open(filename, mode, parallel) result(file_id) + character(*), intent(in) :: filename ! name of file + character(*), intent(in) :: mode ! access mode to file + logical, optional, intent(in) :: parallel ! whether to write in serial + integer(HID_T) :: file_id - character(*), intent(in) :: filename ! name of file - character(*), intent(in) :: mode ! access mode to file - integer(HID_T), intent(inout) :: file_id ! file handle + logical :: parallel_ + integer(HID_T) :: plist ! property list handle + integer :: hdf5_err ! HDF5 error code + integer :: open_mode ! HDF5 open mode - integer :: open_mode ! HDF5 open mode + ! Check for serial option + parallel_ = .false. +#ifdef PHDF5 + if (present(parallel)) parallel_ = parallel +#endif ! Determine access type open_mode = H5F_ACC_RDONLY_F - if (trim(mode) == 'w') then - open_mode = H5F_ACC_RDWR_F - end if + if (mode == 'w') open_mode = H5F_ACC_RDWR_F - ! Open file - call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err) - - end subroutine hdf5_file_open - -!=============================================================================== -! HDF5_FILE_CLOSE closes HDF5 file -!=============================================================================== - - subroutine hdf5_file_close(file_id) - - integer(HID_T), intent(inout) :: file_id ! file handle - - ! Close the file - call h5fclose_f(file_id, hdf5_err) - - end subroutine hdf5_file_close - -#ifdef MPI - -!=============================================================================== -! HDF5_FILE_CREATE_PARALLEL creates HDF5 file with parallel I/O -!=============================================================================== - - subroutine hdf5_file_create_parallel(filename, file_id) - - character(*), intent(in) :: filename ! name of file - integer(HID_T), intent(inout) :: file_id ! file handle - - ! Setup file access property list with parallel I/O access - call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) + if (parallel_) then + ! Setup file access property list with parallel I/O access + call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) +#ifdef PHDF5 #ifdef MPIF08 - call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD%MPI_VAL, & - MPI_INFO_NULL%MPI_VAL, hdf5_err) + call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD%MPI_VAL, & + MPI_INFO_NULL%MPI_VAL, hdf5_err) #else - call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD, MPI_INFO_NULL, hdf5_err) + call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD, MPI_INFO_NULL, hdf5_err) +#endif #endif - ! Create the file collectively - call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err, & + ! Open the file collectively + call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err, & access_prp = plist) - ! Close the property list - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_file_create_parallel - -!=============================================================================== -! HDF5_FILE_OPEN_PARALLEL opens HDF5 file with parallel I/O -!=============================================================================== - - subroutine hdf5_file_open_parallel(filename, file_id, mode) - - character(*), intent(in) :: filename ! name of file - character(*), intent(in) :: mode ! access mode - integer(HID_T), intent(inout) :: file_id ! file handle - - integer :: open_mode ! HDF5 access mode - - ! Setup file access property list with parallel I/O access - call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) -#ifdef MPIF08 - call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD%MPI_VAL, & - MPI_INFO_NULL%MPI_VAL, hdf5_err) -#else - call h5pset_fapl_mpio_f(plist, MPI_COMM_WORLD, MPI_INFO_NULL, hdf5_err) -#endif - - ! Determine access type - open_mode = H5F_ACC_RDONLY_F - if (trim(mode) == 'w') then - open_mode = H5F_ACC_RDWR_F + ! Close the property list + call h5pclose_f(plist, hdf5_err) + else + ! Open file + call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err) end if - ! Create the file collectively - call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err, & - access_prp = plist) - - ! Close the property list - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_file_open_parallel - -#endif + end function file_open !=============================================================================== -! HDF5_OPEN_GROUP creates/opens HDF5 group to temp_group +! FILE_CLOSE closes HDF5 file !=============================================================================== - subroutine hdf5_open_group(hdf5_fh, group, hdf5_grp) + subroutine file_close(file_id) + integer(HID_T), intent(in) :: file_id - character(*), intent(in) :: group ! name of group - integer(HID_T), intent(in) :: hdf5_fh ! file handle of main output file - integer(HID_T), intent(inout) :: hdf5_grp ! handle for group + integer :: hdf5_err - logical :: status ! does the group exist + call h5fclose_f(file_id, hdf5_err) + end subroutine file_close + +!=============================================================================== +! OPEN_GROUP opens an existing HDF5 group +!=============================================================================== + + function open_group(group_id, name) result(newgroup_id) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of group + integer(HID_T) :: newgroup_id + + logical :: exists ! does the group exist + integer :: hdf5_err ! HDF5 error code ! Check if group exists - call h5ltpath_valid_f(hdf5_fh, trim(group), .true., status, hdf5_err) + call h5ltpath_valid_f(group_id, trim(name), .true., exists, hdf5_err) - ! Either create or open group - if (status) then - call h5gopen_f(hdf5_fh, trim(group), hdf5_grp, hdf5_err) + ! open group if it exists + if (exists) then + call h5gopen_f(group_id, trim(name), newgroup_id, hdf5_err) else - call h5gcreate_f(hdf5_fh, trim(group), hdf5_grp, hdf5_err) + call fatal_error("The group '" // trim(name) // "' does not exist.") end if - - end subroutine hdf5_open_group + end function open_group !=============================================================================== -! HDF5_CLOSE_GROUP closes HDF5 temp_group +! CREATE_GROUP creates a new HDF5 group !=============================================================================== - subroutine hdf5_close_group(hdf5_grp) + function create_group(group_id, name) result(newgroup_id) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of group + integer(HID_T) :: newgroup_id - integer(HID_T), intent(inout) :: hdf5_grp + integer :: hdf5_err ! HDF5 error code + logical :: exists ! does the group exist - ! Close the group - call h5gclose_f(hdf5_grp, hdf5_err) + ! Check if group exists + call h5ltpath_valid_f(group_id, trim(name), .true., exists, hdf5_err) - end subroutine hdf5_close_group + ! create group + if (exists) then + call fatal_error("The group '" // trim(name) // "' already exists.") + else + call h5gcreate_f(group_id, trim(name), newgroup_id, hdf5_err) + end if + end function create_group !=============================================================================== -! HDF5_WRITE_INTEGER writes integer scalar data +! CLOSE_GROUP closes HDF5 temp_group !=============================================================================== - subroutine hdf5_write_integer(group, name, buffer) + subroutine close_group(group_id) + integer(HID_T), intent(inout) :: group_id - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer ! data to write + integer :: hdf5_err ! HDF5 error code - ! Set rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims1, & - (/ buffer /), hdf5_err) - - end subroutine hdf5_write_integer + call h5gclose_f(group_id, hdf5_err) + if (hdf5_err < 0) then + call fatal_error("Unable to close HDF5 group.") + end if + end subroutine close_group !=============================================================================== -! HDF5_READ_INTEGER reads integer scalar data +! WRITE_DOUBLE writes double precision scalar data !=============================================================================== - subroutine hdf5_read_integer(group, name, buffer) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer ! read data to here - - integer :: buffer_copy(1) ! need an array for read - - ! Set up dimensions - dims1(1) = 1 - - ! Read data - call h5ltread_dataset_int_f(group, name, buffer_copy, dims1, hdf5_err) - buffer = buffer_copy(1) - - end subroutine hdf5_read_integer - -!=============================================================================== -! HDF5_WRITE_INTEGER_1DARRAY writes integer 1-D array -!=============================================================================== - - subroutine hdf5_write_integer_1Darray(group, name, buffer, len) - - integer, intent(in) :: len ! length of array to write - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer(:) ! data to write - - ! Set rank and dimensions of data - hdf5_rank = 1 - dims1(1) = len - - ! Write data - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims1, & - buffer, hdf5_err) - - end subroutine hdf5_write_integer_1Darray - -!=============================================================================== -! HDF5_READ_INTEGER_1DARRAY reads integer 1-D array -!=============================================================================== - - subroutine hdf5_read_integer_1Darray(group, name, buffer, length) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer(:) ! read data to here - integer, intent(in) :: length ! length of array - - ! Set dimensions - dims1(1) = length - - ! Read data - call h5ltread_dataset_int_f(group, name, buffer, dims1, hdf5_err) - - end subroutine hdf5_read_integer_1Darray - -!=============================================================================== -! HDF5_WRITE_INTEGER_2DARRAY writes integer 2-D array -!=============================================================================== - - subroutine hdf5_write_integer_2Darray(group, name, buffer, length) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer(length(1),length(2)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 2 - dims2 = length - - ! Write data - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims2, & - buffer, hdf5_err) - - end subroutine hdf5_write_integer_2Darray - -!=============================================================================== -! HDF5_READ_INTEGER_2DARRAY reads integer 2-D array -!=============================================================================== - - subroutine hdf5_read_integer_2Darray(group, name, buffer, length) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer(length(1),length(2)) ! data to read - - ! Set rank and dimensions - dims2 = length - - ! Write data - call h5ltread_dataset_int_f(group, name, buffer, dims2, hdf5_err) - - end subroutine hdf5_read_integer_2Darray - -!=============================================================================== -! HDF5_WRITE_INTEGER_3DARRAY writes integer 3-D array -!=============================================================================== - - subroutine hdf5_write_integer_3Darray(group, name, buffer, length) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer(length(1),length(2), & - length(3)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 3 - dims3 = length - - ! Write data - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims3, & - buffer, hdf5_err) - - end subroutine hdf5_write_integer_3Darray - -!=============================================================================== -! HDF5_READ_INTEGER_3DARRAY reads integer 3-D array -!=============================================================================== - - subroutine hdf5_read_integer_3Darray(group, name, buffer, length) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer(length(1),length(2), & - length(3)) ! data to read - - ! Set rank and dimensions - dims3 = length - - ! Write data - call h5ltread_dataset_int_f(group, name, buffer, dims3, hdf5_err) - - end subroutine hdf5_read_integer_3Darray - -!=============================================================================== -! HDF5_WRITE_INTEGER_4DARRAY writes integer 4-D array -!=============================================================================== - - subroutine hdf5_write_integer_4Darray(group, name, buffer, length) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(in) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 4 - dims4 = length - - ! Write data - call h5ltmake_dataset_int_f(group, name, hdf5_rank, dims4, & - buffer, hdf5_err) - - end subroutine hdf5_write_integer_4Darray - -!=============================================================================== -! HDF5_READ_INTEGER_4DARRAY reads integer 4-D array -!=============================================================================== - - subroutine hdf5_read_integer_4Darray(group, name, buffer, length) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to read - - ! Set rank and dimensions - dims4 = length - - ! Write data - call h5ltread_dataset_int_f(group, name, buffer, dims4, hdf5_err) - - end subroutine hdf5_read_integer_4Darray - -!=============================================================================== -! HDF5_WRITE_DOUBLE writes integer scalar data -!=============================================================================== - - subroutine hdf5_write_double(group, name, buffer) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer ! data to write - - ! Set rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims1, & - (/ buffer /), hdf5_err) - - end subroutine hdf5_write_double - -!=============================================================================== -! HDF5_READ_DOUBLE reads double scalar data -!=============================================================================== - - subroutine hdf5_read_double(group, name, buffer) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer ! read data to here - - real(8) :: buffer_copy(1) ! need an array for read - - ! Set up dimensions - dims1(1) = 1 - - ! Read data - call h5ltread_dataset_double_f(group, name, buffer_copy, dims1, hdf5_err) - buffer = buffer_copy(1) - - end subroutine hdf5_read_double - -!=============================================================================== -! HDF5_WRITE_DOUBLE_1DARRAY writes double 1-D array -!=============================================================================== - - subroutine hdf5_write_double_1Darray(group, name, buffer, length) - - integer, intent(in) :: length ! length of array to write - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer(:) ! data to write - - ! Set rank and dimensions of data - hdf5_rank = 1 - dims1(1) = length - - ! Write data - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims1, & - buffer, hdf5_err) - - end subroutine hdf5_write_double_1Darray - -!=============================================================================== -! HDF5_READ_DOUBLE_1DARRAY reads double 1-D array -!=============================================================================== - - subroutine hdf5_read_double_1Darray(group, name, buffer, length) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer(:) ! read data to here - integer, intent(in) :: length ! length of array - - ! Set dimensions - dims1(1) = length - - ! Read data - call h5ltread_dataset_double_f(group, name, buffer, dims1, hdf5_err) - - end subroutine hdf5_read_double_1Darray - -!=============================================================================== -! HDF5_WRITE_DOUBLE_2DARRAY writes double 2-D array -!=============================================================================== - - subroutine hdf5_write_double_2Darray(group, name, buffer, length) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer(length(1),length(2)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 2 - dims2 = length - - ! Write data - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims2, & - buffer, hdf5_err) - - end subroutine hdf5_write_double_2Darray - -!=============================================================================== -! HDF5_READ_DOUBLE_2DARRAY reads double 2-D array -!=============================================================================== - - subroutine hdf5_read_double_2Darray(group, name, buffer, length) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer(length(1),length(2)) ! data to read - - ! Set rank and dimensions - dims2 = length - - ! Write data - call h5ltread_dataset_double_f(group, name, buffer, dims2, hdf5_err) - - end subroutine hdf5_read_double_2Darray - -!=============================================================================== -! HDF5_WRITE_DOUBLE_3DARRAY writes double 3-D array -!=============================================================================== - - subroutine hdf5_write_double_3Darray(group, name, buffer, length) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer(length(1),length(2), & - length(3)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 3 - dims3 = length - - ! Write data - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims3, & - buffer, hdf5_err) - - end subroutine hdf5_write_double_3Darray - -!=============================================================================== -! HDF5_READ_DOUBLE_3DARRAY reads double 3-D array -!=============================================================================== - - subroutine hdf5_read_double_3Darray(group, name, buffer, length) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer(length(1),length(2), & - length(3)) ! data to read - - ! Set rank and dimensions - dims3 = length - - ! Write data - call h5ltread_dataset_double_f(group, name, buffer, dims3, hdf5_err) - - end subroutine hdf5_read_double_3Darray - -!=============================================================================== -! HDF5_WRITE_DOUBLE_4DARRAY writes double 4-D array -!=============================================================================== - - subroutine hdf5_write_double_4Darray(group, name, buffer, length) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(in) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to write - - ! Set rank and dimensions - hdf5_rank = 4 - dims4 = length - - ! Write data - call h5ltmake_dataset_double_f(group, name, hdf5_rank, dims4, & - buffer, hdf5_err) - - end subroutine hdf5_write_double_4Darray - -!=============================================================================== -! HDF5_READ_DOUBLE_4DARRAY reads double 4-D array -!=============================================================================== - - subroutine hdf5_read_double_4Darray(group, name, buffer, length) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to read - - ! Set rank and dimensions - dims4 = length - - ! Write data - call h5ltread_dataset_double_f(group, name, buffer, dims4, hdf5_err) - - end subroutine hdf5_read_double_4Darray - -!=============================================================================== -! HDF5_WRITE_LONG writes long integer scalar data -!=============================================================================== - - subroutine hdf5_write_long(group, name, buffer, long_type) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer(8), target, intent(in) :: buffer ! data to write - integer(HID_T), intent(in) :: long_type ! HDF5 long type - - ! Set up rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 + subroutine write_double(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + real(8), intent(in), target :: buffer ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up independentive vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if ! Create dataspace and dataset - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - call h5dcreate_f(group, name, long_type, dspace, dset, hdf5_err) - - ! Write eight-byte integer - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, long_type, f_ptr, hdf5_err) - - ! Close dataspace and dataset for long integer - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - - end subroutine hdf5_write_long - -!=============================================================================== -! HDF5_READ_LONG read long integer scalar data -!=============================================================================== - - subroutine hdf5_read_long(group, name, buffer, long_type) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer(8), target, intent(out) :: buffer ! read data to here - integer(HID_T), intent(in) :: long_type ! long integer type - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Get pointer to buffer + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) f_ptr = c_loc(buffer) - ! Read data from dataset - call h5dread_f(dset, long_type, f_ptr, hdf5_err) - - ! Close dataset - call h5dclose_f(dset, hdf5_err) - - end subroutine hdf5_read_long - -!=============================================================================== -! HDF5_WRITE_STRING writes string data -!=============================================================================== - - subroutine hdf5_write_string(group, name, buffer, length) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - character(*), intent(in) :: buffer ! data to write - integer, intent(in) :: length - - character(len=length), dimension(1) :: str_tmp - -! Fortran 2003 implementation not compatible with IBM compiler Feb 2013 -! type(c_ptr), dimension(1), target :: wdata -! character(len=length, kind=c_char), dimension(1), target :: c_str -! dims1(1) = 1 -! call h5screate_simple_f(1, dims1, dspace, hdf5_err) -! call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err) -! c_str(1) = buffer -! wdata(1) = c_loc(c_str(1)) -! f_ptr = c_loc(wdata(1)) - - ! Number of strings to write - dims1(1) = 1 - - ! Insert null character at end of string when writing - call h5tset_strpad_f(H5T_STRING, H5T_STR_NULLPAD_F, hdf5_err) - - ! Create the dataspace and dataset - call h5screate_simple_f(1, dims1, dspace, hdf5_err) - call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err) - - ! Set up dimesnions of string to write - dims2 = (/length, 1/) ! full array of strings to write - dims1(1) = length ! length of string - - ! Copy over string buffer to a rank 1 array - str_tmp(1) = buffer - - ! Write the variable dataset - call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - - end subroutine hdf5_write_string - -!=============================================================================== -! HDF5_READ_STRING reads string data -!=============================================================================== - - subroutine hdf5_read_string(group, name, buffer, length) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - character(*), intent(inout) :: buffer ! read data to here - integer, intent(in) :: length ! length of string to read - - character(len=length), dimension(1) :: str_tmp - - ! Fortran 2003 implementation not compatible with IBM Feb 2013 compiler -! type(c_ptr), dimension(1), target :: buf_ptr -! character(len=length, kind=c_char), pointer :: chr_ptr -! f_ptr = c_loc(buf_ptr(1)) -! call h5dread_f(dset, H5T_STRING, f_ptr, hdf5_err, xfer_prp=plist) -! call c_f_pointer(buf_ptr(1), chr_ptr) -! buffer = chr_ptr -! nullify(chr_ptr) - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Get dataspace to read - call h5dget_space_f(dset, dspace, hdf5_err) - - ! Set dimensions - dims2 = (/length, 1/) - dims1(1) = length - - ! Read in the data - call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace, xfer_prp = plist) - - ! Copy over buffer - buffer = str_tmp(1) - - ! Close dataset - call h5dclose_f(dset, hdf5_err) - - end subroutine hdf5_read_string - -!=============================================================================== -! HDF5_WRITE_ATTRIBUTE_STRING writes a string attribute to a variables -!=============================================================================== - - subroutine hdf5_write_attribute_string(group, var, attr_type, attr_str) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: var ! name of varaible to set attr - character(*), intent(in) :: attr_type ! the attr type id - character(*), intent(in) :: attr_str ! attribute sting - - call h5ltset_attribute_string_f(group, var, attr_type, attr_str, hdf5_err) - - end subroutine hdf5_write_attribute_string - -# ifdef MPI - -!=============================================================================== -! HDF5_WRITE_INTEGER_PARALLEL writes integer scalar data in parallel -!=============================================================================== - - subroutine hdf5_write_integer_parallel(group, name, buffer, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collect I/O - - ! Set rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_parallel - -!=============================================================================== -! HDF5_READ_INTEGER_PARALLEL reads integer scalar data -!=============================================================================== - - subroutine hdf5_read_integer_parallel(group, name, buffer, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, target, intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_1DARRAY_PARALLEL writes integer 1-D array in parallel -!=============================================================================== - - subroutine hdf5_write_integer_1Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length ! length of array to write - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer(length) ! data to write - logical, intent(in) :: collect ! collect I/O - - ! Set rank and dimensions of data - hdf5_rank = 1 - dims1(1) = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_1Darray_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_1DARRAY_PARALLEL reads integer 1-D array in parallel -!=============================================================================== - - subroutine hdf5_read_integer_1Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length ! length of array - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer, target, intent(inout) :: buffer(length) ! read data to here - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_1Darray_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_2DARRAY_PARALLEL writes integer 2-D array in parallel -!=============================================================================== - - subroutine hdf5_write_integer_2Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer(length(1),length(2)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 2 - dims2 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims2, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_2Darray_parallel - -!=============================================================================== -! HDF5_READ_INTEGER_2DARRAY_PARALLEL reads integer 2-D array in parallel -!=============================================================================== - - subroutine hdf5_read_integer_2Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(inout) :: buffer(length(1),length(2)) ! data to read - logical, intent(in) :: collect ! collect I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_2Darray_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_3DARRAY_PARALLEL writes integer 3-D array in parallel -!=============================================================================== - - subroutine hdf5_write_integer_3Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer(length(1),length(2), & - length(3)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 3 - dims3 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims3, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_3Darray_parallel - -!=============================================================================== -! HDF5_READ_INTEGER_3DARRAY_PARALLEL reads integer 3-D array in parallel -!=============================================================================== - - subroutine hdf5_read_integer_3Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(inout) :: buffer(length(1),length(2), & - length(3)) ! data to read - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_3Darray_parallel - -!=============================================================================== -! HDF5_WRITE_INTEGER_4DARRAY_PARALLEL writes integer 4-D array in parallel -!=============================================================================== - - subroutine hdf5_write_integer_4Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(in) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 4 - dims4 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims4, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_integer_4Darray_parallel - -!=============================================================================== -! HDF5_READ_INTEGER_4DARRAY_PARALLEL reads integer 4-D array in parallel -!=============================================================================== - - subroutine hdf5_read_integer_4Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer,target, intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to read - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_integer_4Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_PARALLEL writes double scalar data in parallel -!=============================================================================== - - subroutine hdf5_write_double_parallel(group, name, buffer, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collect I/O - - ! Set rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_parallel - -!=============================================================================== -! HDF5_READ_DOUBLE_PARALLEL reads double scalar data -!=============================================================================== - - subroutine hdf5_read_double_parallel(group, name, buffer, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8), target, intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_1DARRAY_PARALLEL writes double 1-D array in parallel -!=============================================================================== - - subroutine hdf5_write_double_1Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length ! length of array to write - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer(length) ! data to write - logical, intent(in) :: collect ! collect I/O - - ! Set rank and dimensions of data - hdf5_rank = 1 - dims1(1) = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_1Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_1DARRAY_PARALLEL reads double 1-D array in parallel -!=============================================================================== - - subroutine hdf5_read_double_1Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length ! length of array - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(inout) :: buffer(length) ! read data to here - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_1Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_2DARRAY_PARALLEL writes double 2-D array in parallel -!=============================================================================== - - subroutine hdf5_write_double_2Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer(length(1),length(2)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 2 - dims2 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims2, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer(1,1)) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_2Darray_parallel - -!=============================================================================== -! HDF5_READ_DOUBLE_2DARRAY_PARALLEL reads double 2-D array in parallel -!=============================================================================== - - subroutine hdf5_read_double_2Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(2) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(inout) :: buffer(length(1),length(2)) ! data to read - logical, intent(in) :: collect ! collect I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_2Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_3DARRAY_PARALLEL writes double 3-D array in parallel -!=============================================================================== - - subroutine hdf5_write_double_3Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer(length(1),length(2), & - length(3)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 3 - dims3 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims3, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_3Darray_parallel - -!=============================================================================== -! HDF5_READ_DOUBLE_3DARRAY_PARALLEL reads double 3-D array in parallel -!=============================================================================== - - subroutine hdf5_read_double_3Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(3) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(inout) :: buffer(length(1),length(2), & - length(3)) ! data to read - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_3Darray_parallel - -!=============================================================================== -! HDF5_WRITE_DOUBLE_4DARRAY_PARALLEL writes double 4-D array in parallel -!=============================================================================== - - subroutine hdf5_write_double_4Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(in) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to write - logical, intent(in) :: collect ! collective I/O - - ! Set rank and dimensions - hdf5_rank = 4 - dims4 = length - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims4, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, H5T_NATIVE_DOUBLE, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_double_4Darray_parallel - -!=============================================================================== -! HDF5_READ_DOUBLE_4DARRAY_PARALLEL reads double 4-D array in parallel -!=============================================================================== - - subroutine hdf5_read_double_4Darray_parallel(group, name, buffer, length, & - collect) - - integer, intent(in) :: length(4) ! length of array dimensions - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - real(8),target, intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! data to read - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_double_4Darray_parallel - -!=============================================================================== -! HDF5_WRITE_LONG_PARALLEL writes long integer scalar data in parallel -!=============================================================================== - - subroutine hdf5_write_long_parallel(group, name, buffer, long_type, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer(8), target, intent(in) :: buffer ! data to write - integer(HID_T), intent(in) :: long_type ! HDF5 long type - logical, intent(in) :: collect ! collective I/O - - ! Set up rank and dimensions - hdf5_rank = 1 - dims1(1) = 1 - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(group, name, long_type, dspace, dset, hdf5_err) - - ! Write data - f_ptr = c_loc(buffer) - call h5dwrite_f(dset, long_type, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_long_parallel - -!=============================================================================== -! HDF5_READ_LONG_PARALLEL read long integer scalar data in parallel -!=============================================================================== - - subroutine hdf5_read_long_parallel(group, name, buffer, long_type, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - integer(8), target, intent(out) :: buffer ! read data to here - integer(HID_T), intent(in) :: long_type ! long integer type - logical, intent(in) :: collect ! collective I/O - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Read data - f_ptr = c_loc(buffer) - call h5dread_f(dset, long_type, f_ptr, hdf5_err, xfer_prp=plist) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_long_parallel - -!=============================================================================== -! HDF5_WRITE_STRING_PARALLEL writes string data in parallel -!=============================================================================== - - subroutine hdf5_write_string_parallel(group, name, buffer, length, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - character(*), intent(in) :: buffer ! data to write - integer, intent(in) :: length ! length of string - logical, intent(in) :: collect ! collective I/O - - character(len=length), dimension(1) :: str_tmp - -! Fortran 2003 implementation not compatible with IBM compiler Feb 2013 -! type(c_ptr), dimension(1), target :: wdata -! character(len=length, kind=c_char), dimension(1), target :: c_str -! dims1(1) = 1 -! call h5screate_simple_f(1, dims1, dspace, hdf5_err) -! call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err) -! c_str(1) = buffer -! wdata(1) = c_loc(c_str(1)) -! f_ptr = c_loc(wdata(1)) - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Number of strings to write - dims1(1) = 1 - - ! Insert null character at end of string when writing - call h5tset_strpad_f(H5T_STRING, H5T_STR_NULLPAD_F, hdf5_err) - - ! Create the dataspace and dataset - call h5screate_simple_f(1, dims1, dspace, hdf5_err) - call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err) - - ! Set up dimesnions of string to write - dims2 = (/length, 1/) ! full array of strings to write - dims1(1) = length ! length of string - - ! Copy over string buffer to a rank 1 array - str_tmp(1) = buffer - - ! Write the variable dataset - call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace, xfer_prp=plist) - - ! Close all - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_write_string_parallel - -!=============================================================================== -! HDF5_READ_STRING_PARALLEL reads string data in parallel -!=============================================================================== - - subroutine hdf5_read_string_parallel(group, name, buffer, length, collect) - - integer(HID_T), intent(in) :: group ! name of group - character(*), intent(in) :: name ! name of data - character(*), intent(inout) :: buffer ! read data to here - integer, intent(in) :: length ! length of string - logical, intent(in) :: collect ! collective I/O - - character(len=length), dimension(1) :: str_tmp - - ! Fortran 2003 implementation not compatible with IBM Feb 2013 compiler -! type(c_ptr), dimension(1), target :: buf_ptr -! character(len=length, kind=c_char), pointer :: chr_ptr -! f_ptr = c_loc(buf_ptr(1)) -! call h5dread_f(dset, H5T_STRING, f_ptr, hdf5_err, xfer_prp=plist) -! call c_f_pointer(buf_ptr(1), chr_ptr) -! buffer = chr_ptr -! nullify(chr_ptr) - - ! Create property list for independent or collective read - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - - ! Set independent or collective option - if (collect) then - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - else - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_INDEPENDENT_F, hdf5_err) - end if - - ! Open dataset - call h5dopen_f(group, name, dset, hdf5_err) - - ! Get dataspace to read - call h5dget_space_f(dset, dspace, hdf5_err) - - ! Set dimensions - dims2 = (/length, 1/) - dims1(1) = length - - ! Read in the data - call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, & - mem_space_id=dspace, xfer_prp = plist) - - ! Copy over buffer - buffer = str_tmp(1) - - ! Close dataset and property list - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - - end subroutine hdf5_read_string_parallel - -# endif - + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) #endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double + +!=============================================================================== +! READ_DOUBLE reads double precision scalar data +!=============================================================================== + + subroutine read_double(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + real(8), intent(inout), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double + +!=============================================================================== +! WRITE_DOUBLE_1D writes double precision 1-D array data +!=============================================================================== + + subroutine write_double_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_double_1D_explicit(group_id, dims, name, buffer, indep) + else + call write_double_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_double_1D + + subroutine write_double_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(dims(1)) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double_1D_explicit + +!=============================================================================== +! READ_DOUBLE_1D reads double precision 1-D array data +!=============================================================================== + + subroutine read_double_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_double_1D_explicit(group_id, dims, name, buffer, indep) + else + call read_double_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_double_1D + + subroutine read_double_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(dims(1)) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double_1D_explicit + +!=============================================================================== +! WRITE_DOUBLE_2D writes double precision 2-D array data +!=============================================================================== + + subroutine write_double_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_double_2D_explicit(group_id, dims, name, buffer, indep) + else + call write_double_2D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_double_2D + + subroutine write_double_2D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(dims(1),dims(2)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(2, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double_2D_explicit + +!=============================================================================== +! READ_DOUBLE_2D reads double precision 2-D array data +!=============================================================================== + + subroutine read_double_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_double_2D_explicit(group_id, dims, name, buffer, indep) + else + call read_double_2D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_double_2D + + subroutine read_double_2D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(dims(1),dims(2)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double_2D_explicit + +!=============================================================================== +! WRITE_DOUBLE_3D writes double precision 3-D array data +!=============================================================================== + + subroutine write_double_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_double_3D_explicit(group_id, dims, name, buffer, indep) + else + call write_double_3D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_double_3D + + subroutine write_double_3D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(3) + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(dims(1),dims(2),dims(3)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(3, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double_3D_explicit + +!=============================================================================== +! READ_DOUBLE_3D reads double precision 3-D array data +!=============================================================================== + + subroutine read_double_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_double_3D_explicit(group_id, dims, name, buffer, indep) + else + call read_double_3D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_double_3D + + subroutine read_double_3D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(3) + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(dims(1),dims(2),dims(3)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double_3D_explicit + +!=============================================================================== +! WRITE_DOUBLE_4D writes double precision 4-D array data +!=============================================================================== + + subroutine write_double_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_double_4D_explicit(group_id, dims, name, buffer, indep) + else + call write_double_4D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_double_4D + + subroutine write_double_4D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(4) + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(dims(1),dims(2),dims(3),dims(4)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(4, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_double_4D_explicit + +!=============================================================================== +! READ_DOUBLE_4D reads double precision 4-D array data +!=============================================================================== + + subroutine read_double_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_double_4D_explicit(group_id, dims, name, buffer, indep) + else + call read_double_4D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_double_4D + + subroutine read_double_4D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(4) + character(*), intent(in) :: name ! name of data + real(8), intent(inout), target :: buffer(dims(1),dims(2),dims(3),dims(4)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_double_4D_explicit + +!=============================================================================== +! WRITE_INTEGER writes integer precision scalar data +!=============================================================================== + + subroutine write_integer(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer, intent(in), target :: buffer ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Create dataspace and dataset + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer + +!=============================================================================== +! READ_INTEGER reads integer precision scalar data +!=============================================================================== + + subroutine read_integer(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer, intent(inout), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer + +!=============================================================================== +! WRITE_INTEGER_1D writes integer precision 1-D array data +!=============================================================================== + + subroutine write_integer_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_integer_1D_explicit(group_id, dims, name, buffer, indep) + else + call write_integer_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_integer_1D + + subroutine write_integer_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(dims(1)) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer_1D_explicit + +!=============================================================================== +! READ_INTEGER_1D reads integer precision 1-D array data +!=============================================================================== + + subroutine read_integer_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_integer_1D_explicit(group_id, dims, name, buffer, indep) + else + call read_integer_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_integer_1D + + subroutine read_integer_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(dims(1)) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer_1D_explicit + +!=============================================================================== +! WRITE_INTEGER_2D writes integer precision 2-D array data +!=============================================================================== + + subroutine write_integer_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_integer_2D_explicit(group_id, dims, name, buffer, indep) + else + call write_integer_2D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_integer_2D + + subroutine write_integer_2D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(dims(1),dims(2)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(2, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer_2D_explicit + +!=============================================================================== +! READ_INTEGER_2D reads integer precision 2-D array data +!=============================================================================== + + subroutine read_integer_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_integer_2D_explicit(group_id, dims, name, buffer, indep) + else + call read_integer_2D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_integer_2D + + subroutine read_integer_2D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(dims(1),dims(2)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer_2D_explicit + +!=============================================================================== +! WRITE_INTEGER_3D writes integer precision 3-D array data +!=============================================================================== + + subroutine write_integer_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_integer_3D_explicit(group_id, dims, name, buffer, indep) + else + call write_integer_3D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_integer_3D + + subroutine write_integer_3D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(3) + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(dims(1),dims(2),dims(3)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(3, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer_3D_explicit + +!=============================================================================== +! READ_INTEGER_3D reads integer precision 3-D array data +!=============================================================================== + + subroutine read_integer_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_integer_3D_explicit(group_id, dims, name, buffer, indep) + else + call read_integer_3D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_integer_3D + + subroutine read_integer_3D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(3) + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(dims(1),dims(2),dims(3)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer_3D_explicit + +!=============================================================================== +! WRITE_INTEGER_4D writes integer precision 4-D array data +!=============================================================================== + + subroutine write_integer_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_integer_4D_explicit(group_id, dims, name, buffer, indep) + else + call write_integer_4D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_integer_4D + + subroutine write_integer_4D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(4) + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(dims(1),dims(2),dims(3),dims(4)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5screate_simple_f(4, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_integer_4D_explicit + +!=============================================================================== +! READ_INTEGER_4D reads integer precision 4-D array data +!=============================================================================== + + subroutine read_integer_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_integer_4D_explicit(group_id, dims, name, buffer, indep) + else + call read_integer_4D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_integer_4D + + subroutine read_integer_4D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(4) + character(*), intent(in) :: name ! name of data + integer, intent(inout), target :: buffer(dims(1),dims(2),dims(3),dims(4)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_integer_4D_explicit + +!=============================================================================== +! WRITE_LONG writes long integer scalar data +!=============================================================================== + + subroutine write_long(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer(8), intent(in), target :: buffer ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Create dataspace and dataset + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), hdf5_integer8_t, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dwrite_f(dset, hdf5_integer8_t, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dwrite_f(dset, hdf5_integer8_t, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_long + +!=============================================================================== +! READ_LONG reads long integer scalar data +!=============================================================================== + + subroutine read_long(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer(8), intent(inout), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, hdf5_integer8_t, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, hdf5_integer8_t, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + end subroutine read_long + +!=============================================================================== +! WRITE_STRING writes string data +!=============================================================================== + + subroutine write_string(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + character(*), intent(in), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: filetype + integer(HID_T) :: memtype + integer(SIZE_T) :: n + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Create datatype for HDF5 file based on C char + n = len_trim(buffer) + call h5tcopy_f(H5T_C_S1, filetype, hdf5_err) + call h5tset_size_f(filetype, n + 1, hdf5_err) + + ! Create datatype in memory based on Fortran character + call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) + if (n > 0) call h5tset_size_f(memtype, n, hdf5_err) + + ! Create dataspace/dataset + call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), filetype, dspace, dset, hdf5_err) + + ! Get pointer to start of string + f_ptr = c_loc(buffer(1:1)) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5tclose_f(memtype, hdf5_err) + call h5tclose_f(filetype, hdf5_err) + end subroutine write_string + +!=============================================================================== +! READ_STRING reads string data +!=============================================================================== + + subroutine read_string(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + character(*), intent(inout), target :: buffer ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: filetype + integer(HID_T) :: memtype + integer(SIZE_T) :: size + integer(SIZE_T) :: n + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Get dataset and dataspace + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + call h5dget_space_f(dset, dspace, hdf5_err) + + ! Make sure buffer is large enough + call h5dget_type_f(dset, filetype, hdf5_err) + call h5tget_size_f(filetype, size, hdf5_err) + if (size > len(buffer) + 1) then + call fatal_error("Character buffer is not long enough to & + &read HDF5 string.") + end if + + ! Get datatype in memory based on Fortran character + n = len(buffer) + call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) + call h5tset_size_f(memtype, n, hdf5_err) + + ! Get pointer to start of string + f_ptr = c_loc(buffer(1:1)) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, memtype, f_ptr, hdf5_err, mem_space_id=dspace, & + xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, memtype, f_ptr, hdf5_err, mem_space_id=dspace) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5tclose_f(filetype, hdf5_err) + call h5tclose_f(memtype, hdf5_err) + end subroutine read_string + +!=============================================================================== +! WRITE_STRING_1D writes string 1-D array data +!=============================================================================== + + subroutine write_string_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + character(*), intent(in), target :: buffer(:) ! read data to here + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call write_string_1D_explicit(group_id, dims, name, buffer, indep) + else + call write_string_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine write_string_1D + + subroutine write_string_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name + character(*), intent(in), target :: buffer(dims(1)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: filetype + integer(HID_T) :: memtype + integer(SIZE_T) :: n + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Create datatype for HDF5 file based on C char + n = maxval(len_trim(buffer)) + call h5tcopy_f(H5T_C_S1, filetype, hdf5_err) + call h5tset_size_f(filetype, n + 1, hdf5_err) + + ! Create datatype in memory based on Fortran character + call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) + call h5tset_size_f(memtype, int(len(buffer(1)), SIZE_T), hdf5_err) + + ! Create dataspace/dataset + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), filetype, dspace, dset, hdf5_err) + + ! Get pointer to start of string + f_ptr = c_loc(buffer(1)(1:1)) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err, xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5tclose_f(memtype, hdf5_err) + call h5tclose_f(filetype, hdf5_err) + end subroutine write_string_1D_explicit + +!=============================================================================== +! READ_STRING_1D reads string 1-D array data +!=============================================================================== + + subroutine read_string_1D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name + character(*), intent(inout), target :: buffer(:) + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + if (present(indep)) then + call read_string_1D_explicit(group_id, dims, name, buffer, indep) + else + call read_string_1D_explicit(group_id, dims, name, buffer) + end if + end subroutine read_string_1D + + subroutine read_string_1D_explicit(group_id, dims, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name + character(*), intent(inout), target :: buffer(dims(1)) + logical, intent(in), optional :: indep ! independent I/O + + integer :: hdf5_err + integer :: data_xfer_mode +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: filetype + integer(HID_T) :: memtype + integer(SIZE_T) :: size + integer(SIZE_T) :: n + type(c_ptr) :: f_ptr + + ! Set up collective vs. independent I/O + data_xfer_mode = H5FD_MPIO_COLLECTIVE_F + if (present(indep)) then + if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F + end if + + ! Get dataset and dataspace + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + call h5dget_space_f(dset, dspace, hdf5_err) + + ! Make sure buffer is large enough + call h5dget_type_f(dset, filetype, hdf5_err) + call h5tget_size_f(filetype, size, hdf5_err) + if (size > len(buffer(1)) + 1) then + call fatal_error("Character buffer is not long enough to & + &read HDF5 string array.") + end if + + ! Get datatype in memory based on Fortran character + n = len(buffer(1)) + call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) + call h5tset_size_f(memtype, n, hdf5_err) + + ! Get pointer to start of string + f_ptr = c_loc(buffer(1)(1:1)) + + if (using_mpio_device(group_id)) then +#ifdef PHDF5 + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) + call h5dread_f(dset, memtype, f_ptr, hdf5_err, mem_space_id=dspace, & + xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#endif + else + call h5dread_f(dset, memtype, f_ptr, hdf5_err, mem_space_id=dspace) + end if + + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5tclose_f(filetype, hdf5_err) + call h5tclose_f(memtype, hdf5_err) + end subroutine read_string_1D_explicit + +!=============================================================================== +! WRITE_ATTRIBUTE_STRING +!=============================================================================== + + subroutine write_attribute_string(group_id, var, attr_type, attr_str) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: var ! variable name for attr + character(*), intent(in) :: attr_type ! attr identifier type + character(*), intent(in) :: attr_str ! string for attr id type + + integer :: hdf5_err + + call h5ltset_attribute_string_f(group_id, var, attr_type, attr_str, hdf5_err) + end subroutine write_attribute_string + +!=============================================================================== +! WRITE_TALLY_RESULT writes an OpenMC TallyResult type +!=============================================================================== + + subroutine write_tally_result_1D(group_id, name, buffer) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(in), target :: buffer(:) ! data to write + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + call write_tally_result_1D_explicit(group_id, dims, name, buffer) + end subroutine write_tally_result_1D + + subroutine write_tally_result_1D_explicit(group_id, dims, name, buffer) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(in), target :: buffer(dims(1)) + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), hdf5_tallyresult_t, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dwrite_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_tally_result_1D_explicit + + subroutine write_tally_result_2D(group_id, name, buffer) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(in), target :: buffer(:,:) ! data to write + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + call write_tally_result_2D_explicit(group_id, dims, name, buffer) + end subroutine write_tally_result_2D + + subroutine write_tally_result_2D_explicit(group_id, dims, name, buffer) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(in), target :: buffer(dims(1),dims(2)) + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + type(c_ptr) :: f_ptr + + call h5screate_simple_f(2, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, trim(name), hdf5_tallyresult_t, & + dspace, dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dwrite_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end subroutine write_tally_result_2D_explicit + +!=============================================================================== +! READ_TALLY_RESULT reads OpenMC TallyResult data +!=============================================================================== + + subroutine read_tally_result_1D(group_id, name, buffer) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(inout), target :: buffer(:) ! read data here + + integer(HSIZE_T) :: dims(1) + + dims(:) = shape(buffer) + call read_tally_result_1D_explicit(group_id, dims, name, buffer) + end subroutine read_tally_result_1D + + subroutine read_tally_result_1D_explicit(group_id, dims, name, buffer) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(1) + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(inout), target :: buffer(dims(1)) + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dread_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) + end subroutine read_tally_result_1D_explicit + + subroutine read_tally_result_2D(group_id, name, buffer) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(inout), target :: buffer(:,:) + + integer(HSIZE_T) :: dims(2) + + dims(:) = shape(buffer) + call read_tally_result_2D_explicit(group_id, dims, name, buffer) + end subroutine read_tally_result_2D + + subroutine read_tally_result_2D_explicit(group_id, dims, name, buffer) + integer(HID_T), intent(in) :: group_id + integer(HSIZE_T), intent(in) :: dims(2) + character(*), intent(in) :: name ! name of data + type(TallyResult), intent(inout), target :: buffer(dims(1),dims(2)) + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + type(c_ptr) :: f_ptr + + call h5dopen_f(group_id, trim(name), dset, hdf5_err) + f_ptr = c_loc(buffer) + call h5dread_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) + call h5dclose_f(dset, hdf5_err) + end subroutine read_tally_result_2D_explicit + + function using_mpio_device(obj_id) result(mpio) + integer(HID_T), intent(in) :: obj_id + logical :: mpio + + integer :: hdf5_err + integer :: driver + integer(HID_T) :: file_id + integer(HID_T) :: fapl_id + + ! Determine file that this object is part of + call h5iget_file_id_f(obj_id, file_id, hdf5_err) + + ! Get file access property list + call h5fget_access_plist_f(file_id, fapl_id, hdf5_err) + + ! Get low-level driver identifier + call h5pget_driver_f(fapl_id, driver, hdf5_err) + + ! Close file access property list access + call h5pclose_f(fapl_id, hdf5_err) + + ! Close file access -- note that this only decreases the reference count so + ! that the file is not actually closed + call h5fclose_f(file_id, hdf5_err) + + mpio = (driver == H5FD_MPIO_F) + end function using_mpio_device end module hdf5_interface diff --git a/src/hdf5_summary.F90 b/src/hdf5_summary.F90 deleted file mode 100644 index 375ab74601..0000000000 --- a/src/hdf5_summary.F90 +++ /dev/null @@ -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 diff --git a/src/initialize.F90 b/src/initialize.F90 index 409d531a38..9d63eb4e93 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -12,17 +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 source, only: initialize_source 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 @@ -34,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 @@ -53,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() @@ -116,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() @@ -128,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 @@ -141,13 +138,9 @@ contains ! Determine how much work each processor should do call calculate_work() - ! Allocate banks and create source particles -- for a fixed source - ! calculation, the external source distribution is sampled during the - ! run, not at initialization - if (run_mode == MODE_EIGENVALUE) then - call allocate_banks() - if (.not. restart_run) call initialize_source() - end if + ! Allocate source bank, and for eigenvalue simulations also allocate the + ! fission bank + call allocate_banks() ! If this is a restart run, load the state point data and binary source ! file @@ -160,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() @@ -181,7 +170,7 @@ contains end if ! Stop initialization timer - call time_initialize % stop() + call time_initialize%stop() end subroutine initialize_run @@ -194,22 +183,22 @@ contains subroutine initialize_mpi() - integer :: bank_blocks(4) ! Count for each datatype + integer :: bank_blocks(5) ! Count for each datatype #ifdef MPIF08 - type(MPI_Datatype) :: bank_types(4) + type(MPI_Datatype) :: bank_types(5) type(MPI_Datatype) :: result_types(1) type(MPI_Datatype) :: temp_type #else - integer :: bank_types(4) ! Datatypes + integer :: bank_types(5) ! Datatypes integer :: result_types(1) ! Datatypes - integer :: temp_type ! temporary derived type + integer :: temp_type ! temporary derived type #endif - integer(MPI_ADDRESS_KIND) :: bank_disp(4) ! Displacements + integer(MPI_ADDRESS_KIND) :: bank_disp(5) ! Displacements integer :: result_blocks(1) ! Count for each datatype integer(MPI_ADDRESS_KIND) :: result_disp(1) ! Displacements integer(MPI_ADDRESS_KIND) :: result_base_disp ! Base displacement - integer(MPI_ADDRESS_KIND) :: lower_bound ! Lower bound for TallyResult - integer(MPI_ADDRESS_KIND) :: extent ! Extent for TallyResult + integer(MPI_ADDRESS_KIND) :: lower_bound ! Lower bound for TallyResult + integer(MPI_ADDRESS_KIND) :: extent ! Extent for TallyResult type(Bank) :: b type(TallyResult) :: tr @@ -234,18 +223,19 @@ 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) + call MPI_GET_ADDRESS(b % delayed_group, bank_disp(5), mpi_err) ! Adjust displacements bank_disp = bank_disp - bank_disp(1) ! Define MPI_BANK for fission sites - bank_blocks = (/ 1, 3, 3, 1 /) - bank_types = (/ MPI_REAL8, MPI_REAL8, MPI_REAL8, MPI_REAL8 /) - call MPI_TYPE_CREATE_STRUCT(4, bank_blocks, bank_disp, & + bank_blocks = (/ 1, 3, 3, 1, 1 /) + bank_types = (/ MPI_REAL8, MPI_REAL8, MPI_REAL8, MPI_REAL8, MPI_INTEGER /) + call MPI_TYPE_CREATE_STRUCT(5, bank_blocks, bank_disp, & bank_types, MPI_BANK, mpi_err) call MPI_TYPE_COMMIT(MPI_BANK, mpi_err) @@ -253,8 +243,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 @@ -280,8 +270,6 @@ contains end subroutine initialize_mpi #endif -#ifdef HDF5 - !=============================================================================== ! HDF5_INITIALIZE !=============================================================================== @@ -290,6 +278,7 @@ contains type(TallyResult), target :: tmp(2) ! temporary TallyResult type(Bank), target :: tmpb(2) ! temporary Bank + integer :: hdf5_err integer(HID_T) :: coordinates_t ! HDF5 type for 3 reals integer(HSIZE_T) :: dims(1) = (/3/) ! size of coordinates @@ -318,14 +307,14 @@ contains c_loc(tmpb(1)%uvw)), coordinates_t, hdf5_err) call h5tinsert_f(hdf5_bank_t, "E", h5offsetof(c_loc(tmpb(1)), & c_loc(tmpb(1)%E)), H5T_NATIVE_DOUBLE, hdf5_err) + call h5tinsert_f(hdf5_bank_t, "delayed_group", h5offsetof(c_loc(tmpb(1)), & + c_loc(tmpb(1)%delayed_group)), H5T_NATIVE_INTEGER, hdf5_err) ! Determine type for integer(8) hdf5_integer8_t = h5kind_to_type(8, H5_INTEGER_KIND) end subroutine hdf5_initialize -#endif - !=============================================================================== ! READ_COMMAND_LINE reads all parameters from the command line !=============================================================================== @@ -335,9 +324,9 @@ contains integer :: i ! loop index integer :: argc ! number of command line arguments integer :: last_flag ! index of last flag - integer :: filetype + character(MAX_WORD_LEN) :: filetype + integer(HID_T) :: file_id character(MAX_WORD_LEN), allocatable :: argv(:) ! command line arguments - type(BinaryOutput) :: sp ! Check number of command line arguments and allocate argv argc = COMMAND_ARGUMENT_COUNT() @@ -374,16 +363,16 @@ 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) - case (FILETYPE_STATEPOINT) + case ('statepoint') path_state_point = argv(i) restart_run = .true. - case (FILETYPE_PARTICLE_RESTART) + case ('particle restart') path_particle_restart = argv(i) particle_restart_run = .true. case default @@ -397,14 +386,13 @@ 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() - if (filetype /= FILETYPE_SOURCE) then + file_id = file_open(argv(i), 'r', parallel=.true.) + call read_dataset(file_id, 'filetype', filetype) + call file_close(file_id) + if (filetype /= 'source') then call fatal_error("Second file after restart flag must be a & &source file") end if @@ -512,26 +500,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 @@ -546,17 +534,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 @@ -583,59 +571,72 @@ contains do i = 1, n_cells ! ======================================================================= - ! ADJUST SURFACE LIST FOR EACH CELL + ! ADJUST REGION SPECIFICATION FOR EACH CELL c => cells(i) - 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) + do j = 1, size(c%region) + id = c%region(j) + ! Make sure that only regions are checked. Since OP_UNION is the + ! operator with the lowest integer value, anything below it must denote + ! a half-space + if (id < OP_UNION) then + if (surface_dict%has_key(abs(id))) then + i_array = surface_dict%get_key(abs(id)) + c%region(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 + ! Also adjust the indices in the reverse Polish notation + do j = 1, size(c%rpn) + id = c%rpn(j) + ! Again, make sure that only regions are checked + if (id < OP_UNION) then + i_array = surface_dict%get_key(abs(id)) + c%rpn(j) = sign(i_array, id) + end if + end do + ! ======================================================================= ! 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 @@ -645,41 +646,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 @@ -687,13 +688,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 @@ -705,68 +706,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 @@ -804,46 +805,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 @@ -904,31 +905,33 @@ contains call fatal_error("Failed to allocate source bank.") end if + if (run_mode == MODE_EIGENVALUE) then #ifdef _OPENMP - ! If OpenMP is being used, each thread needs its own private fission - ! bank. Since the private fission banks need to be combined at the end of a - ! generation, there is also a 'master_fission_bank' that is used to collect - ! the sites from each thread. + ! If OpenMP is being used, each thread needs its own private fission + ! bank. Since the private fission banks need to be combined at the end of + ! a generation, there is also a 'master_fission_bank' that is used to + ! collect the sites from each thread. - n_threads = omp_get_max_threads() + n_threads = omp_get_max_threads() !$omp parallel - thread_id = omp_get_thread_num() + thread_id = omp_get_thread_num() - if (thread_id == 0) then - allocate(fission_bank(3*work)) - else - allocate(fission_bank(3*work/n_threads)) - end if + if (thread_id == 0) then + allocate(fission_bank(3*work)) + else + allocate(fission_bank(3*work/n_threads)) + end if !$omp end parallel - allocate(master_fission_bank(3*work), STAT=alloc_err) + allocate(master_fission_bank(3*work), STAT=alloc_err) #else - allocate(fission_bank(3*work), STAT=alloc_err) + allocate(fission_bank(3*work), STAT=alloc_err) #endif - ! Check for allocation errors - if (alloc_err /= 0) then - call fatal_error("Failed to allocate fission bank.") + ! Check for allocation errors + if (alloc_err /= 0) then + call fatal_error("Failed to allocate fission bank.") + end if end if end subroutine allocate_banks @@ -943,7 +946,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 @@ -956,18 +959,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 @@ -988,15 +991,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 @@ -1037,7 +1040,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 @@ -1045,14 +1048,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 @@ -1063,8 +1066,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 @@ -1086,29 +1089,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 @@ -1116,26 +1119,26 @@ contains ! Allocate the offset tables for lattices do i = 1, n_lattices - lat => lattices(i) % obj + lat => lattices(i)%obj select type(lat) type is (RectLattice) - allocate(lat % offset(n_maps, lat % n_cells(1), lat % n_cells(2), & - lat % n_cells(3))) + allocate(lat%offset(n_maps, lat%n_cells(1), lat%n_cells(2), & + lat%n_cells(3))) type is (HexLattice) - allocate(lat % offset(n_maps, 2 * lat % n_rings - 1, & - 2 * lat % n_rings - 1, lat % n_axial)) + allocate(lat%offset(n_maps, 2 * lat%n_rings - 1, & + 2 * lat%n_rings - 1, lat%n_axial)) end select - lat % offset(:, :, :, :) = 0 + lat%offset(:, :, :, :) = 0 end do ! Allocate offset table for fill cells do i = 1, n_cells - if (cells(i) % material == NONE) then - allocate(cells(i) % offset(n_maps)) + if (cells(i)%material == NONE) then + allocate(cells(i)%offset(n_maps)) end if end do diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 5c939a394f..5449b169dd 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -5,15 +5,17 @@ module input_xml use dict_header, only: DictIntInt, ElemKeyValueCI use energy_grid, only: grid_method, n_log_bins use error, only: fatal_error, warning - use geometry_header, only: Cell, Surface, Lattice, RectLattice, HexLattice + use geometry_header, only: Cell, Lattice, RectLattice, HexLattice use global - use list_header, only: ListChar, ListReal - use mesh_header, only: StructuredMesh + use list_header, only: ListChar, ListInt, ListReal + use mesh_header, only: RegularMesh use output, only: write_message use plot_header use random_lcg, only: prn + use surface_header + use stl_vector, only: VectorInt use string, only: to_lower, to_str, str_to_int, str_to_real, & - starts_with, ends_with + starts_with, ends_with, tokenize use tally_header, only: TallyObject, TallyFilter use tally_initialize, only: add_tallies use xml_interface @@ -987,13 +989,15 @@ contains integer :: coeffs_reqd integer, allocatable :: temp_int_array(:) real(8) :: phi, theta, psi + real(8), allocatable :: coeffs(:) logical :: file_exists logical :: boundary_exists character(MAX_LINE_LEN) :: filename character(MAX_WORD_LEN) :: word - type(Cell), pointer :: c => null() - type(Surface), pointer :: s => null() - class(Lattice), pointer :: lat => null() + character(1000) :: region_spec + type(Cell), pointer :: c + class(Surface), pointer :: s + class(Lattice), pointer :: lat type(Node), pointer :: doc => null() type(Node), pointer :: node_cell => null() type(Node), pointer :: node_surf => null() @@ -1002,6 +1006,8 @@ contains type(NodeList), pointer :: node_surf_list => null() type(NodeList), pointer :: node_rlat_list => null() type(NodeList), pointer :: node_hlat_list => null() + type(VectorInt) :: tokens + type(VectorInt) :: rpn ! Display output message call write_message("Reading geometry XML file...", 5) @@ -1112,17 +1118,42 @@ contains call fatal_error("Cannot specify material and fill simultaneously") end if - ! Allocate array for surfaces and copy + ! Check for region specification (also under deprecated name surfaces) + region_spec = '' if (check_for_node(node_cell, "surfaces")) then - n = get_arraysize_integer(node_cell, "surfaces") - else - n = 0 + call warning("The use of 'surfaces' is deprecated and will be & + &disallowed in a future release. Use 'region' instead. The & + &openmc-update-inputs utility can be used to automatically & + &update geometry.xml files.") + call get_node_value(node_cell, "surfaces", region_spec) + elseif (check_for_node(node_cell, "region")) then + call get_node_value(node_cell, "region", region_spec) end if - c % n_surfaces = n - if (n > 0) then - allocate(c % surfaces(n)) - call get_node_array(node_cell, "surfaces", c % surfaces) + if (len_trim(region_spec) > 0) then + ! Create surfaces array from string + call tokenize(region_spec, tokens) + + ! Use shunting-yard algorithm to determine RPN for surface algorithm + call generate_rpn(c%id, tokens, rpn) + + ! Copy region spec and RPN form to cell arrays + allocate(c % region(tokens%size())) + allocate(c % rpn(rpn%size())) + c % region(:) = tokens%data(1:tokens%size()) + c % rpn(:) = rpn%data(1:rpn%size()) + + call tokens%clear() + call rpn%clear() + end if + if (.not. allocated(c%region)) allocate(c%region(0)) + if (.not. allocated(c%rpn)) allocate(c%rpn(0)) + + ! Check if this is a simple cell + if (any(c%rpn == OP_COMPLEMENT) .or. any(c%rpn == OP_UNION)) then + c%simple = .false. + else + c%simple = .true. end if ! Rotation matrix @@ -1222,71 +1253,74 @@ contains allocate(surfaces(n_surfaces)) do i = 1, n_surfaces - s => surfaces(i) - ! Get pointer to i-th surface node call get_list_item(node_surf_list, i, node_surf) - ! Copy data into cells - if (check_for_node(node_surf, "id")) then - call get_node_value(node_surf, "id", s % id) - else - call fatal_error("Must specify id of surface in geometry XML file.") - end if - - ! Check to make sure 'id' hasn't been used - if (surface_dict % has_key(s % id)) then - call fatal_error("Two or more surfaces use the same unique ID: " & - &// to_str(s % id)) - end if - - ! Copy surface name - if (check_for_node(node_surf, "name")) then - call get_node_value(node_surf, "name", s % name) - end if - ! Copy and interpret surface type word = '' if (check_for_node(node_surf, "type")) & call get_node_value(node_surf, "type", word) select case(to_lower(word)) case ('x-plane') - s % type = SURF_PX coeffs_reqd = 1 + allocate(SurfaceXPlane :: surfaces(i)%obj) case ('y-plane') - s % type = SURF_PY coeffs_reqd = 1 + allocate(SurfaceYPlane :: surfaces(i)%obj) case ('z-plane') - s % type = SURF_PZ coeffs_reqd = 1 + allocate(SurfaceZPlane :: surfaces(i)%obj) case ('plane') - s % type = SURF_PLANE coeffs_reqd = 4 + allocate(SurfacePlane :: surfaces(i)%obj) case ('x-cylinder') - s % type = SURF_CYL_X coeffs_reqd = 3 + allocate(SurfaceXCylinder :: surfaces(i)%obj) case ('y-cylinder') - s % type = SURF_CYL_Y coeffs_reqd = 3 + allocate(SurfaceYCylinder :: surfaces(i)%obj) case ('z-cylinder') - s % type = SURF_CYL_Z coeffs_reqd = 3 + allocate(SurfaceZCylinder :: surfaces(i)%obj) case ('sphere') - s % type = SURF_SPHERE coeffs_reqd = 4 + allocate(SurfaceSphere :: surfaces(i)%obj) case ('x-cone') - s % type = SURF_CONE_X coeffs_reqd = 4 + allocate(SurfaceXCone :: surfaces(i)%obj) case ('y-cone') - s % type = SURF_CONE_Y coeffs_reqd = 4 + allocate(SurfaceYCone :: surfaces(i)%obj) case ('z-cone') - s % type = SURF_CONE_Z coeffs_reqd = 4 + allocate(SurfaceZCone :: surfaces(i)%obj) + case ('quadric') + coeffs_reqd = 10 + allocate(SurfaceQuadric :: surfaces(i)%obj) case default call fatal_error("Invalid surface type: " // trim(word)) end select + s => surfaces(i)%obj + + ! Copy data into cells + if (check_for_node(node_surf, "id")) then + call get_node_value(node_surf, "id", s%id) + else + call fatal_error("Must specify id of surface in geometry XML file.") + end if + + ! Check to make sure 'id' hasn't been used + if (surface_dict % has_key(s%id)) then + call fatal_error("Two or more surfaces use the same unique ID: " & + &// to_str(s%id)) + end if + + ! Copy surface name + if (check_for_node(node_surf, "name")) then + call get_node_value(node_surf, "name", s%name) + end if + ! Check to make sure that the proper number of coefficients ! have been specified for the given type of surface. Then copy ! surface coordinates. @@ -1294,36 +1328,95 @@ contains n = get_arraysize_double(node_surf, "coeffs") if (n < coeffs_reqd) then call fatal_error("Not enough coefficients specified for surface: " & - &// trim(to_str(s % id))) + &// trim(to_str(s%id))) elseif (n > coeffs_reqd) then call fatal_error("Too many coefficients specified for surface: " & - &// trim(to_str(s % id))) - else - allocate(s % coeffs(n)) - call get_node_array(node_surf, "coeffs", s % coeffs) + &// trim(to_str(s%id))) end if + allocate(coeffs(n)) + call get_node_array(node_surf, "coeffs", coeffs) + + select type(s) + type is (SurfaceXPlane) + s%x0 = coeffs(1) + type is (SurfaceYPlane) + s%y0 = coeffs(1) + type is (SurfaceZPlane) + s%z0 = coeffs(1) + type is (SurfacePlane) + s%A = coeffs(1) + s%B = coeffs(2) + s%C = coeffs(3) + s%D = coeffs(4) + type is (SurfaceXCylinder) + s%y0 = coeffs(1) + s%z0 = coeffs(2) + s%r = coeffs(3) + type is (SurfaceYCylinder) + s%x0 = coeffs(1) + s%z0 = coeffs(2) + s%r = coeffs(3) + type is (SurfaceZCylinder) + s%x0 = coeffs(1) + s%y0 = coeffs(2) + s%r = coeffs(3) + type is (SurfaceSphere) + s%x0 = coeffs(1) + s%y0 = coeffs(2) + s%z0 = coeffs(3) + s%r = coeffs(4) + type is (SurfaceXCone) + s%x0 = coeffs(1) + s%y0 = coeffs(2) + s%z0 = coeffs(3) + s%r2 = coeffs(4) + type is (SurfaceYCone) + s%x0 = coeffs(1) + s%y0 = coeffs(2) + s%z0 = coeffs(3) + s%r2 = coeffs(4) + type is (SurfaceZCone) + s%x0 = coeffs(1) + s%y0 = coeffs(2) + s%z0 = coeffs(3) + s%r2 = coeffs(4) + type is (SurfaceQuadric) + s%A = coeffs(1) + s%B = coeffs(2) + s%C = coeffs(3) + s%D = coeffs(4) + s%E = coeffs(5) + s%F = coeffs(6) + s%G = coeffs(7) + s%H = coeffs(8) + s%J = coeffs(9) + s%K = coeffs(10) + end select + + ! No longer need coefficients + deallocate(coeffs) + ! Boundary conditions word = '' if (check_for_node(node_surf, "boundary")) & call get_node_value(node_surf, "boundary", word) select case (to_lower(word)) case ('transmission', 'transmit', '') - s % bc = BC_TRANSMIT + s%bc = BC_TRANSMIT case ('vacuum') - s % bc = BC_VACUUM + s%bc = BC_VACUUM boundary_exists = .true. case ('reflective', 'reflect', 'reflecting') - s % bc = BC_REFLECT + s%bc = BC_REFLECT boundary_exists = .true. case default call fatal_error("Unknown boundary condition '" // trim(word) // & - &"' specified on surface " // trim(to_str(s % id))) + &"' specified on surface " // trim(to_str(s%id))) end select ! Add surface to dictionary - call surface_dict % add_key(s % id, i) - + call surface_dict % add_key(s%id, i) end do ! Check to make sure a boundary condition was applied to at least one @@ -1666,8 +1759,10 @@ contains integer :: i ! loop index for materials integer :: j ! loop index for nuclides + integer :: k ! loop index for elements integer :: n ! number of nuclides integer :: n_sab ! number of sab tables for a material + integer :: n_nuc_ele ! number of nuclides in an element integer :: index_list ! index in xs_listings array integer :: index_nuclide ! index in nuclides integer :: index_sab ! index in sab_tables @@ -1682,6 +1777,7 @@ contains character(MAX_LINE_LEN) :: temp_str ! temporary string when reading type(ListChar) :: list_names ! temporary list of nuclide names type(ListReal) :: list_density ! temporary list of nuclide densities + type(ListInt) :: list_iso_lab ! temporary list of isotropic lab scatterers type(Material), pointer :: mat => null() type(Node), pointer :: doc => null() type(Node), pointer :: node_mat => null() @@ -1841,6 +1937,21 @@ contains end if end if + ! Check enforced isotropic lab scattering + if (check_for_node(node_nuc, "scattering")) then + call get_node_value(node_nuc, "scattering", temp_str) + if (adjustl(to_lower(temp_str)) == "iso-in-lab") then + call list_iso_lab % append(1) + else if (adjustl(to_lower(temp_str)) == "data") then + call list_iso_lab % append(0) + else + call fatal_error("Scattering must be isotropic in lab or follow& + & the ACE file data") + end if + else + call list_iso_lab % append(0) + end if + ! store full name call get_node_value(node_nuc, "name", temp_str) if (check_for_node(node_nuc, "xs")) & @@ -1912,6 +2023,9 @@ contains &element: " // trim(name)) end if + ! Get current number of nuclides + n_nuc_ele = list_names % size() + ! Expand element into naturally-occurring isotopes if (check_for_node(node_ele, "ao")) then call get_node_value(node_ele, "ao", temp_dble) @@ -1921,6 +2035,29 @@ contains call fatal_error("The ability to expand a natural element based on & &weight percentage is not yet supported.") end if + + ! Compute number of new nuclides from the natural element expansion + n_nuc_ele = list_names % size() - n_nuc_ele + + ! Check enforced isotropic lab scattering + if (check_for_node(node_ele, "scattering")) then + call get_node_value(node_ele, "scattering", temp_str) + else + temp_str = "data" + end if + + ! Set ace or iso-in-lab scattering for each nuclide in element + do k = 1, n_nuc_ele + if (adjustl(to_lower(temp_str)) == "iso-in-lab") then + call list_iso_lab % append(1) + else if (adjustl(to_lower(temp_str)) == "data") then + call list_iso_lab % append(0) + else + call fatal_error("Scattering must be isotropic in lab or follow& + & the ACE file data") + end if + end do + end do NATURAL_ELEMENTS ! ======================================================================== @@ -1932,6 +2069,7 @@ contains allocate(mat % names(n)) allocate(mat % nuclide(n)) allocate(mat % atom_density(n)) + allocate(mat % p0(n)) ALL_NUCLIDES: do j = 1, mat % n_nuclides ! Check that this nuclide is listed in the cross_sections.xml file @@ -1968,6 +2106,14 @@ contains ! Copy name and atom/weight percent mat % names(j) = name mat % atom_density(j) = list_density % get_item(j) + + ! Cast integer isotropic lab scattering flag to boolean + if (list_iso_lab % get_item(j) == 1) then + mat % p0(j) = .true. + else + mat % p0(j) = .false. + end if + end do ALL_NUCLIDES ! Check to make sure either all atom percents or all weight percents are @@ -1984,6 +2130,7 @@ contains ! Clear lists call list_names % clear() call list_density % clear() + call list_iso_lab % clear() ! ======================================================================= ! READ AND PARSE TAG FOR S(a,b) DATA @@ -2062,6 +2209,7 @@ contains subroutine read_tallies_xml() + integer :: d ! delayed group index integer :: i ! loop over user-specified tallies integer :: j ! loop over words integer :: k ! another loop index @@ -2085,15 +2233,18 @@ contains integer :: imomstr ! Index of MOMENT_STRS & MOMENT_N_STRS logical :: file_exists ! does tallies.xml file exist? real(8) :: rarray3(3) ! temporary double prec. array + integer :: Nangle ! Number of angular bins + real(8) :: dangle ! Mu spacing if using automatic allocation + integer :: iangle ! Loop counter for building mu filter bins character(MAX_LINE_LEN) :: filename character(MAX_WORD_LEN) :: word character(MAX_WORD_LEN) :: score_name character(MAX_WORD_LEN) :: temp_str character(MAX_WORD_LEN), allocatable :: sarray(:) type(DictCharInt) :: trigger_scores - type(ElemKeyValueCI), pointer :: pair_list => null() - type(TallyObject), pointer :: t => null() - type(StructuredMesh), pointer :: m => null() + type(ElemKeyValueCI), pointer :: pair_list + type(TallyObject), pointer :: t + type(RegularMesh), pointer :: m type(TallyFilter), allocatable :: filters(:) ! temporary filters type(Node), pointer :: doc => null() type(Node), pointer :: node_mesh => null() @@ -2188,9 +2339,11 @@ contains call get_node_value(node_mesh, "type", temp_str) select case (to_lower(temp_str)) case ('rect', 'rectangle', 'rectangular') - m % type = LATTICE_RECT - case ('hex', 'hexagon', 'hexagonal') - m % type = LATTICE_HEX + call warning("Mesh type '" // trim(temp_str) // "' is deprecated. & + &Please use 'regular' instead.") + m % type = MESH_REGULAR + case ('regular') + m % type = MESH_REGULAR case default call fatal_error("Invalid mesh type: " // trim(temp_str)) end select @@ -2350,8 +2503,9 @@ contains ! Determine number of bins if (check_for_node(node_filt, "bins")) then - if (trim(temp_str) == 'energy' .or. & - trim(temp_str) == 'energyout') then + if (temp_str == 'energy' .or. temp_str == 'energyout' .or. & + temp_str == 'mu' .or. temp_str == 'polar' .or. & + temp_str == 'azimuthal') then n_words = get_arraysize_double(node_filt, "bins") else n_words = get_arraysize_integer(node_filt, "bins") @@ -2487,6 +2641,125 @@ contains ! Set to analog estimator t % estimator = ESTIMATOR_ANALOG + case ('delayedgroup') + ! Set type of filter + t % filters(j) % type = FILTER_DELAYEDGROUP + + ! Set number of bins + t % filters(j) % n_bins = n_words + + ! Allocate and store bins + allocate(t % filters(j) % int_bins(n_words)) + call get_node_array(node_filt, "bins", t % filters(j) % int_bins) + + ! Check bins to make sure all are between 1 and MAX_DELAYED_GROUPS + do d = 1, n_words + if (t % filters(j) % int_bins(d) < 1 .or. & + t % filters(j) % int_bins(d) > MAX_DELAYED_GROUPS) then + call fatal_error("Encountered delayedgroup bin with index " & + // trim(to_str(t % filters(j) % int_bins(d))) // " that is& + & outside the range of 1 to MAX_DELAYED_GROUPS ( " & + // trim(to_str(MAX_DELAYED_GROUPS)) // ")") + end if + end do + + case ('mu') + ! Set type of filter + t % filters(j) % type = FILTER_MU + + ! Set number of bins + t % filters(j) % n_bins = n_words - 1 + + ! Allocate and store bins + allocate(t % filters(j) % real_bins(n_words)) + call get_node_array(node_filt, "bins", t % filters(j) % real_bins) + + ! Allow a user to input a lone number which will mean that + ! you subivide [-1,1] evenly with the input being the number of bins + if (n_words == 1) then + Nangle = int(t % filters(j) % real_bins(1)) + if (Nangle > 1) then + t % filters(j) % n_bins = Nangle + dangle = TWO / real(Nangle,8) + deallocate(t % filters(j) % real_bins) + allocate(t % filters(j) % real_bins(Nangle + 1)) + do iangle = 1, Nangle + t % filters(j) % real_bins(iangle) = -ONE + (iangle - 1) * dangle + end do + t % filters(j) % real_bins(Nangle + 1) = ONE + else + call fatal_error("Number of bins for mu filter must be& + & greater than 1 on tally " // trim(to_str(t % id)) // ".") + end if + + end if + + ! Set to analog estimator + t % estimator = ESTIMATOR_ANALOG + + case ('polar') + ! Set type of filter + t % filters(j) % type = FILTER_POLAR + + ! Set number of bins + t % filters(j) % n_bins = n_words - 1 + + ! Allocate and store bins + allocate(t % filters(j) % real_bins(n_words)) + call get_node_array(node_filt, "bins", t % filters(j) % real_bins) + + ! Allow a user to input a lone number which will mean that + ! you subivide [0,pi] evenly with the input being the number of bins + if (n_words == 1) then + Nangle = int(t % filters(j) % real_bins(1)) + if (Nangle > 1) then + t % filters(j) % n_bins = Nangle + dangle = PI / real(Nangle,8) + deallocate(t % filters(j) % real_bins) + allocate(t % filters(j) % real_bins(Nangle + 1)) + do iangle = 1, Nangle + t % filters(j) % real_bins(iangle) = (iangle - 1) * dangle + end do + t % filters(j) % real_bins(Nangle + 1) = PI + else + call fatal_error("Number of bins for polar filter must be& + & greater than 1 on tally " // trim(to_str(t % id)) // ".") + end if + + end if + + case ('azimuthal') + ! Set type of filter + t % filters(j) % type = FILTER_AZIMUTHAL + + ! Set number of bins + t % filters(j) % n_bins = n_words - 1 + + ! Allocate and store bins + allocate(t % filters(j) % real_bins(n_words)) + call get_node_array(node_filt, "bins", t % filters(j) % real_bins) + + ! Allow a user to input a lone number which will mean that + ! you sub-divide [-pi,pi) evenly with the input being the number of + ! bins + if (n_words == 1) then + Nangle = int(t % filters(j) % real_bins(1)) + if (Nangle > 1) then + t % filters(j) % n_bins = Nangle + dangle = TWO * PI / real(Nangle,8) + deallocate(t % filters(j) % real_bins) + allocate(t % filters(j) % real_bins(Nangle + 1)) + do iangle = 1, Nangle + t % filters(j) % real_bins(iangle) = -PI + (iangle - 1) * dangle + end do + t % filters(j) % real_bins(Nangle + 1) = PI + else + call fatal_error("Number of bins for azimuthal filter must be& + & greater than 1 on tally " // trim(to_str(t % id)) // ".") + end if + + end if + case default ! Specified tally filter is invalid, raise error call fatal_error("Unknown filter type '" & @@ -2545,6 +2818,21 @@ contains ! Check if total material was specified if (trim(sarray(j)) == 'total') then + + ! Check if a delayedgroup filter is present for this tally + do l = 1, t % n_filters + if (t % filters(l) % type == FILTER_DELAYEDGROUP) then + call warning("A delayedgroup filter was used on a total & + &nuclide tally. Cross section libraries are not & + &guaranteed to have the same delayed group structure & + &across all isotopes. In particular, ENDF/B-VII.1 does & + ¬ have a consistent delayed group structure across & + &all isotopes while the JEFF 3.1.1 library has the same & + &delayed group structure across all isotopes. Use with & + &caution!") + end if + end do + t % nuclide_bins(j) = -1 cycle end if @@ -2594,6 +2882,19 @@ contains allocate(t % nuclide_bins(1)) t % nuclide_bins(1) = -1 t % n_nuclide_bins = 1 + + ! Check if a delayedgroup filter is present for this tally + do l = 1, t % n_filters + if (t % filters(l) % type == FILTER_DELAYEDGROUP) then + call warning("A delayedgroup filter was used on a total nuclide & + &tally. Cross section libraries are not guaranteed to have the& + & same delayed group structure across all isotopes. In & + &particular, ENDF/B-VII.1 does not have a consistent delayed & + &group structure across all isotopes while the JEFF 3.1.1 & + &library has the same delayed group structure across all & + &isotopes. Use with caution!") + end if + end do end if ! ======================================================================= @@ -2614,6 +2915,10 @@ contains ! MOMENT_STRS(:) ! If so, check the order, store if OK, then reset the number to 'n' score_name = trim(sarray(j)) + + ! Append the score to the list of possible trigger scores + if (trigger_on) call trigger_scores % add_key(trim(score_name), j) + do imomstr = 1, size(MOMENT_STRS) if (starts_with(score_name,trim(MOMENT_STRS(imomstr)))) then n_order_pos = scan(score_name,'0123456789') @@ -2656,6 +2961,7 @@ contains ! scores then strip off the n and store it as an integer to be used ! later. Then perform the select case on this modified (number ! removed) string + n_order = -1 score_name = sarray(l) do imomstr = 1, size(MOMENT_STRS) if (starts_with(score_name,trim(MOMENT_STRS(imomstr)))) then @@ -2701,6 +3007,31 @@ contains end do end if + ! Check if delayed group filter is used with any score besides + ! delayed-nu-fission + if (score_name /= 'delayed-nu-fission' .and. & + t % find_filter(FILTER_DELAYEDGROUP) > 0) then + call fatal_error("Cannot tally " // trim(score_name) // " with a & + &delayedgroup filter.") + end if + + ! Check to see if the mu filter is applied and if that makes sense. + if ((.not. starts_with(score_name,'scatter')) .and. & + (.not. starts_with(score_name,'nu-scatter'))) then + if (t % find_filter(FILTER_MU) > 0) then + call fatal_error("Cannot tally " // trim(score_name) //" with a & + &change of angle (mu) filter.") + end if + ! Also check to see if this is a legendre expansion or not. + ! If so, we can accept this score and filter combo for p0, but not + ! elsewhere. + else if (n_order > 0) then + if (t % find_filter(FILTER_MU) > 0) then + call fatal_error("Cannot tally " // trim(score_name) //" with a & + &change of angle (mu) filter unless order is 0.") + end if + end if + select case (trim(score_name)) case ('flux') ! Prohibit user from tallying flux for an individual nuclide @@ -2730,7 +3061,7 @@ contains t % moment_order(j : j + n_bins - 1) = n_order j = j + n_bins - 1 - case ('total') + case ('total', '(n,total)') t % score_bins(j) = SCORE_TOTAL if (t % find_filter(FILTER_ENERGYOUT) > 0) then call fatal_error("Cannot tally total reaction rate with an & @@ -2816,13 +3147,13 @@ contains ! Set tally estimator to analog t % estimator = ESTIMATOR_ANALOG - case ('n2n') + case ('n2n', '(n,2n)') t % score_bins(j) = N_2N - case ('n3n') + case ('n3n', '(n,3n)') t % score_bins(j) = N_3N - case ('n4n') + case ('n4n', '(n,4n)') t % score_bins(j) = N_4N case ('absorption') @@ -2843,8 +3174,16 @@ contains ! Set tally estimator to analog t % estimator = ESTIMATOR_ANALOG end if + case ('delayed-nu-fission') + t % score_bins(j) = SCORE_DELAYED_NU_FISSION + if (t % find_filter(FILTER_ENERGYOUT) > 0) then + ! Set tally estimator to analog + t % estimator = ESTIMATOR_ANALOG + end if case ('kappa-fission') t % score_bins(j) = SCORE_KAPPA_FISSION + case ('inverse-velocity') + t % score_bins(j) = SCORE_INVERSE_VELOCITY case ('current') t % score_bins(j) = SCORE_CURRENT t % type = TALLY_SURFACE_CURRENT @@ -2903,6 +3242,79 @@ contains case ('events') t % score_bins(j) = SCORE_EVENTS + case ('elastic', '(n,elastic)') + t % score_bins(j) = ELASTIC + case ('(n,2nd)') + t % score_bins(j) = N_2ND + case ('(n,na)') + t % score_bins(j) = N_2NA + case ('(n,n3a)') + t % score_bins(j) = N_N3A + case ('(n,2na)') + t % score_bins(j) = N_2NA + case ('(n,3na)') + t % score_bins(j) = N_3NA + case ('(n,np)') + t % score_bins(j) = N_NP + case ('(n,n2a)') + t % score_bins(j) = N_N2A + case ('(n,2n2a)') + t % score_bins(j) = N_2N2A + case ('(n,nd)') + t % score_bins(j) = N_ND + case ('(n,nt)') + t % score_bins(j) = N_NT + case ('(n,nHe-3)') + t % score_bins(j) = N_N3HE + case ('(n,nd2a)') + t % score_bins(j) = N_ND2A + case ('(n,nt2a)') + t % score_bins(j) = N_NT2A + case ('(n,3nf)') + t % score_bins(j) = N_3NF + case ('(n,2np)') + t % score_bins(j) = N_2NP + case ('(n,3np)') + t % score_bins(j) = N_3NP + case ('(n,n2p)') + t % score_bins(j) = N_N2P + case ('(n,npa)') + t % score_bins(j) = N_NPA + case ('(n,n1)') + t % score_bins(j) = N_N1 + case ('(n,nc)') + t % score_bins(j) = N_NC + case ('(n,gamma)') + t % score_bins(j) = N_GAMMA + case ('(n,p)') + t % score_bins(j) = N_P + case ('(n,d)') + t % score_bins(j) = N_D + case ('(n,t)') + t % score_bins(j) = N_T + case ('(n,3He)') + t % score_bins(j) = N_3HE + case ('(n,a)') + t % score_bins(j) = N_A + case ('(n,2a)') + t % score_bins(j) = N_2A + case ('(n,3a)') + t % score_bins(j) = N_3A + case ('(n,2p)') + t % score_bins(j) = N_2P + case ('(n,pa)') + t % score_bins(j) = N_PA + case ('(n,t2a)') + t % score_bins(j) = N_T2A + case ('(n,d2a)') + t % score_bins(j) = N_D2A + case ('(n,pd)') + t % score_bins(j) = N_PD + case ('(n,pt)') + t % score_bins(j) = N_PT + case ('(n,da)') + t % score_bins(j) = N_DA + case default ! Assume that user has specified an MT number MT = int(str_to_int(score_name)) @@ -2923,11 +3335,8 @@ contains end if end select - - ! Append the score to the list of possible trigger scores - if (trigger_on) call trigger_scores % add_key(trim(score_name), l) - end do + t % n_score_bins = n_scores t % n_user_score_bins = n_words @@ -3132,15 +3541,26 @@ contains ! tally needs post-collision information if (t % estimator == ESTIMATOR_ANALOG) then call fatal_error("Cannot use track-length estimator for tally " & - &// to_str(t % id)) + // to_str(t % id)) end if ! Set estimator to track-length estimator t % estimator = ESTIMATOR_TRACKLENGTH + case ('collision') + ! If the estimator was set to an analog estimator, this means the + ! tally needs post-collision information + if (t % estimator == ESTIMATOR_ANALOG) then + call fatal_error("Cannot use collision estimator for tally " & + // to_str(t % id)) + end if + + ! Set estimator to collision estimator + t % estimator = ESTIMATOR_COLLISION + case default call fatal_error("Invalid estimator '" // trim(temp_str) & - &// "' on tally " // to_str(t % id)) + // "' on tally " // to_str(t % id)) end select end if @@ -3821,7 +4241,6 @@ contains call list_density % append(density * 0.999885_8) call list_names % append('1002.' // xs) call list_density % append(density * 0.000115_8) - case ('he') call list_names % append('2003.' // xs) call list_density % append(density * 0.00000134_8) @@ -4630,4 +5049,91 @@ contains end subroutine expand_natural_element +!=============================================================================== +! GENERATE_RPN implements the shunting-yard algorithm to generate a Reverse +! Polish notation (RPN) expression for the region specification of a cell given +! the infix notation. +!=============================================================================== + + subroutine generate_rpn(cell_id, tokens, output) + integer, intent(in) :: cell_id + type(VectorInt), intent(in) :: tokens ! infix notation + type(VectorInt), intent(inout) :: output ! RPN notation + + integer :: i + integer :: token + integer :: op + type(VectorInt) :: stack + + do i = 1, tokens%size() + token = tokens%data(i) + + if (token < OP_UNION) then + ! If token is not an operator, add it to output + call output%push_back(token) + + elseif (token < OP_RIGHT_PAREN) then + ! Regular operators union, intersection, complement + do while (stack%size() > 0) + op = stack%data(stack%size()) + + if (op < OP_RIGHT_PAREN .and. & + ((token == OP_COMPLEMENT .and. token < op) .or. & + (token /= OP_COMPLEMENT .and. token <= op))) then + ! While there is an operator, op, on top of the stack, if the token + ! is left-associative and its precedence is less than or equal to + ! that of op or if the token is right-associative and its precedence + ! is less than that of op, move op to the output queue and push the + ! token on to the stack. Note that only complement is + ! right-associative. + call output%push_back(op) + call stack%pop_back() + else + exit + end if + end do + + call stack%push_back(token) + + elseif (token == OP_LEFT_PAREN) then + ! If the token is a left parenthesis, push it onto the stack + call stack%push_back(token) + + else + ! If the token is a right parenthesis, move operators from the stack to + ! the output queue until reaching the left parenthesis. + do + ! If we run out of operators without finding a left parenthesis, it + ! means there are mismatched parentheses. + if (stack%size() == 0) then + call fatal_error('Mimatched parentheses in region specification & + &for cell ' // trim(to_str(cell_id)) // '.') + end if + + op = stack%data(stack%size()) + if (op == OP_LEFT_PAREN) exit + call output%push_back(op) + call stack%pop_back() + end do + + ! Pop the left parenthesis. + call stack%pop_back() + end if + end do + + ! While there are operators on the stack, move them to the output queue + do while (stack%size() > 0) + op = stack%data(stack%size()) + + ! If the operator is a parenthesis, it is mismatched + if (op >= OP_RIGHT_PAREN) then + call fatal_error('Mimatched parentheses in region specification & + &for cell ' // trim(to_str(cell_id)) // '.') + end if + + call output%push_back(op) + call stack%pop_back() + end do + end subroutine generate_rpn + end module input_xml diff --git a/src/interpolation.F90 b/src/interpolation.F90 index 5c44ed7c3d..9e28bc086e 100644 --- a/src/interpolation.F90 +++ b/src/interpolation.F90 @@ -21,7 +21,7 @@ contains ! tabulated x's and y's. !=============================================================================== - function interpolate_tab1_array(data, x, loc_start) result(y) + pure function interpolate_tab1_array(data, x, loc_start) result(y) real(8), intent(in) :: data(:) ! array of data real(8), intent(in) :: x ! x value to find y at @@ -106,18 +106,16 @@ contains select case (interp) case (LINEAR_LINEAR) r = (x - x0)/(x1 - x0) - y = (1 - r)*y0 + r*y1 + y = y0 + r*(y1 - y0) case (LINEAR_LOG) - r = (log(x) - log(x0))/(log(x1) - log(x0)) - y = (1 - r)*y0 + r*y1 + r = log(x/x0)/log(x1/x0) + y = y0 + r*(y1 - y0) case (LOG_LINEAR) r = (x - x0)/(x1 - x0) - y = exp((1-r)*log(y0) + r*log(y1)) + y = y0*exp(r*log(y1/y0)) case (LOG_LOG) - r = (log(x) - log(x0))/(log(x1) - log(x0)) - y = exp((1-r)*log(y0) + r*log(y1)) - case default - call fatal_error("Unsupported interpolation scheme: " // to_str(interp)) + r = log(x/x0)/log(x1/x0) + y = y0*exp(r*log(y1/y0)) end select end function interpolate_tab1_array @@ -129,7 +127,7 @@ contains ! tabulated x's and y's. !=============================================================================== - function interpolate_tab1_object(obj, x) result(y) + pure function interpolate_tab1_object(obj, x) result(y) type(Tab1), intent(in) :: obj ! ENDF Tab1 interpolable function real(8), intent(in) :: x ! x value to find y at @@ -191,18 +189,16 @@ contains select case (interp) case (LINEAR_LINEAR) r = (x - x0)/(x1 - x0) - y = (1 - r)*y0 + r*y1 + y = y0 + r*(y1 - y0) case (LINEAR_LOG) - r = (log(x) - log(x0))/(log(x1) - log(x0)) - y = (1 - r)*y0 + r*y1 + r = log(x/x0)/log(x1/x0) + y = y0 + r*(y1 - y0) case (LOG_LINEAR) r = (x - x0)/(x1 - x0) - y = exp((1-r)*log(y0) + r*log(y1)) + y = y0*exp(r*log(y1/y0)) case (LOG_LOG) - r = (log(x) - log(x0))/(log(x1) - log(x0)) - y = exp((1-r)*log(y0) + r*log(y1)) - case default - call fatal_error("Unsupported interpolation scheme: " // to_str(interp)) + r = log(x/x0)/log(x1/x0) + y = y0*exp(r*log(y1/y0)) end select end function interpolate_tab1_object diff --git a/src/main.F90 b/src/main.F90 index e4a33f0096..aff1e21146 100644 --- a/src/main.F90 +++ b/src/main.F90 @@ -1,13 +1,12 @@ program main use constants - use eigenvalue, only: run_eigenvalue use finalize, only: finalize_run - use fixed_source, only: run_fixedsource use global use initialize, only: initialize_run use particle_restart, only: run_particle_restart use plot, only: run_plot + use simulation, only: run_simulation implicit none @@ -16,10 +15,8 @@ program main ! start problem based on mode select case (run_mode) - case (MODE_FIXEDSOURCE) - call run_fixedsource() - case (MODE_EIGENVALUE) - call run_eigenvalue() + case (MODE_FIXEDSOURCE, MODE_EIGENVALUE) + call run_simulation() case (MODE_PLOTTING) call run_plot() case (MODE_PARTICLE) diff --git a/src/material_header.F90 b/src/material_header.F90 index a10382abd9..91c4cdfb82 100644 --- a/src/material_header.F90 +++ b/src/material_header.F90 @@ -8,7 +8,7 @@ module material_header type Material integer :: id ! unique identifier - character(len=52) :: name = "" ! User-defined name + character(len=104) :: name = "" ! User-defined name integer :: n_nuclides ! number of nuclides integer, allocatable :: nuclide(:) ! index in nuclides array real(8) :: density ! total atom density in atom/b-cm @@ -33,6 +33,9 @@ module material_header ! Does this material contain fissionable nuclides? logical :: fissionable = .false. + ! enforce isotropic scattering in lab + logical, allocatable :: p0(:) + end type Material end module material_header diff --git a/src/math.F90 b/src/math.F90 index 826172fa24..15aa672e15 100644 --- a/src/math.F90 +++ b/src/math.F90 @@ -12,7 +12,7 @@ contains ! distribution with a specified probability level !=============================================================================== - function normal_percentile(p) result(z) + elemental function normal_percentile(p) result(z) real(8), intent(in) :: p ! probability level real(8) :: z ! corresponding z-value @@ -71,7 +71,7 @@ contains ! specified probability level and number of degrees of freedom !=============================================================================== - function t_percentile(p, df) result(t) + elemental function t_percentile(p, df) result(t) real(8), intent(in) :: p ! probability level integer, intent(in) :: df ! degrees of freedom @@ -123,7 +123,7 @@ contains ! the return value will be 1.0. !=============================================================================== - pure function calc_pn(n,x) result(pnx) + elemental function calc_pn(n,x) result(pnx) integer, intent(in) :: n ! Legendre order requested real(8), intent(in) :: x ! Independent variable the Legendre is to be @@ -181,7 +181,6 @@ contains if (uvw(1) == ZERO) then phi = ZERO else -! phi = atan(uvw(2) / uvw(1)) phi = atan2(uvw(2), uvw(1)) end if @@ -192,364 +191,364 @@ contains rn(1) = ONE case (1) ! l = 1, m = -1 - rn(1) = ONE*sqrt(w2m1) * sin(phi) + rn(1) = -(ONE*sqrt(w2m1) * sin(phi)) ! l = 1, m = 0 rn(2) = ONE * w ! l = 1, m = 1 - rn(3) = ONE*sqrt(w2m1) * cos(phi) + rn(3) = -(ONE*sqrt(w2m1) * cos(phi)) case (2) ! l = 2, m = -2 rn(1) = 0.288675134594813_8 * (-THREE * w**2 + THREE) * sin(TWO*phi) ! l = 2, m = -1 - rn(2) = 1.73205080756888_8 * w*sqrt(w2m1) * sin(phi) + rn(2) = -(1.73205080756888_8 * w*sqrt(w2m1) * sin(phi)) ! l = 2, m = 0 rn(3) = 1.5_8 * w**2 - HALF ! l = 2, m = 1 - rn(4) = 1.73205080756888_8 * w*sqrt(w2m1) * cos(phi) + rn(4) = -(1.73205080756888_8 * w*sqrt(w2m1) * cos(phi)) ! l = 2, m = 2 rn(5) = 0.288675134594813_8 * (-THREE * w**2 + THREE) * cos(TWO*phi) case (3) ! l = 3, m = -3 - rn(1) = 0.790569415042095_8 * (w2m1)**(THREE/TWO) * sin(THREE * phi) + rn(1) = -(0.790569415042095_8 * (w2m1)**(THREE/TWO) * sin(THREE * phi)) ! l = 3, m = -2 rn(2) = 1.93649167310371_8 * w*(w2m1) * sin(TWO*phi) ! l = 3, m = -1 - rn(3) = 0.408248290463863_8*sqrt(w2m1)*((15.0_8/TWO)*w**2 - THREE/TWO) * & - sin(phi) + rn(3) = -(0.408248290463863_8*sqrt(w2m1)*((15.0_8/TWO)*w**2 - THREE/TWO) * & + sin(phi)) ! l = 3, m = 0 rn(4) = 2.5_8 * w**3 - 1.5_8 * w ! l = 3, m = 1 - rn(5) = 0.408248290463863_8*sqrt(w2m1)*((15.0_8/TWO)*w**2 - THREE/TWO) * & - cos(phi) + rn(5) = -(0.408248290463863_8*sqrt(w2m1)*((15.0_8/TWO)*w**2 - THREE/TWO) * & + cos(phi)) ! l = 3, m = 2 rn(6) = 1.93649167310371_8 * w*(w2m1) * cos(TWO*phi) ! l = 3, m = 3 - rn(7) = 0.790569415042095_8 * (w2m1)**(THREE/TWO) * cos(THREE* phi) + rn(7) = -(0.790569415042095_8 * (w2m1)**(THREE/TWO) * cos(THREE* phi)) case (4) ! l = 4, m = -4 rn(1) = 0.739509972887452_8 * (w2m1)**2 * sin(4.0_8*phi) ! l = 4, m = -3 - rn(2) = 2.09165006633519_8 * w*(w2m1)**(THREE/TWO) * sin(THREE* phi) + rn(2) = -(2.09165006633519_8 * w*(w2m1)**(THREE/TWO) * sin(THREE* phi)) ! l = 4, m = -2 rn(3) = 0.074535599249993_8 * (w2m1)*((105.0_8/TWO)*w**2 - 15.0_8/TWO) * & sin(TWO*phi) ! l = 4, m = -1 - rn(4) = 0.316227766016838_8*sqrt(w2m1)*((35.0_8/TWO)*w**3 - 15.0_8/TWO*w)& - * sin(phi) + rn(4) = -(0.316227766016838_8*sqrt(w2m1)*((35.0_8/TWO)*w**3 - 15.0_8/TWO*w)& + * sin(phi)) ! l = 4, m = 0 rn(5) = 4.375_8 * w**4 - 3.75_8 * w**2 + 0.375_8 ! l = 4, m = 1 - rn(6) = 0.316227766016838_8*sqrt(w2m1)*((35.0_8/TWO)*w**3 - 15.0_8/TWO*w)& - * cos(phi) + rn(6) = -(0.316227766016838_8*sqrt(w2m1)*((35.0_8/TWO)*w**3 - 15.0_8/TWO*w)& + * cos(phi)) ! l = 4, m = 2 rn(7) = 0.074535599249993_8 * (w2m1)*((105.0_8/TWO)*w**2 - 15.0_8/TWO) * & cos(TWO*phi) ! l = 4, m = 3 - rn(8) = 2.09165006633519_8 * w*(w2m1)**(THREE/TWO) * cos(THREE* phi) + rn(8) = -(2.09165006633519_8 * w*(w2m1)**(THREE/TWO) * cos(THREE* phi)) ! l = 4, m = 4 rn(9) = 0.739509972887452_8 * (w2m1)**2 * cos(4.0_8*phi) case (5) ! l = 5, m = -5 - rn(1) = 0.701560760020114_8 * (w2m1)**(5.0_8/TWO) * sin(5.0_8*phi) + rn(1) = -(0.701560760020114_8 * (w2m1)**(5.0_8/TWO) * sin(5.0_8*phi)) ! l = 5, m = -4 rn(2) = 2.21852991866236_8 * w*(w2m1)**2 * sin(4.0_8*phi) ! l = 5, m = -3 - rn(3) = 0.00996023841111995_8 * (w2m1)**(THREE/TWO)* & - ((945.0_8 /TWO)*w**2 - 105.0_8/TWO) * sin(THREE*phi) + rn(3) = -(0.00996023841111995_8 * (w2m1)**(THREE/TWO)* & + ((945.0_8 /TWO)*w**2 - 105.0_8/TWO) * sin(THREE*phi)) ! l = 5, m = -2 rn(4) = 0.0487950036474267_8 * (w2m1) & * ((315.0_8/TWO)*w**3 - 105.0_8/TWO*w) * sin(TWO*phi) ! l = 5, m = -1 - rn(5) = 0.258198889747161_8*sqrt(w2m1)* & + rn(5) = -(0.258198889747161_8*sqrt(w2m1)* & ((315.0_8/8.0_8)*w**4 - 105.0_8/4.0_8 * w**2 + 15.0_8/8.0_8) & - * sin(phi) + * sin(phi)) ! l = 5, m = 0 rn(6) = 7.875_8 * w**5 - 8.75_8 * w**3 + 1.875_8 * w ! l = 5, m = 1 - rn(7) = 0.258198889747161_8*sqrt(w2m1)* & + rn(7) = -(0.258198889747161_8*sqrt(w2m1)* & ((315.0_8/8.0_8)*w**4 - 105.0_8/4.0_8 * w**2 + 15.0_8/8.0_8) & - * cos(phi) + * cos(phi)) ! l = 5, m = 2 rn(8) = 0.0487950036474267_8 * (w2m1)* & ((315.0_8/TWO)*w**3 - 105.0_8/TWO*w) * cos(TWO*phi) ! l = 5, m = 3 - rn(9) = 0.00996023841111995_8 * (w2m1)**(THREE/TWO)* & - ((945.0_8 /TWO)*w**2 - 105.0_8/TWO) * cos(THREE*phi) + rn(9) = -(0.00996023841111995_8 * (w2m1)**(THREE/TWO)* & + ((945.0_8 /TWO)*w**2 - 105.0_8/TWO) * cos(THREE*phi)) ! l = 5, m = 4 rn(10) = 2.21852991866236_8 * w*(w2m1)**2 * cos(4.0_8*phi) ! l = 5, m = 5 - rn(11) = 0.701560760020114_8 * (w2m1)**(5.0_8/TWO) * cos(5.0_8* phi) + rn(11) = -(0.701560760020114_8 * (w2m1)**(5.0_8/TWO) * cos(5.0_8* phi)) case (6) ! l = 6, m = -6 rn(1) = 0.671693289381396_8 * (w2m1)**3 * sin(6.0_8*phi) ! l = 6, m = -5 - rn(2) = 2.32681380862329_8 * w*(w2m1)**(5.0_8/TWO) * sin(5.0_8*phi) + rn(2) = -(2.32681380862329_8 * w*(w2m1)**(5.0_8/TWO) * sin(5.0_8*phi)) ! l = 6, m = -4 rn(3) = 0.00104990131391452_8 * (w2m1)**2 * & ((10395.0_8/TWO)*w**2 - 945.0_8/TWO) * sin(4.0_8*phi) ! l = 6, m = -3 - rn(4) = 0.00575054632785295_8 * (w2m1)**(THREE/TWO) * & - ((3465.0_8/TWO)*w**3 - 945.0_8/TWO*w) * sin(THREE*phi) + rn(4) = -(0.00575054632785295_8 * (w2m1)**(THREE/TWO) * & + ((3465.0_8/TWO)*w**3 - 945.0_8/TWO*w) * sin(THREE*phi)) ! l = 6, m = -2 rn(5) = 0.0345032779671177_8 * (w2m1) * & ((3465.0_8/8.0_8)*w**4 - 945.0_8/4.0_8 * w**2 + 105.0_8/8.0_8) & * sin(TWO*phi) ! l = 6, m = -1 - rn(6) = 0.218217890235992_8*sqrt(w2m1) * & + rn(6) = -(0.218217890235992_8*sqrt(w2m1) * & ((693.0_8/8.0_8)*w**5- 315.0_8/4.0_8 * w**3 + (105.0_8/8.0_8)*w) & - * sin(phi) + * sin(phi)) ! l = 6, m = 0 rn(7) = 14.4375_8 * w**6 - 19.6875_8 * w**4 + 6.5625_8 * w**2 - 0.3125_8 ! l = 6, m = 1 - rn(8) = 0.218217890235992_8*sqrt(w2m1) * & + rn(8) = -(0.218217890235992_8*sqrt(w2m1) * & ((693.0_8/8.0_8)*w**5- 315.0_8/4.0_8 * w**3 + (105.0_8/8.0_8)*w) & - * cos(phi) + * cos(phi)) ! l = 6, m = 2 rn(9) = 0.0345032779671177_8 * (w2m1) * & ((3465.0_8/8.0_8)*w**4 -945.0_8/4.0_8 * w**2 + 105.0_8/8.0_8) & * cos(TWO*phi) ! l = 6, m = 3 - rn(10) = 0.00575054632785295_8 * (w2m1)**(THREE/TWO) * & - ((3465.0_8/TWO)*w**3 - 945.0_8/TWO*w) * cos(THREE*phi) + rn(10) = -(0.00575054632785295_8 * (w2m1)**(THREE/TWO) * & + ((3465.0_8/TWO)*w**3 - 945.0_8/TWO*w) * cos(THREE*phi)) ! l = 6, m = 4 rn(11) = 0.00104990131391452_8 * (w2m1)**2 * & ((10395.0_8/TWO)*w**2 - 945.0_8/TWO) * cos(4.0_8*phi) ! l = 6, m = 5 - rn(12) = 2.32681380862329_8 * w*(w2m1)**(5.0_8/TWO) * cos(5.0_8*phi) + rn(12) = -(2.32681380862329_8 * w*(w2m1)**(5.0_8/TWO) * cos(5.0_8*phi)) ! l = 6, m = 6 rn(13) = 0.671693289381396_8 * (w2m1)**3 * cos(6.0_8*phi) case (7) ! l = 7, m = -7 - rn(1) = 0.647259849287749_8 * (w2m1)**(7.0_8/TWO) * sin(7.0_8*phi) + rn(1) = -(0.647259849287749_8 * (w2m1)**(7.0_8/TWO) * sin(7.0_8*phi)) ! l = 7, m = -6 rn(2) = 2.42182459624969_8 * w*(w2m1)**3 * sin(6.0_8*phi) ! l = 7, m = -5 - rn(3) = 9.13821798555235d-5*(w2m1)**(5.0_8/TWO)* & - ((135135.0_8/TWO)*w**2 - 10395.0_8/TWO) * sin(5.0_8*phi) + rn(3) = -(9.13821798555235d-5*(w2m1)**(5.0_8/TWO)* & + ((135135.0_8/TWO)*w**2 - 10395.0_8/TWO) * sin(5.0_8*phi)) ! l = 7, m = -4 rn(4) = 0.000548293079133141_8 * (w2m1)**2* & ((45045.0_8/TWO)*w**3 - 10395.0_8/TWO*w) * sin(4.0_8*phi) ! l = 7, m = -3 - rn(5) = 0.00363696483726654_8 * (w2m1)**(THREE/TWO)* & - ((45045.0_8/8.0_8)*w**4 - 10395.0_8/4.0_8 * w**2 + 945.0_8/8.0_8)* & - sin(THREE*phi) + rn(5) = -(0.00363696483726654_8 * (w2m1)**(THREE/TWO)* & + ((45045.0_8/8.0_8)*w**4 - 10395.0_8/4.0_8 * w**2 + 945.0_8/8.0_8)* & + sin(THREE*phi)) ! l = 7, m = -2 rn(6) = 0.025717224993682_8 * (w2m1)* & ((9009.0_8/8.0_8)*w**5 -3465.0_8/4.0_8 * w**3 + (945.0_8/8.0_8)*w)* & sin(TWO*phi) ! l = 7, m = -1 - rn(7) = 0.188982236504614_8*sqrt(w2m1)* & - ((3003.0_8/16.0_8)*w**6 - 3465.0_8/16.0_8 * w**4 + & - (945.0_8/16.0_8)*w**2 - 35.0_8/16.0_8) * sin(phi) + rn(7) = -(0.188982236504614_8*sqrt(w2m1)* & + ((3003.0_8/16.0_8)*w**6 - 3465.0_8/16.0_8 * w**4 + & + (945.0_8/16.0_8)*w**2 - 35.0_8/16.0_8) * sin(phi)) ! l = 7, m = 0 rn(8) = 26.8125_8 * w**7 - 43.3125_8 * w**5 + 19.6875_8 * w**3 -2.1875_8 & * w ! l = 7, m = 1 - rn(9) = 0.188982236504614_8*sqrt(w2m1)* & - ((3003.0_8/16.0_8)*w**6 - 3465.0_8/16.0_8 * w**4 + & - (945.0_8/16.0_8)*w**2 - 35.0_8/16.0_8) * cos(phi) + rn(9) = -(0.188982236504614_8*sqrt(w2m1)* & + ((3003.0_8/16.0_8)*w**6 - 3465.0_8/16.0_8 * w**4 + & + (945.0_8/16.0_8)*w**2 - 35.0_8/16.0_8) * cos(phi)) ! l = 7, m = 2 rn(10) = 0.025717224993682_8 * (w2m1)* & ((9009.0_8/8.0_8)*w**5 -3465.0_8/4.0_8 * w**3 + (945.0_8/8.0_8)*w)* & cos(TWO*phi) ! l = 7, m = 3 - rn(11) = 0.00363696483726654_8 * (w2m1)**(THREE/TWO)* & - ((45045.0_8/8.0_8)*w**4 - 10395.0_8/4.0_8 * w**2 + 945.0_8/8.0_8)* & - cos(THREE*phi) + rn(11) = -(0.00363696483726654_8 * (w2m1)**(THREE/TWO)* & + ((45045.0_8/8.0_8)*w**4 - 10395.0_8/4.0_8 * w**2 + 945.0_8/8.0_8)* & + cos(THREE*phi)) ! l = 7, m = 4 rn(12) = 0.000548293079133141_8 * (w2m1)**2 * & ((45045.0_8/TWO)*w**3 - 10395.0_8/TWO*w) * cos(4.0_8*phi) ! l = 7, m = 5 - rn(13) = 9.13821798555235d-5*(w2m1)**(5.0_8/TWO)* & - ((135135.0_8/TWO)*w**2 - 10395.0_8/TWO) * cos(5.0_8*phi) + rn(13) = -(9.13821798555235d-5*(w2m1)**(5.0_8/TWO)* & + ((135135.0_8/TWO)*w**2 - 10395.0_8/TWO) * cos(5.0_8*phi)) ! l = 7, m = 6 rn(14) = 2.42182459624969_8 * w*(w2m1)**3 * cos(6.0_8*phi) ! l = 7, m = 7 - rn(15) = 0.647259849287749_8 * (w2m1)**(7.0_8/TWO) * cos(7.0_8*phi) + rn(15) = -(0.647259849287749_8 * (w2m1)**(7.0_8/TWO) * cos(7.0_8*phi)) case (8) ! l = 8, m = -8 rn(1) = 0.626706654240044_8 * (w2m1)**4 * sin(8.0_8*phi) ! l = 8, m = -7 - rn(2) = 2.50682661696018_8 * w*(w2m1)**(7.0_8/TWO) * sin(7.0_8*phi) + rn(2) = -(2.50682661696018_8 * w*(w2m1)**(7.0_8/TWO) * sin(7.0_8*phi)) ! l = 8, m = -6 rn(3) = 6.77369783729086d-6*(w2m1)**3* & ((2027025.0_8/TWO)*w**2 - 135135.0_8/TWO) * sin(6.0_8*phi) ! l = 8, m = -5 - rn(4) = 4.38985792528482d-5*(w2m1)**(5.0_8/TWO)* & - ((675675.0_8/TWO)*w**3 - 135135.0_8/TWO*w) * sin(5.0_8*phi) + rn(4) = -(4.38985792528482d-5*(w2m1)**(5.0_8/TWO)* & + ((675675.0_8/TWO)*w**3 - 135135.0_8/TWO*w) * sin(5.0_8*phi)) ! l = 8, m = -4 rn(5) = 0.000316557156832328_8 * (w2m1)**2* & ((675675.0_8/8.0_8)*w**4 - 135135.0_8/4.0_8 * w**2 & + 10395.0_8/8.0_8) * sin(4.0_8*phi) ! l = 8, m = -3 - rn(6) = 0.00245204119306875_8 * (w2m1)**(THREE/TWO)* & - ((135135.0_8/8.0_8)*w**5 - 45045.0_8/4.0_8 * w**3 & - + (10395.0_8/8.0_8)*w) * sin(THREE*phi) + rn(6) = -(0.00245204119306875_8 * (w2m1)**(THREE/TWO)* & + ((135135.0_8/8.0_8)*w**5 - 45045.0_8/4.0_8 * w**3 & + + (10395.0_8/8.0_8)*w) * sin(THREE*phi)) ! l = 8, m = -2 rn(7) = 0.0199204768222399_8 * (w2m1)* & ((45045.0_8/16.0_8)*w**6- 45045.0_8/16.0_8 * w**4 + & (10395.0_8/16.0_8)*w**2 - 315.0_8/16.0_8) * sin(TWO*phi) ! l = 8, m = -1 - rn(8) = 0.166666666666667_8*sqrt(w2m1)* & - ((6435.0_8/16.0_8)*w**7 - 9009.0_8/16.0_8 * w**5 + & - (3465.0_8/16.0_8)*w**3 - 315.0_8/16.0_8 * w) * sin(phi) + rn(8) = -(0.166666666666667_8*sqrt(w2m1)* & + ((6435.0_8/16.0_8)*w**7 - 9009.0_8/16.0_8 * w**5 + & + (3465.0_8/16.0_8)*w**3 - 315.0_8/16.0_8 * w) * sin(phi)) ! l = 8, m = 0 rn(9) = 50.2734375_8 * w**8 - 93.84375_8 * w**6 + 54.140625_8 * w**4 -& 9.84375_8 * w**2 + 0.2734375_8 ! l = 8, m = 1 - rn(10) = 0.166666666666667_8*sqrt(w2m1)* & - ((6435.0_8/16.0_8)*w**7 - 9009.0_8/16.0_8 * w**5 + & - (3465.0_8/16.0_8)*w**3 - 315.0_8/16.0_8 * w) * cos(phi) + rn(10) = -(0.166666666666667_8*sqrt(w2m1)* & + ((6435.0_8/16.0_8)*w**7 - 9009.0_8/16.0_8 * w**5 + & + (3465.0_8/16.0_8)*w**3 - 315.0_8/16.0_8 * w) * cos(phi)) ! l = 8, m = 2 rn(11) = 0.0199204768222399_8 * (w2m1)*((45045.0_8/16.0_8)*w**6- & 45045.0_8/16.0_8 * w**4 + (10395.0_8/16.0_8)*w**2 - & 315.0_8/16.0_8) * cos(TWO*phi) ! l = 8, m = 3 - rn(12) = 0.00245204119306875_8 * (w2m1)**(THREE/TWO)* & - ((135135.0_8/8.0_8)*w**5 - 45045.0_8/4.0_8 * w**3 + & - (10395.0_8/8.0_8)*w) * cos(THREE*phi) + rn(12) = -(0.00245204119306875_8 * (w2m1)**(THREE/TWO)* & + ((135135.0_8/8.0_8)*w**5 - 45045.0_8/4.0_8 * w**3 + & + (10395.0_8/8.0_8)*w) * cos(THREE*phi)) ! l = 8, m = 4 rn(13) = 0.000316557156832328_8 * (w2m1)**2*((675675.0_8/8.0_8)*w**4 - & 135135.0_8/4.0_8 * w**2 + 10395.0_8/8.0_8) * cos(4.0_8*phi) ! l = 8, m = 5 - rn(14) = 4.38985792528482d-5*(w2m1)**(5.0_8/TWO)*((675675.0_8/TWO)*w**3 -& - 135135.0_8/TWO*w) * cos(5.0_8*phi) + rn(14) = -(4.38985792528482d-5*(w2m1)**(5.0_8/TWO)*((675675.0_8/TWO)*w**3 -& + 135135.0_8/TWO*w) * cos(5.0_8*phi)) ! l = 8, m = 6 rn(15) = 6.77369783729086d-6*(w2m1)**3*((2027025.0_8/TWO)*w**2 - & 135135.0_8/TWO) * cos(6.0_8*phi) ! l = 8, m = 7 - rn(16) = 2.50682661696018_8 * w*(w2m1)**(7.0_8/TWO) * cos(7.0_8*phi) + rn(16) = -(2.50682661696018_8 * w*(w2m1)**(7.0_8/TWO) * cos(7.0_8*phi)) ! l = 8, m = 8 rn(17) = 0.626706654240044_8 * (w2m1)**4 * cos(8.0_8*phi) case (9) ! l = 9, m = -9 - rn(1) = 0.609049392175524_8 * (w2m1)**(9.0_8/TWO) * sin(9.0_8*phi) + rn(1) = -(0.609049392175524_8 * (w2m1)**(9.0_8/TWO) * sin(9.0_8*phi)) ! l = 9, m = -8 rn(2) = 2.58397773170915_8 * w*(w2m1)**4 * sin(8.0_8*phi) ! l = 9, m = -7 - rn(3) = 4.37240315267812d-7*(w2m1)**(7.0_8/TWO)* & - ((34459425.0_8/TWO)*w**2 - 2027025.0_8/TWO) * sin(7.0_8*phi) + rn(3) = -(4.37240315267812d-7*(w2m1)**(7.0_8/TWO)* & + ((34459425.0_8/TWO)*w**2 - 2027025.0_8/TWO) * sin(7.0_8*phi)) ! l = 9, m = -6 rn(4) = 3.02928976464514d-6*(w2m1)**3* & ((11486475.0_8/TWO)*w**3 - 2027025.0_8/TWO*w) * sin(6.0_8*phi) ! l = 9, m = -5 - rn(5) = 2.34647776186144d-5*(w2m1)**(5.0_8/TWO)* & - ((11486475.0_8/8.0_8)*w**4 - 2027025.0_8/4.0_8 * w**2 + & - 135135.0_8/8.0_8) * sin(5.0_8*phi) + rn(5) = -(2.34647776186144d-5*(w2m1)**(5.0_8/TWO)* & + ((11486475.0_8/8.0_8)*w**4 - 2027025.0_8/4.0_8 * w**2 + & + 135135.0_8/8.0_8) * sin(5.0_8*phi)) ! l = 9, m = -4 rn(6) = 0.000196320414650061_8 * (w2m1)**2*((2297295.0_8/8.0_8)*w**5 - & 675675.0_8/4.0_8 * w**3 + (135135.0_8/8.0_8)*w) * sin(4.0_8*phi) ! l = 9, m = -3 - rn(7) = 0.00173385495536766_8 * (w2m1)**(THREE/TWO)* & - ((765765.0_8/16.0_8)*w**6 - 675675.0_8/16.0_8 * w**4 + & - (135135.0_8/16.0_8)*w**2 - 3465.0_8/16.0_8) * sin(THREE*phi) + rn(7) = -(0.00173385495536766_8 * (w2m1)**(THREE/TWO)* & + ((765765.0_8/16.0_8)*w**6 - 675675.0_8/16.0_8 * w**4 + & + (135135.0_8/16.0_8)*w**2 - 3465.0_8/16.0_8) * sin(THREE*phi)) ! l = 9, m = -2 rn(8) = 0.0158910431540932_8 * (w2m1)*((109395.0_8/16.0_8)*w**7- & 135135.0_8/16.0_8 * w**5 + (45045.0_8/16.0_8)*w**3 & - 3465.0_8/16.0_8 * w) * sin(TWO*phi) ! l = 9, m = -1 - rn(9) = 0.149071198499986_8*sqrt(w2m1)*((109395.0_8/128.0_8)*w**8 - & - 45045.0_8/32.0_8 * w**6 + (45045.0_8/64.0_8)*w**4 - 3465.0_8/32.0_8 & - * w**2 + 315.0_8/128.0_8) * sin(phi) + rn(9) = -(0.149071198499986_8*sqrt(w2m1)*((109395.0_8/128.0_8)*w**8 - & + 45045.0_8/32.0_8 * w**6 + (45045.0_8/64.0_8)*w**4 - 3465.0_8/32.0_8 & + * w**2 + 315.0_8/128.0_8) * sin(phi)) ! l = 9, m = 0 rn(10) = 94.9609375_8 * w**9 - 201.09375_8 * w**7 + 140.765625_8 * w**5- & 36.09375_8 * w**3 + 2.4609375_8 * w ! l = 9, m = 1 - rn(11) = 0.149071198499986_8*sqrt(w2m1)*((109395.0_8/128.0_8)*w**8 - & - 45045.0_8/32.0_8 * w**6 + (45045.0_8/64.0_8)*w**4 -3465.0_8/32.0_8 & - * w**2 + 315.0_8/128.0_8) * cos(phi) + rn(11) = -(0.149071198499986_8*sqrt(w2m1)*((109395.0_8/128.0_8)*w**8 - & + 45045.0_8/32.0_8 * w**6 + (45045.0_8/64.0_8)*w**4 -3465.0_8/32.0_8 & + * w**2 + 315.0_8/128.0_8) * cos(phi)) ! l = 9, m = 2 rn(12) = 0.0158910431540932_8 * (w2m1)*((109395.0_8/16.0_8)*w**7 - & 135135.0_8/16.0_8 * w**5 + (45045.0_8/16.0_8)*w**3 & - 3465.0_8/ 16.0_8 * w) * cos(TWO*phi) ! l = 9, m = 3 - rn(13) = 0.00173385495536766_8 * (w2m1)**(THREE/TWO)*((765765.0_8/16.0_8)& - *w**6 - 675675.0_8/16.0_8 * w**4 + (135135.0_8/16.0_8)*w**2 & - - 3465.0_8/16.0_8)* cos(THREE*phi) + rn(13) = -(0.00173385495536766_8 * (w2m1)**(THREE/TWO)*((765765.0_8/16.0_8)& + *w**6 - 675675.0_8/16.0_8 * w**4 + (135135.0_8/16.0_8)*w**2 & + - 3465.0_8/16.0_8)* cos(THREE*phi)) ! l = 9, m = 4 rn(14) = 0.000196320414650061_8 * (w2m1)**2*((2297295.0_8/8.0_8)*w**5 - & 675675.0_8/4.0_8 * w**3 + (135135.0_8/8.0_8)*w) * cos(4.0_8*phi) ! l = 9, m = 5 - rn(15) = 2.34647776186144d-5*(w2m1)**(5.0_8/TWO)*((11486475.0_8/8.0_8)* & - w**4 - 2027025.0_8/4.0_8 * w**2 + 135135.0_8/8.0_8) * cos(5.0_8*phi) + rn(15) = -(2.34647776186144d-5*(w2m1)**(5.0_8/TWO)*((11486475.0_8/8.0_8)* & + w**4 - 2027025.0_8/4.0_8 * w**2 + 135135.0_8/8.0_8) * cos(5.0_8*phi)) ! l = 9, m = 6 rn(16) = 3.02928976464514d-6*(w2m1)**3*((11486475.0_8/TWO)*w**3 - & 2027025.0_8/TWO*w) * cos(6.0_8*phi) ! l = 9, m = 7 - rn(17) = 4.37240315267812d-7*(w2m1)**(7.0_8/TWO)* & - ((34459425.0_8/TWO)*w**2 - 2027025.0_8/TWO) * cos(7.0_8*phi) + rn(17) = -(4.37240315267812d-7*(w2m1)**(7.0_8/TWO)* & + ((34459425.0_8/TWO)*w**2 - 2027025.0_8/TWO) * cos(7.0_8*phi)) ! l = 9, m = 8 rn(18) = 2.58397773170915_8 * w*(w2m1)**4 * cos(8.0_8*phi) ! l = 9, m = 9 - rn(19) = 0.609049392175524_8 * (w2m1)**(9.0_8/TWO) * cos(9.0_8*phi) + rn(19) = -(0.609049392175524_8 * (w2m1)**(9.0_8/TWO) * cos(9.0_8*phi)) case (10) ! l = 10, m = -10 rn(1) = 0.593627917136573_8 * (w2m1)**5 * sin(10.0_8*phi) ! l = 10, m = -9 - rn(2) = 2.65478475211798_8 * w*(w2m1)**(9.0_8/TWO) * sin(9.0_8*phi) + rn(2) = -(2.65478475211798_8 * w*(w2m1)**(9.0_8/TWO) * sin(9.0_8*phi)) ! l = 10, m = -8 rn(3) = 2.49953651452314d-8*(w2m1)**4*((654729075.0_8/TWO)*w**2 - & 34459425.0_8/TWO) * sin(8.0_8*phi) ! l = 10, m = -7 - rn(4) = 1.83677671621093d-7*(w2m1)**(7.0_8/TWO)* & - ((218243025.0_8/TWO)*w**3 - 34459425.0_8/TWO*w) * sin(7.0_8*phi) + rn(4) = -(1.83677671621093d-7*(w2m1)**(7.0_8/TWO)* & + ((218243025.0_8/TWO)*w**3 - 34459425.0_8/TWO*w) * sin(7.0_8*phi)) ! l = 10, m = -6 rn(5) = 1.51464488232257d-6*(w2m1)**3*((218243025.0_8/8.0_8)*w**4 - & 34459425.0_8/4.0_8 * w**2 + 2027025.0_8/8.0_8) * sin(6.0_8*phi) ! l = 10, m = -5 - rn(6) = 1.35473956745817d-5*(w2m1)**(5.0_8/TWO)* & - ((43648605.0_8/8.0_8)*w**5 - 11486475.0_8/4.0_8 * w**3 + & - (2027025.0_8/8.0_8)*w) * sin(5.0_8*phi) + rn(6) = -(1.35473956745817d-5*(w2m1)**(5.0_8/TWO)* & + ((43648605.0_8/8.0_8)*w**5 - 11486475.0_8/4.0_8 * w**3 + & + (2027025.0_8/8.0_8)*w) * sin(5.0_8*phi)) ! l = 10, m = -4 rn(7) = 0.000128521880085575_8 * (w2m1)**2*((14549535.0_8/16.0_8)*w**6 - & 11486475.0_8/16.0_8 * w**4 + (2027025.0_8/16.0_8)*w**2 - & 45045.0_8/16.0_8) * sin(4.0_8*phi) ! l = 10, m = -3 - rn(8) = 0.00127230170115096_8 * (w2m1)**(THREE/TWO)* & - ((2078505.0_8/16.0_8)*w**7 - 2297295.0_8/16.0_8 * w**5 + & - (675675.0_8/16.0_8)*w**3 - 45045.0_8/16.0_8 * w) * sin(THREE*phi) + rn(8) = -(0.00127230170115096_8 * (w2m1)**(THREE/TWO)* & + ((2078505.0_8/16.0_8)*w**7 - 2297295.0_8/16.0_8 * w**5 + & + (675675.0_8/16.0_8)*w**3 - 45045.0_8/16.0_8 * w) * sin(THREE*phi)) ! l = 10, m = -2 rn(9) = 0.012974982402692_8 * (w2m1)*((2078505.0_8/128.0_8)*w**8 - & 765765.0_8/32.0_8 * w**6 + (675675.0_8/64.0_8)*w**4 - & 45045.0_8/32.0_8 * w**2 + 3465.0_8/128.0_8) * sin(TWO*phi) ! l = 10, m = -1 - rn(10) = 0.134839972492648_8*sqrt(w2m1)*((230945.0_8/128.0_8)*w**9 - & - 109395.0_8/32.0_8 * w**7 + (135135.0_8/64.0_8)*w**5 - & - 15015.0_8/32.0_8 * w**3 + (3465.0_8/128.0_8)*w) * sin(phi) + rn(10) = -(0.134839972492648_8*sqrt(w2m1)*((230945.0_8/128.0_8)*w**9 - & + 109395.0_8/32.0_8 * w**7 + (135135.0_8/64.0_8)*w**5 - & + 15015.0_8/32.0_8 * w**3 + (3465.0_8/128.0_8)*w) * sin(phi)) ! l = 10, m = 0 rn(11) = 180.42578125_8 * w**10 - 427.32421875_8 * w**8 +351.9140625_8 & * w**6 - 117.3046875_8 * w**4 + 13.53515625_8 * w**2 -0.24609375_8 ! l = 10, m = 1 - rn(12) = 0.134839972492648_8*sqrt(w2m1)*((230945.0_8/128.0_8)*w**9 - & - 109395.0_8/32.0_8 * w**7 + (135135.0_8/64.0_8)*w**5 -15015.0_8/ & - 32.0_8 * w**3 + (3465.0_8/128.0_8)*w) * cos(phi) + rn(12) = -(0.134839972492648_8*sqrt(w2m1)*((230945.0_8/128.0_8)*w**9 - & + 109395.0_8/32.0_8 * w**7 + (135135.0_8/64.0_8)*w**5 -15015.0_8/ & + 32.0_8 * w**3 + (3465.0_8/128.0_8)*w) * cos(phi)) ! l = 10, m = 2 rn(13) = 0.012974982402692_8 * (w2m1)*((2078505.0_8/128.0_8)*w**8 - & 765765.0_8/32.0_8 * w**6 + (675675.0_8/64.0_8)*w**4 -& 45045.0_8/32.0_8 * w**2 + 3465.0_8/128.0_8) * cos(TWO*phi) ! l = 10, m = 3 - rn(14) = 0.00127230170115096_8 * (w2m1)**(THREE/TWO)* & - ((2078505.0_8/16.0_8)*w**7 - 2297295.0_8/16.0_8 * w**5 + & - (675675.0_8/16.0_8)*w**3 - 45045.0_8/16.0_8 * w) * cos(THREE*phi) + rn(14) = -(0.00127230170115096_8 * (w2m1)**(THREE/TWO)* & + ((2078505.0_8/16.0_8)*w**7 - 2297295.0_8/16.0_8 * w**5 + & + (675675.0_8/16.0_8)*w**3 - 45045.0_8/16.0_8 * w) * cos(THREE*phi)) ! l = 10, m = 4 rn(15) = 0.000128521880085575_8 * (w2m1)**2*((14549535.0_8/16.0_8)*w**6 -& 11486475.0_8/16.0_8 * w**4 + (2027025.0_8/16.0_8)*w**2 - & 45045.0_8/16.0_8) * cos(4.0_8*phi) ! l = 10, m = 5 - rn(16) = 1.35473956745817d-5*(w2m1)**(5.0_8/TWO)* & - ((43648605.0_8/8.0_8)*w**5 - 11486475.0_8/4.0_8 * w**3 + & - (2027025.0_8/8.0_8)*w) * cos(5.0_8*phi) + rn(16) = -(1.35473956745817d-5*(w2m1)**(5.0_8/TWO)* & + ((43648605.0_8/8.0_8)*w**5 - 11486475.0_8/4.0_8 * w**3 + & + (2027025.0_8/8.0_8)*w) * cos(5.0_8*phi)) ! l = 10, m = 6 rn(17) = 1.51464488232257d-6*(w2m1)**3*((218243025.0_8/8.0_8)*w**4 - & 34459425.0_8/4.0_8 * w**2 + 2027025.0_8/8.0_8) * cos(6.0_8*phi) ! l = 10, m = 7 - rn(18) = 1.83677671621093d-7*(w2m1)**(7.0_8/TWO)* & - ((218243025.0_8/TWO)*w**3 - 34459425.0_8/TWO*w) * cos(7.0_8*phi) + rn(18) = -(1.83677671621093d-7*(w2m1)**(7.0_8/TWO)* & + ((218243025.0_8/TWO)*w**3 - 34459425.0_8/TWO*w) * cos(7.0_8*phi)) ! l = 10, m = 8 rn(19) = 2.49953651452314d-8*(w2m1)**4* & ((654729075.0_8/TWO)*w**2 - 34459425.0_8/TWO) * cos(8.0_8*phi) ! l = 10, m = 9 - rn(20) = 2.65478475211798_8 * w*(w2m1)**(9.0_8/TWO) * cos(9.0_8*phi) + rn(20) = -(2.65478475211798_8 * w*(w2m1)**(9.0_8/TWO) * cos(9.0_8*phi)) ! l = 10, m = 10 rn(21) = 0.593627917136573_8 * (w2m1)**5 * cos(10.0_8*phi) case default diff --git a/src/mesh.F90 b/src/mesh.F90 index b9d85f4397..905772eb05 100644 --- a/src/mesh.F90 +++ b/src/mesh.F90 @@ -18,9 +18,8 @@ contains ! GET_MESH_BIN determines the tally bin for a particle in a structured mesh !=============================================================================== - subroutine get_mesh_bin(m, xyz, bin) - - type(StructuredMesh), pointer :: m ! mesh pointer + pure subroutine get_mesh_bin(m, xyz, bin) + type(RegularMesh), intent(in) :: m ! mesh pointer real(8), intent(in) :: xyz(:) ! coordinates integer, intent(out) :: bin ! tally bin @@ -71,9 +70,8 @@ contains ! GET_MESH_INDICES determines the indices of a particle in a structured mesh !=============================================================================== - subroutine get_mesh_indices(m, xyz, ijk, in_mesh) - - type(StructuredMesh), pointer :: m + pure subroutine get_mesh_indices(m, xyz, ijk, in_mesh) + type(RegularMesh), intent(in) :: m real(8), intent(in) :: xyz(:) ! coordinates to check integer, intent(out) :: ijk(:) ! indices in mesh logical, intent(out) :: in_mesh ! were given coords in mesh? @@ -96,11 +94,10 @@ contains ! use in a TallyObject results array !=============================================================================== - function mesh_indices_to_bin(m, ijk, surface_current) result(bin) - - type(StructuredMesh), pointer :: m + pure function mesh_indices_to_bin(m, ijk, surface_current) result(bin) + type(RegularMesh), intent(in) :: m integer, intent(in) :: ijk(:) - logical, optional :: surface_current + logical, intent(in), optional :: surface_current integer :: bin integer :: n_y ! number of mesh cells in y direction @@ -130,9 +127,8 @@ contains ! (i,j) or (i,j,k) indices !=============================================================================== - subroutine bin_to_mesh_indices(m, bin, ijk) - - type(StructuredMesh), pointer :: m + pure subroutine bin_to_mesh_indices(m, bin, ijk) + type(RegularMesh), intent(in) :: m integer, intent(in) :: bin integer, intent(out) :: ijk(:) @@ -163,13 +159,13 @@ contains subroutine count_bank_sites(m, bank_array, cnt, energies, size_bank, & sites_outside) - type(StructuredMesh), pointer :: m ! mesh to count sites + type(RegularMesh), pointer :: m ! mesh to count sites type(Bank), intent(in) :: bank_array(:) ! fission or source bank real(8), intent(out) :: cnt(:,:,:,:) ! weight of sites in each ! cell and energy group - real(8), optional :: energies(:) ! energy grid to search - integer(8), optional :: size_bank ! # of bank sites (on each proc) - logical, optional :: sites_outside ! were there sites outside mesh? + real(8), intent(in), optional :: energies(:) ! energy grid to search + integer(8), intent(in), optional :: size_bank ! # of bank sites (on each proc) + logical, intent(inout), optional :: sites_outside ! were there sites outside mesh? integer :: i ! loop index for local fission sites integer :: n_sites ! size of bank array @@ -262,9 +258,8 @@ contains ! track will score to a mesh tally. !=============================================================================== - function mesh_intersects_2d(m, xyz0, xyz1) result(intersects) - - type(StructuredMesh), pointer :: m + pure function mesh_intersects_2d(m, xyz0, xyz1) result(intersects) + type(RegularMesh), intent(in) :: m real(8), intent(in) :: xyz0(2) real(8), intent(in) :: xyz1(2) logical :: intersects @@ -328,9 +323,8 @@ contains end function mesh_intersects_2d - function mesh_intersects_3d(m, xyz0, xyz1) result(intersects) - - type(StructuredMesh), pointer :: m + pure function mesh_intersects_3d(m, xyz0, xyz1) result(intersects) + type(RegularMesh), intent(in) :: m real(8), intent(in) :: xyz0(3) real(8), intent(in) :: xyz1(3) logical :: intersects diff --git a/src/mesh_header.F90 b/src/mesh_header.F90 index 9aa57df90f..9da06f813e 100644 --- a/src/mesh_header.F90 +++ b/src/mesh_header.F90 @@ -7,7 +7,7 @@ module mesh_header ! congruent squares or cubes !=============================================================================== - type StructuredMesh + type RegularMesh integer :: id ! user-specified id integer :: type ! rectangular, hexagonal integer :: n_dimension ! rank of mesh @@ -16,6 +16,6 @@ module mesh_header real(8), allocatable :: lower_left(:) ! lower-left corner of mesh real(8), allocatable :: upper_right(:) ! upper-right corner of mesh real(8), allocatable :: width(:) ! width of each mesh cell - end type StructuredMesh + end type RegularMesh end module mesh_header diff --git a/src/mpiio_interface.F90 b/src/mpiio_interface.F90 deleted file mode 100644 index b9652c8ae4..0000000000 --- a/src/mpiio_interface.F90 +++ /dev/null @@ -1,610 +0,0 @@ -module mpiio_interface - -#ifdef MPI -#ifndef HDF5 - use message_passing - - implicit none - -#ifdef MPIF08 -#define FH_TYPE type(MPI_File) -#else -#define FH_TYPE integer -#endif - - integer :: mpiio_err ! MPI error code - - ! Generic HDF5 write procedure interface - interface mpi_write_data - module procedure mpi_write_double - module procedure mpi_write_double_1Darray - module procedure mpi_write_double_2Darray - module procedure mpi_write_double_3Darray - module procedure mpi_write_double_4Darray - module procedure mpi_write_integer - module procedure mpi_write_integer_1Darray - module procedure mpi_write_integer_2Darray - module procedure mpi_write_integer_3Darray - module procedure mpi_write_integer_4Darray - module procedure mpi_write_long - module procedure mpi_write_string - end interface mpi_write_data - - ! Generic HDF5 read procedure interface - interface mpi_read_data - module procedure mpi_read_double - module procedure mpi_read_double_1Darray - module procedure mpi_read_double_2Darray - module procedure mpi_read_double_3Darray - module procedure mpi_read_double_4Darray - module procedure mpi_read_integer - module procedure mpi_read_integer_1Darray - module procedure mpi_read_integer_2Darray - module procedure mpi_read_integer_3Darray - module procedure mpi_read_integer_4Darray - module procedure mpi_read_long - module procedure mpi_read_string - end interface mpi_read_data - -contains - -!=============================================================================== -! MPI_CREATE_FILE creates a file using MPI file I/O -!=============================================================================== - - subroutine mpi_create_file(filename, fh) - - character(*), intent(in) :: filename ! name of file to create - FH_TYPE, intent(inout) :: fh ! file handle - - ! Create the file - call MPI_FILE_OPEN(MPI_COMM_WORLD, filename, MPI_MODE_CREATE + & - MPI_MODE_WRONLY, MPI_INFO_NULL, fh, mpiio_err) - - end subroutine mpi_create_file - -!=============================================================================== -! MPI_OPEN_FILE opens a file using MPI file I/O -!=============================================================================== - - subroutine mpi_open_file(filename, fh, mode) - - character(*), intent(in) :: filename ! name of file to open - character(*), intent(in) :: mode ! open 'r' read, 'w' write - FH_TYPE, intent(inout) :: fh ! file handle - - integer :: open_mode - - ! Determine access mode - open_mode = MPI_MODE_RDONLY - if (mode == 'w') then - open_mode = ior(MPI_MODE_APPEND, MPI_MODE_WRONLY) - end if - - ! Create the file - call MPI_FILE_OPEN(MPI_COMM_WORLD, filename, & - open_mode, MPI_INFO_NULL, fh, mpiio_err) - - end subroutine mpi_open_file - -!=============================================================================== -! MPI_CLOSE_FILE closes a file using MPI file I/O -!=============================================================================== - - subroutine mpi_close_file(fh) - - FH_TYPE, intent(inout) :: fh ! file handle - - call MPI_FILE_CLOSE(fh, mpiio_err) - - end subroutine mpi_close_file - -!=============================================================================== -! MPI_WRITE_INTEGER writes integer scalar data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, 1, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, 1, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer - -!=============================================================================== -! MPI_READ_INTEGER reads integer scalar data using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, 1, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, 1, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer - -!=============================================================================== -! MPI_WRITE_INTEGER_1DARRAY writes integer 1-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer_1Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of array - integer, intent(in) :: buffer(:) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, length, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, length, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer_1Darray - -!=============================================================================== -! MPI_READ_INTEGER_1DARRAY reads integer 1-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer_1Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of array - integer, intent(inout) :: buffer(:) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, length, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, length, MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer_1Darray - -!=============================================================================== -! MPI_WRITE_INTEGER_2DARRAY writes integer 2-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer_2Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(2) ! length of array - integer, intent(in) :: buffer(length(1),length(2)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer_2Darray - -!=============================================================================== -! MPI_READ_INTEGER_2DARRAY reads integer 2-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer_2Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(2) ! length of array - integer, intent(inout) :: buffer(length(1),length(2)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer_2Darray - -!=============================================================================== -! MPI_WRITE_INTEGER_3DARRAY writes integer 3-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer_3Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(3) ! length of array - integer, intent(in) :: buffer(length(1),length(2),& - length(3)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer_3Darray - -!=============================================================================== -! MPI_READ_INTEGER_3DARRAY reads integer 3-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer_3Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(3) ! length of array - integer, intent(inout) :: buffer(length(1),length(2), & - length(3)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer_3Darray - -!=============================================================================== -! MPI_WRITE_INTEGER_4DARRAY writes integer 4-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_integer_4Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(4) ! length of array - integer, intent(in) :: buffer(length(1),length(2),& - length(3),length(4)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_integer_4Darray - -!=============================================================================== -! MPI_READ_INTEGER_4DARRAY reads integer 4-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_integer_4Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(4) ! length of array - integer, intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_INTEGER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_integer_4Darray - -!=============================================================================== -! MPI_WRITE_DOUBLE writes integer scalar data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - real(8), intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, 1, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, 1, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double - -!=============================================================================== -! MPI_READ_DOUBLE reads integer scalar data using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - real(8), intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, 1, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, 1, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double - -!=============================================================================== -! MPI_WRITE_DOUBLE_1DARRAY writes integer 1-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double_1Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of array - real(8), intent(in) :: buffer(:) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, length, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, length, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double_1Darray - -!=============================================================================== -! MPI_READ_DOUBLE_1DARRAY reads integer 1-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double_1Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of array - real(8), intent(inout) :: buffer(:) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, length, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, length, MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double_1Darray - -!=============================================================================== -! MPI_WRITE_DOUBLE_2DARRAY writes integer 2-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double_2Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(2) ! length of array - real(8), intent(in) :: buffer(length(1),length(2)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double_2Darray - -!=============================================================================== -! MPI_READ_DOUBLE_2DARRAY reads integer 2-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double_2Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(2) ! length of array - real(8), intent(inout) :: buffer(length(1),length(2)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double_2Darray - -!=============================================================================== -! MPI_WRITE_DOUBLE_3DARRAY writes integer 3-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double_3Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(3) ! length of array - real(8), intent(in) :: buffer(length(1),length(2),& - length(3)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double_3Darray - -!=============================================================================== -! MPI_READ_DOUBLE_3DARRAY reads integer 3-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double_3Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(3) ! length of array - real(8), intent(inout) :: buffer(length(1),length(2), & - length(3)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double_3Darray - -!=============================================================================== -! MPI_WRITE_DOUBLE_4DARRAY writes integer 4-D array data using MPI File I/O -!=============================================================================== - - subroutine mpi_write_double_4Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(4) ! length of array - real(8), intent(in) :: buffer(length(1),length(2),& - length(3),length(4)) ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_double_4Darray - -!=============================================================================== -! MPI_READ_DOUBLE_4DARRAY reads integer 4-D array using MPI file I/O -!=============================================================================== - - subroutine mpi_read_double_4Darray(fh, buffer, length, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length(4) ! length of array - real(8), intent(inout) :: buffer(length(1),length(2), & - length(3),length(4)) ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, product(length), MPI_REAL8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_double_4Darray - -!=============================================================================== -! MPI_WRITE_LONG writes long integer scalar data using MPI file I/O -!=============================================================================== - - subroutine mpi_write_long(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer(8), intent(in) :: buffer ! data to write - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, 1, MPI_INTEGER8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, 1, MPI_INTEGER8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_long - -!=============================================================================== -! MPI_READ_LONG reads long integer scalar data using MPI file I/O -!=============================================================================== - - subroutine mpi_read_long(fh, buffer, collect) - - FH_TYPE, intent(in) :: fh ! file handle - integer(8), intent(inout) :: buffer ! read data to here - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, 1, MPI_INTEGER8, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, 1, MPI_INTEGER8, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_long - -!=============================================================================== -! MPI_WRITE_STRING writes string data using MPI file I/O -!=============================================================================== - - subroutine mpi_write_string(fh, buffer, length, collect) - - character(*), intent(in) :: buffer ! data to write - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of data - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_WRITE_ALL(fh, buffer, length, MPI_CHARACTER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_WRITE(fh, buffer, length, MPI_CHARACTER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_write_string - -!=============================================================================== -! MPI_READ_STRING reads string data using MPI file I/O -!=============================================================================== - - subroutine mpi_read_string(fh, buffer, length, collect) - - character(*), intent(inout) :: buffer ! read data to here - FH_TYPE, intent(in) :: fh ! file handle - integer, intent(in) :: length ! length of string - logical, intent(in) :: collect ! collective I/O - - if (collect) then - call MPI_FILE_READ_ALL(fh, buffer, length, MPI_CHARACTER, & - MPI_STATUS_IGNORE, mpiio_err) - else - call MPI_FILE_READ(fh, buffer, length, MPI_CHARACTER, & - MPI_STATUS_IGNORE, mpiio_err) - end if - - end subroutine mpi_read_string - -#endif -#endif -end module mpiio_interface diff --git a/src/output.F90 b/src/output.F90 index 939451c6fb..c31b20b70b 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -6,11 +6,11 @@ module output use constants use endf, only: reaction_name use error, only: fatal_error, warning - use geometry_header, only: Cell, Universe, Surface, Lattice, RectLattice, & + use geometry_header, only: Cell, Universe, Lattice, RectLattice, & HexLattice, BASE_UNIVERSE use global use math, only: t_percentile - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use mesh, only: mesh_indices_to_bin, bin_to_mesh_indices use particle_header, only: LocalCoord, Particle use plot_header @@ -100,10 +100,9 @@ contains !=============================================================================== subroutine header(msg, unit, level) - character(*), intent(in) :: msg ! header message - integer, optional :: unit ! unit to write to - integer, optional :: level ! specified header level + integer, intent(in), optional :: unit ! unit to write to + integer, intent(in), optional :: level ! specified header level integer :: n ! number of = signs on left integer :: m ! number of = signs on right @@ -195,9 +194,8 @@ contains !=============================================================================== subroutine write_message(message, level) - - character(*) :: message - integer, optional :: level ! verbosity level + character(*), intent(in) :: message ! message to write + integer, intent(in), optional :: level ! verbosity level integer :: i_start ! starting position integer :: i_end ! ending position @@ -250,14 +248,12 @@ contains !=============================================================================== subroutine print_particle(p) - type(Particle), intent(in) :: p integer :: i ! index for coordinate levels - type(Cell), pointer :: c => null() - type(Surface), pointer :: s => null() - type(Universe), pointer :: u => null() - class(Lattice), pointer :: l => null() + type(Cell), pointer :: c + type(Universe), pointer :: u + class(Lattice), pointer :: l ! display type of particle select case (p % type) @@ -304,714 +300,25 @@ contains ! Print surface if (p % surface /= NONE) then - s => surfaces(abs(p % surface)) - write(ou,*) ' Surface = ' // to_str(sign(s % id, p % surface)) + write(ou,*) ' Surface = ' // to_str(sign(surfaces(i)%obj%id, p % surface)) end if ! Display weight, energy, grid index, and interpolation factor write(ou,*) ' Weight = ' // to_str(p % wgt) write(ou,*) ' Energy = ' // to_str(p % E) + write(ou,*) ' Delayed Group = ' // to_str(p % delayed_group) write(ou,*) end subroutine print_particle -!=============================================================================== -! PRINT_REACTION displays the attributes of a reaction -!=============================================================================== - - subroutine print_reaction(rxn) - - type(Reaction), pointer :: rxn - - write(ou,*) 'Reaction ' // reaction_name(rxn % MT) - write(ou,*) ' MT = ' // to_str(rxn % MT) - write(ou,*) ' Q-value = ' // to_str(rxn % Q_value) - write(ou,*) ' Multiplicity = ' // to_str(rxn % multiplicity) - write(ou,*) ' Threshold = ' // to_str(rxn % threshold) - if (rxn % has_energy_dist) then - write(ou,*) ' Energy: Law ' // to_str(rxn % edist % law) - end if - write(ou,*) - - end subroutine print_reaction - -!=============================================================================== -! PRINT_CELL displays the attributes of a cell -!=============================================================================== - - subroutine print_cell(c, unit) - - type(Cell), pointer :: c - integer, optional :: unit ! specified unit to write to - - integer :: index_cell ! index in cells array - integer :: i ! loop index for surfaces - integer :: index_surf ! index in surfaces array - integer :: unit_ ! unit to write to - character(MAX_LINE_LEN) :: string - type(Universe), pointer :: u => null() - class(Lattice), pointer :: l => null() - type(Material), pointer :: m => null() - - ! Set unit to stdout if not already set - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write user-specified id for cell - write(unit_,*) 'Cell ' // to_str(c % id) - - ! Write user-specified name for cell - write(unit_,*) ' Name = ' // c % name - - ! Find index in cells array and write - index_cell = cell_dict % get_key(c % id) - write(unit_,*) ' Array Index = ' // to_str(index_cell) - - ! Write what universe this cell is in - u => universes(c % universe) - write(unit_,*) ' Universe = ' // to_str(u % id) - - ! Write information on fill for cell - select case (c % type) - case (CELL_NORMAL) - write(unit_,*) ' Fill = NONE' - case (CELL_FILL) - u => universes(c % fill) - write(unit_,*) ' Fill = Universe ' // to_str(u % id) - case (CELL_LATTICE) - l => lattices(c % fill) % obj - write(unit_,*) ' Fill = Lattice ' // to_str(l % id) - end select - - ! Write information on material - if (c % material == 0) then - write(unit_,*) ' Material = NONE' - elseif (c % material == MATERIAL_VOID) then - write(unit_,*) ' Material = Void' - else - m => materials(c % material) - write(unit_,*) ' Material = ' // to_str(m % id) - end if - - ! Write surface specification - string = "" - do i = 1, c % n_surfaces - select case (c % surfaces(i)) - case (OP_LEFT_PAREN) - string = trim(string) // ' (' - case (OP_RIGHT_PAREN) - string = trim(string) // ' )' - case (OP_UNION) - string = trim(string) // ' :' - case (OP_DIFFERENCE) - string = trim(string) // ' !' - case default - index_surf = abs(c % surfaces(i)) - string = trim(string) // ' ' // to_str(sign(& - surfaces(index_surf) % id, c % surfaces(i))) - end select - end do - write(unit_,*) ' Surface Specification:' // trim(string) - write(unit_,*) - - end subroutine print_cell - -!=============================================================================== -! PRINT_UNIVERSE displays the attributes of a universe -!=============================================================================== - - subroutine print_universe(univ, unit) - - type(Universe), pointer :: univ - integer, optional :: unit - - integer :: i ! loop index for cells in this universe - integer :: unit_ ! unit to write to - character(MAX_LINE_LEN) :: string - type(Cell), pointer :: c => null() - type(Universe), pointer :: base_u => null() - - ! Set default unit to stdout if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Get a pointer to the base universe - base_u => universes(BASE_UNIVERSE) - - ! Write user-specified id for this universe - write(unit_,*) 'Universe ' // to_str(univ % id) - - ! If this is the base universe, indicate so - if (associated(univ, base_u)) then - write(unit_,*) ' Base Universe' - end if - - ! Write list of cells in this universe - string = "" - do i = 1, univ % n_cells - c => cells(univ % cells(i)) - string = trim(string) // ' ' // to_str(c % id) - end do - write(unit_,*) ' Cells =' // trim(string) - write(unit_,*) - - end subroutine print_universe - -!=============================================================================== -! PRINT_LATTICE displays the attributes of a lattice -!=============================================================================== - - subroutine print_lattice(lat, unit) - - class(Lattice), pointer :: lat - integer, optional :: unit - - integer :: unit_ ! unit to write to - - ! set default unit if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write information about lattice - write(unit_,*) 'Lattice ' // to_str(lat % id) - - ! Write user-specified name for lattice - write(unit_,*) ' Name = ' // lat % name - - select type(lat) - type is (RectLattice) - ! Write dimension of lattice. - if (lat % is_3d) then - write(unit_, *) ' Dimension = ' // to_str(lat % n_cells(1)) & - &// ' ' // to_str(lat % n_cells(2)) // ' ' & - &// to_str(lat % n_cells(3)) - else - write(unit_, *) ' Dimension = ' // to_str(lat % n_cells(1)) & - &// ' ' // to_str(lat % n_cells(2)) - end if - - ! Write lower-left coordinates of lattice. - if (lat % is_3d) then - write(unit_, *) ' Lower-left = ' // to_str(lat % lower_left(1)) & - &// ' ' // to_str(lat % lower_left(2)) // ' ' & - &// to_str(lat % lower_left(3)) - else - write(unit_, *) ' Lower-left = ' // to_str(lat % lower_left(1)) & - &// ' ' // to_str(lat % lower_left(2)) - end if - - ! Write lattice pitch along each axis. - if (lat % is_3d) then - write(unit_, *) ' Pitch = ' // to_str(lat % pitch(1)) & - &// ' ' // to_str(lat % pitch(2)) // ' ' & - &// to_str(lat % pitch(3)) - else - write(unit_, *) ' Pitch = ' // to_str(lat % pitch(1)) & - &// ' ' // to_str(lat % pitch(2)) - end if - write(unit_,*) - - type is (HexLattice) - ! Write dimension of lattice. - write(unit_,*) ' N-rings = ' // to_str(lat % n_rings) - if (lat % is_3d) write(unit_,*) ' N-axial = ' // to_str(lat % n_axial) - - ! Write center coordinates of lattice. - if (lat % is_3d) then - write(unit_, *) ' Center = ' // to_str(lat % center(1)) & - &// ' ' // to_str(lat % center(2)) // ' ' & - &// to_str(lat % center(3)) - else - write(unit_, *) ' Center = ' // to_str(lat % center(1)) & - &// ' ' // to_str(lat % center(2)) - end if - - ! Write lattice pitch along each axis. - if (lat % is_3d) then - write(unit_, *) ' Pitch = ' // to_str(lat % pitch(1)) & - &// ' ' // to_str(lat % pitch(2)) - else - write(unit_, *) ' Pitch = ' // to_str(lat % pitch(1)) - end if - write(unit_,*) - end select - - - end subroutine print_lattice - -!=============================================================================== -! PRINT_SURFACE displays the attributes of a surface -!=============================================================================== - - subroutine print_surface(surf, unit) - - type(Surface), pointer :: surf - integer, optional :: unit ! specified unit to write to - - integer :: i ! loop index for coefficients - integer :: unit_ ! unit to write to - character(MAX_LINE_LEN) :: string - type(Cell), pointer :: c => null() - - ! set default unit if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write user-specified id of surface - write(unit_,*) 'Surface ' // to_str(surf % id) - - ! Write user-specified name for surface - write(unit_,*) ' Name = ' // surf % name - - ! Write type of surface - select case (surf % type) - case (SURF_PX) - string = "X Plane" - case (SURF_PY) - string = "Y Plane" - case (SURF_PZ) - string = "Z Plane" - case (SURF_PLANE) - string = "Plane" - case (SURF_CYL_X) - string = "X Cylinder" - case (SURF_CYL_Y) - string = "Y Cylinder" - case (SURF_CYL_Z) - string = "Z Cylinder" - case (SURF_SPHERE) - string = "Sphere" - case (SURF_CONE_X) - string = "X Cone" - case (SURF_CONE_Y) - string = "Y Cone" - case (SURF_CONE_Z) - string = "Z Cone" - end select - write(unit_,*) ' Type = ' // trim(string) - - ! Write coefficients for this surface - string = "" - do i = 1, size(surf % coeffs) - string = trim(string) // ' ' // to_str(surf % coeffs(i), 4) - end do - write(unit_,*) ' Coefficients = ' // trim(string) - - ! Write neighboring cells on positive side of this surface - string = "" - if (allocated(surf % neighbor_pos)) then - do i = 1, size(surf % neighbor_pos) - c => cells(abs(surf % neighbor_pos(i))) - string = trim(string) // ' ' // to_str(& - sign(c % id, surf % neighbor_pos(i))) - end do - end if - write(unit_,*) ' Positive Neighbors = ' // trim(string) - - ! Write neighboring cells on negative side of this surface - string = "" - if (allocated(surf % neighbor_neg)) then - do i = 1, size(surf % neighbor_neg) - c => cells(abs(surf % neighbor_neg(i))) - string = trim(string) // ' ' // to_str(& - sign(c % id, surf % neighbor_neg(i))) - end do - end if - write(unit_,*) ' Negative Neighbors =' // trim(string) - - ! Write boundary condition for this surface - select case (surf % bc) - case (BC_TRANSMIT) - write(unit_,*) ' Boundary Condition = Transmission' - case (BC_VACUUM) - write(unit_,*) ' Boundary Condition = Vacuum' - case (BC_REFLECT) - write(unit_,*) ' Boundary Condition = Reflective' - case (BC_PERIODIC) - write(unit_,*) ' Boundary Condition = Periodic' - end select - write(unit_,*) - - end subroutine print_surface - -!=============================================================================== -! PRINT_MATERIAL displays the attributes of a material -!=============================================================================== - - subroutine print_material(mat, unit) - - type(Material), pointer :: mat - integer, optional :: unit - - integer :: i ! loop index for nuclides - integer :: unit_ ! unit to write to - real(8) :: density ! density in atom/b-cm - character(MAX_LINE_LEN) :: string - type(Nuclide), pointer :: nuc => null() - - ! set default unit to stdout if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write identifier for material - write(unit_,*) 'Material ' // to_str(mat % id) - - ! Write user-specified name for material - write(unit_,*) ' Name = ' // mat % name - - ! Write total atom density in atom/b-cm - write(unit_,*) ' Atom Density = ' // trim(to_str(mat % density)) & - // ' atom/b-cm' - - ! Write atom density for each nuclide in material - write(unit_,*) ' Nuclides:' - do i = 1, mat % n_nuclides - nuc => nuclides(mat % nuclide(i)) - density = mat % atom_density(i) - string = ' ' // trim(nuc % name) // ' = ' // & - trim(to_str(density)) // ' atom/b-cm' - write(unit_,*) trim(string) - end do - - ! Write information on S(a,b) table - if (mat % n_sab > 0) then - write(unit_,*) ' S(a,b) tables:' - do i = 1, mat % n_sab - write(unit_,*) ' ' // trim(& - sab_tables(mat % i_sab_tables(i)) % name) - end do - end if - write(unit_,*) - - end subroutine print_material - -!=============================================================================== -! PRINT_TALLY displays the attributes of a tally -!=============================================================================== - - subroutine print_tally(t, unit) - - type(TallyObject), pointer :: t - integer, optional :: unit - - integer :: i ! index for filter or score bins - integer :: j ! index in filters array - integer :: id ! user-specified id - integer :: unit_ ! unit to write to - integer :: n ! moment order to include in name - character(MAX_LINE_LEN) :: string - character(MAX_WORD_LEN) :: pn_string - type(Cell), pointer :: c => null() - type(Surface), pointer :: s => null() - type(Universe), pointer :: u => null() - type(Material), pointer :: m => null() - type(StructuredMesh), pointer :: sm => null() - - ! set default unit to stdout if not specified - if (present(unit)) then - unit_ = unit - else - unit_ = OUTPUT_UNIT - end if - - ! Write user-specified id of tally - write(unit_,*) 'Tally ' // to_str(t % id) - - ! Write the type of tally - select case(t % type) - case (TALLY_VOLUME) - write(unit_,*) ' Type: Volume' - case (TALLY_SURFACE_CURRENT) - write(unit_,*) ' Type: Surface Current' - end select - - ! Write the estimator used - select case(t % estimator) - case(ESTIMATOR_ANALOG) - write(unit_,*) ' Estimator: Analog' - case(ESTIMATOR_TRACKLENGTH) - write(unit_,*) ' Estimator: Track-length' - end select - - ! Write any cells bins if present - j = t % find_filter(FILTER_DISTRIBCELL) - if (j > 0) then - string = "" - id = t % filters(j) % int_bins(1) - c => cells(id) - string = trim(string) // ' ' // trim(to_str(c % id)) - write(unit_, *) ' Distribcell Bins:' // trim(string) - end if - - ! Write any cells bins if present - j = t % find_filter(FILTER_CELL) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - c => cells(id) - string = trim(string) // ' ' // trim(to_str(c % id)) - end do - write(unit_, *) ' Cell Bins:' // trim(string) - end if - - ! Write any surface bins if present - j = t % find_filter(FILTER_SURFACE) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - s => surfaces(id) - string = trim(string) // ' ' // trim(to_str(s % id)) - end do - write(unit_, *) ' Surface Bins:' // trim(string) - end if - - ! Write any universe bins if present - j = t % find_filter(FILTER_UNIVERSE) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - u => universes(id) - string = trim(string) // ' ' // trim(to_str(u % id)) - end do - write(unit_, *) ' Universe Bins:' // trim(string) - end if - - ! Write any material bins if present - j = t % find_filter(FILTER_MATERIAL) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - m => materials(id) - string = trim(string) // ' ' // trim(to_str(m % id)) - end do - write(unit_, *) ' Material Bins:' // trim(string) - end if - - ! Write any mesh bins if present - j = t % find_filter(FILTER_MESH) - if (j > 0) then - string = "" - id = t % filters(j) % int_bins(1) - sm => meshes(id) - string = trim(string) // ' ' // trim(to_str(sm % dimension(1))) - do i = 2, sm % n_dimension - string = trim(string) // ' x ' // trim(to_str(sm % dimension(i))) - end do - write(unit_, *) ' Mesh Bins:' // trim(string) - end if - - ! Write any birth region bins if present - j = t % find_filter(FILTER_CELLBORN) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins - id = t % filters(j) % int_bins(i) - c => cells(id) - string = trim(string) // ' ' // trim(to_str(c % id)) - end do - write(unit_, *) ' Birth Region Bins:' // trim(string) - end if - - ! Write any incoming energy bins if present - j = t % find_filter(FILTER_ENERGYIN) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins + 1 - string = trim(string) // ' ' // trim(to_str(& - t % filters(j) % real_bins(i))) - end do - write(unit_,*) ' Incoming Energy Bins:' // trim(string) - end if - - ! Write any outgoing energy bins if present - j = t % find_filter(FILTER_ENERGYOUT) - if (j > 0) then - string = "" - do i = 1, t % filters(j) % n_bins + 1 - string = trim(string) // ' ' // trim(to_str(& - t % filters(j) % real_bins(i))) - end do - write(unit_,*) ' Outgoing Energy Bins:' // trim(string) - end if - - ! Write nuclides bins - write(unit_,fmt='(1X,A)',advance='no') ' Nuclide Bins:' - do i = 1, t % n_nuclide_bins - if (t % nuclide_bins(i) == -1) then - write(unit_,fmt='(A)',advance='no') ' total' - else - write(unit_,fmt='(A)',advance='no') ' ' // trim(adjustl(& - nuclides(t % nuclide_bins(i)) % name)) - end if - if (mod(i,4) == 0 .and. i /= t % n_nuclide_bins) & - write(unit_,'(/18X)',advance='no') - end do - write(unit_,*) - - ! Write score bins - string = "" - j = 0 - do i = 1, t % n_user_score_bins - j = j + 1 - select case (t % score_bins(j)) - case (SCORE_FLUX) - string = trim(string) // ' flux' - case (SCORE_FLUX_YN) - pn_string = ' flux' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' flux-y' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_TOTAL) - string = trim(string) // ' total' - case (SCORE_TOTAL_YN) - pn_string = ' total' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' total-y' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_SCATTER) - string = trim(string) // ' scatter' - case (SCORE_NU_SCATTER) - string = trim(string) // ' nu-scatter' - case (SCORE_SCATTER_N) - pn_string = ' scatter-' // trim(to_str(t % moment_order(j))) - string = trim(string) // pn_string - case (SCORE_SCATTER_PN) - pn_string = ' scatter' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' scatter-p' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_NU_SCATTER_N) - pn_string = ' nu-scatter-' // trim(to_str(t % moment_order(j))) - string = trim(string) // pn_string - case (SCORE_NU_SCATTER_PN) - pn_string = ' nu-scatter' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' nu-scatter-p' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_SCATTER_YN) - pn_string = ' scatter' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' scatter-y' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_NU_SCATTER_YN) - pn_string = ' nu-scatter' - string = trim(string) // pn_string - do n = 1, t % moment_order(j) - pn_string = ' nu-scatter-y' // trim(to_str(n)) - string = trim(string) // pn_string - end do - j = j + n - 1 - case (SCORE_TRANSPORT) - string = trim(string) // ' transport' - case (SCORE_N_1N) - string = trim(string) // ' n1n' - case (SCORE_ABSORPTION) - string = trim(string) // ' absorption' - case (SCORE_FISSION) - string = trim(string) // ' fission' - case (SCORE_NU_FISSION) - string = trim(string) // ' nu-fission' - case (SCORE_KAPPA_FISSION) - string = trim(string) // ' kappa-fission' - case (SCORE_CURRENT) - string = trim(string) // ' current' - case default - string = trim(string) // ' ' // reaction_name(t % score_bins(j)) - end select - end do - write(unit_,*) ' Scores:' // trim(string) - write(unit_,*) - - end subroutine print_tally - -!=============================================================================== -! PRINT_GEOMETRY displays the attributes of all cells, surfaces, universes, -! surfaces, and lattices read in the input files. -!=============================================================================== - - subroutine print_geometry() - - integer :: i ! loop index for various arrays - type(Surface), pointer :: s => null() - type(Cell), pointer :: c => null() - type(Universe), pointer :: u => null() - class(Lattice), pointer :: l => null() - - ! print summary of surfaces - call header("SURFACE SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_surfaces - s => surfaces(i) - call print_surface(s, unit=UNIT_SUMMARY) - end do - - ! print summary of cells - call header("CELL SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_cells - c => cells(i) - call print_cell(c, unit=UNIT_SUMMARY) - end do - - ! print summary of universes - call header("UNIVERSE SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_universes - u => universes(i) - call print_universe(u, unit=UNIT_SUMMARY) - end do - - ! print summary of lattices - if (n_lattices > 0) then - call header("LATTICE SUMMARY", unit=UNIT_SUMMARY) - do i = 1, n_lattices - l => lattices(i) % obj - call print_lattice(l, unit=UNIT_SUMMARY) - end do - end if - - end subroutine print_geometry - !=============================================================================== ! PRINT_NUCLIDE displays information about a continuous-energy neutron ! cross_section table and its reactions and secondary angle/energy distributions !=============================================================================== subroutine print_nuclide(nuc, unit) - - type(Nuclide), pointer :: nuc - integer, optional :: unit + type(Nuclide), intent(in) :: nuc + integer, intent(in), optional :: unit integer :: i ! loop index over nuclides integer :: unit_ ! unit to write to @@ -1023,8 +330,7 @@ contains integer :: size_energy ! memory used for a energy distributions (bytes) integer :: size_urr ! memory used for probability tables (bytes) character(11) :: law ! secondary energy distribution law - type(Reaction), pointer :: rxn => null() - type(UrrData), pointer :: urr => null() + type(UrrData), pointer :: urr ! set default unit for writing information if (present(unit)) then @@ -1052,32 +358,32 @@ contains ! Information on each reaction write(unit_,*) ' Reaction Q-value COM Law IE size(angle) size(energy)' do i = 1, nuc % n_reaction - rxn => nuc % reactions(i) + associate (rxn => nuc % reactions(i)) + ! 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 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 and law + if (rxn % has_energy_dist) then + size_energy = size(rxn % edist % data) * 8 + law = to_str(rxn % edist % law) + else + size_energy = 0 + law = 'None' + end if - ! Determine size of energy distribution and law - if (rxn % has_energy_dist) then - size_energy = size(rxn % edist % data) * 8 - law = to_str(rxn % edist % law) - else - size_energy = 0 - law = 'None' - end if + write(unit_,'(3X,A11,1X,F8.3,3X,L1,3X,A4,1X,I6,1X,I11,1X,I11)') & + reaction_name(rxn % MT), rxn % Q_value, rxn % scatter_in_cm, & + law(1:4), rxn % threshold, size_angle, size_energy - write(unit_,'(3X,A11,1X,F8.3,3X,L1,3X,A4,1X,I6,1X,I11,1X,I11)') & - reaction_name(rxn % MT), rxn % Q_value, rxn % scatter_in_cm, & - law(1:4), rxn % threshold, size_angle, size_energy - - ! Accumulate data size - size_xs = size_xs + (nuc % n_grid - rxn%threshold + 1) * 8 - size_angle_total = size_angle_total + size_angle - size_energy_total = size_energy_total + size_energy + ! Accumulate data size + size_xs = size_xs + (nuc % n_grid - rxn%threshold + 1) * 8 + size_angle_total = size_angle_total + size_angle + size_energy_total = size_energy_total + size_energy + end associate end do ! Add memory required for summary reactions (total, absorption, fission, @@ -1127,9 +433,8 @@ contains !=============================================================================== subroutine print_sab_table(sab, unit) - - type(SAlphaBeta), pointer :: sab - integer, optional :: unit + type(SAlphaBeta), intent(in) :: sab + integer, intent(in), optional :: unit integer :: size_sab ! memory used by S(a,b) table integer :: unit_ ! unit to write to @@ -1203,98 +508,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 @@ -1304,26 +517,27 @@ contains subroutine write_xs_summary() - integer :: i ! loop index + integer :: i ! loop index + integer :: unit_xs ! cross_sections.out file unit character(MAX_FILE_LEN) :: path ! path of summary file - type(Nuclide), pointer :: nuc => null() - type(SAlphaBeta), pointer :: sab => null() + type(Nuclide), pointer :: nuc + type(SAlphaBeta), pointer :: sab ! Create filename for log file path = trim(path_output) // "cross_sections.out" ! Open log file for writing - open(UNIT=UNIT_XS, FILE=path, STATUS='replace', ACTION='write') + open(NEWUNIT=unit_xs, FILE=path, STATUS='replace', ACTION='write') ! Write header - call header("CROSS SECTION TABLES", unit=UNIT_XS) + call header("CROSS SECTION TABLES", unit=unit_xs) NUCLIDE_LOOP: do i = 1, n_nuclides_total ! Get pointer to nuclide nuc => nuclides(i) ! Print information about nuclide - call print_nuclide(nuc, unit=UNIT_XS) + call print_nuclide(nuc, unit=unit_xs) end do NUCLIDE_LOOP SAB_TABLES_LOOP: do i = 1, n_sab_tables @@ -1331,11 +545,11 @@ contains sab => sab_tables(i) ! Print information about S(a,b) table - call print_sab_table(sab, unit=UNIT_XS) + call print_sab_table(sab, unit=unit_xs) end do SAB_TABLES_LOOP ! Close cross section summary file - close(UNIT_XS) + close(unit_xs) end subroutine write_xs_summary @@ -1461,7 +675,7 @@ contains subroutine print_plot() integer :: i ! loop index for plots - type(ObjectPlot), pointer :: pl => null() + type(ObjectPlot), pointer :: pl ! Display header for plotting call header("PLOTTING SUMMARY") @@ -1547,11 +761,15 @@ contains write(ou,100) "Total time in simulation", time_inactive % elapsed + & time_active % elapsed write(ou,100) " Time in transport only", time_transport % elapsed - write(ou,100) " Time in inactive batches", time_inactive % elapsed + if (run_mode == MODE_EIGENVALUE) then + write(ou,100) " Time in inactive batches", time_inactive % elapsed + end if write(ou,100) " Time in active batches", time_active % elapsed - write(ou,100) " Time synchronizing fission bank", time_bank % elapsed - write(ou,100) " Sampling source sites", time_bank_sample % elapsed - write(ou,100) " SEND/RECV source sites", time_bank_sendrecv % elapsed + if (run_mode == MODE_EIGENVALUE) then + write(ou,100) " Time synchronizing fission bank", time_bank % elapsed + write(ou,100) " Sampling source sites", time_bank_sample % elapsed + write(ou,100) " SEND/RECV source sites", time_bank_sendrecv % elapsed + end if write(ou,100) " Time accumulating tallies", time_tallies % elapsed if (cmfd_run) write(ou,100) " Time in CMFD", time_cmfd % elapsed if (cmfd_run) write(ou,100) " Building matrices", & @@ -1712,6 +930,7 @@ contains integer :: i_listing ! index in xs_listings array integer :: n_order ! loop index for moment orders integer :: nm_order ! loop index for Ynm moment orders + integer :: unit_tally ! tallies.out file unit real(8) :: t_value ! t-values for confidence intervals real(8) :: alpha ! significance level for CI character(MAX_FILE_LEN) :: filename ! name of output file @@ -1725,42 +944,48 @@ contains if (n_tallies == 0) return ! Initialize names for tally filter types - filter_name(FILTER_UNIVERSE) = "Universe" - filter_name(FILTER_MATERIAL) = "Material" - filter_name(FILTER_DISTRIBCELL) = "Distributed Cell" - filter_name(FILTER_CELL) = "Cell" - filter_name(FILTER_CELLBORN) = "Birth Cell" - filter_name(FILTER_SURFACE) = "Surface" - filter_name(FILTER_MESH) = "Mesh" - filter_name(FILTER_ENERGYIN) = "Incoming Energy" - filter_name(FILTER_ENERGYOUT) = "Outgoing Energy" + filter_name(FILTER_UNIVERSE) = "Universe" + filter_name(FILTER_MATERIAL) = "Material" + filter_name(FILTER_DISTRIBCELL) = "Distributed Cell" + filter_name(FILTER_CELL) = "Cell" + filter_name(FILTER_CELLBORN) = "Birth Cell" + filter_name(FILTER_SURFACE) = "Surface" + filter_name(FILTER_MESH) = "Mesh" + filter_name(FILTER_ENERGYIN) = "Incoming Energy" + filter_name(FILTER_ENERGYOUT) = "Outgoing Energy" + filter_name(FILTER_MU) = "Change-in-Angle" + filter_name(FILTER_POLAR) = "Polar Angle" + filter_name(FILTER_AZIMUTHAL) = "Azimuthal Angle" + filter_name(FILTER_DELAYEDGROUP) = "Delayed Group" ! Initialize names for scores - score_names(abs(SCORE_FLUX)) = "Flux" - score_names(abs(SCORE_TOTAL)) = "Total Reaction Rate" - score_names(abs(SCORE_SCATTER)) = "Scattering Rate" - score_names(abs(SCORE_NU_SCATTER)) = "Scattering Production Rate" - score_names(abs(SCORE_TRANSPORT)) = "Transport Rate" - score_names(abs(SCORE_N_1N)) = "(n,1n) Rate" - score_names(abs(SCORE_ABSORPTION)) = "Absorption Rate" - score_names(abs(SCORE_FISSION)) = "Fission Rate" - score_names(abs(SCORE_NU_FISSION)) = "Nu-Fission Rate" - score_names(abs(SCORE_KAPPA_FISSION)) = "Kappa-Fission Rate" - score_names(abs(SCORE_EVENTS)) = "Events" - score_names(abs(SCORE_FLUX_YN)) = "Flux Moment" - score_names(abs(SCORE_TOTAL_YN)) = "Total Reaction Rate Moment" - score_names(abs(SCORE_SCATTER_N)) = "Scattering Rate Moment" - score_names(abs(SCORE_SCATTER_PN)) = "Scattering Rate Moment" - score_names(abs(SCORE_SCATTER_YN)) = "Scattering Rate Moment" - score_names(abs(SCORE_NU_SCATTER_N)) = "Scattering Prod. Rate Moment" - score_names(abs(SCORE_NU_SCATTER_PN)) = "Scattering Prod. Rate Moment" - score_names(abs(SCORE_NU_SCATTER_YN)) = "Scattering Prod. Rate Moment" + score_names(abs(SCORE_FLUX)) = "Flux" + score_names(abs(SCORE_TOTAL)) = "Total Reaction Rate" + score_names(abs(SCORE_SCATTER)) = "Scattering Rate" + score_names(abs(SCORE_NU_SCATTER)) = "Scattering Production Rate" + score_names(abs(SCORE_TRANSPORT)) = "Transport Rate" + score_names(abs(SCORE_N_1N)) = "(n,1n) Rate" + score_names(abs(SCORE_ABSORPTION)) = "Absorption Rate" + score_names(abs(SCORE_FISSION)) = "Fission Rate" + score_names(abs(SCORE_NU_FISSION)) = "Nu-Fission Rate" + score_names(abs(SCORE_KAPPA_FISSION)) = "Kappa-Fission Rate" + score_names(abs(SCORE_EVENTS)) = "Events" + score_names(abs(SCORE_FLUX_YN)) = "Flux Moment" + score_names(abs(SCORE_TOTAL_YN)) = "Total Reaction Rate Moment" + score_names(abs(SCORE_SCATTER_N)) = "Scattering Rate Moment" + score_names(abs(SCORE_SCATTER_PN)) = "Scattering Rate Moment" + score_names(abs(SCORE_SCATTER_YN)) = "Scattering Rate Moment" + score_names(abs(SCORE_NU_SCATTER_N)) = "Scattering Prod. Rate Moment" + score_names(abs(SCORE_NU_SCATTER_PN)) = "Scattering Prod. Rate Moment" + score_names(abs(SCORE_NU_SCATTER_YN)) = "Scattering Prod. Rate Moment" + score_names(abs(SCORE_DELAYED_NU_FISSION)) = "Delayed-Nu-Fission Rate" + score_names(abs(SCORE_INVERSE_VELOCITY)) = "Flux-Weighted Inverse Velocity" ! Create filename for tally output filename = trim(path_output) // "tallies.out" ! Open tally file for writing - open(FILE=filename, UNIT=UNIT_TALLY, STATUS='replace', ACTION='write') + open(FILE=filename, NEWUNIT=unit_tally, STATUS='replace', ACTION='write') ! Calculate t-value for confidence intervals if (confidence_intervals) then @@ -1784,16 +1009,16 @@ contains ! Write header block if (t % name == "") then - call header("TALLY " // trim(to_str(t % id)), unit=UNIT_TALLY, & + call header("TALLY " // trim(to_str(t % id)), unit=unit_tally, & level=3) else call header("TALLY " // trim(to_str(t % id)) // ": " & - // trim(t % name), unit=UNIT_TALLY, level=3) + // trim(t % name), unit=unit_tally, level=3) endif ! Handle surface current tallies separately if (t % type == TALLY_SURFACE_CURRENT) then - call write_surface_current(t) + call write_surface_current(t, unit_tally) cycle end if @@ -1836,7 +1061,7 @@ contains ! Print current filter information type = t % filters(j) % type - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A)') repeat(" ", indent), & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), & trim(filter_name(type)), trim(get_label(t, j)) indent = indent + 2 j = j + 1 @@ -1847,7 +1072,7 @@ contains ! Print filter information if (t % n_filters > 0) then type = t % filters(j) % type - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A)') repeat(" ", indent), & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), & trim(filter_name(type)), trim(get_label(t, j)) end if @@ -1868,11 +1093,11 @@ contains ! Write label for nuclide i_nuclide = t % nuclide_bins(n) if (i_nuclide == -1) then - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A)') repeat(" ", indent), & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), & "Total Material" else i_listing = nuclides(i_nuclide) % listing - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A)') repeat(" ", indent), & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A)') repeat(" ", indent), & trim(xs_listings(i_listing) % alias) end if @@ -1885,7 +1110,7 @@ contains case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) score_name = 'P' // trim(to_str(t % moment_order(k))) // " " // & score_names(abs(t % score_bins(k))) - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & to_str(t % results(score_index,filter_index) % sum), & trim(to_str(t % results(score_index,filter_index) % sum_sq)) @@ -1895,7 +1120,7 @@ contains score_index = score_index + 1 score_name = 'P' // trim(to_str(n_order)) // " " //& score_names(abs(t % score_bins(k))) - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & to_str(t % results(score_index,filter_index) % sum), & trim(to_str(t % results(score_index,filter_index) & @@ -1911,7 +1136,7 @@ contains score_name = 'Y' // trim(to_str(n_order)) // ',' // & trim(to_str(nm_order)) // " " & // score_names(abs(t % score_bins(k))) - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & to_str(t % results(score_index,filter_index) % sum), & trim(to_str(t % results(score_index,filter_index)& @@ -1925,7 +1150,7 @@ contains else score_name = score_names(abs(t % score_bins(k))) end if - write(UNIT=UNIT_TALLY, FMT='(1X,2A,1X,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & repeat(" ", indent), score_name, & to_str(t % results(score_index,filter_index) % sum), & trim(to_str(t % results(score_index,filter_index) % sum_sq)) @@ -1942,7 +1167,7 @@ contains end do TALLY_LOOP - close(UNIT=UNIT_TALLY) + close(UNIT=unit_tally) end subroutine write_tallies @@ -1951,9 +1176,9 @@ contains ! tallies.out file. !=============================================================================== - subroutine write_surface_current(t) - - type(TallyObject), pointer :: t + subroutine write_surface_current(t, unit_tally) + type(TallyObject), intent(in) :: t + integer, intent(in) :: unit_tally integer :: i ! mesh index for x integer :: j ! mesh index for y @@ -1968,7 +1193,7 @@ contains integer :: filter_index ! index in results array for filters logical :: print_ebin ! should incoming energy bin be displayed? character(MAX_LINE_LEN) :: string - type(StructuredMesh), pointer :: m => null() + type(RegularMesh), pointer :: m ! Get pointer to mesh i_filter_mesh = t % find_filter(FILTER_MESH) @@ -1997,7 +1222,7 @@ contains do k = 1, m % dimension(3) ! Write mesh cell index string = string(1:len2+1) // trim(to_str(k)) // ")" - write(UNIT=UNIT_TALLY, FMT='(1X,A)') trim(string) + write(UNIT=unit_tally, FMT='(1X,A)') trim(string) do l = 1, n if (print_ebin) then @@ -2005,7 +1230,7 @@ contains matching_bins(i_filter_ein) = l ! Write incoming energy bin - write(UNIT=UNIT_TALLY, FMT='(3X,A,1X,A)') & + write(UNIT=unit_tally, FMT='(3X,A,1X,A)') & "Incoming Energy", trim(get_label(t, i_filter_ein)) end if @@ -2014,14 +1239,14 @@ contains mesh_indices_to_bin(m, (/ i-1, j, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_RIGHT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Left", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_RIGHT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Left", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -2031,14 +1256,14 @@ contains mesh_indices_to_bin(m, (/ i, j, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_RIGHT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Right", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_RIGHT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Right", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -2048,14 +1273,14 @@ contains mesh_indices_to_bin(m, (/ i, j-1, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_FRONT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Back", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_FRONT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Back", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -2065,14 +1290,14 @@ contains mesh_indices_to_bin(m, (/ i, j, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_FRONT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Front", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_FRONT filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Front", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -2082,14 +1307,14 @@ contains mesh_indices_to_bin(m, (/ i, j, k-1 /) + 1, .true.) matching_bins(i_filter_surf) = IN_TOP filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Bottom", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_TOP filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Bottom", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -2099,14 +1324,14 @@ contains mesh_indices_to_bin(m, (/ i, j, k /) + 1, .true.) matching_bins(i_filter_surf) = IN_TOP filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current from Top", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) matching_bins(i_filter_surf) = OUT_TOP filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 - write(UNIT=UNIT_TALLY, FMT='(5X,A,T35,A,"+/- ",A)') & + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current to Top", & to_str(t % results(1,filter_index) % sum), & trim(to_str(t % results(1,filter_index) % sum_sq)) @@ -2124,10 +1349,9 @@ contains !=============================================================================== function get_label(t, i_filter) result(label) - - type(TallyObject), pointer :: t ! tally object - integer, intent(in) :: i_filter ! index in filters array - character(100) :: label ! user-specified identifier + type(TallyObject), intent(in) :: t ! tally object + integer, intent(in) :: i_filter ! index in filters array + character(100) :: label ! user-specified identifier integer :: i ! index in cells/surfaces/etc array integer :: bin @@ -2135,8 +1359,8 @@ contains integer, allocatable :: ijk(:) ! indices in mesh real(8) :: E0 ! lower bound for energy bin real(8) :: E1 ! upper bound for energy bin - type(StructuredMesh), pointer :: m => null() - type(Universe), pointer :: univ => null() + type(RegularMesh), pointer :: m + type(Universe), pointer :: univ bin = matching_bins(i_filter) @@ -2159,7 +1383,7 @@ contains univ, bin-1, offset, label) case (FILTER_SURFACE) i = t % filters(i_filter) % int_bins(bin) - label = to_str(surfaces(i) % id) + label = to_str(surfaces(i)%obj%id) case (FILTER_MESH) m => meshes(t % filters(i_filter) % int_bins(1)) allocate(ijk(m % n_dimension)) @@ -2171,10 +1395,14 @@ contains label = "Index (" // trim(to_str(ijk(1))) // ", " // & trim(to_str(ijk(2))) // ", " // trim(to_str(ijk(3))) // ")" end if - case (FILTER_ENERGYIN, FILTER_ENERGYOUT) + case (FILTER_ENERGYIN, FILTER_ENERGYOUT, FILTER_MU, FILTER_POLAR, & + FILTER_AZIMUTHAL) E0 = t % filters(i_filter) % real_bins(bin) E1 = t % filters(i_filter) % real_bins(bin + 1) label = "[" // trim(to_str(E0)) // ", " // trim(to_str(E1)) // ")" + case (FILTER_DELAYEDGROUP) + i = t % filters(i_filter) % int_bins(bin) + label = to_str(i) end select end function get_label @@ -2187,12 +1415,12 @@ contains recursive subroutine find_offset(map, goal, univ, final, offset, path) - integer, intent(in) :: map ! Index in maps vector - integer, intent(in) :: goal ! The target cell ID - type(Universe), pointer, intent(in) :: univ ! Universe to begin search - integer, intent(in) :: final ! Target offset - integer, intent(inout) :: offset ! Current offset - character(100) :: path ! Path to offset + integer, intent(in) :: map ! Index in maps vector + integer, intent(in) :: goal ! The target cell ID + type(Universe), intent(in) :: univ ! Universe to begin search + integer, intent(in) :: final ! Target offset + integer, intent(inout) :: offset ! Current offset + character(*), intent(inout) :: path ! Path to offset integer :: i, j ! Index over cells integer :: k, l, m ! Indices in lattice @@ -2204,7 +1432,7 @@ contains integer :: temp_offset ! Looped sum of offsets logical :: this_cell = .false. ! Advance in this cell? logical :: later_cell = .false. ! Fill cells after this one? - type(Cell), pointer:: c ! Pointer to current cell + type(Cell), pointer :: c ! Pointer to current cell type(Universe), pointer :: next_univ ! Next universe to loop through class(Lattice), pointer :: lat ! Pointer to current lattice diff --git a/src/output_interface.F90 b/src/output_interface.F90 deleted file mode 100644 index 05fcd0010b..0000000000 --- a/src/output_interface.F90 +++ /dev/null @@ -1,2165 +0,0 @@ -module output_interface - - use constants - use error, only: warning, fatal_error - use global - use tally_header, only: TallyResult - -#ifdef HDF5 - use hdf5_interface -#else -#ifdef MPI - use mpiio_interface -#endif -#endif - - implicit none - private - - type, public :: BinaryOutput - private - ! Compilation specific data -#ifdef HDF5 - integer(HID_T) :: hdf5_fh - integer(HID_T) :: hdf5_grp -#else - integer :: unit_fh -#ifdef MPIF08 - type(MPI_File) :: mpi_fh -#else - integer :: mpi_fh -#endif -#endif - logical :: serial ! Serial I/O when using MPI/PHDF5 - contains - generic, public :: write_data => write_double, & - write_double_1Darray, & - write_double_2Darray, & - write_double_3Darray, & - write_double_4Darray, & - write_integer, & - write_integer_1Darray, & - write_integer_2Darray, & - write_integer_3Darray, & - write_integer_4Darray, & - write_long, & - write_string - generic, public :: read_data => read_double, & - read_double_1Darray, & - read_double_2Darray, & - read_double_3Darray, & - read_double_4Darray, & - read_integer, & - read_integer_1Darray, & - read_integer_2Darray, & - read_integer_3Darray, & - read_integer_4Darray, & - read_long, & - read_string - procedure :: write_double => write_double - procedure :: write_double_1Darray => write_double_1Darray - procedure :: write_double_2Darray => write_double_2Darray - procedure :: write_double_3Darray => write_double_3Darray - procedure :: write_double_4Darray => write_double_4Darray - procedure :: write_integer => write_integer - procedure :: write_integer_1Darray => write_integer_1Darray - procedure :: write_integer_2Darray => write_integer_2Darray - procedure :: write_integer_3Darray => write_integer_3Darray - procedure :: write_integer_4Darray => write_integer_4Darray - procedure :: write_long => write_long - procedure :: write_string => write_string - procedure :: read_double => read_double - procedure :: read_double_1Darray => read_double_1Darray - procedure :: read_double_2Darray => read_double_2Darray - procedure :: read_double_3Darray => read_double_3Darray - procedure :: read_double_4Darray => read_double_4Darray - procedure :: read_integer => read_integer - procedure :: read_integer_1Darray => read_integer_1Darray - procedure :: read_integer_2Darray => read_integer_2Darray - procedure :: read_integer_3Darray => read_integer_3Darray - procedure :: read_integer_4Darray => read_integer_4Darray - procedure :: read_long => read_long - procedure :: read_string => read_string - procedure, public :: file_create => file_create - procedure, public :: file_open => file_open - procedure, public :: file_close => file_close - procedure, public :: write_tally_result => write_tally_result - procedure, public :: read_tally_result => read_tally_result - procedure, public :: write_source_bank => write_source_bank - procedure, public :: read_source_bank => read_source_bank -#ifdef HDF5 - procedure, public :: write_attribute_string => write_attribute_string - procedure, public :: open_group => open_group - procedure, public :: close_group => close_group -#endif - end type BinaryOutput - -contains - -!=============================================================================== -! FILE_CREATE creates a new file to write data to -!=============================================================================== - - subroutine file_create(self, filename, serial) - - character(*), intent(in) :: filename ! name of file to be created - logical, optional, intent(in) :: serial ! processor rank to write from - class(BinaryOutput) :: self - - ! Check for serial option - if (present(serial)) then - self % serial = serial - else - self % serial = .true. - end if - -#ifdef HDF5 -# ifdef MPI - if (self % serial) then - call hdf5_file_create(filename, self % hdf5_fh) - else - call hdf5_file_create_parallel(filename, self % hdf5_fh) - endif -# else - call hdf5_file_create(filename, self % hdf5_fh) -# endif -#elif MPI - if (self % serial) then - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION="write", & - STATUS='replace', ACCESS='stream') - else - call mpi_create_file(filename, self % mpi_fh) - end if -#else - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION="write", & - STATUS='replace', ACCESS='stream') -#endif - - end subroutine file_create - -!=============================================================================== -! FILE_OPEN opens an existing file for reading or read/writing -!=============================================================================== - - subroutine file_open(self, filename, mode, serial) - - character(*), intent(in) :: filename ! name of file to be opened - character(*), intent(in) :: mode ! file access mode - logical, optional, intent(in) :: serial ! processor rank to write from - class(BinaryOutput) :: self - - ! Check for serial option - if (present(serial)) then - self % serial = serial - else - self % serial = .true. - end if - -#ifdef HDF5 -# ifdef MPI - if (self % serial) then - call hdf5_file_open(filename, self % hdf5_fh, mode) - else - call hdf5_file_open_parallel(filename, self % hdf5_fh, mode) - endif -# else - call hdf5_file_open(filename, self % hdf5_fh, mode) -# endif -#elif MPI - if (self % serial) then - ! Check for read/write mode to open, default is read only - if (mode == 'w') then - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION='write', & - STATUS='old', ACCESS='stream', POSITION='append') - else - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION='read', & - STATUS='old', ACCESS='stream') - end if - else - call mpi_open_file(filename, self % mpi_fh, mode) - end if -#else - ! Check for read/write mode to open, default is read only - if (mode == 'w') then - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION='write', & - STATUS='old', ACCESS='stream', POSITION='append') - else - open(NEWUNIT=self % unit_fh, FILE=filename, ACTION='read', & - STATUS='old', ACCESS='stream') - end if -#endif - - end subroutine file_open - -!=============================================================================== -! FILE_CLOSE closes a file -!=============================================================================== - - subroutine file_close(self) - - class(BinaryOutput) :: self - -#ifdef HDF5 -# ifdef MPI - call hdf5_file_close(self % hdf5_fh) -# else - call hdf5_file_close(self % hdf5_fh) -# endif -#elif MPI - if (self % serial) then - close(UNIT=self % unit_fh) - else - call mpi_close_file(self % mpi_fh) - end if -#else - close(UNIT=self % unit_fh) -#endif - - end subroutine file_close - -!=============================================================================== -! OPEN_GROUP call hdf5 routine to open a group within binary output context -!=============================================================================== - -#ifdef HDF5 - subroutine open_group(self, group) - - character(*), intent(in) :: group ! HDF5 group name - class(BinaryOutput) :: self - - call hdf5_open_group(self % hdf5_fh, group, self % hdf5_grp) - - end subroutine open_group -#endif - -!=============================================================================== -! CLOSE_GROUP call hdf5 routine to close a group within binary output context -!=============================================================================== - -#ifdef HDF5 - subroutine close_group(self) - - class(BinaryOutput) :: self - - call hdf5_close_group(self % hdf5_grp) - - end subroutine close_group -#endif - -!=============================================================================== -! WRITE_DOUBLE writes double precision scalar data -!=============================================================================== - - subroutine write_double(self, buffer, name, group, collect) - - real(8), intent(in) :: buffer ! data to write - character(*), intent(in) :: name ! name for data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_double(self % hdf5_grp, name_, buffer) - else - call hdf5_write_double_parallel(self % hdf5_grp, name_, buffer, collect_) - end if -# else - call hdf5_write_double(self % hdf5_grp, name_, buffer) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer - else - call mpi_write_double(self % mpi_fh, buffer, collect_) - end if -#else - write(self % unit_fh) buffer -#endif - - end subroutine write_double - -!=============================================================================== -! READ_DOUBLE reads double precision scalar data -!=============================================================================== - - subroutine read_double(self, buffer, name, group, collect) - - real(8), intent(inout) :: buffer ! read data to here - character(*), intent(in) :: name ! name for data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_double(self % hdf5_grp, name_, buffer) - else - call hdf5_read_double_parallel(self % hdf5_grp, name_, buffer, collect_) - end if -# else - call hdf5_read_double(self % hdf5_grp, name_, buffer) -# endif - ! Check if HDf5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer - else - call mpi_read_double(self % mpi_fh, buffer, collect_) - end if -#else - read(self % unit_fh) buffer -#endif - - end subroutine read_double - -!=============================================================================== -! WRITE_DOUBLE_1DARRAY writes double precision 1-D array data -!=============================================================================== - - subroutine write_double_1Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length ! length of array to write - real(8), intent(in) :: buffer(:) ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_double_1Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_double_1Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_write_double_1Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length) - else - call mpi_write_double_1Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length) -#endif - - end subroutine write_double_1Darray - -!=============================================================================== -! READ_DOUBLE_1DARRAY reads double precision 1-D array data -!=============================================================================== - - subroutine read_double_1Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length ! length of array to read - real(8), intent(inout) :: buffer(:) ! read data to here - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_double_1Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_double_1Darray_parallel(self % hdf5_grp, name_, buffer, & - length, collect_) - end if -# else - call hdf5_read_double_1Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length) - else - call mpi_read_double_1Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length) -#endif - - end subroutine read_double_1Darray - -!=============================================================================== -! WRITE_DOUBLE_2DARRAY writes double precision 2-D array data -!=============================================================================== - - subroutine write_double_2Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(2) ! dimension of array - real(8), intent(in) :: buffer(length(1),length(2)) ! the data - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_double_2Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_double_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_write_double_2Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2)) - else - call mpi_write_double_2Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2)) -#endif - - end subroutine write_double_2Darray - -!=============================================================================== -! READ_DOUBLE_2DARRAY reads double precision 2-D array data -!=============================================================================== - - subroutine read_double_2Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(2) ! dimension of array - real(8), intent(inout) :: buffer(length(1),length(2)) ! the data - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_double_2Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_double_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_read_double_2Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2)) - else - call mpi_read_double_2Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2)) -#endif - - end subroutine read_double_2Darray - -!=============================================================================== -! WRITE_DOUBLE_3DARRAY writes double precision 3-D array data -!=============================================================================== - - subroutine write_double_3Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(3) ! length of each dimension - real(8), intent(in) :: buffer(length(1),length(2),length(3)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_double_3Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_double_3Darray_parallel(self % hdf5_grp, name_, buffer, & - length, collect_) - end if -# else - call hdf5_write_double_3Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) - else - call mpi_write_double_3Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) -#endif - - end subroutine write_double_3Darray - -!=============================================================================== -! READ_DOUBLE_3DARRAY reads double precision 3-D array data -!=============================================================================== - - subroutine read_double_3Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(3) ! length of each dimension - real(8), intent(inout) :: buffer(length(1),length(2),length(3)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_double_3Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_double_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_read_double_3Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) - else - call mpi_read_double_3Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) -#endif - - end subroutine read_double_3Darray - -!=============================================================================== -! WRITE_DOUBLE_4DARRAY writes double precision 4-D array data -!=============================================================================== - - subroutine write_double_4Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(4) ! length of each dimension - real(8), intent(in) :: buffer(length(1),length(2),& - length(3),length(4)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_double_4Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_double_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - ! Write the data in serial - call hdf5_write_double_4Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) - else - call mpi_write_double_4Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) -#endif - - end subroutine write_double_4Darray - -!=============================================================================== -! READ_DOUBLE_4DARRAY reads double precision 4-D array data -!=============================================================================== - - subroutine read_double_4Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(4) ! length of each dimension - real(8), intent(inout) :: buffer(length(1),length(2),& - length(3),length(4)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_double_4Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_double_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_read_double_4Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) - else - call mpi_read_double_4Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) -#endif - - end subroutine read_double_4Darray - -!=============================================================================== -! WRITE_INTEGER writes integer precision scalar data -!=============================================================================== - - subroutine write_integer(self, buffer, name, group, collect) - - integer, intent(in) :: buffer ! data to write - character(*), intent(in) :: name ! name for data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_integer(self % hdf5_grp, name_, buffer) - else - call hdf5_write_integer_parallel(self % hdf5_grp, name_, buffer, collect_) - end if -# else - call hdf5_write_integer(self % hdf5_grp, name_, buffer) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer - else - call mpi_write_integer(self % mpi_fh, buffer, collect_) - end if -#else - write(self % unit_fh) buffer -#endif - - end subroutine write_integer - -!=============================================================================== -! READ_INTEGER reads integer precision scalar data -!=============================================================================== - - subroutine read_integer(self, buffer, name, group, collect) - - integer, intent(inout) :: buffer ! read data to here - character(*), intent(in) :: name ! name for data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_integer(self % hdf5_grp, name_, buffer) - else - call hdf5_read_integer_parallel(self % hdf5_grp, name_, buffer, collect_) - end if -# else - call hdf5_read_integer(self % hdf5_grp, name_, buffer) -# endif - ! Check if HDf5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer - else - call mpi_read_integer(self % mpi_fh, buffer, collect_) - end if -#else - read(self % unit_fh) buffer -#endif - - end subroutine read_integer - -!=============================================================================== -! WRITE_INTEGER_1DARRAY writes integer precision 1-D array data -!=============================================================================== - - subroutine write_integer_1Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length ! length of array to write - integer, intent(in) :: buffer(:) ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_integer_1Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_integer_1Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_write_integer_1Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length) - else - call mpi_write_integer_1Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length) -#endif - - end subroutine write_integer_1Darray - -!=============================================================================== -! READ_INTEGER_1DARRAY reads integer precision 1-D array data -!=============================================================================== - - subroutine read_integer_1Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length ! length of array to read - integer, intent(inout) :: buffer(:) ! read data to here - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_integer_1Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_integer_1Darray_parallel(self % hdf5_grp, name_, buffer, & - length, collect_) - end if -# else - ! Read the data in serial - call hdf5_read_integer_1Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length) - else - call mpi_read_integer_1Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length) -#endif - - end subroutine read_integer_1Darray - -!=============================================================================== -! WRITE_INTEGER_2DARRAY writes integer precision 2-D array data -!=============================================================================== - - subroutine write_integer_2Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(2) ! dimension of array - integer, intent(in) :: buffer(length(1),length(2)) ! the data - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_integer_2Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_integer_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_write_integer_2Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2)) - else - call mpi_write_integer_2Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2)) -#endif - - end subroutine write_integer_2Darray - -!=============================================================================== -! READ_INTEGER_2DARRAY reads integer precision 2-D array data -!=============================================================================== - - subroutine read_integer_2Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(2) ! dimension of array - integer, intent(inout) :: buffer(length(1),length(2)) ! the data - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_integer_2Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_integer_2Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_read_integer_2Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2)) - else - call mpi_read_integer_2Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2)) -#endif - - end subroutine read_integer_2Darray - -!=============================================================================== -! WRITE_INTEGER_3DARRAY writes integer precision 3-D array data -!=============================================================================== - - subroutine write_integer_3Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(3) ! length of each dimension - integer, intent(in) :: buffer(length(1),length(2),length(3)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_integer_3Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_integer_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_write_integer_3Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) - else - call mpi_write_integer_3Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) -#endif - - end subroutine write_integer_3Darray - -!=============================================================================== -! READ_INTEGER_3DARRAY reads integer precision 3-D array data -!=============================================================================== - - subroutine read_integer_3Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(3) ! length of each dimension - integer, intent(inout) :: buffer(length(1),length(2),length(3)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_integer_3Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_integer_3Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_read_integer_3Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) - else - call mpi_read_integer_3Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3)) -#endif - - end subroutine read_integer_3Darray - -!=============================================================================== -! WRITE_INTEGER_4DARRAY writes integer precision 4-D array data -!=============================================================================== - - subroutine write_integer_4Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(4) ! length of each dimension - integer, intent(in) :: buffer(length(1),length(2),& - length(3),length(4)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_integer_4Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_write_integer_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_write_integer_4Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) - else - call mpi_write_integer_4Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - write(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) -#endif - - end subroutine write_integer_4Darray - -!=============================================================================== -! READ_INTEGER_4DARRAY reads integer precision 4-D array data -!=============================================================================== - - subroutine read_integer_4Darray(self, buffer, name, group, length, collect) - - integer, intent(in) :: length(4) ! length of each dimension - integer, intent(inout) :: buffer(length(1),length(2),& - length(3),length(4)) - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_integer_4Darray(self % hdf5_grp, name_, buffer, length) - else - call hdf5_read_integer_4Darray_parallel(self % hdf5_grp, name_, buffer, length, & - collect_) - end if -# else - call hdf5_read_integer_4Darray(self % hdf5_grp, name_, buffer, length) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) - else - call mpi_read_integer_4Darray(self % mpi_fh, buffer, length, collect_) - end if -#else - read(self % unit_fh) buffer(1:length(1),1:length(2),1:length(3), & - 1:length(4)) -#endif - - end subroutine read_integer_4Darray - -!=============================================================================== -! WRITE_LONG writes long integer scalar data -!=============================================================================== - - subroutine write_long(self, buffer, name, group, collect) - - integer(8), intent(in) :: buffer ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) - else - call hdf5_write_long_parallel(self % hdf5_grp, name_, buffer, & - hdf5_integer8_t, collect_) - end if -# else - call hdf5_write_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer - else - call mpi_write_long(self % mpi_fh, buffer, collect_) - end if -#else - write(self % unit_fh) buffer -#endif - - end subroutine write_long - -!=============================================================================== -! READ_LONG reads long integer scalar data -!=============================================================================== - - subroutine read_long(self, buffer, name, group, collect) - - integer(8), intent(inout) :: buffer ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - logical :: collect_ - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) - else - call hdf5_read_long_parallel(self % hdf5_grp, name_, buffer, & - hdf5_integer8_t, collect_) - end if -# else - call hdf5_read_long(self % hdf5_grp, name_, buffer, hdf5_integer8_t) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer - else - call mpi_read_long(self % mpi_fh, buffer, collect_) - end if -#else - read(self % unit_fh) buffer -#endif - - end subroutine read_long - -!=============================================================================== -! WRITE_STRING writes string data -!=============================================================================== - - subroutine write_string(self, buffer, name, group, collect) - - character(*), intent(in) :: buffer ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - integer :: n - logical :: collect_ - - ! Get string length - n = len_trim(buffer) - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_write_string(self % hdf5_grp, name_, buffer, n) - else - call hdf5_write_string_parallel(self % hdf5_grp, name_, buffer, n, collect_) - end if -# else - ! Write the data - call hdf5_write_string(self % hdf5_grp, name_, buffer, n) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - write(self % unit_fh) buffer - else - call mpi_write_string(self % mpi_fh, buffer, n, collect_) - end if -#else - write(self % unit_fh) buffer -#endif - - end subroutine write_string - -!=============================================================================== -! READ_STRING reads string data -!=============================================================================== - - subroutine read_string(self, buffer, name, group, collect) - - character(*), intent(inout) :: buffer ! data to write - character(*), intent(in) :: name ! name of data - character(*), intent(in), optional :: group ! HDF5 group name - logical, intent(in), optional :: collect ! collective I/O - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - integer :: n - logical :: collect_ - - ! Get string length - n = len(buffer) - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - - ! Set up collective vs. independent I/O - if (present(collect)) then - collect_ = collect - else - collect_ = .true. - end if - - -#ifdef HDF5 - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif -# ifdef MPI - if (self % serial) then - call hdf5_read_string(self % hdf5_grp, name_, buffer, n) - else - call hdf5_read_string_parallel(self % hdf5_grp, name_, buffer, n, collect_) - end if -# else - call hdf5_read_string(self % hdf5_grp, name_, buffer, n) -# endif - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) -#elif MPI - if (self % serial) then - read(self % unit_fh) buffer - else - call mpi_read_string(self % mpi_fh, buffer, n, collect_) - end if -#else - read(self % unit_fh) buffer -#endif - - end subroutine read_string - -!=============================================================================== -! WRITE_ATTRIBUTE_STRING -!=============================================================================== - -#ifdef HDF5 - subroutine write_attribute_string(self, var, attr_type, attr_str, group) - - character(*), intent(in) :: var ! variable name for attr - character(*), intent(in) :: attr_type ! attr identifier type - character(*), intent(in) :: attr_str ! string for attr id type - character(*), intent(in), optional :: group ! HDF5 group name - class(BinaryOutput) :: self - - ! Check if HDF5 group should be created/opened - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - endif - - ! Write the attribute string - call hdf5_write_attribute_string(self % hdf5_grp, var, attr_type, attr_str) - - ! Check if HDF5 group should be closed - if (present(group)) call hdf5_close_group(self % hdf5_grp) - - end subroutine write_attribute_string -#endif - -!=============================================================================== -! WRITE_TALLY_RESULT writes an OpenMC TallyResult type -!=============================================================================== - - subroutine write_tally_result(self, buffer, name, group, n1, n2) - - character(*), intent(in), optional :: group ! HDF5 group name - character(*), intent(in) :: name ! name of data - integer, intent(in) :: n1, n2 ! TallyResult dims - type(TallyResult), intent(in), target :: buffer(n1, n2) ! data to write - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - -#ifndef HDF5 - integer :: j,k ! iteration counters -#endif - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - -#ifdef HDF5 - - ! Open up sub-group if present - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - end if - - ! Set overall size of vector to write - dims1(1) = n1*n2 - - ! Create up a dataspace for size - call h5screate_simple_f(1, dims1, dspace, hdf5_err) - - ! Create the dataset - call h5dcreate_f(self % hdf5_grp, name_, hdf5_tallyresult_t, dspace, dset, & - hdf5_err) - - ! Set pointer to first value and write - f_ptr = c_loc(buffer(1,1)) - call h5dwrite_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) - - ! Close ids - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - if (present(group)) then - call hdf5_close_group(self % hdf5_grp) - end if - -#else - - ! Write out tally buffer - do k = 1, n2 - do j = 1, n1 - write(self % unit_fh) buffer(j,k) % sum - write(self % unit_fh) buffer(j,k) % sum_sq - end do - end do - -#endif - - end subroutine write_tally_result - -!=============================================================================== -! READ_TALLY_RESULT reads OpenMC TallyResult data -!=============================================================================== - - subroutine read_tally_result(self, buffer, name, group, n1, n2) - - character(*), intent(in), optional :: group ! HDF5 group name - character(*), intent(in) :: name ! name of data - integer, intent(in) :: n1, n2 ! TallyResult dims - type(TallyResult), intent(inout), target :: buffer(n1, n2) ! read data here - class(BinaryOutput) :: self - - character(len=MAX_WORD_LEN) :: name_ ! HDF5 dataset name - character(len=MAX_WORD_LEN) :: group_ ! HDF5 group name - -#ifndef HDF5 -# ifndef MPI - integer :: j,k ! iteration counters -# endif -#endif - - ! Set name - name_ = trim(name) - - ! Set group - if (present(group)) then - group_ = trim(group) - end if - -#ifdef HDF5 - - ! Open up sub-group if present - if (present(group)) then - call hdf5_open_group(self % hdf5_fh, group_, self % hdf5_grp) - else - self % hdf5_grp = self % hdf5_fh - end if - - ! Open the dataset - call h5dopen_f(self % hdf5_grp, name, dset, hdf5_err) - - ! Set pointer to first value and write - f_ptr = c_loc(buffer(1,1)) - call h5dread_f(dset, hdf5_tallyresult_t, f_ptr, hdf5_err) - - ! Close ids - call h5dclose_f(dset, hdf5_err) - if (present(group)) call hdf5_close_group(self % hdf5_grp) - -# elif MPI - - ! Write out tally buffer - call MPI_FILE_READ(self % mpi_fh, buffer, n1*n2, MPI_TALLYRESULT, & - MPI_STATUS_IGNORE, mpiio_err) - -#else - - ! Read tally result - do k = 1, n2 - do j = 1, n1 - read(self % unit_fh) buffer(j,k) % sum - read(self % unit_fh) buffer(j,k) % sum_sq - end do - end do - -#endif - - end subroutine read_tally_result - -!=============================================================================== -! WRITE_SOURCE_BANK writes OpenMC source_bank data -!=============================================================================== - - subroutine write_source_bank(self) - - class(BinaryOutput) :: self - -#ifdef MPI -# ifndef HDF5 - integer(MPI_OFFSET_KIND) :: offset ! offset of data - integer :: size_bank ! size of bank to write -#ifdef MPIF08 - type(MPI_Datatype) :: datatype -#else - integer :: datatype -#endif -# endif -# ifdef HDF5 - integer(8) :: offset(1) ! source data offset -# endif -#endif - -#ifdef HDF5 -#ifdef MPI - - ! Set size of total dataspace for all procs and rank - dims1(1) = n_particles - hdf5_rank = 1 - - ! Create that dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create the dataset for that dataspace - call h5dcreate_f(self % hdf5_fh, "source_bank", hdf5_bank_t, dspace, dset, hdf5_err) - - ! Close the dataspace - call h5sclose_f(dspace, hdf5_err) - - ! Create another data space but for each proc individually - dims1(1) = work - call h5screate_simple_f(hdf5_rank, dims1, memspace, hdf5_err) - - ! Get the individual local proc dataspace - call h5dget_space_f(dset, dspace, hdf5_err) - - ! Select hyperslab for this dataspace - offset(1) = work_index(rank) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims1, hdf5_err) - - ! Set up the property list for parallel writing - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank(1)) - - ! Write data to file in parallel - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id = dspace, mem_space_id = memspace, & - xfer_prp = plist) - - ! Close all ids - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - -# else - - ! Set size - dims1(1) = work - hdf5_rank = 1 - - ! Create dataspace - call h5screate_simple_f(hdf5_rank, dims1, dspace, hdf5_err) - - ! Create dataset - call h5dcreate_f(self % hdf5_fh, "source_bank", hdf5_bank_t, & - dspace, dset, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank(1)) - - ! Write dataset to file - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err) - - ! Close all ids - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - -# endif - -#elif MPI - - ! Get current offset for master - if (master) call MPI_FILE_GET_POSITION(self % mpi_fh, offset, mpiio_err) - - ! Determine offset on master process and broadcast to all processors - call MPI_TYPE_MATCH_SIZE(MPI_TYPECLASS_INTEGER, MPI_OFFSET_KIND, & - datatype, mpi_err) - call MPI_BCAST(offset, 1, datatype, 0, MPI_COMM_WORLD, mpi_err) - - ! Set the proper offset for source data on this processor - call MPI_TYPE_SIZE(MPI_BANK, size_bank, mpi_err) - offset = offset + size_bank*work_index(rank) - - ! Write all source sites - call MPI_FILE_WRITE_AT(self % mpi_fh, offset, source_bank(1), int(work), & - MPI_BANK, MPI_STATUS_IGNORE, mpiio_err) - -#else - - ! Write out source sites - write(self % unit_fh) source_bank - -#endif - - end subroutine write_source_bank - -!=============================================================================== -! READ_SOURCE_BANK reads OpenMC source_bank data -!=============================================================================== - - subroutine read_source_bank(self) - - class(BinaryOutput) :: self - -#ifdef MPI -# ifndef HDF5 - integer(MPI_OFFSET_KIND) :: offset ! offset of data - integer :: size_bank ! size of bank to read -# endif -# ifdef HDF5 - integer(8) :: offset(1) ! offset of data -# endif -#endif - -#ifdef HDF5 -# ifdef MPI - - ! Set size of total dataspace for all procs and rank - dims1(1) = n_particles - hdf5_rank = 1 - - ! Open the dataset - call h5dopen_f(self % hdf5_fh, "source_bank", dset, hdf5_err) - - ! Create another data space but for each proc individually - dims1(1) = work - call h5screate_simple_f(hdf5_rank, dims1, memspace, hdf5_err) - - ! Get the individual local proc dataspace - call h5dget_space_f(dset, dspace, hdf5_err) - - ! Select hyperslab for this dataspace - offset(1) = work_index(rank) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims1, hdf5_err) - - ! Set up the property list for parallel writing - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank(1)) - - ! Read data from file in parallel - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id = dspace, mem_space_id = memspace, & - xfer_prp = plist) - - ! Close all ids - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - -# else - - ! Open dataset - call h5dopen_f(self % hdf5_fh, "source_bank", dset, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank(1)) - - ! Read dataset from file - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err) - - ! Close all ids - call h5dclose_f(dset, hdf5_err) - -# endif - -#elif MPI - - ! Go to the end of the file to set file pointer - offset = 0 - call MPI_FILE_SEEK(self % mpi_fh, offset, MPI_SEEK_END, & - mpiio_err) - - ! Get current offset (will be at EOF) - call MPI_FILE_GET_POSITION(self % mpi_fh, offset, mpiio_err) - - ! Get the size of the source bank on all procs - call MPI_TYPE_SIZE(MPI_BANK, size_bank, mpi_err) - - ! Calculate offset where the source bank will begin - offset = offset - n_particles*size_bank - - ! Set the proper offset for source data on this processor - offset = offset + size_bank*work_index(rank) - - ! Write all source sites - call MPI_FILE_READ_AT(self % mpi_fh, offset, source_bank(1), int(work), & - MPI_BANK, MPI_STATUS_IGNORE, mpiio_err) - -#else - - ! Write out source sites - read(self % unit_fh) source_bank - -#endif - - end subroutine read_source_bank - -end module output_interface diff --git a/src/particle_header.F90 b/src/particle_header.F90 index 7c2586c3e2..0b9b251ee5 100644 --- a/src/particle_header.F90 +++ b/src/particle_header.F90 @@ -1,6 +1,9 @@ module particle_header - use constants, only: NEUTRON, ONE, NONE, ZERO + use bank_header, only: Bank + use constants, only: NEUTRON, ONE, NONE, ZERO, MAX_SECONDARY, & + MAX_DELAYED_GROUPS + use error, only: fatal_error use geometry_header, only: BASE_UNIVERSE implicit none @@ -62,10 +65,13 @@ module particle_header integer :: event ! scatter, absorption integer :: event_nuclide ! index in nuclides array integer :: event_MT ! reaction MT + integer :: delayed_group ! delayed group ! Post-collision physical data integer :: n_bank ! number of fission sites banked real(8) :: wgt_bank ! weight of fission sites banked + integer :: n_delayed_bank(MAX_DELAYED_GROUPS) ! number of delayed fission + ! sites banked ! Indices for various arrays integer :: surface ! index for surface particle is on @@ -79,9 +85,15 @@ module particle_header ! Track output logical :: write_track = .false. + ! Secondary particles created + integer :: n_secondary = 0 + type(Bank) :: secondary_bank(MAX_SECONDARY) + contains procedure :: initialize => initialize_particle procedure :: clear => clear_particle + procedure :: initialize_from_source + procedure :: create_secondary end type Particle contains @@ -103,17 +115,19 @@ contains this % alive = .true. ! clear attributes - this % surface = NONE - this % cell_born = NONE - this % material = NONE - this % last_material = NONE - this % wgt = ONE - this % last_wgt = ONE - this % absorb_wgt = ZERO - this % n_bank = 0 - this % wgt_bank = ZERO - this % n_collision = 0 - this % fission = .false. + this % surface = NONE + this % cell_born = NONE + this % material = NONE + this % last_material = NONE + this % wgt = ONE + this % last_wgt = ONE + this % absorb_wgt = ZERO + this % n_bank = 0 + this % wgt_bank = ZERO + this % n_collision = 0 + this % fission = .false. + this % delayed_group = 0 + this % n_delayed_bank(:) = 0 ! Set up base level coordinates this % coord(1) % universe = BASE_UNIVERSE @@ -122,7 +136,7 @@ contains end subroutine initialize_particle !=============================================================================== -! CLEAR_PARTICLE +! CLEAR_PARTICLE resets all coordinate levels for the particle !=============================================================================== subroutine clear_particle(this) @@ -138,7 +152,7 @@ contains end subroutine clear_particle !=============================================================================== -! RESET_COORD +! RESET_COORD clears data from a single coordinate level !=============================================================================== elemental subroutine reset_coord(this) @@ -154,4 +168,56 @@ contains end subroutine reset_coord +!=============================================================================== +! INITIALIZE_FROM_SOURCE initializes a particle from data stored in a source +! site. The source site may have been produced from an external source, from +! fission, or simply as a secondary particle. +!=============================================================================== + + subroutine initialize_from_source(this, src) + class(Particle), intent(inout) :: this + type(Bank), intent(in) :: src + + ! set defaults + call this % initialize() + + ! copy attributes from source bank site + this % wgt = src % wgt + this % last_wgt = src % wgt + this % coord(1) % xyz = src % xyz + this % coord(1) % uvw = src % uvw + this % last_xyz = src % xyz + this % last_uvw = src % uvw + this % E = src % E + this % last_E = src % E + + end subroutine initialize_from_source + +!=============================================================================== +! CREATE_SECONDARY stores the current phase space attributes of the particle in +! the secondary bank and increments the number of sites in the secondary bank. +!=============================================================================== + + subroutine create_secondary(this, uvw, type) + class(Particle), intent(inout) :: this + real(8), intent(in) :: uvw(3) + integer, intent(in) :: type + + integer :: n + + ! Check to make sure that the hard-limit on secondary particles is not + ! exceeded. + if (this % n_secondary == MAX_SECONDARY) then + call fatal_error("Too many secondary particles created.") + end if + + n = this % n_secondary + 1 + this % secondary_bank(n) % wgt = this % wgt + this % secondary_bank(n) % xyz(:) = this % coord(1) % xyz + this % secondary_bank(n) % uvw(:) = uvw + this % secondary_bank(n) % E = this % E + this % n_secondary = n + + end subroutine create_secondary + end module particle_header diff --git a/src/particle_restart.F90 b/src/particle_restart.F90 index 0ed25fdc80..2e0523d484 100644 --- a/src/particle_restart.F90 +++ b/src/particle_restart.F90 @@ -6,18 +6,18 @@ module particle_restart use constants use geometry_header, only: BASE_UNIVERSE use global + use hdf5_interface, only: file_open, file_close, read_dataset use output, only: write_message, print_particle - use output_interface, only: BinaryOutput use particle_header, only: Particle use random_lcg, only: set_particle_seed use tracking, only: transport + use hdf5, only: HID_T + implicit none private public :: run_particle_restart - type(BinaryOutput) :: pr ! Binary file - contains !=============================================================================== @@ -34,7 +34,7 @@ contains verbosity = 10 ! Initialize the particle to be tracked - call p % initialize() + call p%initialize() ! Read in the restart information call read_particle_restart(p, previous_run_mode) @@ -46,9 +46,9 @@ contains select case (previous_run_mode) case (MODE_EIGENVALUE) particle_seed = ((current_batch - 1)*gen_per_batch + & - current_gen - 1)*n_particles + p % id + current_gen - 1)*n_particles + p%id case (MODE_FIXEDSOURCE) - particle_seed = p % id + particle_seed = p%id end select call set_particle_seed(particle_seed) @@ -66,40 +66,48 @@ 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 + character(MAX_WORD_LEN) :: mode ! 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', mode) + select case (mode) + case ('k-eigenvalue') + previous_run_mode = MODE_EIGENVALUE + case ('fixed source') + previous_run_mode = MODE_FIXEDSOURCE + end select + call read_dataset(file_id, 'id', p%id) + call read_dataset(file_id, 'weight', p%wgt) + call read_dataset(file_id, 'energy', p%E) + call read_dataset(file_id, 'xyz', p%coord(1)%xyz) + call read_dataset(file_id, 'uvw', p%coord(1)%uvw) ! Set particle last attributes - p % last_wgt = p % wgt - p % last_xyz = p % coord(1) % xyz - p % last_uvw = p % coord(1) % uvw - p % last_E = p % E + p%last_wgt = p%wgt + p%last_xyz = p%coord(1)%xyz + p%last_uvw = p%coord(1)%uvw + p%last_E = p%E ! Close hdf5 file - call pr % file_close() + call file_close(file_id) end subroutine read_particle_restart diff --git a/src/particle_restart_write.F90 b/src/particle_restart_write.F90 index 0ac55bd273..edd779df09 100644 --- a/src/particle_restart_write.F90 +++ b/src/particle_restart_write.F90 @@ -2,17 +2,16 @@ module particle_restart_write use bank_header, only: Bank use global - use output_interface, only: BinaryOutput + use hdf5_interface use particle_header, only: Particle use string, only: to_str + use hdf5 + implicit none private public :: write_particle_restart - ! Binary output file - type(BinaryOutput) :: pr - contains !=============================================================================== @@ -20,52 +19,49 @@ 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 - select case (run_mode) - case (MODE_EIGENVALUE) - src => source_bank(current_work) - case (MODE_FIXEDSOURCE) - src => source_site - end select + 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', '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) + select case(run_mode) + case (MODE_FIXEDSOURCE) + call write_dataset(file_id, 'run_mode', 'fixed source') + case (MODE_EIGENVALUE) + call write_dataset(file_id, 'run_mode', 'k-eigenvalue') + case (MODE_PARTICLE) + call write_dataset(file_id, 'run_mode', 'particle restart') + end select + call write_dataset(file_id, 'id', p%id) + call write_dataset(file_id, 'weight', src%wgt) + call write_dataset(file_id, 'energy', src%E) + call write_dataset(file_id, 'xyz', src%xyz) + call write_dataset(file_id, 'uvw', src%uvw) ! Close file - call pr % file_close() + call file_close(file_id) !$omp end critical (WriteParticleRestart) end subroutine write_particle_restart diff --git a/src/physics.F90 b/src/physics.F90 index 9ca59a9872..a01a3a30cb 100644 --- a/src/physics.F90 +++ b/src/physics.F90 @@ -73,10 +73,11 @@ contains type(Particle), intent(inout) :: p integer :: i_nuclide ! index in nuclides array + integer :: i_nuc_mat ! index in material's nuclides array integer :: i_reaction ! index in nuc % reactions array type(Nuclide), pointer :: nuc - i_nuclide = sample_nuclide(p, 'total ') + call sample_nuclide(p, 'total ', i_nuclide, i_nuc_mat) ! Get pointer to table nuc => nuclides(i_nuclide) @@ -106,7 +107,7 @@ contains ! Sample a scattering reaction and determine the secondary energy of the ! exiting neutron - call scatter(p, i_nuclide) + call scatter(p, i_nuclide, i_nuc_mat) ! Play russian roulette if survival biasing is turned on @@ -121,13 +122,13 @@ contains ! SAMPLE_NUCLIDE !=============================================================================== - function sample_nuclide(p, base) result(i_nuclide) + subroutine sample_nuclide(p, base, i_nuclide, i_nuc_mat) type(Particle), intent(in) :: p character(7), intent(in) :: base ! which reaction to sample based on - integer :: i_nuclide + integer, intent(out) :: i_nuclide + integer, intent(out) :: i_nuc_mat - integer :: i real(8) :: prob real(8) :: cutoff real(8) :: atom_density ! atom density of nuclide in atom/b-cm @@ -147,20 +148,20 @@ contains cutoff = prn() * material_xs % fission end select - i = 0 + i_nuc_mat = 0 prob = ZERO do while (prob < cutoff) - i = i + 1 + i_nuc_mat = i_nuc_mat + 1 ! Check to make sure that a nuclide was sampled - if (i > mat % n_nuclides) then + if (i_nuc_mat > mat % n_nuclides) then call write_particle_restart(p) call fatal_error("Did not sample any nuclide during collision.") end if ! Find atom density - i_nuclide = mat % nuclide(i) - atom_density = mat % atom_density(i) + i_nuclide = mat % nuclide(i_nuc_mat) + atom_density = mat % atom_density(i_nuc_mat) ! Determine microscopic cross section select case (base) @@ -177,14 +178,13 @@ contains prob = prob + sigma end do - end function sample_nuclide + end subroutine sample_nuclide !=============================================================================== ! SAMPLE_FISSION !=============================================================================== subroutine sample_fission(i_nuclide, i_reaction) - integer, intent(in) :: i_nuclide ! index in nuclides array integer, intent(out) :: i_reaction ! index in nuc % reactions array @@ -194,7 +194,6 @@ contains real(8) :: prob real(8) :: cutoff type(Nuclide), pointer :: nuc - type(Reaction), pointer :: rxn ! Get pointer to nuclide nuc => nuclides(i_nuclide) @@ -219,14 +218,15 @@ contains FISSION_REACTION_LOOP: do i = 1, nuc % n_fission i_reaction = nuc % index_fission(i) - rxn => nuc % reactions(i_reaction) - ! if energy is below threshold for this reaction, skip it - if (i_grid < rxn % threshold) cycle + associate (rxn => nuc % reactions(i_reaction)) + ! if energy is below threshold for this reaction, skip it + if (i_grid < rxn % threshold) cycle - ! add to cumulative probability - prob = prob + ((ONE - f)*rxn%sigma(i_grid - rxn%threshold + 1) & - + f*(rxn%sigma(i_grid - rxn%threshold + 2))) + ! add to cumulative probability + prob = prob + ((ONE - f)*rxn%sigma(i_grid - rxn%threshold + 1) & + + f*(rxn%sigma(i_grid - rxn%threshold + 2))) + end associate ! Create fission bank sites if fission occurs if (prob > cutoff) exit FISSION_REACTION_LOOP @@ -300,18 +300,24 @@ contains ! SCATTER !=============================================================================== - subroutine scatter(p, i_nuclide) + subroutine scatter(p, i_nuclide, i_nuc_mat) type(Particle), intent(inout) :: p integer, intent(in) :: i_nuclide + integer, intent(in) :: i_nuc_mat integer :: i integer :: i_grid real(8) :: f real(8) :: prob real(8) :: cutoff + real(8) :: uvw_new(3) ! outgoing uvw for iso-in-lab scattering + real(8) :: uvw_old(3) ! incoming uvw for iso-in-lab scattering + real(8) :: phi ! azimuthal angle for iso-in-lab scattering type(Nuclide), pointer :: nuc - type(Reaction), pointer :: rxn + + ! copy incoming direction + uvw_old(:) = p % coord(1) % uvw ! Get pointer to nuclide and grid index/interpolation factor nuc => nuclides(i_nuclide) @@ -335,11 +341,8 @@ contains p % E, p % coord(1) % uvw, p % mu) else - ! get pointer to elastic scattering reaction - rxn => nuc % reactions(1) - ! Perform collision physics for elastic scattering - call elastic_scatter(i_nuclide, rxn, & + call elastic_scatter(i_nuclide, nuc % reactions(1), & p % E, p % coord(1) % uvw, p % mu, p % wgt) end if @@ -362,35 +365,48 @@ contains &// trim(nuc % name)) end if - rxn => nuc % reactions(i) + associate (rxn => nuc % reactions(i)) + ! Skip fission reactions + if (rxn % MT == N_FISSION .or. rxn % MT == N_F .or. rxn % MT == N_NF & + .or. rxn % MT == N_2NF .or. rxn % MT == N_3NF) cycle - ! Skip fission reactions - if (rxn % MT == N_FISSION .or. rxn % MT == N_F .or. rxn % MT == N_NF & - .or. rxn % MT == N_2NF .or. rxn % MT == N_3NF) cycle + ! some materials have gas production cross sections with MT > 200 that + ! are duplicates. Also MT=4 is total level inelastic scattering which + ! should be skipped + if (rxn % MT >= 200 .or. rxn % MT == N_LEVEL) cycle - ! some materials have gas production cross sections with MT > 200 that - ! are duplicates. Also MT=4 is total level inelastic scattering which - ! should be skipped - if (rxn % MT >= 200 .or. rxn % MT == N_LEVEL) cycle + ! if energy is below threshold for this reaction, skip it + if (i_grid < rxn % threshold) cycle - ! if energy is below threshold for this reaction, skip it - if (i_grid < rxn % threshold) cycle - - ! add to cumulative probability - prob = prob + ((ONE - f)*rxn%sigma(i_grid - rxn%threshold + 1) & - + f*(rxn%sigma(i_grid - rxn%threshold + 2))) + ! add to cumulative probability + prob = prob + ((ONE - f)*rxn%sigma(i_grid - rxn%threshold + 1) & + + f*(rxn%sigma(i_grid - rxn%threshold + 2))) + end associate end do ! Perform collision physics for inelastic scattering - call inelastic_scatter(nuc, rxn, p % E, p % coord(1) % uvw, & - p % mu, p % wgt) - p % event_MT = rxn % MT + call inelastic_scatter(nuc, nuc%reactions(i), p) + p % event_MT = nuc%reactions(i)%MT end if ! Set event component p % event = EVENT_SCATTER + ! sample new outgoing angle for isotropic in lab scattering + if (materials(p % material) % p0(i_nuc_mat)) then + + ! sample isotropic-in-lab outgoing direction + uvw_new(1) = TWO * prn() - ONE + phi = TWO * PI * prn() + uvw_new(2) = cos(phi) * sqrt(ONE - uvw_new(1)*uvw_new(1)) + uvw_new(3) = sin(phi) * sqrt(ONE - uvw_new(1)*uvw_new(1)) + p % mu = dot_product(uvw_old, uvw_new) + + ! change direction of particle + p % coord(1) % uvw = uvw_new + end if + end subroutine scatter !=============================================================================== @@ -399,9 +415,8 @@ contains !=============================================================================== subroutine elastic_scatter(i_nuclide, rxn, E, uvw, mu_lab, wgt) - integer, intent(in) :: i_nuclide - type(Reaction), pointer :: rxn + type(Reaction), intent(in) :: rxn real(8), intent(inout) :: E real(8), intent(inout) :: uvw(3) real(8), intent(out) :: mu_lab @@ -466,6 +481,12 @@ contains ! Set energy and direction of particle in LAB frame uvw = v_n / vel + ! Because of floating-point roundoff, it may be possible for mu_lab to be + ! outside of the range [-1,1). In these cases, we just set mu_lab to exactly + ! -1 or 1 + + if (abs(mu_lab) > ONE) mu_lab = sign(ONE,mu_lab) + end subroutine elastic_scatter !=============================================================================== @@ -712,6 +733,12 @@ contains end if ! (inelastic secondary energy treatment) end if ! (elastic or inelastic) + ! Because of floating-point roundoff, it may be possible for mu to be + ! outside of the range [-1,1). In these cases, we just set mu to exactly + ! -1 or 1 + + if (abs(mu) > ONE) mu = sign(ONE,mu) + ! change direction of particle uvw = rotate_angle(uvw, mu) @@ -726,9 +753,7 @@ contains !=============================================================================== subroutine sample_target_velocity(nuc, v_target, E, uvw, v_neut, wgt, xs_eff) - - type(Nuclide), pointer :: nuc ! target nuclide at temperature T - + type(Nuclide), intent(in) :: nuc ! target nuclide at temperature T real(8), intent(out) :: v_target(3) ! target velocity real(8), intent(in) :: v_neut(3) ! neutron velocity real(8), intent(in) :: E ! particle energy @@ -973,8 +998,7 @@ contains !=============================================================================== subroutine sample_cxs_target_velocity(nuc, v_target, E, uvw) - - type(Nuclide), pointer :: nuc ! target nuclide at temperature + type(Nuclide), intent(in) :: nuc ! target nuclide at temperature real(8), intent(out) :: v_target(3) real(8), intent(in) :: E real(8), intent(in) :: uvw(3) @@ -1047,25 +1071,23 @@ contains !=============================================================================== subroutine create_fission_sites(p, i_nuclide, i_reaction) - type(Particle), intent(inout) :: p integer, intent(in) :: i_nuclide integer, intent(in) :: i_reaction - integer :: i ! loop index - integer :: nu ! actual number of neutrons produced - integer :: ijk(3) ! indices in ufs mesh - real(8) :: nu_t ! total nu - real(8) :: mu ! fission neutron angular cosine - real(8) :: phi ! fission neutron azimuthal angle - real(8) :: weight ! weight adjustment for ufs method - logical :: in_mesh ! source site in ufs mesh? + integer :: nu_d(MAX_DELAYED_GROUPS) ! number of delayed neutrons born + integer :: i ! loop index + integer :: nu ! actual number of neutrons produced + integer :: ijk(3) ! indices in ufs mesh + real(8) :: nu_t ! total nu + real(8) :: mu ! fission neutron angular cosine + real(8) :: phi ! fission neutron azimuthal angle + real(8) :: weight ! weight adjustment for ufs method + logical :: in_mesh ! source site in ufs mesh? type(Nuclide), pointer :: nuc - type(Reaction), pointer :: rxn ! Get pointers nuc => nuclides(i_nuclide) - rxn => nuc % reactions(i_reaction) ! TODO: Heat generation from fission @@ -1109,6 +1131,11 @@ contains ! Bank source neutrons if (nu == 0 .or. n_bank == size(fission_bank)) return + + ! Initialize counter of delayed neutrons encountered for each delayed group + ! to zero. + nu_d(:) = 0 + p % fission = .true. ! Fission neutrons will be banked do i = int(n_bank,4) + 1, int(min(n_bank + nu, int(size(fission_bank),8)),4) ! Bank source neutrons by copying particle data @@ -1131,15 +1158,25 @@ contains ! Sample secondary energy distribution for fission reaction and set energy ! in fission bank - fission_bank(i) % E = sample_fission_energy(nuc, rxn, p % E) + fission_bank(i) % E = sample_fission_energy(nuc, nuc%reactions(& + i_reaction), p) + + ! Set the delayed group of the neutron + fission_bank(i) % delayed_group = p % delayed_group + + ! Increment the number of neutrons born delayed + if (p % delayed_group > 0) then + nu_d(p % delayed_group) = nu_d(p % delayed_group) + 1 + end if end do ! increment number of bank sites n_bank = min(n_bank + nu, int(size(fission_bank),8)) - ! Store total weight banked for analog fission tallies + ! Store total and delayed weight banked for analog fission tallies p % n_bank = nu p % wgt_bank = nu/weight + p % n_delayed_bank(:) = nu_d(:) end subroutine create_fission_sites @@ -1147,12 +1184,12 @@ contains ! SAMPLE_FISSION_ENERGY !=============================================================================== - function sample_fission_energy(nuc, rxn, E) result(E_out) + function sample_fission_energy(nuc, rxn, p) result(E_out) - type(Nuclide), pointer :: nuc - type(Reaction), pointer :: rxn - real(8), intent(in) :: E ! incoming energy of neutron - real(8) :: E_out ! outgoing energy of fission neutron + type(Nuclide), intent(in) :: nuc + type(Reaction), intent(in) :: rxn + type(Particle), intent(inout) :: p ! Particle causing fission + real(8) :: E_out ! outgoing energy of fission neutron integer :: j ! index on nu energy grid / precursor group integer :: lc ! index before start of energies/nu values @@ -1170,10 +1207,10 @@ contains type(DistEnergy), pointer :: edist ! Determine total nu - nu_t = nu_total(nuc, E) + nu_t = nu_total(nuc, p % E) ! Determine delayed nu - nu_d = nu_delayed(nuc, E) + nu_d = nu_delayed(nuc, p % E) ! Determine delayed neutron fraction beta = nu_d / nu_t @@ -1193,7 +1230,7 @@ contains ! determine delayed neutron precursor yield for group j yield = interpolate_tab1(nuc % nu_d_precursor_data( & - lc+1:lc+2+2*NR+2*NE), E) + lc+1:lc+2+2*NR+2*NE), p % E) ! Check if this group is sampled prob = prob + yield @@ -1208,6 +1245,9 @@ contains ! n_precursor -- check for this condition j = min(j, nuc % n_precursor) + ! set the delayed group for the particle born from fission + p % delayed_group = j + ! select energy distribution for group j law = nuc % nu_d_edist(j) % law edist => nuc % nu_d_edist(j) @@ -1216,13 +1256,13 @@ contains n_sample = 0 do if (law == 44 .or. law == 61) then - call sample_energy(edist, E, E_out, mu) + call sample_energy(edist, p % E, E_out, mu) else - call sample_energy(edist, E, E_out) + call sample_energy(edist, p % E, E_out) end if - ! resample if energy is >= 20 MeV - if (E_out < 20) exit + ! resample if energy is greater than maximum neutron energy + if (E_out < energy_max_neutron) exit ! check for large number of resamples n_sample = n_sample + 1 @@ -1237,18 +1277,21 @@ contains ! ==================================================================== ! PROMPT NEUTRON SAMPLED + ! set the delayed group for the particle born from fission to 0 + p % delayed_group = 0 + ! sample from prompt neutron energy distribution law = rxn % edist % law n_sample = 0 do if (law == 44 .or. law == 61) then - call sample_energy(rxn%edist, E, E_out, prob) + call sample_energy(rxn%edist, p % E, E_out, prob) else - call sample_energy(rxn%edist, E, E_out) + call sample_energy(rxn%edist, p % E, E_out) end if - ! resample if energy is >= 20 MeV - if (E_out < 20) exit + ! resample if energy is greater than maximum neutron energy + if (E_out < energy_max_neutron) exit ! check for large number of resamples n_sample = n_sample + 1 @@ -1268,24 +1311,23 @@ contains ! than fission), i.e. level scattering, (n,np), (n,na), etc. !=============================================================================== - subroutine inelastic_scatter(nuc, rxn, E, uvw, mu, wgt) + subroutine inelastic_scatter(nuc, rxn, p) + type(Nuclide), intent(in) :: nuc + type(Reaction), intent(in) :: rxn + type(Particle), intent(inout) :: p - type(Nuclide), pointer :: nuc - type(Reaction), pointer :: rxn - real(8), intent(inout) :: E ! energy in lab (incoming/outgoing) - real(8), intent(inout) :: uvw(3) ! directional cosines - real(8), intent(out) :: mu ! cosine of scattering angle in lab - real(8), intent(inout) :: wgt ! particle weight - - integer :: law ! secondary energy distribution law - real(8) :: A ! atomic weight ratio of nuclide - real(8) :: E_in ! incoming energy - real(8) :: E_cm ! outgoing energy in center-of-mass - real(8) :: Q ! Q-value of reaction - real(8) :: yield ! neutron yield + integer :: i ! loop index + integer :: law ! secondary energy distribution law + real(8) :: E ! energy in lab (incoming/outgoing) + real(8) :: mu ! cosine of scattering angle in lab + real(8) :: A ! atomic weight ratio of nuclide + real(8) :: E_in ! incoming energy + real(8) :: E_cm ! outgoing energy in center-of-mass + real(8) :: Q ! Q-value of reaction + real(8) :: yield ! neutron yield ! copy energy of neutron - E_in = E + E_in = p % E ! determine A and Q A = nuc % awr @@ -1300,6 +1342,11 @@ contains ! sample outgoing energy if (law == 44 .or. law == 61) then call sample_energy(rxn%edist, E_in, E, mu) + ! Because of floating-point roundoff, it may be possible for mu to be + ! outside of the range [-1,1). In these cases, we just set mu to exactly + ! -1 or 1 + + if (abs(mu) > ONE) mu = sign(ONE,mu) elseif (law == 66) then call sample_energy(rxn%edist, E_in, E, A=A, Q=Q) else @@ -1317,18 +1364,30 @@ contains ! determine outgoing angle in lab mu = mu * sqrt(E_cm/E) + ONE/(A+ONE) * sqrt(E_in/E) + + ! Because of floating-point roundoff, it may be possible for mu to be + ! outside of the range [-1,1). In these cases, we just set mu to exactly + ! -1 or 1 + + if (abs(mu) > ONE) mu = sign(ONE,mu) end if + ! Set outgoing energy and scattering angle + p % E = E + p % mu = mu + ! change direction of particle - uvw = rotate_angle(uvw, mu) + p % coord(1) % uvw = rotate_angle(p % coord(1) % uvw, mu) ! change weight of particle based on yield if (rxn % multiplicity_with_E) then yield = interpolate_tab1(rxn % multiplicity_E, E_in) + p % wgt = yield * p % wgt else - yield = rxn % multiplicity + do i = 1, rxn % multiplicity - 1 + call p % create_secondary(p % coord(1) % uvw, NEUTRON) + end do end if - wgt = yield * wgt end subroutine inelastic_scatter @@ -1339,8 +1398,7 @@ contains !=============================================================================== function sample_angle(rxn, E) result(mu) - - type(Reaction), pointer :: rxn ! reaction + type(Reaction), intent(in) :: rxn ! reaction real(8), intent(in) :: E ! incoming energy real(8) :: xi ! random number on [0,1) @@ -1466,7 +1524,6 @@ contains !=============================================================================== function rotate_angle(uvw0, mu) result(uvw) - real(8), intent(in) :: uvw0(3) ! directional cosine real(8), intent(in) :: mu ! cosine of angle in lab or CM real(8) :: uvw(3) ! rotated directional cosine @@ -1515,8 +1572,7 @@ contains !=============================================================================== recursive subroutine sample_energy(edist, E_in, E_out, mu_out, A, Q) - - type(DistEnergy), pointer :: edist + type(DistEnergy), intent(in) :: edist real(8), intent(in) :: E_in ! incoming energy of neutron real(8), intent(out) :: E_out ! outgoing energy real(8), intent(inout), optional :: mu_out ! outgoing cosine of angle diff --git a/src/plot.F90 b/src/plot.F90 index e507b6093b..a5497bc203 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -5,7 +5,9 @@ module plot use geometry, only: find_cell, check_cell_overlap use geometry_header, only: Cell, BASE_UNIVERSE use global + use hdf5_interface use mesh, only: get_mesh_indices + use mesh_header, only: RegularMesh use output, only: write_message use particle_header, only: Particle, LocalCoord use plot_header @@ -14,6 +16,8 @@ module plot use progress_header, only: ProgressBar use string, only: to_str + use hdf5 + implicit none contains @@ -212,7 +216,7 @@ contains real(8) :: xyz_ur_plot(3) ! upper right xyz of plot image real(8) :: xyz_ll(3) ! lower left xyz real(8) :: xyz_ur(3) ! upper right xyz - type(StructuredMesh), pointer :: m => null() + type(RegularMesh), pointer :: m m => pl % meshlines_mesh @@ -305,25 +309,26 @@ contains integer :: i ! loop index for height integer :: j ! loop index for width + integer :: unit_plot ! Open PPM file for writing - open(UNIT=UNIT_PLOT, FILE=pl % path_plot) + open(NEWUNIT=unit_plot, FILE=pl % path_plot) ! Write header - write(UNIT_PLOT, '(A2)') 'P6' - write(UNIT_PLOT, '(I0,'' '',I0)') img%width, img%height - write(UNIT_PLOT, '(A)') '255' + write(unit_plot, '(A2)') 'P6' + write(unit_plot, '(I0,'' '',I0)') img%width, img%height + write(unit_plot, '(A)') '255' ! Write color for each pixel do j = 1, img % height do i = 1, img % width - write(UNIT_PLOT, '(3A1)', advance='no') achar(img%red(i,j)), & + write(unit_plot, '(3A1)', advance='no') achar(img%red(i,j)), & achar(img%green(i,j)), achar(img%blue(i,j)) end do end do ! Close plot file - close(UNIT=UNIT_PLOT) + close(UNIT=unit_plot) end subroutine output_ppm @@ -346,10 +351,20 @@ contains integer :: x, y, z ! voxel location indices integer :: rgb(3) ! colors (red, green, blue) from 0-255 integer :: id ! id of cell or material + integer :: hdf5_err + integer, target :: data(pl%pixels(3),pl%pixels(2)) + integer(HID_T) :: file_id + integer(HID_T) :: dspace + integeR(HID_T) :: memspace + integer(HID_T) :: dset + integer(HSIZE_T) :: dims(3) + integer(HSIZE_T) :: dims_slab(3) + integer(HSIZE_T) :: offset(3) real(8) :: vox(3) ! x, y, and z voxel widths real(8) :: ll(3) ! lower left starting point for each sweep direction type(Particle) :: p type(ProgressBar) :: progress + type(c_ptr) :: f_ptr ! compute voxel widths in each direction vox = pl % width/dble(pl % pixels) @@ -364,11 +379,30 @@ contains p % coord(1) % universe = BASE_UNIVERSE ! Open binary plot file for writing - open(UNIT=UNIT_PLOT, FILE=pl % path_plot, STATUS='replace', & - ACCESS='stream') + file_id = file_create(pl%path_plot) ! write plot header info - write(UNIT_PLOT) pl % pixels, vox, ll + call write_dataset(file_id, "filetype", 'voxel') + call write_dataset(file_id, "num_voxels", pl%pixels) + call write_dataset(file_id, "voxel_width", vox) + call write_dataset(file_id, "lower_left", ll) + + ! Create dataset for voxel data -- note that the dimensions are reversed + ! since we want the order in the file to be z, y, x + dims(:) = [pl%pixels(3), pl%pixels(2), pl%pixels(1)] + call h5screate_simple_f(3, dims, dspace, hdf5_err) + call h5dcreate_f(file_id, "data", H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) + + ! Create another dataspace for 2D array in memory + dims_slab(1) = pl%pixels(3) + dims_slab(2) = pl%pixels(2) + dims_slab(3) = 1 + call h5screate_simple_f(2, dims_slab(1:2), memspace, hdf5_err) + + ! Initialize offset and get pointer to data + offset(:) = 0 + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims_slab, hdf5_err) + f_ptr = c_loc(data) ! move to center of voxels ll = ll + vox / TWO @@ -377,22 +411,19 @@ contains call progress % set_value(dble(x)/dble(pl % pixels(1))*100) do y = 1, pl % pixels(2) do z = 1, pl % pixels(3) - ! get voxel color call position_rgb(p, pl, rgb, id) ! write to plot file - write(UNIT_PLOT) id + data(z,y) = id ! advance particle in z direction p % coord(1) % xyz(3) = p % coord(1) % xyz(3) + vox(3) - end do ! advance particle in y direction p % coord(1) % xyz(2) = p % coord(1) % xyz(2) + vox(2) p % coord(1) % xyz(3) = ll(3) - end do ! advance particle in y direction @@ -400,9 +431,17 @@ contains p % coord(1) % xyz(2) = ll(2) p % coord(1) % xyz(3) = ll(3) + ! Write to HDF5 dataset + offset(3) = x - 1 + call h5soffset_simple_f(dspace, offset, hdf5_err) + call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, & + mem_space_id=memspace, file_space_id=dspace) end do - close(UNIT_PLOT) + call h5dclose_f(dset, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call file_close(file_id) end subroutine create_3d_dump diff --git a/src/plot_header.F90 b/src/plot_header.F90 index 8dc725d9d4..a6ea9a580d 100644 --- a/src/plot_header.F90 +++ b/src/plot_header.F90 @@ -1,7 +1,7 @@ module plot_header use constants - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh implicit none @@ -28,7 +28,7 @@ module plot_header integer :: pixels(3) ! pixel width/height of plot slice integer :: meshlines_width ! pixel width of meshlines integer :: level ! universe depth to plot the cells of - type(StructuredMesh), pointer :: meshlines_mesh => null() ! mesh to plot + type(RegularMesh), pointer :: meshlines_mesh => null() ! mesh to plot type(ObjectColor) :: meshlines_color ! Color for meshlines type(ObjectColor) :: not_found ! color for positions where no cell found type(ObjectColor), allocatable :: colors(:) ! colors of cells/mats diff --git a/src/relaxng/geometry.rnc b/src/relaxng/geometry.rnc index cebbc5b6a3..2a8d07b8c0 100644 --- a/src/relaxng/geometry.rnc +++ b/src/relaxng/geometry.rnc @@ -6,10 +6,10 @@ element geometry { (element universe { xsd:int } | attribute universe { xsd:int })? & ( (element fill { xsd:int } | attribute fill { xsd:int }) | - (element material { ( xsd:int | "void" ) } | + (element material { ( xsd:int | "void" ) } | attribute material { ( xsd:int | "void" ) }) ) & - (element surfaces { list { xsd:int* } } | attribute surfaces { list { xsd:int* } })? & + (element region { xsd:string } | attribute region { xsd:string })? & (element rotation { list { xsd:double+ } } | attribute rotation { list { xsd:double+ } })? & (element translation { list { xsd:double+ } } | attribute translation { list { xsd:double+ } })? }* @@ -18,7 +18,7 @@ element geometry { (element id { xsd:int } | attribute id { xsd:int }) & (element name { xsd:string { maxLength="52" } } | attribute name { xsd:string { maxLength="52" } })? & - (element type { xsd:string { maxLength = "15" } } | + (element type { xsd:string { maxLength = "15" } } | attribute type { xsd:string { maxLength = "15" } }) & (element coeffs { list { xsd:double+ } } | attribute coeffs { list { xsd:double+ } }) & (element boundary { ( "transmit" | "reflective" | "vacuum" ) } | @@ -29,12 +29,12 @@ element geometry { (element id { xsd:int } | attribute id { xsd:int }) & (element name { xsd:string { maxLength="52" } } | attribute name { xsd:string { maxLength="52" } })? & - (element dimension { list { xsd:positiveInteger+ } } | + (element dimension { list { xsd:positiveInteger+ } } | attribute dimension { list { xsd:positiveInteger+ } }) & (element lower_left { list { xsd:double+ } } | attribute lower_left { list { xsd:double+ } }) & (element pitch { list { xsd:double+ } } | attribute pitch { list { xsd:double+ } }) & (element universes { list { xsd:int+ } } | attribute universes { list { xsd:int+ } }) & - (element outside { xsd:int } | attribute outside { xsd:int })? + (element outer { xsd:int } | attribute outer { xsd:int })? }* & element hex_lattice { diff --git a/src/relaxng/geometry.rng b/src/relaxng/geometry.rng index fdbf74cbd5..fcb310d0b3 100644 --- a/src/relaxng/geometry.rng +++ b/src/relaxng/geometry.rng @@ -62,19 +62,11 @@ - - - - - - + + - - - - - - + + @@ -282,10 +274,10 @@ - + - + diff --git a/src/relaxng/materials.rnc b/src/relaxng/materials.rnc index ae85654972..da68ebf9ea 100644 --- a/src/relaxng/materials.rnc +++ b/src/relaxng/materials.rnc @@ -15,6 +15,8 @@ element materials { attribute name { xsd:string { maxLength = "7" } }) & (element xs { xsd:string { maxLength = "3" } } | attribute xs { xsd:string { maxLength = "3" } })? & + (element scattering { ( "data" | "iso-in-lab" ) } | + attribute scattering { ( "data" | "iso-in-lab" ) })? & ( (element ao { xsd:double } | attribute ao { xsd:double }) | (element wo { xsd:double } | attribute wo { xsd:double }) @@ -26,6 +28,8 @@ element materials { attribute name { xsd:string { maxLength = "2" } }) & (element xs { xsd:string { maxLength = "3" } } | attribute xs { xsd:string { maxLength = "3" } })? & + (element scattering { ( "data" | "iso-in-lab" ) } | + attribute scattering { ( "data" | "iso-in-lab" ) })? & ( (element ao { xsd:double } | attribute ao { xsd:double }) | (element wo { xsd:double } | attribute wo { xsd:double }) diff --git a/src/relaxng/materials.rng b/src/relaxng/materials.rng index 4c9496eae4..7aba5f7382 100644 --- a/src/relaxng/materials.rng +++ b/src/relaxng/materials.rng @@ -12,6 +12,20 @@ + + + + + 52 + + + + + 52 + + + + @@ -67,6 +81,22 @@ + + + + + data + iso-in-lab + + + + + data + iso-in-lab + + + + @@ -117,6 +147,22 @@ + + + + + data + iso-in-lab + + + + + data + iso-in-lab + + + + diff --git a/src/relaxng/tallies.rnc b/src/relaxng/tallies.rnc index c2e0860b8e..75afb0f231 100644 --- a/src/relaxng/tallies.rnc +++ b/src/relaxng/tallies.rnc @@ -1,8 +1,8 @@ element tallies { element mesh { (element id { xsd:int } | attribute id { xsd:int }) & - (element type { ( "rectangular" | "hexagonal" ) } | - attribute type { ( "rectangular" | "hexagonal" ) }) & + (element type { ( "regular" ) } | + attribute type { ( "regular" ) }) & (element dimension { list { xsd:positiveInteger+ } } | attribute dimension { list { xsd:positiveInteger+ } }) & (element lower_left { list { xsd:double+ } } | @@ -23,16 +23,18 @@ element tallies { attribute estimator { ( "analog" | "tracklength" ) })? & element filter { (element type { ( "cell" | "cellborn" | "material" | "universe" | - "surface" | "distribcell" | "mesh" | "energy" | "energyout" ) } | + "surface" | "distribcell" | "mesh" | "energy" | "energyout" | "mu" | + "polar" | "azimuthal" | "delayedgroup") } | attribute type { ( "cell" | "cellborn" | "material" | "universe" | - "surface" | "distribcell" | "mesh" | "energy" | "energyout" ) }) & + "surface" | "distribcell" | "mesh" | "energy" | "energyout" | "mu" | + "polar" | "azimuthal" | "delayedgroup") }) & (element bins { list { xsd:double+ } } | attribute bins { list { xsd:double+ } }) }* & element nuclides { list { xsd:string { maxLength = "12" }+ } }? & - element scores { + element scores { list { xsd:string { maxLength = "20" }+ } } & element trigger { diff --git a/src/relaxng/tallies.rng b/src/relaxng/tallies.rng index 9ea941feab..d35c170042 100644 --- a/src/relaxng/tallies.rng +++ b/src/relaxng/tallies.rng @@ -14,16 +14,10 @@ - - rectangular - hexagonal - + regular - - rectangular - hexagonal - + regular @@ -151,6 +145,10 @@ mesh energy energyout + delayedgroup + mu + polar + azimuthal @@ -164,6 +162,10 @@ mesh energy energyout + delayedgroup + mu + polar + azimuthal diff --git a/src/search.F90 b/src/search.F90 index dab7fa67ca..0c345471c2 100644 --- a/src/search.F90 +++ b/src/search.F90 @@ -18,7 +18,7 @@ contains ! value lies in the array. This is used extensively for energy grid searching !=============================================================================== - function binary_search_real(array, n, val) result(array_index) + pure function binary_search_real(array, n, val) result(array_index) integer, intent(in) :: n real(8), intent(in) :: array(n) @@ -28,41 +28,30 @@ contains integer :: L integer :: R integer :: n_iteration - real(8) :: testval L = 1 R = n if (val < array(L) .or. val > array(R)) then - call fatal_error("Value outside of array during binary search") + array_index = -1 + return end if n_iteration = 0 do while (R - L > 1) - - ! Check boundaries - if (val > array(L) .and. val < array(L+1)) then - array_index = L - return - elseif (val > array(R-1) .and. val < array(R)) then - array_index = R - 1 - return - end if - ! Find values at midpoint array_index = L + (R - L)/2 - testval = array(array_index) - if (val >= testval) then + if (val >= array(array_index)) then L = array_index - elseif (val < testval) then + else R = array_index end if ! check for large number of iterations n_iteration = n_iteration + 1 if (n_iteration == MAX_ITERATION) then - call fatal_error("Reached maximum number of iterations on binary & - &search.") + array_index = -2 + return end if end do @@ -70,7 +59,7 @@ contains end function binary_search_real - function binary_search_int4(array, n, val) result(array_index) + pure function binary_search_int4(array, n, val) result(array_index) integer, intent(in) :: n integer, intent(in) :: array(n) @@ -80,41 +69,30 @@ contains integer :: L integer :: R integer :: n_iteration - real(8) :: testval L = 1 R = n if (val < array(L) .or. val > array(R)) then - call fatal_error("Value outside of array during binary search") + array_index = -1 + return end if n_iteration = 0 do while (R - L > 1) - - ! Check boundaries - if (val > array(L) .and. val < array(L+1)) then - array_index = L - return - elseif (val > array(R-1) .and. val < array(R)) then - array_index = R - 1 - return - end if - ! Find values at midpoint array_index = L + (R - L)/2 - testval = array(array_index) - if (val >= testval) then + if (val >= array(array_index)) then L = array_index - elseif (val < testval) then + else R = array_index end if ! check for large number of iterations n_iteration = n_iteration + 1 if (n_iteration == MAX_ITERATION) then - call fatal_error("Reached maximum number of iterations on binary & - &search.") + array_index = -2 + return end if end do @@ -122,7 +100,7 @@ contains end function binary_search_int4 - function binary_search_int8(array, n, val) result(array_index) + pure function binary_search_int8(array, n, val) result(array_index) integer, intent(in) :: n integer(8), intent(in) :: array(n) @@ -132,41 +110,30 @@ contains integer :: L integer :: R integer :: n_iteration - real(8) :: testval L = 1 R = n if (val < array(L) .or. val > array(R)) then - call fatal_error("Value outside of array during binary search") + array_index = -1 + return end if n_iteration = 0 do while (R - L > 1) - - ! Check boundaries - if (val > array(L) .and. val < array(L+1)) then - array_index = L - return - elseif (val > array(R-1) .and. val < array(R)) then - array_index = R - 1 - return - end if - ! Find values at midpoint array_index = L + (R - L)/2 - testval = array(array_index) - if (val >= testval) then + if (val >= array(array_index)) then L = array_index - elseif (val < testval) then + else R = array_index end if ! check for large number of iterations n_iteration = n_iteration + 1 if (n_iteration == MAX_ITERATION) then - call fatal_error("Reached maximum number of iterations on binary & - &search.") + array_index = -2 + return end if end do diff --git a/src/simulation.F90 b/src/simulation.F90 new file mode 100644 index 0000000000..cc230d645b --- /dev/null +++ b/src/simulation.F90 @@ -0,0 +1,371 @@ +module simulation + +#ifdef MPI + use mpi +#endif + + use cmfd_execute, only: cmfd_init_batch, execute_cmfd + use constants, only: ZERO + use eigenvalue, only: count_source_for_ufs, calculate_average_keff, & + calculate_combined_keff, calculate_generation_keff, & + shannon_entropy, synchronize_bank, keff_generation +#ifdef _OPENMP + use eigenvalue, only: join_bank_from_threads +#endif + use global + use output, only: write_message, header, print_columns, & + print_batch_keff, print_generation + use particle_header, only: Particle + use random_lcg, only: set_particle_seed + use source, only: initialize_source + use state_point, only: write_state_point, write_source_point + use string, only: to_str + use tally, only: synchronize_tallies, setup_active_usertallies, & + reset_result + use trigger, only: check_triggers + use tracking, only: transport + + implicit none + private + public :: run_simulation + +contains + +!=============================================================================== +! RUN_SIMULATION encompasses all the main logic where iterations are performed +! over the batches, generations, and histories in a fixed source or k-eigenvalue +! calculation. +!=============================================================================== + + subroutine run_simulation() + + type(Particle) :: p + integer(8) :: i_work + + if (.not. restart_run) call initialize_source() + + ! Display header + if (master) then + if (run_mode == MODE_FIXEDSOURCE) then + call header("FIXED SOURCE TRANSPORT SIMULATION", level=1) + elseif (run_mode == MODE_EIGENVALUE) then + call header("K EIGENVALUE SIMULATION", level=1) + call print_columns() + end if + end if + + ! Turn on inactive timer + call time_inactive % start() + + ! ========================================================================== + ! LOOP OVER BATCHES + BATCH_LOOP: do current_batch = 1, n_max_batches + + call initialize_batch() + + ! Handle restart runs + if (restart_run .and. current_batch <= restart_batch) then + call replay_batch_history() + cycle BATCH_LOOP + end if + + ! ======================================================================= + ! LOOP OVER GENERATIONS + GENERATION_LOOP: do current_gen = 1, gen_per_batch + + call initialize_generation() + + ! Start timer for transport + call time_transport % start() + + ! ==================================================================== + ! LOOP OVER PARTICLES +!$omp parallel do schedule(static) firstprivate(p) + PARTICLE_LOOP: do i_work = 1, work + current_work = i_work + + ! grab source particle from bank + call initialize_history(p, current_work) + + ! transport particle + call transport(p) + + end do PARTICLE_LOOP +!$omp end parallel do + + ! Accumulate time for transport + call time_transport % stop() + + call finalize_generation() + + end do GENERATION_LOOP + + call finalize_batch() + + if (satisfy_triggers) exit BATCH_LOOP + + end do BATCH_LOOP + + call time_active % stop() + + ! ========================================================================== + ! END OF RUN WRAPUP + + if (master) call header("SIMULATION FINISHED", level=1) + + ! Clear particle + call p % clear() + + end subroutine run_simulation + +!=============================================================================== +! INITIALIZE_HISTORY +!=============================================================================== + + subroutine initialize_history(p, index_source) + + type(Particle), intent(inout) :: p + integer(8), intent(in) :: index_source + + integer(8) :: particle_seed ! unique index for particle + integer :: i + + ! set defaults + call p % initialize_from_source(source_bank(index_source)) + + ! set identifier for particle + p % id = work_index(rank) + index_source + + ! set random number seed + particle_seed = (overall_gen - 1)*n_particles + p % id + call set_particle_seed(particle_seed) + + ! set particle trace + trace = .false. + if (current_batch == trace_batch .and. current_gen == trace_gen .and. & + p % id == trace_particle) trace = .true. + + ! Set particle track. + p % write_track = .false. + if (write_all_tracks) then + p % write_track = .true. + else if (allocated(track_identifiers)) then + do i=1, size(track_identifiers(1,:)) + if (current_batch == track_identifiers(1,i) .and. & + ¤t_gen == track_identifiers(2,i) .and. & + &p % id == track_identifiers(3,i)) then + p % write_track = .true. + exit + end if + end do + end if + + end subroutine initialize_history + +!=============================================================================== +! INITIALIZE_BATCH +!=============================================================================== + + subroutine initialize_batch() + + if (run_mode == MODE_FIXEDSOURCE) then + call write_message("Simulating batch " // trim(to_str(current_batch)) & + // "...", 1) + end if + + ! Reset total starting particle weight used for normalizing tallies + total_weight = ZERO + + if (current_batch == n_inactive + 1) then + ! Switch from inactive batch timer to active batch timer + call time_inactive % stop() + call time_active % start() + + ! Enable active batches (and tallies_on if it hasn't been enabled) + active_batches = .true. + tallies_on = .true. + + ! Add user tallies to active tallies list +!$omp parallel + call setup_active_usertallies() +!$omp end parallel + end if + + ! check CMFD initialize batch + if (run_mode == MODE_EIGENVALUE) then + if (cmfd_run) call cmfd_init_batch() + end if + + end subroutine initialize_batch + +!=============================================================================== +! INITIALIZE_GENERATION +!=============================================================================== + + subroutine initialize_generation() + + ! set overall generation number + overall_gen = gen_per_batch*(current_batch - 1) + current_gen + + if (run_mode == MODE_EIGENVALUE) then + ! Reset number of fission bank sites + n_bank = 0 + + ! Count source sites if using uniform fission source weighting + if (ufs) call count_source_for_ufs() + + ! Store current value of tracklength k + keff_generation = global_tallies(K_TRACKLENGTH) % value + end if + + end subroutine initialize_generation + +!=============================================================================== +! FINALIZE_GENERATION +!=============================================================================== + + subroutine finalize_generation() + + ! Update global tallies with the omp private accumulation variables +!$omp parallel +!$omp critical + if (run_mode == MODE_EIGENVALUE) then + global_tallies(K_COLLISION) % value = & + global_tallies(K_COLLISION) % value + global_tally_collision + global_tallies(K_ABSORPTION) % value = & + global_tallies(K_ABSORPTION) % value + global_tally_absorption + global_tallies(K_TRACKLENGTH) % value = & + global_tallies(K_TRACKLENGTH) % value + global_tally_tracklength + end if + global_tallies(LEAKAGE) % value = & + global_tallies(LEAKAGE) % value + global_tally_leakage +!$omp end critical + + ! reset private tallies + if (run_mode == MODE_EIGENVALUE) then + global_tally_collision = 0 + global_tally_absorption = 0 + global_tally_tracklength = 0 + end if + global_tally_leakage = 0 +!$omp end parallel + + if (run_mode == MODE_EIGENVALUE) then +#ifdef _OPENMP + ! Join the fission bank from each thread into one global fission bank + call join_bank_from_threads() +#endif + + ! Distribute fission bank across processors evenly + call time_bank % start() + call synchronize_bank() + call time_bank % stop() + + ! Calculate shannon entropy + if (entropy_on) call shannon_entropy() + + ! Collect results and statistics + call calculate_generation_keff() + call calculate_average_keff() + + ! Write generation output + if (master .and. current_gen /= gen_per_batch) call print_generation() + end if + + end subroutine finalize_generation + +!=============================================================================== +! FINALIZE_BATCH handles synchronization and accumulation of tallies, +! calculation of Shannon entropy, getting single-batch estimate of keff, and +! turning on tallies when appropriate +!=============================================================================== + + subroutine finalize_batch() + + ! Collect tallies + call time_tallies % start() + call synchronize_tallies() + call time_tallies % stop() + + ! Reset global tally results + if (.not. active_batches) then + call reset_result(global_tallies) + n_realizations = 0 + end if + + if (run_mode == MODE_EIGENVALUE) then + ! Perform CMFD calculation if on + if (cmfd_on) call execute_cmfd() + + ! Display output + if (master) call print_batch_keff() + + ! Calculate combined estimate of k-effective + if (master) call calculate_combined_keff() + end if + + ! Check_triggers + if (master) call check_triggers() +#ifdef MPI + call MPI_BCAST(satisfy_triggers, 1, MPI_LOGICAL, 0, & + MPI_COMM_WORLD, mpi_err) +#endif + if (satisfy_triggers .or. & + (trigger_on .and. current_batch == n_max_batches)) then + call statepoint_batch % add(current_batch) + end if + + ! Write out state point if it's been specified for this batch + if (statepoint_batch % contains(current_batch)) then + call write_state_point() + end if + + ! Write out source point if it's been specified for this batch + if ((sourcepoint_batch % contains(current_batch) .or. source_latest) .and. & + source_write) then + call write_source_point() + end if + + if (master .and. current_batch == n_max_batches .and. & + run_mode == MODE_EIGENVALUE) then + ! Make sure combined estimate of k-effective is calculated at the last + ! batch in case no state point is written + call calculate_combined_keff() + end if + + end subroutine finalize_batch + +!=============================================================================== +! REPLAY_BATCH_HISTORY displays keff and entropy for each generation within a +! batch using data read from a state point file +!=============================================================================== + + subroutine replay_batch_history + + ! Write message at beginning + if (current_batch == 1) then + call write_message("Replaying history from state point...", 1) + end if + + if (run_mode == MODE_EIGENVALUE) then + do current_gen = 1, gen_per_batch + overall_gen = overall_gen + 1 + call calculate_average_keff() + + ! print out batch keff + if (current_gen < gen_per_batch) then + if (master) call print_generation() + else + if (master) call print_batch_keff() + end if + end do + end if + + ! Write message at end + if (current_batch == restart_batch) then + call write_message("Resuming simulation...", 1) + end if + + end subroutine replay_batch_history + +end module simulation diff --git a/src/source.F90 b/src/source.F90 index 7cfdcf655c..a16eb245d0 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -6,17 +6,20 @@ module source use geometry, only: find_cell use geometry_header, only: BASE_UNIVERSE use global + use hdf5_interface, only: file_create, file_open, file_close, read_dataset use math, only: maxwell_spectrum, watt_spectrum use output, only: write_message - use output_interface, only: BinaryOutput use particle_header, only: Particle use random_lcg, only: prn, set_particle_seed, prn_set_stream + use state_point, only: read_source_bank, write_source_bank use string, only: to_str #ifdef MPI use message_passing #endif + use hdf5, only: HID_T + implicit none contains @@ -27,12 +30,12 @@ contains subroutine initialize_source() - character(MAX_FILE_LEN) :: filename integer(8) :: i ! loop index over bank sites integer(8) :: id ! particle id - integer(4) :: itmp ! temporary integer - type(Bank), pointer :: src => null() ! source bank site - type(BinaryOutput) :: sp ! statepoint/source binary file + integer(HID_T) :: file_id + character(MAX_WORD_LEN) :: filetype + character(MAX_FILE_LEN) :: filename + type(Bank), pointer :: src ! source bank site call write_message("Initializing source particles...", 6) @@ -44,22 +47,22 @@ 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", filetype) ! Check to make sure this is a source file - if (itmp /= FILETYPE_SOURCE) then + if (filetype /= 'source') then call fatal_error("Specified starting source file not a source file & &type.") end if ! 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 @@ -78,26 +81,22 @@ contains ! Write out initial source if (write_initial_source) then - call write_message('Writing out initial source guess...', 1) -#ifdef HDF5 + call write_message('Writing out initial source...', 1) 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 !=============================================================================== -! SAMPLE_EXTERNAL_SOURCE +! SAMPLE_EXTERNAL_SOURCE samples the user-specified external source and stores +! the position, angle, and energy in a Bank type. !=============================================================================== subroutine sample_external_source(site) - - type(Bank), pointer :: site ! source site + type(Bank), intent(inout) :: site ! source site integer :: i ! dummy loop index real(8) :: r(3) ! sampled coordinates @@ -112,28 +111,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) @@ -145,24 +144,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) @@ -174,66 +173,67 @@ 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 - call fatal_error("Source energies above 20 MeV not allowed.") + site%E = external_source%params_energy(1) + if (site%E >= energy_max_neutron) then + call fatal_error("Source energy above range of energies of at least & + &one cross section table") 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 + ! resample if energy is greater than maximum neutron energy + if (site%E < energy_max_neutron) 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 + ! resample if energy is greater than maximum neutron energy + if (site%E < energy_max_neutron) exit end do case default @@ -245,74 +245,4 @@ contains end subroutine sample_external_source -!=============================================================================== -! GET_SOURCE_PARTICLE returns the next source particle -!=============================================================================== - - subroutine get_source_particle(p, index_source) - - type(Particle), intent(inout) :: p - integer(8), intent(in) :: index_source - - integer(8) :: particle_seed ! unique index for particle - integer :: i - type(Bank), pointer :: src - - ! set defaults - call p % initialize() - - ! Copy attributes from source to particle - src => source_bank(index_source) - call copy_source_attributes(p, src) - - ! set identifier for particle - p % id = work_index(rank) + index_source - - ! set random number seed - particle_seed = (overall_gen - 1)*n_particles + p % id - call set_particle_seed(particle_seed) - - ! set particle trace - trace = .false. - if (current_batch == trace_batch .and. current_gen == trace_gen .and. & - p % id == trace_particle) trace = .true. - - ! Set particle track. - p % write_track = .false. - if (write_all_tracks) then - p % write_track = .true. - else if (allocated(track_identifiers)) then - do i=1, size(track_identifiers(1,:)) - if (current_batch == track_identifiers(1,i) .and. & - ¤t_gen == track_identifiers(2,i) .and. & - &p % id == track_identifiers(3,i)) then - p % write_track = .true. - exit - end if - end do - end if - - end subroutine get_source_particle - -!=============================================================================== -! COPY_SOURCE_ATTRIBUTES -!=============================================================================== - - subroutine copy_source_attributes(p, src) - - type(Particle), intent(inout) :: p - type(Bank), pointer :: src - - ! copy attributes from source bank site - p % wgt = src % wgt - p % last_wgt = src % wgt - p % coord(1) % xyz = src % xyz - p % coord(1) % uvw = src % uvw - p % last_xyz = src % xyz - p % last_uvw = src % uvw - p % E = src % E - p % last_E = src % E - - end subroutine copy_source_attributes - end module source diff --git a/src/state_point.F90 b/src/state_point.F90 index 6b983231f6..f9f4b5b757 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -13,22 +13,25 @@ module state_point use constants + use endf, only: reaction_name use error, only: fatal_error, warning use global + use hdf5_interface use output, only: write_message, time_stamp use string, only: to_str, zero_padded, count_digits - use output_interface use tally_header, only: TallyObject - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use dict_header, only: ElemKeyValueII, ElemKeyValueCI #ifdef MPI use message_passing #endif - implicit none + use hdf5 - type(BinaryOutput) :: sp ! Statepoint/source output file + use, intrinsic :: ISO_C_BINDING, only: c_loc, c_ptr + + implicit none contains @@ -38,177 +41,160 @@ contains subroutine write_state_point() - character(MAX_FILE_LEN) :: filename - integer :: i, j, k - integer, allocatable :: id_array(:) - integer, allocatable :: key_array(:) - type(StructuredMesh), pointer :: mesh + integer :: i, j, k + integer :: i_list, i_xs + integer :: n_order ! loop index for moment orders + integer :: nm_order ! loop index for Ynm moment orders + integer, allocatable :: id_array(:) + integer, allocatable :: key_array(:) + integer(HID_T) :: file_id + integer(HID_T) :: cmfd_group + integer(HID_T) :: tallies_group, tally_group + integer(HID_T) :: meshes_group, mesh_group + integer(HID_T) :: filter_group + character(20), allocatable :: str_array(:) + character(MAX_FILE_LEN) :: filename + type(RegularMesh), pointer :: meshp type(TallyObject), pointer :: tally type(ElemKeyValueII), pointer :: current type(ElemKeyValueII), pointer :: next - character(8) :: moment_name ! name of moment (e.g, P3) - integer :: n_order ! loop index for moment orders - integer :: nm_order ! loop index for Ynm moment orders ! Set filename for state point filename = trim(path_output) // 'statepoint.' // & & zero_padded(current_batch, count_digits(n_max_batches)) - - ! Append appropriate extension -#ifdef HDF5 filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif ! Write message call write_message("Creating state point " // trim(filename) // "...", 1) if (master) then ! Create statepoint file - call sp % file_create(filename) + file_id = file_create(filename) ! Write file type - call sp % write_data(FILETYPE_STATEPOINT, "filetype") + call write_dataset(file_id, "filetype", 'statepoint') ! Write revision number for state point file - call sp % write_data(REVISION_STATEPOINT, "revision") + call write_dataset(file_id, "revision", REVISION_STATEPOINT) ! Write OpenMC version - call sp % write_data(VERSION_MAJOR, "version_major") - call sp % write_data(VERSION_MINOR, "version_minor") - call sp % write_data(VERSION_RELEASE, "version_release") + call write_dataset(file_id, "version_major", VERSION_MAJOR) + call write_dataset(file_id, "version_minor", VERSION_MINOR) + call write_dataset(file_id, "version_release", VERSION_RELEASE) ! Write current date and time - call sp % write_data(time_stamp(), "date_and_time") + call write_dataset(file_id, "date_and_time", time_stamp()) ! Write path to input - call sp % write_data(path_input, "path") + call write_dataset(file_id, "path", path_input) ! Write out random number seed - call sp % write_data(seed, "seed") + call write_dataset(file_id, "seed", seed) ! Write run information - call sp % write_data(run_mode, "run_mode") - call sp % write_data(n_particles, "n_particles") - call sp % write_data(n_batches, "n_batches") + select case(run_mode) + case (MODE_FIXEDSOURCE) + call write_dataset(file_id, "run_mode", "fixed source") + case (MODE_EIGENVALUE) + call write_dataset(file_id, "run_mode", "k-eigenvalue") + end select + call write_dataset(file_id, "n_particles", n_particles) + call write_dataset(file_id, "n_batches", n_batches) ! Write out current batch number - call sp % write_data(current_batch, "current_batch") + call write_dataset(file_id, "current_batch", current_batch) ! Indicate whether source bank is stored in statepoint if (source_separate) then - call sp % write_data(0, "source_present") + call write_dataset(file_id, "source_present", 0) else - call sp % write_data(1, "source_present") + call write_dataset(file_id, "source_present", 1) end if ! Write out information for eigenvalue run if (run_mode == MODE_EIGENVALUE) then - call sp % write_data(n_inactive, "n_inactive") - call sp % write_data(gen_per_batch, "gen_per_batch") - call sp % write_data(k_generation, "k_generation", & - length=current_batch*gen_per_batch) - call sp % write_data(entropy, "entropy", & - length=current_batch*gen_per_batch) - call sp % write_data(k_col_abs, "k_col_abs") - call sp % write_data(k_col_tra, "k_col_tra") - call sp % write_data(k_abs_tra, "k_abs_tra") - call sp % write_data(k_combined, "k_combined", length=2) + call write_dataset(file_id, "n_inactive", n_inactive) + call write_dataset(file_id, "gen_per_batch", gen_per_batch) + call write_dataset(file_id, "k_generation", k_generation) + call write_dataset(file_id, "entropy", entropy) + call write_dataset(file_id, "k_col_abs", k_col_abs) + call write_dataset(file_id, "k_col_tra", k_col_tra) + call write_dataset(file_id, "k_abs_tra", k_abs_tra) + call write_dataset(file_id, "k_combined", k_combined) ! Write out CMFD info if (cmfd_on) then -#ifdef HDF5 - call sp % open_group("cmfd") - call sp % close_group() -#endif - call sp % write_data(1, "cmfd_on") - call sp % write_data(cmfd % indices, "indices", length=4, group="cmfd") - call sp % write_data(cmfd % k_cmfd, "k_cmfd", length=current_batch, & - group="cmfd") - call sp % write_data(cmfd % cmfd_src, "cmfd_src", & - length=(/cmfd % indices(4), cmfd % indices(1), & - cmfd % indices(2), cmfd % indices(3)/), & - group="cmfd") - call sp % write_data(cmfd % entropy, "cmfd_entropy", & - length=current_batch, group="cmfd") - call sp % write_data(cmfd % balance, "cmfd_balance", & - length=current_batch, group="cmfd") - call sp % write_data(cmfd % dom, "cmfd_dominance", & - length = current_batch, group="cmfd") - call sp % write_data(cmfd % src_cmp, "cmfd_srccmp", & - length = current_batch, group="cmfd") + call write_dataset(file_id, "cmfd_on", 1) + + cmfd_group = create_group(file_id, "cmfd") + call write_dataset(cmfd_group, "indices", cmfd%indices) + call write_dataset(cmfd_group, "k_cmfd", cmfd%k_cmfd) + call write_dataset(cmfd_group, "cmfd_src", cmfd%cmfd_src) + call write_dataset(cmfd_group, "cmfd_entropy", cmfd%entropy) + call write_dataset(cmfd_group, "cmfd_balance", cmfd%balance) + call write_dataset(cmfd_group, "cmfd_dominance", cmfd%dom) + call write_dataset(cmfd_group, "cmfd_srccmp", cmfd%src_cmp) + call close_group(cmfd_group) else - call sp % write_data(0, "cmfd_on") + call write_dataset(file_id, "cmfd_on", 0) end if end if -#ifdef HDF5 - call sp % open_group("tallies") - call sp % close_group() -#endif + tallies_group = create_group(file_id, "tallies") ! Write number of meshes - call sp % write_data(n_meshes, "n_meshes", group="tallies/meshes") + meshes_group = create_group(tallies_group, "meshes") + call write_dataset(meshes_group, "n_meshes", n_meshes) if (n_meshes > 0) then ! Print list of mesh IDs - current => mesh_dict % keys() + current => mesh_dict%keys() allocate(id_array(n_meshes)) allocate(key_array(n_meshes)) i = 1 do while (associated(current)) - key_array(i) = current % key - id_array(i) = current % value + key_array(i) = current%key + id_array(i) = current%value ! Move to next mesh - next => current % next + next => current%next deallocate(current) current => next i = i + 1 end do - call sp % write_data(id_array, "ids", & - group="tallies/meshes", length=n_meshes) - call sp % write_data(key_array, "keys", & - group="tallies/meshes", length=n_meshes) + call write_dataset(meshes_group, "ids", id_array) + call write_dataset(meshes_group, "keys", key_array) deallocate(key_array) ! Write information for meshes MESH_LOOP: do i = 1, n_meshes + meshp => meshes(id_array(i)) + mesh_group = create_group(meshes_group, "mesh " // trim(to_str(meshp%id))) - mesh => meshes(id_array(i)) + select case (meshp%type) + case (MESH_REGULAR) + call write_dataset(mesh_group, "type", "regular") + end select + call write_dataset(mesh_group, "dimension", meshp%dimension) + call write_dataset(mesh_group, "lower_left", meshp%lower_left) + call write_dataset(mesh_group, "upper_right", meshp%upper_right) + call write_dataset(mesh_group, "width", meshp%width) - call sp % write_data(mesh % id, "id", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id))) - call sp % write_data(mesh % type, "type", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id))) - call sp % write_data(mesh % n_dimension, "n_dimension", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id))) - call sp % write_data(mesh % dimension, "dimension", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id)), & - length=mesh % n_dimension) - call sp % write_data(mesh % lower_left, "lower_left", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id)), & - length=mesh % n_dimension) - call sp % write_data(mesh % upper_right, "upper_right", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id)), & - length=mesh % n_dimension) - call sp % write_data(mesh % width, "width", & - group="tallies/meshes/mesh " // trim(to_str(mesh % id)), & - length=mesh % n_dimension) + call close_group(mesh_group) end do MESH_LOOP deallocate(id_array) - end if + call close_group(meshes_group) + ! Write number of tallies - call sp % write_data(n_tallies, "n_tallies", group="tallies") + call write_dataset(tallies_group, "n_tallies", n_tallies) if (n_tallies > 0) then @@ -219,14 +205,12 @@ contains ! Write all tally information except results do i = 1, n_tallies tally => tallies(i) - key_array(i) = tally % id + key_array(i) = tally%id id_array(i) = i end do - call sp % write_data(id_array, "ids", & - group="tallies", length=n_tallies) - call sp % write_data(key_array, "keys", & - group="tallies", length=n_tallies) + call write_dataset(tallies_group, "ids", id_array) + call write_dataset(tallies_group, "keys", key_array) deallocate(key_array) @@ -235,110 +219,188 @@ contains ! Get pointer to tally tally => tallies(i) + tally_group = create_group(tallies_group, "tally " // & + trim(to_str(tally%id))) - call sp % write_data(tally % estimator, "estimator", & - group="tallies/tally " // trim(to_str(tally % id))) - call sp % write_data(tally % n_realizations, "n_realizations", & - group="tallies/tally " // trim(to_str(tally % id))) - call sp % write_data(tally % n_filters, "n_filters", & - group="tallies/tally " // trim(to_str(tally % id))) + select case(tally%estimator) + case (ESTIMATOR_ANALOG) + call write_dataset(tally_group, "estimator", "analog") + case (ESTIMATOR_TRACKLENGTH) + call write_dataset(tally_group, "estimator", "tracklength") + case (ESTIMATOR_COLLISION) + call write_dataset(tally_group, "estimator", "collision") + end select + call write_dataset(tally_group, "n_realizations", tally%n_realizations) + call write_dataset(tally_group, "n_filters", tally%n_filters) ! Write filter information - FILTER_LOOP: do j = 1, tally % n_filters + FILTER_LOOP: do j = 1, tally%n_filters + filter_group = create_group(tally_group, "filter " // & + trim(to_str(j))) - call sp % write_data(tally % filters(j) % type, "type", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j)) - call sp % write_data(tally % filters(j) % offset, "offset", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j)) - call sp % write_data(tally % filters(j) % n_bins, "n_bins", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j)) + ! Write name of type + select case (tally%filters(j)%type) + case(FILTER_UNIVERSE) + call write_dataset(filter_group, "type", "universe") + case(FILTER_MATERIAL) + call write_dataset(filter_group, "type", "material") + case(FILTER_CELL) + call write_dataset(filter_group, "type", "cell") + case(FILTER_CELLBORN) + call write_dataset(filter_group, "type", "cellborn") + case(FILTER_SURFACE) + call write_dataset(filter_group, "type", "surface") + case(FILTER_MESH) + call write_dataset(filter_group, "type", "mesh") + case(FILTER_ENERGYIN) + call write_dataset(filter_group, "type", "energy") + case(FILTER_ENERGYOUT) + call write_dataset(filter_group, "type", "energyout") + case(FILTER_MU) + call write_dataset(filter_group, "type", "mu") + case(FILTER_POLAR) + call write_dataset(filter_group, "type", "polar") + case(FILTER_AZIMUTHAL) + call write_dataset(filter_group, "type", "azimuthal") + case(FILTER_DISTRIBCELL) + call write_dataset(filter_group, "type", "distribcell") + case(FILTER_DELAYEDGROUP) + call write_dataset(filter_group, "type", "delayedgroup") + end select + + call write_dataset(filter_group, "offset", tally%filters(j)%offset) + call write_dataset(filter_group, "n_bins", tally%filters(j)%n_bins) if (tally % filters(j) % type == FILTER_ENERGYIN .or. & - tally % filters(j) % type == FILTER_ENERGYOUT) then - call sp % write_data(tally % filters(j) % real_bins, "bins", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j), & - length=size(tally % filters(j) % real_bins)) + tally % filters(j) % type == FILTER_ENERGYOUT .or. & + tally % filters(j) % type == FILTER_MU .or. & + tally % filters(j) % type == FILTER_POLAR .or. & + tally % filters(j) % type == FILTER_AZIMUTHAL) then + call write_dataset(filter_group, "bins", & + tally%filters(j)%real_bins) else - call sp % write_data(tally % filters(j) % int_bins, "bins", & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/filter " // to_str(j), & - length=size(tally % filters(j) % int_bins)) + call write_dataset(filter_group, "bins", & + tally%filters(j)%int_bins) end if + call close_group(filter_group) end do FILTER_LOOP - call sp % write_data(tally % n_nuclide_bins, "n_nuclides", & - group="tallies/tally " // trim(to_str(tally % id))) - ! Set up nuclide bin array and then write - allocate(key_array(tally % n_nuclide_bins)) - NUCLIDE_LOOP: do j = 1, tally % n_nuclide_bins - if (tally % nuclide_bins(j) > 0) then - key_array(j) = nuclides(tally % nuclide_bins(j)) % zaid + allocate(str_array(tally%n_nuclide_bins)) + NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins + if (tally%nuclide_bins(j) > 0) then + ! Get index in cross section listings for this nuclide + i_list = nuclides(tally%nuclide_bins(j))%listing + + ! Determine position of . in alias string (e.g. "U-235.71c"). If + ! no . is found, just use the entire string. + i_xs = index(xs_listings(i_list)%alias, '.') + if (i_xs > 0) then + str_array(j) = xs_listings(i_list)%alias(1:i_xs - 1) + else + str_array(j) = xs_listings(i_list)%alias + end if else - key_array(j) = tally % nuclide_bins(j) + str_array(j) = 'total' end if end do NUCLIDE_LOOP - call sp % write_data(key_array, "nuclides", & - group="tallies/tally " // trim(to_str(tally % id)), & - length=tally % n_nuclide_bins) - deallocate(key_array) + call write_dataset(tally_group, "nuclides", str_array) + deallocate(str_array) - call sp % write_data(tally % n_score_bins, "n_score_bins", & - group="tallies/tally " // trim(to_str(tally % id))) - call sp % write_data(tally % score_bins, "score_bins", & - group="tallies/tally " // trim(to_str(tally % id)), & - length=tally % n_score_bins) - call sp % write_data(tally % n_user_score_bins, "n_user_score_bins", & - group="tallies/tally " // to_str(tally % id)) + call write_dataset(tally_group, "n_score_bins", tally%n_score_bins) + allocate(str_array(size(tally%score_bins))) + do j = 1, size(tally%score_bins) + select case(tally%score_bins(j)) + case (SCORE_FLUX) + str_array(j) = "flux" + case (SCORE_TOTAL) + str_array(j) = "total" + case (SCORE_SCATTER) + str_array(j) = "scatter" + case (SCORE_NU_SCATTER) + str_array(j) = "nu-scatter" + case (SCORE_SCATTER_N) + str_array(j) = "scatter-n" + case (SCORE_SCATTER_PN) + str_array(j) = "scatter-pn" + case (SCORE_NU_SCATTER_N) + str_array(j) = "nu-scatter-n" + case (SCORE_NU_SCATTER_PN) + str_array(j) = "nu-scatter-pn" + case (SCORE_TRANSPORT) + str_array(j) = "transport" + case (SCORE_N_1N) + str_array(j) = "n1n" + case (SCORE_ABSORPTION) + str_array(j) = "absorption" + case (SCORE_FISSION) + str_array(j) = "fission" + case (SCORE_NU_FISSION) + str_array(j) = "nu-fission" + case (SCORE_DELAYED_NU_FISSION) + str_array(j) = "delayed-nu-fission" + case (SCORE_KAPPA_FISSION) + str_array(j) = "kappa-fission" + case (SCORE_CURRENT) + str_array(j) = "current" + case (SCORE_FLUX_YN) + str_array(j) = "flux-yn" + case (SCORE_TOTAL_YN) + str_array(j) = "total-yn" + case (SCORE_SCATTER_YN) + str_array(j) = "scatter-yn" + case (SCORE_NU_SCATTER_YN) + str_array(j) = "nu-scatter-yn" + case (SCORE_EVENTS) + str_array(j) = "events" + case (SCORE_INVERSE_VELOCITY) + str_array(j) = "inverse-velocity" + case default + str_array(j) = reaction_name(tally%score_bins(j)) + end select + end do + call write_dataset(tally_group, "score_bins", str_array) + call write_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) + + deallocate(str_array) ! Write explicit moment order strings for each score bin k = 1 - MOMENT_LOOP: do j = 1, tally % n_user_score_bins - select case(tally % score_bins(k)) + allocate(str_array(tally%n_score_bins)) + MOMENT_LOOP: do j = 1, tally%n_user_score_bins + select case(tally%score_bins(k)) case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - moment_name = 'P' // trim(to_str(tally % moment_order(k))) - call sp % write_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/moments") + str_array(k) = 'P' // trim(to_str(tally%moment_order(k))) k = k + 1 case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - do n_order = 0, tally % moment_order(k) - moment_name = 'P' // trim(to_str(n_order)) - call sp % write_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/moments") + do n_order = 0, tally%moment_order(k) + str_array(k) = 'P' // trim(to_str(n_order)) k = k + 1 end do case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & - SCORE_TOTAL_YN) - do n_order = 0, tally % moment_order(k) + SCORE_TOTAL_YN) + do n_order = 0, tally%moment_order(k) do nm_order = -n_order, n_order - moment_name = 'Y' // trim(to_str(n_order)) // ',' // & + str_array(k) = 'Y' // trim(to_str(n_order)) // ',' // & trim(to_str(nm_order)) - call sp % write_data(moment_name, "order" // & - trim(to_str(k)), & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/moments") - k = k + 1 + k = k + 1 end do end do case default - moment_name = '' - call sp % write_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(tally % id)) // & - "/moments") + str_array(k) = '' k = k + 1 end select - end do MOMENT_LOOP + call write_dataset(tally_group, "moment_orders", str_array) + deallocate(str_array) + + call close_group(tally_group) end do TALLY_METADATA end if + + call close_group(tallies_group) end if ! Check for the no-tally-reduction method @@ -346,47 +408,41 @@ contains ! If using the no-tally-reduction method, we need to collect tally ! results before writing them to the state point file. - call write_tally_results_nr() + call write_tally_results_nr(file_id) elseif (master) then ! Write number of global realizations - call sp % write_data(n_realizations, "n_realizations") + call write_dataset(file_id, "n_realizations", n_realizations) ! Write global tallies - call sp % write_data(N_GLOBAL_TALLIES, "n_global_tallies") - call sp % write_tally_result(global_tallies, "global_tallies", & - n1=N_GLOBAL_TALLIES, n2=1) + call write_dataset(file_id, "n_global_tallies", N_GLOBAL_TALLIES) + call write_dataset(file_id, "global_tallies", global_tallies) ! Write tallies + tallies_group = open_group(file_id, "tallies") if (tallies_on) then - ! Indicate that tallies are on - call sp % write_data(1, "tallies_present", group="tallies") + call write_dataset(tallies_group, "tallies_present", 1) ! Write all tally results TALLY_RESULTS: do i = 1, n_tallies - ! Set point to current tally tally => tallies(i) ! Write sum and sum_sq for each bin - call sp % write_tally_result(tally % results, "results", & - group="tallies/tally " // trim(to_str(tally % id)), & - n1=size(tally % results, 1), n2=size(tally % results, 2)) - + tally_group = open_group(tallies_group, "tally " // to_str(tally%id)) + call write_dataset(tally_group, "results", tally%results) + call close_group(tally_group) end do TALLY_RESULTS else - ! Indicate tallies are off - call sp % write_data(0, "tallies_present", group="tallies") - + call write_dataset(tallies_group, "tallies_present", 0) end if - ! Close the file for serial writing - call sp % file_close() - + call close_group(tallies_group) + call file_close(file_id) end if if (master .and. n_tallies > 0) then @@ -401,85 +457,60 @@ contains subroutine write_source_point() - type(BinaryOutput) :: sp + logical :: parallel + integer(HID_T) :: file_id character(MAX_FILE_LEN) :: filename + ! When using parallel HDF5, the file is written to collectively by all + ! processes. With MPI-only, the file is opened and written by the master + ! (note that the call to write_source_bank is by all processes since slave + ! processes need to send source bank data to the master. +#ifdef PHDF5 + parallel = .true. +#else + parallel = .false. +#endif + ! Check to write out source for a specified batch - if (sourcepoint_batch % contains(current_batch)) then - - ! Create or open up file + if (sourcepoint_batch%contains(current_batch)) then if (source_separate) then - - ! Set filename filename = trim(path_output) // 'source.' // & & zero_padded(current_batch, count_digits(n_max_batches)) - -#ifdef HDF5 filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif - - ! Write message for new file creation - call write_message("Creating source file " // trim(filename) // "...", & - &1) + call write_message("Creating source file " // trim(filename) & + // "...", 1) ! Create separate source file - call sp % file_create(filename, serial = .false.) - - ! Write file type - call sp % write_data(FILETYPE_SOURCE, "filetype") - + if (master .or. parallel) then + file_id = file_create(filename, parallel=.true.) + call write_dataset(file_id, "filetype", 'source') + end if else - - ! Set filename for state point filename = trim(path_output) // 'statepoint.' // & - & zero_padded(current_batch, count_digits(n_max_batches)) -#ifdef HDF5 + zero_padded(current_batch, count_digits(n_max_batches)) filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif - - ! Reopen statepoint file in parallel - call sp % file_open(filename, 'w', serial = .false.) + if (master .or. parallel) then + file_id = file_open(filename, 'w', parallel=.true.) + end if end if - ! Write out source - call sp % write_source_bank() - - ! Close file - call sp % file_close() - + call write_source_bank(file_id) + if (master .or. parallel) call file_close(file_id) end if ! Also check to write source separately in overwritten file if (source_latest) then - - ! Set filename - filename = trim(path_output) // 'source' -#ifdef HDF5 - filename = trim(filename) // '.h5' -#else - filename = trim(filename) // '.binary' -#endif - - ! Write message for new file creation + filename = trim(path_output) // 'source' // '.h5' call write_message("Creating source file " // trim(filename) // "...", 1) + if (master .or. parallel) then + file_id = file_create(filename, parallel=.true.) + call write_dataset(file_id, "filetype", 'source') + end if - ! Always create this file because it will be overwritten - call sp % file_create(filename, serial = .false.) - - ! Write file type - call sp % write_data(FILETYPE_SOURCE, "filetype") - - ! Write out source - call sp % write_source_bank() - - ! Close file - call sp % file_close() + call write_source_bank(file_id) + if (master .or. parallel) call file_close(file_id) end if end subroutine write_source_point @@ -488,12 +519,14 @@ contains ! WRITE_TALLY_RESULTS_NR !=============================================================================== - subroutine write_tally_results_nr() + subroutine write_tally_results_nr(file_id) + integer(HID_T), intent(in) :: file_id integer :: i ! loop index integer :: n ! number of filter bins integer :: m ! number of score bins integer :: n_bins ! total number of bins + integer(HID_T) :: tallies_group, tally_group real(8), allocatable :: tally_temp(:,:,:) ! contiguous array of results real(8), target :: global_temp(2,N_GLOBAL_TALLIES) #ifdef MPI @@ -510,16 +543,18 @@ contains if (master) then ! Write number of realizations - call sp % write_data(n_realizations, "n_realizations") + call write_dataset(file_id, "n_realizations", n_realizations) ! Write number of global tallies - call sp % write_data(N_GLOBAL_TALLIES, "n_global_tallies") + call write_dataset(file_id, "n_global_tallies", N_GLOBAL_TALLIES) + + tallies_group = open_group(file_id, "tallies") end if ! Copy global tallies into temporary array for reducing n_bins = 2 * N_GLOBAL_TALLIES - global_temp(1,:) = global_tallies(:) % sum - global_temp(2,:) = global_tallies(:) % sum_sq + global_temp(1,:) = global_tallies(:)%sum + global_temp(2,:) = global_tallies(:)%sum_sq if (master) then ! The MPI_IN_PLACE specifier allows the master to copy values into a @@ -531,19 +566,17 @@ contains ! Transfer values to value on master if (current_batch == n_max_batches .or. satisfy_triggers) then - global_tallies(:) % sum = global_temp(1,:) - global_tallies(:) % sum_sq = global_temp(2,:) + global_tallies(:)%sum = global_temp(1,:) + global_tallies(:)%sum_sq = global_temp(2,:) end if ! Put reduced value in temporary tally result allocate(tallyresult_temp(N_GLOBAL_TALLIES, 1)) - tallyresult_temp(:,1) % sum = global_temp(1,:) - tallyresult_temp(:,1) % sum_sq = global_temp(2,:) - + tallyresult_temp(:,1)%sum = global_temp(1,:) + tallyresult_temp(:,1)%sum_sq = global_temp(2,:) ! Write out global tallies sum and sum_sq - call sp % write_tally_result(tallyresult_temp, "global_tallies", & - n1=N_GLOBAL_TALLIES, n2=1) + call write_dataset(file_id, "global_tallies", tallyresult_temp) ! Deallocate temporary tally result deallocate(tallyresult_temp) @@ -558,17 +591,17 @@ contains if (tallies_on) then ! Indicate that tallies are on if (master) then - call sp % write_data(1, "tallies_present", group="tallies") + call write_dataset(tallies_group, "tallies_present", 1) ! Build list of tally IDs - current => tally_dict % keys() + current => tally_dict%keys() allocate(id_array(n_tallies)) i = 1 do while (associated(current)) - id_array(i) = current % value + id_array(i) = current%value ! Move to next tally - next => current % next + next => current%next deallocate(current) current => next i = i + 1 @@ -582,17 +615,20 @@ contains tally => tallies(i) ! Determine size of tally results array - m = size(tally % results, 1) - n = size(tally % results, 2) + m = size(tally%results, 1) + n = size(tally%results, 2) n_bins = m*n*2 ! Allocate array for storing sums and sums of squares, but ! contiguously in memory for each allocate(tally_temp(2,m,n)) - tally_temp(1,:,:) = tally % results(:,:) % sum - tally_temp(2,:,:) = tally % results(:,:) % sum_sq + tally_temp(1,:,:) = tally%results(:,:)%sum + tally_temp(2,:,:) = tally%results(:,:)%sum_sq if (master) then + tally_group = open_group(tallies_group, "tally " // & + trim(to_str(tally%id))) + ! The MPI_IN_PLACE specifier allows the master to copy values into ! a receive buffer without having a temporary variable #ifdef MPI @@ -603,18 +639,17 @@ contains ! At the end of the simulation, store the results back in the ! regular TallyResults array if (current_batch == n_max_batches .or. satisfy_triggers) then - tally % results(:,:) % sum = tally_temp(1,:,:) - tally % results(:,:) % sum_sq = tally_temp(2,:,:) + tally%results(:,:)%sum = tally_temp(1,:,:) + tally%results(:,:)%sum_sq = tally_temp(2,:,:) end if ! Put in temporary tally result allocate(tallyresult_temp(m,n)) - tallyresult_temp(:,:) % sum = tally_temp(1,:,:) - tallyresult_temp(:,:) % sum_sq = tally_temp(2,:,:) + tallyresult_temp(:,:)%sum = tally_temp(1,:,:) + tallyresult_temp(:,:)%sum_sq = tally_temp(2,:,:) ! Write reduced tally results to file - call sp % write_tally_result(tally % results, "results", & - group="tallies/tally " // trim(to_str(tally % id)), n1=m, n2=n) + call write_dataset(tally_group, "results", tally%results) ! Deallocate temporary tally result deallocate(tallyresult_temp) @@ -628,6 +663,8 @@ contains ! Deallocate temporary copy of tally results deallocate(tally_temp) + + if (master) call close_group(tally_group) end do TALLY_RESULTS deallocate(id_array) @@ -635,10 +672,12 @@ contains else if (master) then ! Indicate that tallies are off - call sp % write_data(0, "tallies_present", group="tallies") + call write_dataset(tallies_group, "tallies_present", 0) end if end if + if (master) call close_group(tallies_group) + end subroutine write_tally_results_nr !=============================================================================== @@ -647,73 +686,57 @@ contains subroutine load_state_point() - character(MAX_FILE_LEN) :: path_temp - character(19) :: current_time - integer :: i, j, k - integer :: length(4) - integer :: int_array(3) - integer, allocatable :: id_array(:) - integer, allocatable :: key_array(:) - integer :: curr_key - integer, allocatable :: temp_array(:) - logical :: source_present - real(8) :: real_array(3) - type(StructuredMesh), pointer :: mesh + integer :: i + integer :: int_array(3) + integer(HID_T) :: file_id + integer(HID_T) :: cmfd_group + integer(HID_T) :: tallies_group + integer(HID_T) :: tally_group + real(8) :: real_array(3) + logical :: source_present + character(MAX_WORD_LEN) :: word type(TallyObject), pointer :: tally - integer :: n_order ! loop index for moment orders - integer :: nm_order ! loop index for Ynm moment orders - character(8) :: moment_name ! name of moment (e.g, P3, Y-1,1) ! Write message call write_message("Loading state point " // trim(path_state_point) & - &// "...", 1) + // "...", 1) ! Open file for reading - call sp % file_open(path_state_point, 'r', serial = .false.) + file_id = file_open(path_state_point, 'r', parallel=.true.) ! Read filetype - call sp % read_data(int_array(1), "filetype") + call read_dataset(file_id, "filetype", int_array(1)) ! Read revision number for state point file and make sure it matches with ! current version - call sp % read_data(int_array(1), "revision") + call read_dataset(file_id, "revision", int_array(1)) if (int_array(1) /= REVISION_STATEPOINT) then call fatal_error("State point version does not match current version & &in OpenMC.") end if - ! Read OpenMC version - call sp % read_data(int_array(1), "version_major") - call sp % read_data(int_array(2), "version_minor") - call sp % read_data(int_array(3), "version_release") - if (int_array(1) /= VERSION_MAJOR .or. int_array(2) /= VERSION_MINOR & - .or. int_array(3) /= VERSION_RELEASE) then - if (master) call warning("State point file was created with a different & - &version of OpenMC.") - end if - - ! Read date and time - call sp % read_data(current_time, "date_and_time") - - ! Read path to input - call sp % read_data(path_temp, "path") - ! Read and overwrite random number seed - call sp % read_data(seed, "seed") + call read_dataset(file_id, "seed", seed) ! Read and overwrite run information except number of batches - call sp % read_data(run_mode, "run_mode") - call sp % read_data(n_particles, "n_particles") - call sp % read_data(int_array(1), "n_batches") + call read_dataset(file_id, "run_mode", word) + select case(word) + case ('fixed source') + run_mode = MODE_FIXEDSOURCE + case ('k-eigenvalue') + run_mode = MODE_EIGENVALUE + end select + call read_dataset(file_id, "n_particles", n_particles) + call read_dataset(file_id, "n_batches", int_array(1)) ! Take maximum of statepoint n_batches and input n_batches n_batches = max(n_batches, int_array(1)) ! Read batch number to restart at - call sp % read_data(restart_batch, "current_batch") + call read_dataset(file_id, "current_batch", restart_batch) ! Check for source in statepoint if needed - call sp % read_data(int_array(1), "source_present") + call read_dataset(file_id, "source_present", int_array(1)) if (int_array(1) == 1) then source_present = .true. else @@ -727,198 +750,41 @@ contains ! Read information specific to eigenvalue run if (run_mode == MODE_EIGENVALUE) then - call sp % read_data(int_array(1), "n_inactive") - call sp % read_data(gen_per_batch, "gen_per_batch") - call sp % read_data(k_generation, "k_generation", & - length=restart_batch*gen_per_batch) - call sp % read_data(entropy, "entropy", length=restart_batch*gen_per_batch) - call sp % read_data(k_col_abs, "k_col_abs") - call sp % read_data(k_col_tra, "k_col_tra") - call sp % read_data(k_abs_tra, "k_abs_tra") - call sp % read_data(real_array(1:2), "k_combined", length=2) + call read_dataset(file_id, "n_inactive", int_array(1)) + call read_dataset(file_id, "gen_per_batch", gen_per_batch) + call read_dataset(file_id, "k_generation", & + k_generation(1:restart_batch*gen_per_batch)) + call read_dataset(file_id, "entropy", & + entropy(1:restart_batch*gen_per_batch)) + call read_dataset(file_id, "k_col_abs", k_col_abs) + call read_dataset(file_id, "k_col_tra", k_col_tra) + call read_dataset(file_id, "k_abs_tra", k_abs_tra) + call read_dataset(file_id, "k_combined", real_array(1:2)) ! Take maximum of statepoint n_inactive and input n_inactive n_inactive = max(n_inactive, int_array(1)) ! Read in to see if CMFD was on - call sp % read_data(int_array(1), "cmfd_on") + call read_dataset(file_id, "cmfd_on", int_array(1)) ! Read in CMFD info if (int_array(1) == 1) then - call sp % read_data(cmfd % indices, "indices", length=4, group="cmfd") - call sp % read_data(cmfd % k_cmfd, "k_cmfd", length=restart_batch, & - group="cmfd") - length = cmfd % indices([4,1,2,3]) - call sp % read_data(cmfd % cmfd_src, "cmfd_src", & - length=length, group="cmfd") - call sp % read_data(cmfd % entropy, "cmfd_entropy", & - length=restart_batch, group="cmfd") - call sp % read_data(cmfd % balance, "cmfd_balance", & - length=restart_batch, group="cmfd") - call sp % read_data(cmfd % dom, "cmfd_dominance", & - length = restart_batch, group="cmfd") - call sp % read_data(cmfd % src_cmp, "cmfd_srccmp", & - length = restart_batch, group="cmfd") + cmfd_group = open_group(file_id, "cmfd") + call read_dataset(cmfd_group, "indices", cmfd%indices) + call read_dataset(cmfd_group, "k_cmfd", cmfd%k_cmfd(1:restart_batch)) + call read_dataset(cmfd_group, "cmfd_src", cmfd%cmfd_src) + call read_dataset(cmfd_group, "cmfd_entropy", & + cmfd%entropy(1:restart_batch)) + call read_dataset(cmfd_group, "cmfd_balance", & + cmfd%balance(1:restart_batch)) + call read_dataset(cmfd_group, "cmfd_dominance", & + cmfd%dom(1:restart_batch)) + call read_dataset(cmfd_group, "cmfd_srccmp", & + cmfd%src_cmp(1:restart_batch)) + call close_group(cmfd_group) end if end if - ! Read number of meshes - call sp % read_data(n_meshes, "n_meshes", group="tallies/meshes") - - if (n_meshes > 0) then - - ! Read list of mesh keys-> IDs - allocate(id_array(n_meshes)) - allocate(key_array(n_meshes)) - - call sp % read_data(id_array, "ids", & - group="tallies/meshes", length=n_meshes) - call sp % read_data(key_array, "keys", & - group="tallies/meshes", length=n_meshes) - - ! Read and overwrite mesh information - MESH_LOOP: do i = 1, n_meshes - - mesh => meshes(id_array(i)) - curr_key = key_array(id_array(i)) - - call sp % read_data(mesh % id, "id", & - group="tallies/meshes/mesh " // trim(to_str(curr_key))) - call sp % read_data(mesh % type, "type", & - group="tallies/meshes/mesh " // trim(to_str(curr_key))) - call sp % read_data(mesh % n_dimension, "n_dimension", & - group="tallies/meshes/mesh " // trim(to_str(meshes(i) % id))) - call sp % read_data(mesh % dimension, "dimension", & - group="tallies/meshes/mesh " // trim(to_str(curr_key)), & - length=mesh % n_dimension) - call sp % read_data(mesh % lower_left, "lower_left", & - group="tallies/meshes/mesh " // trim(to_str(curr_key)), & - length=mesh % n_dimension) - call sp % read_data(mesh % upper_right, "upper_right", & - group="tallies/meshes/mesh " // trim(to_str(curr_key)), & - length=mesh % n_dimension) - call sp % read_data(mesh % width, "width", & - group="tallies/meshes/mesh " // trim(to_str(curr_key)), & - length=meshes(i) % n_dimension) - - end do MESH_LOOP - - deallocate(id_array) - deallocate(key_array) - - end if - - ! Read and overwrite number of tallies - call sp % read_data(n_tallies, "n_tallies", group="tallies") - - ! Read list of tally keys-> IDs - allocate(id_array(n_tallies)) - allocate(key_array(n_tallies)) - - call sp % read_data(id_array, "ids", group="tallies", length=n_tallies) - call sp % read_data(key_array, "keys", group="tallies", length=n_tallies) - - ! Read in tally metadata - TALLY_METADATA: do i = 1, n_tallies - - ! Get pointer to tally - tally => tallies(i) - curr_key = key_array(id_array(i)) - - call sp % read_data(tally % estimator, "estimator", & - group="tallies/tally " // trim(to_str(curr_key))) - call sp % read_data(tally % n_realizations, "n_realizations", & - group="tallies/tally " // trim(to_str(curr_key))) - call sp % read_data(tally % n_filters, "n_filters", & - group="tallies/tally " // trim(to_str(curr_key))) - - FILTER_LOOP: do j = 1, tally % n_filters - call sp % read_data(tally % filters(j) % type, "type", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j)) - call sp % read_data(tally % filters(j) % offset, "offset", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j)) - call sp % read_data(tally % filters(j) % n_bins, "n_bins", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j)) - if (tally % filters(j) % type == FILTER_ENERGYIN .or. & - tally % filters(j) % type == FILTER_ENERGYOUT) then - call sp % read_data(tally % filters(j) % real_bins, "bins", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j), & - length=size(tally % filters(j) % real_bins)) - else - call sp % read_data(tally % filters(j) % int_bins, "bins", & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/filter " // to_str(j), & - length=size(tally % filters(j) % int_bins)) - end if - - end do FILTER_LOOP - - call sp % read_data(tally % n_nuclide_bins, "n_nuclides", & - group="tallies/tally " // trim(to_str(curr_key))) - - ! Set up nuclide bin array and then read - allocate(temp_array(tally % n_nuclide_bins)) - call sp % read_data(temp_array, "nuclides", & - group="tallies/tally " // trim(to_str(curr_key)), & - length=tally % n_nuclide_bins) - - NUCLIDE_LOOP: do j = 1, tally % n_nuclide_bins - if (temp_array(j) > 0) then - tally % nuclide_bins(j) = temp_array(j) - else - tally % nuclide_bins(j) = temp_array(j) - end if - end do NUCLIDE_LOOP - - deallocate(temp_array) - - ! Write number of score bins, score bins, user score bins - call sp % read_data(tally % n_score_bins, "n_score_bins", & - group="tallies/tally " // trim(to_str(curr_key))) - call sp % read_data(tally % score_bins, "score_bins", & - group="tallies/tally " // trim(to_str(curr_key)), & - length=tally % n_score_bins) - call sp % read_data(tally % n_user_score_bins, "n_user_score_bins", & - group="tallies/tally " // trim(to_str(curr_key))) - - ! Read explicit moment order strings for each score bin - k = 1 - MOMENT_LOOP: do j = 1, tally % n_user_score_bins - select case(tally % score_bins(k)) - case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - call sp % read_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(curr_key)) // "/moments") - k = k + 1 - case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - do n_order = 0, tally % moment_order(k) - call sp % read_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(curr_key)) // "/moments") - k = k + 1 - end do - case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & - SCORE_TOTAL_YN) - do n_order = 0, tally % moment_order(k) - do nm_order = -n_order, n_order - call sp % read_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(curr_key)) // & - "/moments") - k = k + 1 - end do - end do - case default - call sp % read_data(moment_name, "order" // trim(to_str(k)), & - group="tallies/tally " // trim(to_str(curr_key)) // "/moments") - k = k + 1 - end select - - end do MOMENT_LOOP - - end do TALLY_METADATA - ! Check to make sure source bank is present if (path_source_point == path_state_point .and. .not. source_present) then call fatal_error("Source bank must be contained in statepoint restart & @@ -929,43 +795,32 @@ contains if (master) then ! Read number of realizations for global tallies - call sp % read_data(n_realizations, "n_realizations", collect=.false.) - - ! Read number of global tallies - call sp % read_data(int_array(1), "n_global_tallies", collect=.false.) - if (int_array(1) /= N_GLOBAL_TALLIES) then - call fatal_error("Number of global tallies does not match in state & - &point.") - end if + call read_dataset(file_id, "n_realizations", n_realizations, indep=.true.) ! Read global tally data - call sp % read_tally_result(global_tallies, "global_tallies", & - n1=N_GLOBAL_TALLIES, n2=1) + call read_dataset(file_id, "global_tallies", global_tallies) ! Check if tally results are present - call sp % read_data(int_array(1), "tallies_present", & - group="tallies", collect=.false.) + tallies_group = open_group(file_id, "tallies") + call read_dataset(file_id, "tallies_present", int_array(1), indep=.true.) ! Read in sum and sum squared if (int_array(1) == 1) then TALLY_RESULTS: do i = 1, n_tallies - ! Set pointer to tally tally => tallies(i) - curr_key = key_array(id_array(i)) ! Read sum and sum_sq for each bin - call sp % read_tally_result(tally % results, "results", & - group="tallies/tally " // trim(to_str(curr_key)), & - n1=size(tally % results, 1), n2=size(tally % results, 2)) - + tally_group = open_group(tallies_group, "tally " // & + trim(to_str(tally%id))) + call read_dataset(tally_group, "results", tally%results) + call close_group(tally_group) end do TALLY_RESULTS - end if + + call close_group(tallies_group) end if - deallocate(id_array) - deallocate(key_array) ! Read source if in eigenvalue mode if (run_mode == MODE_EIGENVALUE) then @@ -974,32 +829,201 @@ contains if (.not. source_present) then ! Close statepoint file - call sp % file_close() + call file_close(file_id) ! Write message call write_message("Loading source file " // trim(path_source_point) & - &// "...", 1) + // "...", 1) ! Open source file - call sp % file_open(path_source_point, 'r', serial = .false.) + file_id = file_open(path_source_point, 'r', parallel=.true.) ! Read file type - call sp % read_data(int_array(1), "filetype") + call read_dataset(file_id, "filetype", int_array(1)) end if ! Write out source - call sp % read_source_bank() + call read_source_bank(file_id) end if ! Close file - call sp % file_close() + call file_close(file_id) end subroutine load_state_point - subroutine read_source -! TODO write this routine -! TODO what if n_particles does not match source bank - end subroutine read_source +!=============================================================================== +! WRITE_SOURCE_BANK writes OpenMC source_bank data +!=============================================================================== + + subroutine write_source_bank(group_id) + use bank_header, only: Bank + + integer(HID_T), intent(in) :: group_id + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data or file space handle + integer(HID_T) :: memspace ! memory space handle + integer(HSIZE_T) :: offset(1) ! source data offset + integer(HSIZE_T) :: dims(1) + type(c_ptr) :: f_ptr +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#else + integer :: i +#ifdef MPI + type(Bank), allocatable, target :: temp_source(:) +#endif +#endif + +#ifdef PHDF5 + ! Set size of total dataspace for all procs and rank + dims(1) = n_particles + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, dspace, dset, hdf5_err) + + ! Create another data space but for each proc individually + dims(1) = work + call h5screate_simple_f(1, dims, memspace, hdf5_err) + + ! Select hyperslab for this dataspace + offset(1) = work_index(rank) + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) + + ! Set up the property list for parallel writing + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + + ! Write data to file in parallel + call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace, & + xfer_prp=plist) + + ! Close all ids + call h5sclose_f(dspace, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call h5dclose_f(dset, hdf5_err) + call h5pclose_f(plist, hdf5_err) + +#else + + if (master) then + ! Create dataset big enough to hold all source sites + dims(1) = n_particles + call h5screate_simple_f(1, dims, dspace, hdf5_err) + call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, & + dspace, dset, hdf5_err) + + ! Save source bank sites since the souce_bank array is overwritten below +#ifdef MPI + allocate(temp_source(work)) + temp_source(:) = source_bank(:) +#endif + + do i = 0, n_procs - 1 + ! Create memory space + dims(1) = work_index(i+1) - work_index(i) + call h5screate_simple_f(1, dims, memspace, hdf5_err) + +#ifdef MPI + ! Receive source sites from other processes + if (i > 0) then + call MPI_RECV(source_bank, int(dims(1)), MPI_BANK, i, i, & + MPI_COMM_WORLD, MPI_STATUS_IGNORE, mpi_err) + end if +#endif + + ! Select hyperslab for this dataspace + call h5dget_space_f(dset, dspace, hdf5_err) + offset(1) = work_index(i) + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) + + ! Set up pointer to data and write data to hyperslab + f_ptr = c_loc(source_bank) + call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace) + + call h5sclose_f(memspace, hdf5_err) + call h5sclose_f(dspace, hdf5_err) + end do + + ! Close all ids + call h5dclose_f(dset, hdf5_err) + + ! Restore state of source bank +#ifdef MPI + source_bank(:) = temp_source(:) + deallocate(temp_source) +#endif + else +#ifdef MPI + call MPI_SEND(source_bank, int(work), MPI_BANK, 0, rank, & + MPI_COMM_WORLD, mpi_err) +#endif + end if + +#endif + + end subroutine write_source_bank + +!=============================================================================== +! READ_SOURCE_BANK reads OpenMC source_bank data +!=============================================================================== + + subroutine read_source_bank(group_id) + use bank_header, only: Bank + + integer(HID_T), intent(in) :: group_id + + integer :: hdf5_err + integer(HID_T) :: dset ! data set handle + integer(HID_T) :: dspace ! data space handle + integer(HID_T) :: memspace ! memory space handle + integer(HSIZE_T) :: dims(1) + integer(HSIZE_T) :: offset(1) ! offset of data + type(c_ptr) :: f_ptr +#ifdef PHDF5 + integer(HID_T) :: plist ! property list +#endif + + ! Open the dataset + call h5dopen_f(group_id, "source_bank", dset, hdf5_err) + + ! Create another data space but for each proc individually + dims(1) = work + call h5screate_simple_f(1, dims, memspace, hdf5_err) + + ! Select hyperslab for each process + call h5dget_space_f(dset, dspace, hdf5_err) + offset(1) = work_index(rank) + call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) + + ! Set up pointer to data + f_ptr = c_loc(source_bank) + +#ifdef PHDF5 + ! Read data in parallel + call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) + call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) + call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace, & + xfer_prp=plist) + call h5pclose_f(plist, hdf5_err) +#else + call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & + file_space_id=dspace, mem_space_id=memspace) +#endif + + ! Close all ids + call h5sclose_f(dspace, hdf5_err) + call h5sclose_f(memspace, hdf5_err) + call h5dclose_f(dset, hdf5_err) + + end subroutine read_source_bank + end module state_point diff --git a/src/stl_vector.F90 b/src/stl_vector.F90 new file mode 100644 index 0000000000..8038628fb6 --- /dev/null +++ b/src/stl_vector.F90 @@ -0,0 +1,351 @@ +module stl_vector + + ! This module provides derived types that are meant to mimic the + ! std::vector type in C++. The vector type has numerous advantages over + ! simple arrays and linked lists in that storage can grow and shrink + ! dynamically, yet it is still contiguous in memory. Vectors can be filled + ! element-by-element with automatic memory allocation in amortized constant + ! time. In the implementation here, we grow the vector by a factor of 1.5 each + ! time the capacity is exceed. + ! + ! The member functions which have been implemented here are: + ! + ! capacity -- Returns the size of the storage space currently allocated for + ! the vector + ! + ! clear -- Remove all elements from the vector, leaving it with a size of + ! 0. Note that this doesn't imply that storage is deallocated. + ! + ! initialize -- Set the storage size of the vector and optionally fill it with + ! a particular value. + ! + ! pop_back -- Remove the last element of the vector, reducing the size by one. + ! + ! push_back -- Add a new element at the end of the vector. This increases the + ! size of the vector by one. Note that the underlying storage is + ! reallocated only if the size exceeds the capacity. + ! + ! reserve -- Requests that the capacity of the vector be a certain size. + ! + ! resize -- Resize the vector so it contains n elements. If n is larger than + ! the current size, an optional fill value can be used to set the + ! extra elements. + ! + ! shrink_to_fit -- Request that the capacity be reduced to fit the size. + ! + ! size -- Returns the number of elements in the vector. + + implicit none + private + + real(8), parameter :: GROWTH_FACTOR = 1.5 + + type, public :: VectorInt + integer, private :: size_ = 0 + integer, private :: capacity_ = 0 + integer, allocatable :: data(:) + contains + procedure :: capacity => capacity_int + procedure :: clear => clear_int + generic :: initialize => & + initialize_fill_int + procedure, private :: initialize_fill_int + procedure :: pop_back => pop_back_int + procedure :: push_back => push_back_int + procedure :: reserve => reserve_int + procedure :: resize => resize_int + procedure :: shrink_to_fit => shrink_to_fit_int + procedure :: size => size_int + end type VectorInt + + type, public :: VectorReal + integer, private :: size_ = 0 + integer, private :: capacity_ = 0 + real(8), allocatable :: data(:) + contains + procedure :: capacity => capacity_real + procedure :: clear => clear_real + generic :: initialize => & + initialize_fill_real + procedure, private :: initialize_fill_real + procedure :: pop_back => pop_back_real + procedure :: push_back => push_back_real + procedure :: reserve => reserve_real + procedure :: resize => resize_real + procedure :: shrink_to_fit => shrink_to_fit_real + procedure :: size => size_real + end type VectorReal + +contains + +!=============================================================================== +! Implementation of VectorInt +!=============================================================================== + + pure function capacity_int(this) result(capacity) + class(VectorInt), intent(in) :: this + integer :: capacity + + capacity = this%capacity_ + end function capacity_int + + subroutine clear_int(this) + class(VectorInt), intent(inout) :: this + + ! Since integer is trivially destructible, we only need to set size to zero + ! and can leave capacity as is + this%size_ = 0 + end subroutine clear_int + + subroutine initialize_fill_int(this, n, val) + class(VectorInt), intent(inout) :: this + integer, intent(in) :: n + integer, optional, intent(in) :: val + + integer :: val_ + + ! If no value given, fill the vector with zeros + if (present(val)) then + val_ = val + else + val_ = 0 + end if + + if (allocated(this%data)) deallocate(this%data) + + allocate(this%data(n), SOURCE=val_) + this%size_ = n + this%capacity_ = n + end subroutine initialize_fill_int + + subroutine pop_back_int(this) + class(VectorInt), intent(inout) :: this + if (this%size_ > 0) this%size_ = this%size_ - 1 + end subroutine pop_back_int + + subroutine push_back_int(this, val) + class(VectorInt), intent(inout) :: this + integer, intent(in) :: val + + integer :: capacity + integer, allocatable :: data(:) + + if (this%capacity_ == this%size_) then + ! Create new data array that is GROWTH_FACTOR larger. Note that + if (this%capacity_ == 0) then + capacity = 8 + else + capacity = int(GROWTH_FACTOR*this%capacity_) + end if + allocate(data(capacity)) + + ! Copy existing elements + if (this%size_ > 0) data(1:this%size_) = this%data + + ! Move allocation + call move_alloc(FROM=data, TO=this%data) + this%capacity_ = capacity + end if + + ! Increase size of vector by one and set new element + this%size_ = this%size_ + 1 + this%data(this%size_) = val + end subroutine push_back_int + + subroutine reserve_int(this, n) + class(VectorInt), intent(inout) :: this + integer, intent(in) :: n + + integer, allocatable :: data(:) + + if (n > this%capacity_) then + allocate(data(n)) + + ! Copy existing elements + if (this%size_ > 0) data(1:this%size_) = this%data(1:this%size_) + + ! Move allocation + call move_alloc(FROM=data, TO=this%data) + this%capacity_ = n + end if + end subroutine reserve_int + + subroutine resize_int(this, n, val) + class(VectorInt), intent(inout) :: this + integer, intent(in) :: n + integer, intent(in), optional :: val + + if (n < this%size_) then + this%size_ = n + elseif (n > this%size_) then + ! If requested size is greater than capacity, first reserve that many + ! elements + if (n > this%capacity_) call this%reserve(n) + + ! Fill added elements with specified value and increase size + if (present(val)) this%data(this%size_ + 1 : n) = val + this%size_ = n + end if + + end subroutine resize_int + + subroutine shrink_to_fit_int(this) + class(VectorInt), intent(inout) :: this + + integer, allocatable :: data(:) + + if (this%capacity_ > this%size_) then + if (this%size_ > 0) then + allocate(data(this%size_)) + data(:) = this%data(1:this%size_) + call move_alloc(FROM=data, TO=this%data) + this%capacity_ = this%size_ + else + if (allocated(this%data)) deallocate(this%data) + end if + end if + end subroutine shrink_to_fit_int + + pure function size_int(this) result(size) + class(VectorInt), intent(in) :: this + integer :: size + + size = this%size_ + end function size_int + +!=============================================================================== +! Implementation of VectorReal +!=============================================================================== + + pure function capacity_real(this) result(capacity) + class(VectorReal), intent(in) :: this + integer :: capacity + + capacity = this%capacity_ + end function capacity_real + + subroutine clear_real(this) + class(VectorReal), intent(inout) :: this + + ! Since real is trivially destructible, we only need to set size to zero and + ! can leave capacity as is + this%size_ = 0 + end subroutine clear_real + + subroutine initialize_fill_real(this, n, val) + class(VectorReal), intent(inout) :: this + integer, intent(in) :: n + real(8), optional, intent(in) :: val + + real(8) :: val_ + + ! If no value given, fill the vector with zeros + if (present(val)) then + val_ = val + else + val_ = 0 + end if + + if (allocated(this%data)) deallocate(this%data) + + allocate(this%data(n), SOURCE=val_) + this%size_ = n + this%capacity_ = n + end subroutine initialize_fill_real + + subroutine pop_back_real(this) + class(VectorReal), intent(inout) :: this + if (this%size_ > 0) this%size_ = this%size_ - 1 + end subroutine pop_back_real + + subroutine push_back_real(this, val) + class(VectorReal), intent(inout) :: this + real(8), intent(in) :: val + + integer :: capacity + real(8), allocatable :: data(:) + + if (this%capacity_ == this%size_) then + ! Create new data array that is GROWTH_FACTOR larger. Note that + if (this%capacity_ == 0) then + capacity = 8 + else + capacity = int(GROWTH_FACTOR*this%capacity_) + end if + allocate(data(capacity)) + + ! Copy existing elements + if (this%size_ > 0) data(1:this%size_) = this%data + + ! Move allocation + call move_alloc(FROM=data, TO=this%data) + this%capacity_ = capacity + end if + + ! Increase size of vector by one and set new element + this%size_ = this%size_ + 1 + this%data(this%size_) = val + end subroutine push_back_real + + subroutine reserve_real(this, n) + class(VectorReal), intent(inout) :: this + integer, intent(in) :: n + + real(8), allocatable :: data(:) + + if (n > this%capacity_) then + allocate(data(n)) + + ! Copy existing elements + if (this%size_ > 0) data(1:this%size_) = this%data(1:this%size_) + + ! Move allocation + call move_alloc(FROM=data, TO=this%data) + this%capacity_ = n + end if + end subroutine reserve_real + + subroutine resize_real(this, n, val) + class(VectorReal), intent(inout) :: this + integer, intent(in) :: n + real(8), intent(in), optional :: val + + if (n < this%size_) then + this%size_ = n + elseif (n > this%size_) then + ! If requested size is greater than capacity, first reserve that many + ! elements + if (n > this%capacity_) call this%reserve(n) + + ! Fill added elements with specified value and increase size + if (present(val)) this%data(this%size_ + 1 : n) = val + this%size_ = n + end if + + end subroutine resize_real + + subroutine shrink_to_fit_real(this) + class(VectorReal), intent(inout) :: this + + real(8), allocatable :: data(:) + + if (this%capacity_ > this%size_) then + if (this%size_ > 0) then + allocate(data(this%size_)) + data(:) = this%data(1:this%size_) + call move_alloc(FROM=data, TO=this%data) + this%capacity_ = this%size_ + else + if (allocated(this%data)) deallocate(this%data) + end if + end if + end subroutine shrink_to_fit_real + + pure function size_real(this) result(size) + class(VectorReal), intent(in) :: this + integer :: size + + size = this%size_ + end function size_real + +end module stl_vector diff --git a/src/string.F90 b/src/string.F90 index 5f57bb3855..ce130a212d 100644 --- a/src/string.F90 +++ b/src/string.F90 @@ -1,8 +1,10 @@ module string - use constants, only: MAX_WORDS, MAX_LINE_LEN, ERROR_INT, ERROR_REAL + use constants, only: MAX_WORDS, MAX_LINE_LEN, ERROR_INT, ERROR_REAL, & + OP_LEFT_PAREN, OP_RIGHT_PAREN, OP_COMPLEMENT, OP_INTERSECTION, OP_UNION use error, only: fatal_error, warning use global, only: master + use stl_vector, only: VectorInt implicit none @@ -23,7 +25,6 @@ contains !=============================================================================== subroutine split_string(string, words, n) - character(*), intent(in) :: string character(*), intent(out) :: words(MAX_WORDS) integer, intent(out) :: n @@ -63,63 +64,96 @@ contains end subroutine split_string !=============================================================================== -! SPLIT_STRING_WL takes a string that includes logical expressions for a list of -! bounding surfaces in a cell and splits it into separate words. The characters -! (, ), :, and # count as separate words since they represent operators. -! -! Arguments: -! string = input line -! words = array of words -! n = number of words +! TOKENIZE takes a string that includes logical expressions for a list of +! bounding surfaces in a cell and splits it into separate tokens. The characters +! (, ), |, and ~ count as separate tokens since they represent operators. !=============================================================================== - subroutine split_string_wl(string, words, n) + subroutine tokenize(string, tokens) + character(*), intent(in) :: string + type(VectorInt), intent(inout) :: tokens - character(*), intent(in) :: string - character(*), intent(out) :: words(MAX_WORDS) - integer, intent(out) :: n + integer :: i ! current index + integer :: i_start ! starting index of word + integer :: token + character(len=len_trim(string)) :: string_ - character(1) :: chr ! current character - integer :: i ! current index - integer :: i_start ! starting index of word - integer :: i_end ! ending index of word + ! Remove leading blanks + string_ = adjustl(string) i_start = 0 - i_end = 0 - n = 0 - do i = 1, len_trim(string) - chr = string(i:i) - + i = 1 + do while (i <= len_trim(string_)) ! Check for special characters - if (index('():#', chr) > 0) then + if (index('()|~ ', string_(i:i)) > 0) then + ! If the special character appears immediately after a non-operator, + ! create a token with the surface half-space if (i_start > 0) then - i_end = i - 1 - n = n + 1 - words(n) = string(i_start:i_end) + call tokens%push_back(int(str_to_int(& + string_(i_start:i - 1)), 4)) end if - n = n + 1 - words(n) = chr + + select case (string_(i:i)) + case ('(') + call tokens%push_back(OP_LEFT_PAREN) + case (')') + if (tokens%size() > 0) then + token = tokens%data(tokens%size()) + if (token >= OP_UNION .and. token < OP_RIGHT_PAREN) then + call fatal_error("Right parentheses cannot follow an operator in & + ®ion specification: " // trim(string)) + end if + end if + call tokens%push_back(OP_RIGHT_PAREN) + case ('|') + if (tokens%size() > 0) then + token = tokens%data(tokens%size()) + if (.not. (token < OP_UNION .or. token == OP_RIGHT_PAREN)) then + call fatal_error("Union cannot follow an operator in region & + &specification: " // trim(string)) + end if + end if + call tokens%push_back(OP_UNION) + case ('~') + call tokens%push_back(OP_COMPLEMENT) + case (' ') + ! Find next non-space character + do while (string_(i+1:i+1) == ' ') + i = i + 1 + end do + + ! If previous token is a halfspace or right parenthesis and next token + ! is not a left parenthese or union operator, that implies that the + ! whitespace is to be interpreted as an intersection operator + if (i_start > 0 .or. tokens%data(tokens%size()) == OP_RIGHT_PAREN) then + if (index(')|', string_(i+1:i+1)) == 0) then + call tokens%push_back(OP_INTERSECTION) + end if + end if + end select + i_start = 0 - i_end = 0 - cycle + else + ! Check for invalid characters + if (index('-+0123456789', string_(i:i)) == 0) then + call fatal_error("Invalid character '" // string_(i:i) // "' in & + ®ion specification.") + end if + + ! If we haven't yet reached the start of a word, start a new word + if (i_start == 0) i_start = i end if - if ((i_start == 0) .and. (chr /= ' ')) then - i_start = i - end if - if (i_start > 0) then - if (chr == ' ') i_end = i - 1 - if (i == len_trim(string)) i_end = i - if (i_end > 0) then - n = n + 1 - words(n) = string(i_start:i_end) - ! reset indices - i_start = 0 - i_end = 0 - end if - end if + i = i + 1 end do - end subroutine split_string_wl + + ! If we've reached the end and we're still in a word, create a token from it + ! and add it to the list + if (i_start > 0) then + call tokens%push_back(int(str_to_int(& + string_(i_start:len_trim(string_))), 4)) + end if + end subroutine tokenize !=============================================================================== ! CONCATENATE takes an array of words and concatenates them together in one @@ -131,7 +165,7 @@ contains ! string = concatenated string !=============================================================================== - function concatenate(words, n_words) result(string) + pure function concatenate(words, n_words) result(string) integer, intent(in) :: n_words character(*), intent(in) :: words(n_words) @@ -151,8 +185,7 @@ contains ! TO_LOWER converts a string to all lower case characters !=============================================================================== - function to_lower(word) result(word_lower) - + pure function to_lower(word) result(word_lower) character(*), intent(in) :: word character(len=len(word)) :: word_lower @@ -174,8 +207,7 @@ contains ! TO_UPPER converts a string to all upper case characters !=============================================================================== - function to_upper(word) result(word_upper) - + pure function to_upper(word) result(word_upper) character(*), intent(in) :: word character(len=len(word)) :: word_upper @@ -199,39 +231,38 @@ contains ! integers. !=============================================================================== -function zero_padded(num, n_digits) result(str) - integer, intent(in) :: num - integer, intent(in) :: n_digits - character(11) :: str + function zero_padded(num, n_digits) result(str) + integer, intent(in) :: num + integer, intent(in) :: n_digits + character(11) :: str - character(8) :: zp_form + character(8) :: zp_form - ! Make sure n_digits is reasonable. 10 digits is the maximum needed for the - ! largest integer(4). - if (n_digits > 10) then - call fatal_error('zero_padded called with an unreasonably large & - &n_digits (>10)') - end if + ! Make sure n_digits is reasonable. 10 digits is the maximum needed for the + ! largest integer(4). + if (n_digits > 10) then + call fatal_error('zero_padded called with an unreasonably large & + &n_digits (>10)') + end if - ! Write a format string of the form '(In.m)' where n is the max width and - ! m is the min width. If a sign is present, then n must be one greater - ! than m. - if (num < 0) then - write(zp_form, '("(I", I0, ".", I0, ")")') n_digits+1, n_digits - else - write(zp_form, '("(I", I0, ".", I0, ")")') n_digits, n_digits - end if + ! Write a format string of the form '(In.m)' where n is the max width and + ! m is the min width. If a sign is present, then n must be one greater + ! than m. + if (num < 0) then + write(zp_form, '("(I", I0, ".", I0, ")")') n_digits+1, n_digits + else + write(zp_form, '("(I", I0, ".", I0, ")")') n_digits, n_digits + end if - ! Format the number. - write(str, zp_form) num -end function zero_padded + ! Format the number. + write(str, zp_form) num + end function zero_padded !=============================================================================== ! IS_NUMBER determines whether a string of characters is all 0-9 characters !=============================================================================== - function is_number(word) result(number) - + pure function is_number(word) result(number) character(*), intent(in) :: word logical :: number @@ -251,10 +282,9 @@ end function zero_padded ! sequence of characters !=============================================================================== - logical function starts_with(str, seq) - - character(*) :: str ! string to check - character(*) :: seq ! sequence of characters + pure logical function starts_with(str, seq) + character(*), intent(in) :: str ! string to check + character(*), intent(in) :: seq ! sequence of characters integer :: i integer :: i_start @@ -286,10 +316,9 @@ end function zero_padded ! of characters !=============================================================================== - logical function ends_with(str, seq) - - character(*) :: str ! string to check - character(*) :: seq ! sequence of characters + pure logical function ends_with(str, seq) + character(*), intent(in) :: str ! string to check + character(*), intent(in) :: seq ! sequence of characters integer :: i_start integer :: str_len @@ -315,7 +344,7 @@ end function zero_padded ! integer. !=============================================================================== - function count_digits(num) result(n_digits) + pure function count_digits(num) result(n_digits) integer, intent(in) :: num integer :: n_digits @@ -333,7 +362,7 @@ end function zero_padded ! INT4_TO_STR converts an integer(4) to a string. !=============================================================================== - function int4_to_str(num) result(str) + pure function int4_to_str(num) result(str) integer, intent(in) :: num character(11) :: str @@ -347,7 +376,7 @@ end function zero_padded ! INT8_TO_STR converts an integer(8) to a string. !=============================================================================== - function int8_to_str(num) result(str) + pure function int8_to_str(num) result(str) integer(8), intent(in) :: num character(21) :: str @@ -361,7 +390,7 @@ end function zero_padded ! STR_TO_INT converts a string to an integer. !=============================================================================== - function str_to_int(str) result(num) + pure function str_to_int(str) result(num) character(*), intent(in) :: str integer(8) :: num @@ -386,7 +415,7 @@ end function zero_padded ! STR_TO_REAL converts an arbitrary string to a real(8) !=============================================================================== - function str_to_real(string) result(num) + pure function str_to_real(string) result(num) character(*), intent(in) :: string real(8) :: num @@ -405,7 +434,7 @@ end function zero_padded ! are used. !=============================================================================== - function real_to_str(num, sig_digits) result(string) + pure function real_to_str(num, sig_digits) result(string) real(8), intent(in) :: num ! number to convert integer, optional, intent(in) :: sig_digits ! # of significant digits diff --git a/src/summary.F90 b/src/summary.F90 new file mode 100644 index 0000000000..f2c261ec75 --- /dev/null +++ b/src/summary.F90 @@ -0,0 +1,733 @@ +module summary + + use ace_header, only: Reaction, UrrData, Nuclide + use constants + use endf, only: reaction_name + use geometry_header, only: Cell, Universe, Lattice, RectLattice, & + &HexLattice + use global + use hdf5_interface + use material_header, only: Material + use mesh_header, only: RegularMesh + use output, only: time_stamp + use surface_header + 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) + 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 filetype and revision + call write_dataset(file_id, "filetype", "summary") + call write_dataset(file_id, "revision", REVISION_SUMMARY) + + ! Write version information + call write_dataset(file_id, "version_major", VERSION_MAJOR) + call write_dataset(file_id, "version_minor", VERSION_MINOR) + 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 + real(8), allocatable :: coeffs(:) + character(MAX_LINE_LEN) :: region_spec + type(Cell), pointer :: c + class(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) + 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, "translation", c%translation) + end if + if (allocated(c%rotation)) then + call write_dataset(cell_group, "rotation", c%rotation) + 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 + region_spec = "" + do j = 1, size(c%region) + k = c%region(j) + select case(k) + case (OP_LEFT_PAREN) + region_spec = trim(region_spec) // " (" + case (OP_RIGHT_PAREN) + region_spec = trim(region_spec) // " )" + case (OP_COMPLEMENT) + region_spec = trim(region_spec) // " ~" + case (OP_INTERSECTION) + case (OP_UNION) + region_spec = trim(region_spec) // " |" + case default + region_spec = trim(region_spec) // " " // to_str(& + sign(surfaces(abs(k))%obj%id, k)) + end select + end do + call write_dataset(cell_group, "region", adjustl(region_spec)) + + 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(geom_group, "surfaces") + + ! Write information on each surface + SURFACE_LOOP: do i = 1, n_surfaces + s => surfaces(i)%obj + 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 type (s) + type is (SurfaceXPlane) + call write_dataset(surface_group, "type", "x-plane") + allocate(coeffs(1)) + coeffs(1) = s%x0 + + type is (SurfaceYPlane) + call write_dataset(surface_group, "type", "y-plane") + allocate(coeffs(1)) + coeffs(1) = s%y0 + + type is (SurfaceZPlane) + call write_dataset(surface_group, "type", "z-plane") + allocate(coeffs(1)) + coeffs(1) = s%z0 + + type is (SurfacePlane) + call write_dataset(surface_group, "type", "plane") + allocate(coeffs(4)) + coeffs(:) = [s%A, s%B, s%C, s%D] + + type is (SurfaceXCylinder) + call write_dataset(surface_group, "type", "x-cylinder") + allocate(coeffs(3)) + coeffs(:) = [s%y0, s%z0, s%r] + + type is (SurfaceYCylinder) + call write_dataset(surface_group, "type", "y-cylinder") + allocate(coeffs(3)) + coeffs(:) = [s%x0, s%z0, s%r] + + type is (SurfaceZCylinder) + call write_dataset(surface_group, "type", "z-cylinder") + allocate(coeffs(3)) + coeffs(:) = [s%x0, s%y0, s%r] + + type is (SurfaceSphere) + call write_dataset(surface_group, "type", "sphere") + allocate(coeffs(4)) + coeffs(:) = [s%x0, s%y0, s%z0, s%r] + + type is (SurfaceXCone) + call write_dataset(surface_group, "type", "x-cone") + allocate(coeffs(4)) + coeffs(:) = [s%x0, s%y0, s%z0, s%r2] + + type is (SurfaceYCone) + call write_dataset(surface_group, "type", "y-cone") + allocate(coeffs(4)) + coeffs(:) = [s%x0, s%y0, s%z0, s%r2] + + type is (SurfaceZCone) + call write_dataset(surface_group, "type", "z-cone") + allocate(coeffs(4)) + coeffs(:) = [s%x0, s%y0, s%z0, s%r2] + + type is (SurfaceQuadric) + call write_dataset(surface_group, "type", "quadric") + allocate(coeffs(10)) + coeffs(:) = [s%A, s%B, s%C, s%D, s%E, s%F, s%G, s%H, s%J, s%K] + + end select + call write_dataset(surface_group, "coefficients", coeffs) + deallocate(coeffs) + + ! 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, pitch, and outer universe + call write_dataset(lattice_group, "name", lat%name) + call write_dataset(lattice_group, "pitch", lat%pitch) + call write_dataset(lattice_group, "outer", lat%outer) + + ! Write distribcell offsets if present + if (size(lat%offset) > 0) then + call write_dataset(lattice_group, "offsets", lat%offset) + end if + + 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) + + ! 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 + + 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 + call write_dataset(lattice_group, "center", lat%center) + + ! 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 + end select + + ! Write lattice universes + call write_dataset(lattice_group, "universes", lattice_universes) + deallocate(lattice_universes) + + call close_group(lattice_group) + end do LATTICE_LOOP + + 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 :: i_list + character(12), allocatable :: nucnames(:) + integer(HID_T) :: materials_group + integer(HID_T) :: material_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(nucnames(m%n_nuclides)) + do j = 1, m%n_nuclides + i_list = nuclides(m%nuclide(j))%listing + nucnames(j) = xs_listings(i_list)%alias + end do + + ! Write temporary array to 'nuclides' + call write_dataset(material_group, "nuclides", nucnames) + + ! Deallocate temporary array + deallocate(nucnames) + + ! Write atom densities + call write_dataset(material_group, "nuclide_densities", m%atom_density) + + if (m%n_sab > 0) then + call write_dataset(material_group, "sab_names", m%sab_names) + 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 :: i_list, i_xs + integer(HID_T) :: tallies_group + integer(HID_T) :: mesh_group + integer(HID_T) :: tally_group + integer(HID_T) :: filter_group + character(20), allocatable :: str_array(:) + type(RegularMesh), 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 internal OpenMC index for this mesh + call write_dataset(mesh_group, "index", i) + + ! Write type and number of dimensions + call write_dataset(mesh_group, "type", "regular") + + ! 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 internal OpenMC index for this tally + call write_dataset(tally_group, "index", i) + + ! Write the name for this tally + call write_dataset(tally_group, "name", t%name) + + ! 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 number of bins for this filter + call write_dataset(filter_group, "offset", t%filters(j)%offset) + call write_dataset(filter_group, "n_bins", t%filters(j)%n_bins) + + ! Write filter bins + if (t%filters(j)%type == FILTER_ENERGYIN .or. & + t%filters(j)%type == FILTER_ENERGYOUT .or. & + t%filters(j)%type == FILTER_MU .or. & + t%filters(j)%type == FILTER_POLAR .or. & + t%filters(j)%type == FILTER_AZIMUTHAL) 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", "universe") + case(FILTER_MATERIAL) + call write_dataset(filter_group, "type", "material") + case(FILTER_CELL) + call write_dataset(filter_group, "type", "cell") + case(FILTER_CELLBORN) + call write_dataset(filter_group, "type", "cellborn") + case(FILTER_SURFACE) + call write_dataset(filter_group, "type", "surface") + case(FILTER_MESH) + call write_dataset(filter_group, "type", "mesh") + case(FILTER_ENERGYIN) + call write_dataset(filter_group, "type", "energy") + case(FILTER_ENERGYOUT) + call write_dataset(filter_group, "type", "energyout") + case(FILTER_DISTRIBCELL) + call write_dataset(filter_group, "type", "distribcell") + case(FILTER_MU) + call write_dataset(filter_group, "type", "mu") + case(FILTER_POLAR) + call write_dataset(filter_group, "type", "polar") + case(FILTER_AZIMUTHAL) + call write_dataset(filter_group, "type", "azimuthal") + case(FILTER_DELAYEDGROUP) + call write_dataset(filter_group, "type", "delayedgroup") + end select + + call close_group(filter_group) + end do FILTER_LOOP + + ! Create temporary array for nuclide bins + allocate(str_array(t%n_nuclide_bins)) + NUCLIDE_LOOP: do j = 1, t%n_nuclide_bins + if (t%nuclide_bins(j) > 0) then + i_list = nuclides(t%nuclide_bins(j))%listing + i_xs = index(xs_listings(i_list)%alias, '.') + if (i_xs > 0) then + str_array(j) = xs_listings(i_list)%alias(1:i_xs - 1) + else + str_array(j) = xs_listings(i_list)%alias + end if + else + str_array(j) = 'total' + end if + end do NUCLIDE_LOOP + + ! Write and deallocate nuclide bins + call write_dataset(tally_group, "nuclides", str_array) + deallocate(str_array) + + ! Write number of score bins + call write_dataset(tally_group, "n_score_bins", t%n_score_bins) + allocate(str_array(size(t%score_bins))) + do j = 1, size(t%score_bins) + select case(t%score_bins(j)) + case (SCORE_FLUX) + str_array(j) = "flux" + case (SCORE_TOTAL) + str_array(j) = "total" + case (SCORE_SCATTER) + str_array(j) = "scatter" + case (SCORE_NU_SCATTER) + str_array(j) = "nu-scatter" + case (SCORE_SCATTER_N) + str_array(j) = "scatter-n" + case (SCORE_SCATTER_PN) + str_array(j) = "scatter-pn" + case (SCORE_NU_SCATTER_N) + str_array(j) = "nu-scatter-n" + case (SCORE_NU_SCATTER_PN) + str_array(j) = "nu-scatter-pn" + case (SCORE_TRANSPORT) + str_array(j) = "transport" + case (SCORE_N_1N) + str_array(j) = "n1n" + case (SCORE_ABSORPTION) + str_array(j) = "absorption" + case (SCORE_FISSION) + str_array(j) = "fission" + case (SCORE_NU_FISSION) + str_array(j) = "nu-fission" + case (SCORE_DELAYED_NU_FISSION) + str_array(j) = "delayed-nu-fission" + case (SCORE_KAPPA_FISSION) + str_array(j) = "kappa-fission" + case (SCORE_CURRENT) + str_array(j) = "current" + case (SCORE_FLUX_YN) + str_array(j) = "flux-yn" + case (SCORE_TOTAL_YN) + str_array(j) = "total-yn" + case (SCORE_SCATTER_YN) + str_array(j) = "scatter-yn" + case (SCORE_NU_SCATTER_YN) + str_array(j) = "nu-scatter-yn" + case (SCORE_EVENTS) + str_array(j) = "events" + case (SCORE_INVERSE_VELOCITY) + str_array(j) = "inverse-velocity" + case default + str_array(j) = reaction_name(t%score_bins(j)) + end select + end do + call write_dataset(tally_group, "score_bins", str_array) + + deallocate(str_array) + + call close_group(tally_group) + end do TALLY_METADATA + + call close_group(tallies_group) + + end subroutine write_tallies + +!=============================================================================== +! 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 diff --git a/src/surface_header.F90 b/src/surface_header.F90 new file mode 100644 index 0000000000..76562f4937 --- /dev/null +++ b/src/surface_header.F90 @@ -0,0 +1,1052 @@ +module surface_header + + use constants, only: ONE, TWO, ZERO, HALF, INFINITY, FP_COINCIDENT + + implicit none + +!=============================================================================== +! SURFACE type defines a first- or second-order surface that can be used to +! construct closed volumes (cells) +!=============================================================================== + + type, abstract :: Surface + integer :: id ! Unique ID + integer, allocatable :: & + neighbor_pos(:), & ! List of cells on positive side + neighbor_neg(:) ! List of cells on negative side + integer :: bc ! Boundary condition + character(len=104) :: name = "" ! User-defined name + contains + procedure :: sense + procedure :: reflect + procedure(iEvaluate), deferred :: evaluate + procedure(iDistance), deferred :: distance + procedure(iNormal), deferred :: normal + end type Surface + + abstract interface + pure function iEvaluate(this, xyz) result(f) + import Surface + class(Surface), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + end function iEvaluate + + pure function iDistance(this, xyz, uvw, coincident) result(d) + import Surface + class(Surface), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + end function iDistance + + pure function iNormal(this, xyz) result(uvw) + import Surface + class(Surface), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + end function iNormal + end interface + +!=============================================================================== +! SURFACECONTAINER allows us to store an array of different types of surfaces +!=============================================================================== + + type :: SurfaceContainer + class(Surface), allocatable :: obj + end type SurfaceContainer + +!=============================================================================== +! All the derived types below are extensions of the abstract Surface type. They +! inherent the reflect() and sense() type-bound procedures and must implement +! evaluate(), distance(), and normal() +!=============================================================================== + + type, extends(Surface) :: SurfaceXPlane + ! x = x0 + real(8) :: x0 + contains + procedure :: evaluate => x_plane_evaluate + procedure :: distance => x_plane_distance + procedure :: normal => x_plane_normal + end type SurfaceXPlane + + type, extends(Surface) :: SurfaceYPlane + ! y = y0 + real(8) :: y0 + contains + procedure :: evaluate => y_plane_evaluate + procedure :: distance => y_plane_distance + procedure :: normal => y_plane_normal + end type SurfaceYPlane + + type, extends(Surface) :: SurfaceZPlane + ! z = z0 + real(8) :: z0 + contains + procedure :: evaluate => z_plane_evaluate + procedure :: distance => z_plane_distance + procedure :: normal => z_plane_normal + end type SurfaceZPlane + + type, extends(Surface) :: SurfacePlane + ! Ax + By + Cz = D + real(8) :: A + real(8) :: B + real(8) :: C + real(8) :: D + contains + procedure :: evaluate => plane_evaluate + procedure :: distance => plane_distance + procedure :: normal => plane_normal + end type SurfacePlane + + type, extends(Surface) :: SurfaceXCylinder + ! (y - y0)^2 + (z - z0)^2 = R^2 + real(8) :: y0 + real(8) :: z0 + real(8) :: r + contains + procedure :: evaluate => x_cylinder_evaluate + procedure :: distance => x_cylinder_distance + procedure :: normal => x_cylinder_normal + end type SurfaceXCylinder + + type, extends(Surface) :: SurfaceYCylinder + ! (x - x0)^2 + (z - z0)^2 = R^2 + real(8) :: x0 + real(8) :: z0 + real(8) :: r + contains + procedure :: evaluate => y_cylinder_evaluate + procedure :: distance => y_cylinder_distance + procedure :: normal => y_cylinder_normal + end type SurfaceYCylinder + + type, extends(Surface) :: SurfaceZCylinder + ! (x - x0)^2 + (y - y0)^2 = R^2 + real(8) :: x0 + real(8) :: y0 + real(8) :: r + contains + procedure :: evaluate => z_cylinder_evaluate + procedure :: distance => z_cylinder_distance + procedure :: normal => z_cylinder_normal + end type SurfaceZCylinder + + type, extends(Surface) :: SurfaceSphere + ! (x - x0)^2 + (y - y0)^2 + (z - z0)^2 = R^2 + real(8) :: x0 + real(8) :: y0 + real(8) :: z0 + real(8) :: r + contains + procedure :: evaluate => sphere_evaluate + procedure :: distance => sphere_distance + procedure :: normal => sphere_normal + end type SurfaceSphere + + type, extends(Surface) :: SurfaceXCone + ! (y - y0)^2 + (z - z0)^2 = R^2*(x - x0)^2 + real(8) :: x0 + real(8) :: y0 + real(8) :: z0 + real(8) :: r2 + contains + procedure :: evaluate => x_cone_evaluate + procedure :: distance => x_cone_distance + procedure :: normal => x_cone_normal + end type SurfaceXCone + + type, extends(Surface) :: SurfaceYCone + ! (x - x0)^2 + (z - z0)^2 = R^2*(y - y0)^2 + real(8) :: x0 + real(8) :: y0 + real(8) :: z0 + real(8) :: r2 + contains + procedure :: evaluate => y_cone_evaluate + procedure :: distance => y_cone_distance + procedure :: normal => y_cone_normal + end type SurfaceYCone + + type, extends(Surface) :: SurfaceZCone + ! (x - x0)^2 + (y - y0)^2 = R^2*(z - z0)^2 + real(8) :: x0 + real(8) :: y0 + real(8) :: z0 + real(8) :: r2 + contains + procedure :: evaluate => z_cone_evaluate + procedure :: distance => z_cone_distance + procedure :: normal => z_cone_normal + end type SurfaceZCone + + type, extends(Surface) :: SurfaceQuadric + ! Ax^2 + By^2 + Cz^2 + Dxy + Eyz + Fxz + Gx + Hy + Jz + K = 0 + real(8) :: A, B, C, D, E, F, G, H, J, K + contains + procedure :: evaluate => quadric_evaluate + procedure :: distance => quadric_distance + procedure :: normal => quadric_normal + end type SurfaceQuadric + +contains + +!=============================================================================== +! SENSE determines whether a point is on the 'positive' or 'negative' side of a +! surface. This routine is crucial for determining what cell a particular point +! is in. The positive side is indicated by a returned value of .true. and the +! negative side is indicated by a returned value of .false. +!=============================================================================== + + pure function sense(this, xyz, uvw) result(s) + class(Surface), intent(in) :: this ! surface + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical :: s ! sense of particle + + real(8) :: f ! surface function evaluated at point + + ! Evaluate the surface equation at the particle's coordinates to determine + ! which side the particle is on + f = this%evaluate(xyz) + + ! Check which side of surface the point is on + if (abs(f) < FP_COINCIDENT) then + ! Particle may be coincident with this surface. To determine the sense, we + ! look at the direction of the particle relative to the surface normal (by + ! default in the positive direction) via their dot product. + s = (dot_product(uvw, this%normal(xyz)) > ZERO) + else + s = (f > ZERO) + end if + end function sense + +!=============================================================================== +! REFLECT determines the direction a particle will travel if it is specularly +! reflected from the surface at a given position and direction. The position is +! needed because the reflection is performed using the surface normal, which +! depends on the position for second-order surfaces. +!=============================================================================== + + pure subroutine reflect(this, xyz, uvw) + class(Surface), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(inout) :: uvw(3) + + real(8) :: projection + real(8) :: magnitude + real(8) :: n(3) + + ! Construct normal vector + n(:) = this%normal(xyz) + + ! Determine projection of direction onto normal and squared magnitude of + ! normal + projection = n(1)*uvw(1) + n(2)*uvw(2) + n(3)*uvw(3) + magnitude = n(1)*n(1) + n(2)*n(2) + n(3)*n(3) + + ! Reflect direction according to normal + uvw(:) = uvw - TWO*projection/magnitude * n + end subroutine reflect + +!=============================================================================== +! SurfaceXPlane Implementation +!=============================================================================== + + pure function x_plane_evaluate(this, xyz) result(f) + class(SurfaceXPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + f = xyz(1) - this%x0 + end function x_plane_evaluate + + pure function x_plane_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceXPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: f + + f = this%x0 - xyz(1) + if (coincident .or. abs(f) < FP_COINCIDENT .or. uvw(1) == ZERO) then + d = INFINITY + else + d = f/uvw(1) + if (d < ZERO) d = INFINITY + end if + end function x_plane_distance + + pure function x_plane_normal(this, xyz) result(uvw) + class(SurfaceXPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(:) = [ONE, ZERO, ZERO] + end function x_plane_normal + +!=============================================================================== +! SurfaceYPlane Implementation +!=============================================================================== + + pure function y_plane_evaluate(this, xyz) result(f) + class(SurfaceYPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + f = xyz(2) - this%y0 + end function y_plane_evaluate + + pure function y_plane_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceYPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: f + + f = this%y0 - xyz(2) + if (coincident .or. abs(f) < FP_COINCIDENT .or. uvw(2) == ZERO) then + d = INFINITY + else + d = f/uvw(2) + if (d < ZERO) d = INFINITY + end if + end function y_plane_distance + + pure function y_plane_normal(this, xyz) result(uvw) + class(SurfaceYPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(:) = [ZERO, ONE, ZERO] + end function y_plane_normal + +!=============================================================================== +! SurfaceZPlane Implementation +!=============================================================================== + + pure function z_plane_evaluate(this, xyz) result(f) + + class(SurfaceZPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + f = xyz(3) - this%z0 + + end function z_plane_evaluate + + pure function z_plane_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceZPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: f + + f = this%z0 - xyz(3) + if (coincident .or. abs(f) < FP_COINCIDENT .or. uvw(3) == ZERO) then + d = INFINITY + else + d = f/uvw(3) + if (d < ZERO) d = INFINITY + end if + end function z_plane_distance + + pure function z_plane_normal(this, xyz) result(uvw) + class(SurfaceZPlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(:) = [ZERO, ZERO, ONE] + end function z_plane_normal + +!=============================================================================== +! SurfacePlane Implementation +!=============================================================================== + + pure function plane_evaluate(this, xyz) result(f) + class(SurfacePlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + f = this%A*xyz(1) + this%B*xyz(2) + this%C*xyz(3) - this%D + end function plane_evaluate + + pure function plane_distance(this, xyz, uvw, coincident) result(d) + class(SurfacePlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: f + real(8) :: projection + + f = this%A*xyz(1) + this%B*xyz(2) + this%C*xyz(3) - this%D + projection = this%A*uvw(1) + this%B*uvw(2) + this%C*uvw(3) + if (coincident .or. abs(f) < FP_COINCIDENT .or. projection == ZERO) then + d = INFINITY + else + d = -f/projection + if (d < ZERO) d = INFINITY + end if + end function plane_distance + + pure function plane_normal(this, xyz) result(uvw) + class(SurfacePlane), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(:) = [this%A, this%B, this%C] + end function plane_normal + +!=============================================================================== +! SurfaceXCylinder Implementation +!=============================================================================== + + pure function x_cylinder_evaluate(this, xyz) result(f) + class(SurfaceXCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + real(8) :: y, z + + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + f = y*y + z*z - this%r*this%r + end function x_cylinder_evaluate + + pure function x_cylinder_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceXCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: y, z, k, a, c, quad + + a = ONE - uvw(1)*uvw(1) ! v^2 + w^2 + if (a == ZERO) then + d = INFINITY + else + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + k = y*uvw(2) + z*uvw(3) + c = y*y + z*z - this%r*this%r + quad = k*k - a*c + + if (quad < ZERO) then + ! no intersection with cylinder + + d = INFINITY + + elseif (coincident .or. abs(c) < FP_COINCIDENT) then + ! particle is on the cylinder, thus one distance is positive/negative + ! and the other is zero. The sign of k determines if we are facing in or + ! out + + if (k >= ZERO) then + d = INFINITY + else + d = (-k + sqrt(quad))/a + end if + + elseif (c < ZERO) then + ! particle is inside the cylinder, thus one distance must be negative + ! and one must be positive. The positive distance will be the one with + ! negative sign on sqrt(quad) + + d = (-k + sqrt(quad))/a + + else + ! particle is outside the cylinder, thus both distances are either + ! positive or negative. If positive, the smaller distance is the one + ! with positive sign on sqrt(quad) + + d = (-k - sqrt(quad))/a + if (d < ZERO) d = INFINITY + + end if + end if + end function x_cylinder_distance + + pure function x_cylinder_normal(this, xyz) result(uvw) + class(SurfaceXCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(1) = ZERO + uvw(2) = TWO*(xyz(2) - this%y0) + uvw(3) = TWO*(xyz(3) - this%z0) + end function x_cylinder_normal + +!=============================================================================== +! SurfaceYCylinder Implementation +!=============================================================================== + + pure function y_cylinder_evaluate(this, xyz) result(f) + class(SurfaceYCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + real(8) :: x, z + + x = xyz(1) - this%x0 + z = xyz(3) - this%z0 + f = x*x + z*z - this%r*this%r + end function y_cylinder_evaluate + + pure function y_cylinder_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceYCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: x, z, k, a, c, quad + + a = ONE - uvw(2)*uvw(2) ! u^2 + w^2 + if (a == ZERO) then + d = INFINITY + else + x = xyz(1) - this%x0 + z = xyz(3) - this%z0 + k = x*uvw(1) + z*uvw(3) + c = x*x + z*z - this%r*this%r + quad = k*k - a*c + + if (quad < ZERO) then + ! no intersection with cylinder + + d = INFINITY + + elseif (coincident .or. abs(c) < FP_COINCIDENT) then + ! particle is on the cylinder, thus one distance is positive/negative + ! and the other is zero. The sign of k determines if we are facing in or + ! out + + if (k >= ZERO) then + d = INFINITY + else + d = (-k + sqrt(quad))/a + end if + + elseif (c < ZERO) then + ! particle is inside the cylinder, thus one distance must be negative + ! and one must be positive. The positive distance will be the one with + ! negative sign on sqrt(quad) + + d = (-k + sqrt(quad))/a + + else + ! particle is outside the cylinder, thus both distances are either + ! positive or negative. If positive, the smaller distance is the one + ! with positive sign on sqrt(quad) + + d = (-k - sqrt(quad))/a + if (d < ZERO) d = INFINITY + + end if + end if + end function y_cylinder_distance + + pure function y_cylinder_normal(this, xyz) result(uvw) + class(SurfaceYCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(1) = TWO*(xyz(1) - this%x0) + uvw(2) = ZERO + uvw(3) = TWO*(xyz(3) - this%z0) + end function y_cylinder_normal + +!=============================================================================== +! SurfaceZCylinder Implementation +!=============================================================================== + + pure function z_cylinder_evaluate(this, xyz) result(f) + class(SurfaceZCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + real(8) :: x, y + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + f = x*x + y*y - this%r*this%r + end function z_cylinder_evaluate + + pure function z_cylinder_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceZCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: x, y, k, a, c, quad + + a = ONE - uvw(3)*uvw(3) ! u^2 + v^2 + if (a == ZERO) then + d = INFINITY + else + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + k = x*uvw(1) + y*uvw(2) + c = x*x + y*y - this%r*this%r + quad = k*k - a*c + + if (quad < ZERO) then + ! no intersection with cylinder + + d = INFINITY + + elseif (coincident .or. abs(c) < FP_COINCIDENT) then + ! particle is on the cylinder, thus one distance is positive/negative + ! and the other is zero. The sign of k determines if we are facing in or + ! out + + if (k >= ZERO) then + d = INFINITY + else + d = (-k + sqrt(quad))/a + end if + + elseif (c < ZERO) then + ! particle is inside the cylinder, thus one distance must be negative + ! and one must be positive. The positive distance will be the one with + ! negative sign on sqrt(quad) + + d = (-k + sqrt(quad))/a + + else + ! particle is outside the cylinder, thus both distances are either + ! positive or negative. If positive, the smaller distance is the one + ! with positive sign on sqrt(quad) + + d = (-k - sqrt(quad))/a + if (d < ZERO) d = INFINITY + + end if + end if + end function z_cylinder_distance + + pure function z_cylinder_normal(this, xyz) result(uvw) + class(SurfaceZCylinder), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(1) = TWO*(xyz(1) - this%x0) + uvw(2) = TWO*(xyz(2) - this%y0) + uvw(3) = ZERO + end function z_cylinder_normal + +!=============================================================================== +! SurfaceSphere Implementation +!=============================================================================== + + pure function sphere_evaluate(this, xyz) result(f) + class(SurfaceSphere), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + real(8) :: x, y, z + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + f = x*x + y*y + z*z - this%r*this%r + end function sphere_evaluate + + pure function sphere_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceSphere), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: x, y, z, k, c, quad + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + k = x*uvw(1) + y*uvw(2) + z*uvw(3) + c = x*x + y*y + z*z - this%r*this%r + quad = k*k - c + + if (quad < ZERO) then + ! no intersection with sphere + + d = INFINITY + + elseif (coincident .or. abs(c) < FP_COINCIDENT) then + ! particle is on the sphere, thus one distance is positive/negative and + ! the other is zero. The sign of k determines if we are facing in or out + + if (k >= ZERO) then + d = INFINITY + else + d = -k + sqrt(quad) + end if + + elseif (c < ZERO) then + ! particle is inside the sphere, thus one distance must be negative and + ! one must be positive. The positive distance will be the one with + ! negative sign on sqrt(quad) + + d = -k + sqrt(quad) + + else + ! particle is outside the sphere, thus both distances are either positive + ! or negative. If positive, the smaller distance is the one with positive + ! sign on sqrt(quad) + + d = -k - sqrt(quad) + if (d < ZERO) d = INFINITY + + end if + end function sphere_distance + + pure function sphere_normal(this, xyz) result(uvw) + class(SurfaceSphere), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(:) = TWO*(xyz - [this%x0, this%y0, this%z0]) + end function sphere_normal + +!=============================================================================== +! SurfaceXCone Implementation +!=============================================================================== + + pure function x_cone_evaluate(this, xyz) result(f) + class(SurfaceXCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + real(8) :: x, y, z + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + f = y*y + z*z - this%r2*x*x + end function x_cone_evaluate + + pure function x_cone_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceXCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: x, y, z, k, a, b, c, quad + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + a = uvw(2)*uvw(2) + uvw(3)*uvw(3) - this%r2*uvw(1)*uvw(1) + k = y*uvw(2) + z*uvw(3) - this%r2*x*uvw(1) + c = y*y + z*z - this%r2*x*x + quad = k*k - a*c + + if (quad < ZERO) then + ! no intersection with cone + + d = INFINITY + + elseif (coincident .or. abs(c) < FP_COINCIDENT) then + ! particle is on the cone, thus one distance is positive/negative and the + ! other is zero. The sign of k determines which distance is zero and which + ! is not. + + if (k >= ZERO) then + d = (-k - sqrt(quad))/a + else + d = (-k + sqrt(quad))/a + end if + + else + ! calculate both solutions to the quadratic + quad = sqrt(quad) + d = (-k - quad)/a + b = (-k + quad)/a + + ! determine the smallest positive solution + if (d < ZERO) then + if (b > ZERO) then + d = b + end if + else + if (b > ZERO) d = min(d, b) + end if + end if + + ! If the distance was negative, set boundary distance to infinity + if (d <= ZERO) d = INFINITY + end function x_cone_distance + + pure function x_cone_normal(this, xyz) result(uvw) + class(SurfaceXCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(1) = -TWO*this%r2*(xyz(1) - this%x0) + uvw(2) = TWO*(xyz(2) - this%y0) + uvw(3) = TWO*(xyz(3) - this%z0) + end function x_cone_normal + +!=============================================================================== +! SurfaceYCone Implementation +!=============================================================================== + + pure function y_cone_evaluate(this, xyz) result(f) + class(SurfaceYCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + real(8) :: x, y, z + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + f = x*x + z*z - this%r2*y*y + end function y_cone_evaluate + + pure function y_cone_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceYCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: x, y, z, k, a, b, c, quad + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + a = uvw(1)*uvw(1) + uvw(3)*uvw(3) - this%r2*uvw(2)*uvw(2) + k = x*uvw(1) + z*uvw(3) - this%r2*y*uvw(2) + c = x*x + z*z - this%r2*y*y + quad = k*k - a*c + + if (quad < ZERO) then + ! no intersection with cone + + d = INFINITY + + elseif (coincident .or. abs(c) < FP_COINCIDENT) then + ! particle is on the cone, thus one distance is positive/negative and the + ! other is zero. The sign of k determines which distance is zero and which + ! is not. + + if (k >= ZERO) then + d = (-k - sqrt(quad))/a + else + d = (-k + sqrt(quad))/a + end if + + else + ! calculate both solutions to the quadratic + quad = sqrt(quad) + d = (-k - quad)/a + b = (-k + quad)/a + + ! determine the smallest positive solution + if (d < ZERO) then + if (b > ZERO) then + d = b + end if + else + if (b > ZERO) d = min(d, b) + end if + end if + + ! If the distance was negative, set boundary distance to infinity + if (d <= ZERO) d = INFINITY + end function y_cone_distance + + pure function y_cone_normal(this, xyz) result(uvw) + class(SurfaceYCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(1) = TWO*(xyz(1) - this%x0) + uvw(2) = -TWO*this%r2*(xyz(2) - this%y0) + uvw(3) = TWO*(xyz(3) - this%z0) + end function y_cone_normal + +!=============================================================================== +! SurfaceZCone Implementation +!=============================================================================== + + pure function z_cone_evaluate(this, xyz) result(f) + class(SurfaceZCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + real(8) :: x, y, z + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + f = x*x + y*y - this%r2*z*z + end function z_cone_evaluate + + pure function z_cone_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceZCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: x, y, z, k, a, b, c, quad + + x = xyz(1) - this%x0 + y = xyz(2) - this%y0 + z = xyz(3) - this%z0 + a = uvw(1)*uvw(1) + uvw(2)*uvw(2) - this%r2*uvw(3)*uvw(3) + k = x*uvw(1) + y*uvw(2) - this%r2*z*uvw(3) + c = x*x + y*y - this%r2*z*z + quad = k*k - a*c + + if (quad < ZERO) then + ! no intersection with cone + + d = INFINITY + + elseif (coincident .or. abs(c) < FP_COINCIDENT) then + ! particle is on the cone, thus one distance is positive/negative and the + ! other is zero. The sign of k determines which distance is zero and which + ! is not. + + if (k >= ZERO) then + d = (-k - sqrt(quad))/a + else + d = (-k + sqrt(quad))/a + end if + + else + ! calculate both solutions to the quadratic + quad = sqrt(quad) + d = (-k - quad)/a + b = (-k + quad)/a + + ! determine the smallest positive solution + if (d < ZERO) then + if (b > ZERO) then + d = b + end if + else + if (b > ZERO) d = min(d, b) + end if + end if + + ! If the distance was negative, set boundary distance to infinity + if (d <= ZERO) d = INFINITY + end function z_cone_distance + + pure function z_cone_normal(this, xyz) result(uvw) + class(SurfaceZCone), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + uvw(1) = TWO*(xyz(1) - this%x0) + uvw(2) = TWO*(xyz(2) - this%y0) + uvw(3) = -TWO*this%r2*(xyz(3) - this%z0) + end function z_cone_normal + +!=============================================================================== +! SurfaceQuadric Implementation +!=============================================================================== + + pure function quadric_evaluate(this, xyz) result(f) + class(SurfaceQuadric), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: f + + associate (x => xyz(1), y => xyz(2), z => xyz(3)) + f = x*(this%A*x + this%D*y + this%G) + & + y*(this%B*y + this%E*z + this%H) + & + z*(this%C*z + this%F*x + this%J) + this%K + end associate + end function quadric_evaluate + + pure function quadric_distance(this, xyz, uvw, coincident) result(d) + class(SurfaceQuadric), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8), intent(in) :: uvw(3) + logical, intent(in) :: coincident + real(8) :: d + + real(8) :: a, k, c + real(8) :: quad, b + + associate (x => xyz(1), y => xyz(2), z => xyz(3), & + u => uvw(1), v => uvw(2), w => uvw(3)) + + a = this%A*u*u + this%B*v*v + this%C*w*w + this%D*u*v + this%E*v*w + & + this%F*u*w + k = (this%A*u*x + this%B*v*y + this%C*w*z + HALF*(this%D*(u*y + v*x) + & + this%E*(v*z + w*y) + this%F*(w*x + u*z) + this%G*u + this%H*v + & + this%J*w)) + c = this%A*x*x + this%B*y*y + this%C*z*z + this%D*x*y + this%E*y*z + & + this%F*x*z + this%G*x + this%H*y + this%J*z + this%K + quad = k*k - a*c + + if (quad < ZERO) then + ! no intersection with surface + + d = INFINITY + + elseif (coincident .or. abs(c) < FP_COINCIDENT) then + ! particle is on the surface, thus one distance is positive/negative and + ! the other is zero. The sign of k determines which distance is zero and + ! which is not. + + if (k >= ZERO) then + d = (-k - sqrt(quad))/a + else + d = (-k + sqrt(quad))/a + end if + + else + ! calculate both solutions to the quadratic + quad = sqrt(quad) + d = (-k - quad)/a + b = (-k + quad)/a + + ! determine the smallest positive solution + if (d < ZERO) then + if (b > ZERO) then + d = b + end if + else + if (b > ZERO) d = min(d, b) + end if + end if + + ! If the distance was negative, set boundary distance to infinity + if (d <= ZERO) d = INFINITY + end associate + end function quadric_distance + + pure function quadric_normal(this, xyz) result(uvw) + class(SurfaceQuadric), intent(in) :: this + real(8), intent(in) :: xyz(3) + real(8) :: uvw(3) + + associate (x => xyz(1), y => xyz(2), z => xyz(3)) + uvw(1) = TWO*this%A*x + this%D*y + this%F*z + this%G + uvw(2) = TWO*this%B*y + this%D*x + this%E*z + this%H + uvw(3) = TWO*this%C*z + this%E*y + this%F*x + this%J + end associate + end function quadric_normal + +end module surface_header diff --git a/src/tally.F90 b/src/tally.F90 index e78e58f284..09e30a2426 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -9,12 +9,14 @@ module tally use mesh, only: get_mesh_bin, bin_to_mesh_indices, & get_mesh_indices, mesh_indices_to_bin, & mesh_intersects_2d, mesh_intersects_3d - use mesh_header, only: StructuredMesh + use mesh_header, only: RegularMesh use output, only: header use particle_header, only: LocalCoord, Particle use search, only: binary_search use string, only: to_str use tally_header, only: TallyResult, TallyMapItem, TallyMapElement + use fission, only: nu_total, nu_delayed, yield_delayed + use interpolation, only: interpolate_tab1 #ifdef MPI use message_passing @@ -35,13 +37,13 @@ contains subroutine score_general(p, t, start_index, filter_index, i_nuclide, & atom_density, flux) - type(Particle), intent(in) :: p - type(TallyObject), pointer, intent(inout) :: t - integer, intent(in) :: start_index - integer, intent(in) :: i_nuclide - integer, intent(in) :: filter_index ! for % results - real(8), intent(in) :: flux ! flux estimate - real(8), intent(in) :: atom_density ! atom/b-cm + type(Particle), intent(in) :: p + type(TallyObject), intent(inout) :: t + integer, intent(in) :: start_index + integer, intent(in) :: i_nuclide + integer, intent(in) :: filter_index ! for % results + real(8), intent(in) :: flux ! flux estimate + real(8), intent(in) :: atom_density ! atom/b-cm integer :: i ! loop index for scoring bins integer :: l ! loop index for nuclides in material @@ -53,14 +55,17 @@ contains integer :: i_energy ! index in nuclide energy grid integer :: score_bin ! scoring bin, e.g. SCORE_FLUX integer :: score_index ! scoring bin index + integer :: d ! delayed neutron index + integer :: d_bin ! delayed group bin index + integer :: dg_filter ! index of delayed group filter + real(8) :: yield ! delayed neutron yield real(8) :: atom_density_ ! atom/b-cm real(8) :: f ! interpolation factor real(8) :: score ! analog tally score real(8) :: macro_total ! material macro total xs real(8) :: macro_scatt ! material macro scatt xs real(8) :: uvw(3) ! particle direction - type(Material), pointer :: mat - type(Reaction), pointer :: rxn + real(8) :: E ! particle energy i = 0 SCORE_LOOP: do q = 1, t % n_user_score_bins @@ -81,8 +86,8 @@ contains case (SCORE_FLUX, SCORE_FLUX_YN) if (t % estimator == ESTIMATOR_ANALOG) then ! All events score to a flux bin. We actually use a collision - ! estimator since there is no way to count 'events' exactly for - ! the flux + ! estimator in place of an analog one since there is no way to count + ! 'events' exactly for the flux if (survival_biasing) then ! We need to account for the fact that some weight was already ! absorbed @@ -92,7 +97,7 @@ contains end if score = score / material_xs % total - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else ! For flux, we need no cross section score = flux end if @@ -111,7 +116,7 @@ contains score = p % last_wgt end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % total * atom_density * flux else @@ -120,6 +125,39 @@ contains end if + case (SCORE_INVERSE_VELOCITY) + + ! make sure the correct energy is used + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + E = p % E + else + E = p % last_E + end if + + if (t % estimator == ESTIMATOR_ANALOG) then + ! All events score to an inverse velocity bin. We actually use a + ! collision estimator in place of an analog one since there is no way + ! to count 'events' exactly for the inverse velocity + if (survival_biasing) then + ! We need to account for the fact that some weight was already + ! absorbed + score = p % last_wgt + p % absorb_wgt + else + score = p % last_wgt + end if + + ! Score the flux weighted inverse velocity with velocity in units of + ! cm/s + score = score / material_xs % total & + / (sqrt(TWO * E / (MASS_NEUTRON_MEV)) * C_LIGHT * 100.0_8) + + else + ! For inverse velocity, we don't need a cross section. The velocity is + ! in units of cm/s. + score = flux / (sqrt(TWO * E / (MASS_NEUTRON_MEV)) * C_LIGHT * 100.0_8) + end if + + case (SCORE_SCATTER, SCORE_SCATTER_N) if (t % estimator == ESTIMATOR_ANALOG) then ! Skip any event where the particle didn't scatter @@ -129,8 +167,8 @@ contains ! reaction rate score = p % last_wgt - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then - ! Note SCORE_SCATTER_N not available for tracklength. + else + ! Note SCORE_SCATTER_N not available for tracklength/collision. if (i_nuclide > 0) then score = (micro_xs(i_nuclide) % total & - micro_xs(i_nuclide) % absorption) * atom_density * flux @@ -170,10 +208,30 @@ contains ! Only analog estimators are available. ! Skip any event where the particle didn't scatter if (p % event /= EVENT_SCATTER) cycle SCORE_LOOP - ! For scattering production, we need to use the post-collision - ! weight as the estimate for the number of neutrons exiting a - ! reaction with neutrons in the exit channel - score = p % wgt + ! For scattering production, we need to use the pre-collision + ! weight times the multiplicity as the estimate for the number of + ! neutrons exiting a reaction with neutrons in the exit channel + if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + ! Don't waste time on very common reactions we know have multiplicities + ! of one. + score = p % last_wgt + else + m = nuclides(p%event_nuclide)%reaction_index% & + get_key(p % event_MT) + + ! Get multiplicity and apply to score + associate (rxn => nuclides(p%event_nuclide)%reactions(m)) + if (rxn % multiplicity_with_E) then + ! Then the multiplicity was already incorporated in to p % wgt + ! per the scattering routine, + score = p % wgt + else + ! Grab the multiplicity from the rxn + score = p % last_wgt * rxn % multiplicity + end if + end associate + end if case (SCORE_NU_SCATTER_PN) @@ -183,10 +241,30 @@ contains i = i + t % moment_order(i) cycle SCORE_LOOP end if - ! For scattering production, we need to use the post-collision - ! weight as the estimate for the number of neutrons exiting a - ! reaction with neutrons in the exit channel - score = p % wgt + ! For scattering production, we need to use the pre-collision + ! weight times the multiplicity as the estimate for the number of + ! neutrons exiting a reaction with neutrons in the exit channel + if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + ! Don't waste time on very common reactions we know have multiplicities + ! of one. + score = p % last_wgt + else + m = nuclides(p%event_nuclide)%reaction_index% & + get_key(p % event_MT) + + ! Get multiplicity and apply to score + associate (rxn => nuclides(p%event_nuclide)%reactions(m)) + if (rxn % multiplicity_with_E) then + ! Then the multiplicity was already incorporated in to p % wgt + ! per the scattering routine, + score = p % wgt + else + ! Grab the multiplicity from the rxn + score = p % last_wgt * rxn % multiplicity + end if + end associate + end if case (SCORE_NU_SCATTER_YN) @@ -196,10 +274,30 @@ contains i = i + (t % moment_order(i) + 1)**2 - 1 cycle SCORE_LOOP end if - ! For scattering production, we need to use the post-collision - ! weight as the estimate for the number of neutrons exiting a - ! reaction with neutrons in the exit channel - score = p % wgt + ! For scattering production, we need to use the pre-collision + ! weight times the multiplicity as the estimate for the number of + ! neutrons exiting a reaction with neutrons in the exit channel + if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & + (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then + ! Don't waste time on very common reactions we know have multiplicities + ! of one. + score = p % last_wgt + else + m = nuclides(p%event_nuclide)%reaction_index% & + get_key(p % event_MT) + + ! Get multiplicity and apply to score + associate (rxn => nuclides(p%event_nuclide)%reactions(m)) + if (rxn % multiplicity_with_E) then + ! Then the multiplicity was already incorporated in to p % wgt + ! per the scattering routine, + score = p % wgt + else + ! Grab the multiplicity from the rxn + score = p % last_wgt * rxn % multiplicity + end if + end associate + end if case (SCORE_TRANSPORT) @@ -240,7 +338,7 @@ contains score = p % last_wgt end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % absorption * atom_density * flux else @@ -271,7 +369,7 @@ contains / micro_xs(p % event_nuclide) % absorption end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % fission * atom_density * flux else @@ -314,7 +412,7 @@ contains score = keff * p % wgt_bank end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (i_nuclide > 0) then score = micro_xs(i_nuclide) % nu_fission * atom_density * flux else @@ -323,43 +421,260 @@ contains end if + case (SCORE_DELAYED_NU_FISSION) + + ! make sure the correct energy is used + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + E = p % E + else + E = p % last_E + end if + + ! Set the delayedgroup filter index and the number of delayed group bins + dg_filter = t % find_filter(FILTER_DELAYEDGROUP) + + if (t % estimator == ESTIMATOR_ANALOG) then + if (survival_biasing .or. p % fission) then + if (t % find_filter(FILTER_ENERGYOUT) > 0) then + ! Normally, we only need to make contributions to one scoring + ! bin. However, in the case of fission, since multiple fission + ! neutrons were emitted with different energies, multiple + ! outgoing energy bins may have been scored to. The following + ! logic treats this special case and results to multiple bins + call score_fission_delayed_eout(p, t, score_index) + cycle SCORE_LOOP + end if + end if + if (survival_biasing) then + ! No fission events occur if survival biasing is on -- need to + ! calculate fraction of absorptions that would have resulted in + ! delayed-nu-fission + if (micro_xs(p % event_nuclide) % absorption > ZERO) then + + ! Check if the delayed group filter is present + if (dg_filter > 0) then + + ! Loop over all delayed group bins and tally to them + ! individually + do d_bin = 1, t % filters(dg_filter) % n_bins + + ! Get the delayed group for this bin + d = t % filters(dg_filter) % int_bins(d_bin) + + ! Compute the yield for this delayed group + yield = yield_delayed(nuclides(p % event_nuclide), E, d) + + ! Compute the score and tally to bin + score = p % absorb_wgt * yield * micro_xs(p % event_nuclide) & + % fission * nu_delayed(nuclides(p % event_nuclide), E) / & + micro_xs(p % event_nuclide) % absorption + call score_fission_delayed_dg(t, d_bin, score, score_index) + end do + cycle SCORE_LOOP + else + ! If the delayed group filter is not present, compute the score + ! by multiplying the absorbed weight by the fraction of the + ! delayed-nu-fission xs to the absorption xs + score = p % absorb_wgt * micro_xs(p % event_nuclide) & + % fission * nu_delayed(nuclides(p % event_nuclide), E) / & + micro_xs(p % event_nuclide) % absorption + end if + end if + else + ! Skip any non-fission events + if (.not. p % fission) cycle SCORE_LOOP + ! If there is no outgoing energy filter, than we only need to + ! score to one bin. For the score to be 'analog', we need to + ! score the number of particles that were banked in the fission + ! bank. Since this was weighted by 1/keff, we multiply by keff + ! to get the proper score. Loop over the neutrons produced from + ! fission and check which ones are delayed. If a delayed neutron is + ! encountered, add its contribution to the fission bank to the + ! score. + + ! Check if the delayed group filter is present + if (dg_filter > 0) then + + ! Loop over all delayed group bins and tally to them individually + do d_bin = 1, t % filters(dg_filter) % n_bins + + ! Get the delayed group for this bin + d = t % filters(dg_filter) % int_bins(d_bin) + + ! Compute the score and tally to bin + score = keff * p % wgt_bank / p % n_bank * p % n_delayed_bank(d) + call score_fission_delayed_dg(t, d_bin, score, score_index) + end do + cycle SCORE_LOOP + else + + ! Add the contribution from all delayed groups + score = keff * p % wgt_bank / p % n_bank * sum(p % n_delayed_bank) + end if + end if + else + + ! Check if tally is on a single nuclide + if (i_nuclide > 0) then + + ! Check if the delayed group filter is present + if (dg_filter > 0) then + + ! Loop over all delayed group bins and tally to them individually + do d_bin = 1, t % filters(dg_filter) % n_bins + + ! Get the delayed group for this bin + d = t % filters(dg_filter) % int_bins(d_bin) + + ! Compute the yield for this delayed group + yield = yield_delayed(nuclides(i_nuclide), E, d) + + ! Compute the score and tally to bin + score = micro_xs(i_nuclide) % fission * yield & + * nu_delayed(nuclides(i_nuclide), E) * atom_density * flux + call score_fission_delayed_dg(t, d_bin, score, score_index) + end do + cycle SCORE_LOOP + else + + ! If the delayed group filter is not present, compute the score + ! by multiplying the delayed-nu-fission macro xs by the flux + score = micro_xs(i_nuclide) % fission * & + nu_delayed(nuclides(i_nuclide), E) * atom_density * flux + end if + + ! Tally is on total nuclides + else + + ! Check if the delayed group filter is present + if (dg_filter > 0) then + + ! Loop over all nuclides in the current material + do l = 1, materials(p % material) % n_nuclides + + ! Get atom density + atom_density_ = materials(p % material) % atom_density(l) + + ! Get index in nuclides array + i_nuc = materials(p % material) % nuclide(l) + + ! Loop over all delayed group bins and tally to them individually + do d_bin = 1, t % filters(dg_filter) % n_bins + + ! Get the delayed group for this bin + d = t % filters(dg_filter) % int_bins(d_bin) + + ! Get the yield for the desired nuclide and delayed group + yield = yield_delayed(nuclides(i_nuc), E, d) + + ! Compute the score and tally to bin + score = micro_xs(i_nuc) % fission * yield & + * nu_delayed(nuclides(i_nuc), E) * atom_density_ * flux + call score_fission_delayed_dg(t, d_bin, score, score_index) + end do + end do + cycle SCORE_LOOP + else + + score = ZERO + + ! Loop over all nuclides in the current material + do l = 1, materials(p % material) % n_nuclides + + ! Get atom density + atom_density_ = materials(p % material) % atom_density(l) + + ! Get index in nuclides array + i_nuc = materials(p % material) % nuclide(l) + + ! Accumulate the contribution from each nuclide + score = score + micro_xs(i_nuc) % fission & + * nu_delayed(nuclides(i_nuc), E) * atom_density_ * flux + end do + end if + end if + end if + + case (SCORE_KAPPA_FISSION) + ! Determine kappa-fission cross section on the fly. The ENDF standard + ! (ENDF-102) states that MT 18 stores the fission energy as the Q_value + ! (fission(1)) + + score = ZERO + if (t % estimator == ESTIMATOR_ANALOG) then if (survival_biasing) then ! No fission events occur if survival biasing is on -- need to ! calculate fraction of absorptions that would have resulted in ! fission scale by kappa-fission - if (micro_xs(p % event_nuclide) % absorption > ZERO) then - score = p % absorb_wgt * & - micro_xs(p % event_nuclide) % kappa_fission / & - micro_xs(p % event_nuclide) % absorption - else - score = ZERO - end if + associate (nuc => nuclides(p%event_nuclide)) + if (micro_xs(p%event_nuclide)%absorption > ZERO .and. & + nuc%fissionable) then + score = p%absorb_wgt * & + nuc%reactions(nuc%index_fission(1))%Q_value * & + micro_xs(p%event_nuclide)%fission / & + micro_xs(p%event_nuclide)%absorption + end if + end associate else ! Skip any non-absorption events if (p % event == EVENT_SCATTER) cycle SCORE_LOOP ! All fission events will contribute, so again we can use ! particle's weight entering the collision as the estimate for ! the fission energy production rate - score = p % last_wgt * & - micro_xs(p % event_nuclide) % kappa_fission / & - micro_xs(p % event_nuclide) % absorption + associate (nuc => nuclides(p%event_nuclide)) + if (nuc%fissionable) then + score = p%last_wgt * & + nuc%reactions(nuc%index_fission(1))%Q_value * & + micro_xs(p%event_nuclide)%fission / & + micro_xs(p%event_nuclide)%absorption + end if + end associate end if - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else if (i_nuclide > 0) then - score = micro_xs(i_nuclide) % kappa_fission * atom_density * flux + associate (nuc => nuclides(i_nuclide)) + if (nuc%fissionable) then + score = nuc%reactions(nuc%index_fission(1))%Q_value * & + micro_xs(i_nuclide)%fission * atom_density * flux + end if + end associate else - score = material_xs % kappa_fission * flux + do l = 1, materials(p%material)%n_nuclides + ! Determine atom density and index of nuclide + atom_density_ = materials(p%material)%atom_density(l) + i_nuc = materials(p%material)%nuclide(l) + + ! If nuclide is fissionable, accumulate kappa fission + associate(nuc => nuclides(i_nuc)) + if (nuc % fissionable) then + score = score + nuc%reactions(nuc%index_fission(1))%Q_value * & + micro_xs(i_nuc)%fission * atom_density_ * flux + end if + end associate + end do end if end if - case (SCORE_EVENTS) ! Simply count number of scoring events score = ONE + case (ELASTIC) + if (t % estimator == ESTIMATOR_ANALOG) then + ! Check if event MT matches + if (p % event_MT /= ELASTIC) cycle SCORE_LOOP + score = p % last_wgt + + else + if (i_nuclide > 0) then + score = micro_xs(i_nuclide) % elastic * atom_density * flux + else + score = material_xs % elastic * flux + end if + end if case default if (t % estimator == ESTIMATOR_ANALOG) then @@ -368,7 +683,7 @@ contains if (p % event_MT /= score_bin) cycle SCORE_LOOP score = p % last_wgt - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then + else ! Any other cross section has to be calculated on-the-fly. For ! cross sections that are used often (e.g. n2n, ngamma, etc. for ! depletion), it might make sense to optimize this section or @@ -378,14 +693,10 @@ contains score = ZERO if (i_nuclide > 0) then - ! TODO: The following search for the matching reaction could - ! be replaced by adding a dictionary on each Nuclide instance - ! of the form {MT: i_reaction, ...} - REACTION_LOOP: do m = 1, nuclides(i_nuclide) % n_reaction - ! Get pointer to reaction - rxn => nuclides(i_nuclide) % reactions(m) - ! Check if this is the desired MT - if (score_bin == rxn % MT) then + if (nuclides(i_nuclide)%reaction_index%has_key(score_bin)) then + m = nuclides(i_nuclide)%reaction_index%get_key(score_bin) + associate (rxn => nuclides(i_nuclide) % reactions(m)) + ! Retrieve index on nuclide energy grid and interpolation ! factor i_energy = micro_xs(i_nuclide) % index_grid @@ -395,26 +706,20 @@ contains rxn%threshold + 1) + f * rxn % sigma(i_energy - & rxn%threshold + 2)) * atom_density * flux end if - exit REACTION_LOOP - end if - end do REACTION_LOOP + end associate + end if else - ! Get pointer to current material - mat => materials(p % material) - do l = 1, mat % n_nuclides + do l = 1, materials(p % material) % n_nuclides ! Get atom density - atom_density_ = mat % atom_density(l) + atom_density_ = materials(p % material) % atom_density(l) + ! Get index in nuclides array - i_nuc = mat % nuclide(l) - ! TODO: The following search for the matching reaction could - ! be replaced by adding a dictionary on each Nuclide - ! instance of the form {MT: i_reaction, ...} - do m = 1, nuclides(i_nuc) % n_reaction - ! Get pointer to reaction - rxn => nuclides(i_nuc) % reactions(m) - ! Check if this is the desired MT - if (score_bin == rxn % MT) then + i_nuc = materials(p % material) % nuclide(l) + + if (nuclides(i_nuc)%reaction_index%has_key(score_bin)) then + m = nuclides(i_nuc)%reaction_index%get_key(score_bin) + associate (rxn => nuclides(i_nuc) % reactions(m)) ! Retrieve index on nuclide energy grid and interpolation ! factor i_energy = micro_xs(i_nuc) % index_grid @@ -424,9 +729,8 @@ contains rxn%threshold + 1) + f * rxn % sigma(i_energy - & rxn%threshold + 2)) * atom_density_ * flux end if - exit - end if - end do + end associate + end if end do end if @@ -484,7 +788,8 @@ contains case(SCORE_FLUX_YN, SCORE_TOTAL_YN) score_index = score_index - 1 num_nm = 1 - if (t % estimator == ESTIMATOR_ANALOG) then + if (t % estimator == ESTIMATOR_ANALOG .or. & + t % estimator == ESTIMATOR_COLLISION) then uvw = p % last_uvw else if (t % estimator == ESTIMATOR_TRACKLENGTH) then uvw = p % coord(1) % uvw @@ -536,6 +841,59 @@ contains end do SCORE_LOOP end subroutine score_general +!=============================================================================== +! SCORE_ALL_NUCLIDES tallies individual nuclide reaction rates specifically when +! the user requests all. +!=============================================================================== + + subroutine score_all_nuclides(p, i_tally, flux, filter_index) + + type(Particle), intent(in) :: p + integer, intent(in) :: i_tally + real(8), intent(in) :: flux + integer, intent(in) :: filter_index + + integer :: i ! loop index for nuclides in material + integer :: i_nuclide ! index in nuclides array + real(8) :: atom_density ! atom density of single nuclide in atom/b-cm + type(TallyObject), pointer :: t + type(Material), pointer :: mat + + ! Get pointer to tally + t => tallies(i_tally) + + ! Get pointer to current material. We need this in order to determine what + ! nuclides are in the material + mat => materials(p % material) + + ! ========================================================================== + ! SCORE ALL INDIVIDUAL NUCLIDE REACTION RATES + + NUCLIDE_LOOP: do i = 1, mat % n_nuclides + + ! Determine index in nuclides array and atom density for i-th nuclide in + ! current material + i_nuclide = mat % nuclide(i) + atom_density = mat % atom_density(i) + + ! Determine score for each bin + call score_general(p, t, (i_nuclide-1)*t % n_score_bins, filter_index, & + i_nuclide, atom_density, flux) + + end do NUCLIDE_LOOP + + ! ========================================================================== + ! SCORE TOTAL MATERIAL REACTION RATES + + i_nuclide = -1 + atom_density = ZERO + + ! Determine score for each bin + call score_general(p, t, n_nuclides_total*t % n_score_bins, filter_index, & + i_nuclide, atom_density, flux) + + end subroutine score_all_nuclides + !=============================================================================== ! SCORE_ANALOG_TALLY keeps track of how many events occur in a specified cell, ! energy range, etc. Note that since these are "analog" tallies, they are only @@ -651,9 +1009,8 @@ contains !=============================================================================== subroutine score_fission_eout(p, t, i_score) - type(Particle), intent(in) :: p - type(TallyObject), pointer :: t + type(TallyObject), intent(inout) :: t integer, intent(in) :: i_score ! index for score integer :: i ! index of outgoing energy filter @@ -705,6 +1062,132 @@ contains end subroutine score_fission_eout +!=============================================================================== +! SCORE_FISSION_DELAYED_EOUT handles a special case where we need to store +! delayed neutron production rate with an outgoing energy filter (think of a +! fission matrix). In this case, we may need to score to multiple bins if there +! were multiple neutrons produced with different energies. +!=============================================================================== + + subroutine score_fission_delayed_eout(p, t, i_score) + + type(Particle), intent(in) :: p + type(TallyObject), intent(inout) :: t + integer, intent(in) :: i_score ! index for score + + integer :: i ! index of outgoing energy filter + integer :: j ! index of delayedgroup filter + integer :: d ! delayed group + integer :: g ! another delayed group + integer :: d_bin ! delayed group bin index + integer :: n ! number of energies on filter + integer :: k ! loop index for bank sites + integer :: bin_energyout ! original outgoing energy bin + integer :: i_filter ! index for matching filter bin combination + real(8) :: score ! actual score + real(8) :: E_out ! energy of fission bank site + + ! Save original outgoing energy bin + i = t % find_filter(FILTER_ENERGYOUT) + bin_energyout = matching_bins(i) + + ! Get the index of delayed group filter + j = t % find_filter(FILTER_DELAYEDGROUP) + + ! Get number of energies on filter + n = size(t % filters(i) % real_bins) + + ! Since the creation of fission sites is weighted such that it is + ! expected to create n_particles sites, we need to multiply the + ! score by keff to get the true delayed-nu-fission rate. + + ! loop over number of particles banked + do k = 1, p % n_bank + + ! get the delayed group + g = fission_bank(n_bank - p % n_bank + k) % delayed_group + + ! check if the particle was born delayed + if (g /= 0) then + + ! determine score based on bank site weight and keff + score = keff * fission_bank(n_bank - p % n_bank + k) % wgt + + ! determine outgoing energy from fission bank + E_out = fission_bank(n_bank - p % n_bank + k) % E + + ! check if outgoing energy is within specified range on filter + if (E_out < t % filters(i) % real_bins(1) .or. & + E_out > t % filters(i) % real_bins(n)) cycle + + ! change outgoing energy bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, n, E_out) + + ! if the delayed group filter is present, tally to corresponding + ! delayed group bin if it exists + if (j > 0) then + + ! loop over delayed group bins until the corresponding bin is found + do d_bin = 1, t % filters(j) % n_bins + d = t % filters(j) % int_bins(d_bin) + + ! check whether the delayed group of the particle is equal to the + ! delayed group of this bin + if (d == g) then + call score_fission_delayed_dg(t, d_bin, score, i_score) + end if + end do + + ! if the delayed group filter is not present, add score to tally + else + + ! determine scoring index + i_filter = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 + + ! Add score to tally +!$omp atomic + t % results(i_score, i_filter) % value = & + t % results(i_score, i_filter) % value + score + end if + end if + end do + + ! reset outgoing energy bin + matching_bins(i) = bin_energyout + + end subroutine score_fission_delayed_eout + +!=============================================================================== +! SCORE_FISSION_DELAYED_DG helper function used to increment the tally when a +! delayed group filter is present. +!=============================================================================== + + subroutine score_fission_delayed_dg(t, d_bin, score, score_index) + + type(TallyObject), intent(inout) :: t + integer, intent(in) :: score_index ! index for score + integer, intent(in) :: d_bin ! delayed group bin index + + integer :: bin_original ! original bin index + integer :: filter_index ! index for matching filter bin combination + real(8) :: score ! actual score + + ! save original delayed group bin + bin_original = matching_bins(t % find_filter(FILTER_DELAYEDGROUP)) + matching_bins(t % find_filter(FILTER_DELAYEDGROUP)) = d_bin + + ! Compute the filter index based on the modified matching_bins + filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 + +!$omp atomic + t % results(score_index, filter_index) % value = & + t % results(score_index, filter_index) % value + score + + ! reset original delayed group bin + matching_bins(t % find_filter(FILTER_DELAYEDGROUP)) = bin_original + + end subroutine score_fission_delayed_dg + !=============================================================================== ! SCORE_TRACKLENGTH_TALLY calculates fluxes and reaction rates based on the ! track-length estimate of the flux. This is triggered at every event (surface @@ -819,59 +1302,6 @@ contains end subroutine score_tracklength_tally -!=============================================================================== -! SCORE_ALL_NUCLIDES tallies individual nuclide reaction rates specifically when -! the user requests all. -!=============================================================================== - - subroutine score_all_nuclides(p, i_tally, flux, filter_index) - - type(Particle), intent(in) :: p - integer, intent(in) :: i_tally - real(8), intent(in) :: flux - integer, intent(in) :: filter_index - - integer :: i ! loop index for nuclides in material - integer :: i_nuclide ! index in nuclides array - real(8) :: atom_density ! atom density of single nuclide in atom/b-cm - type(TallyObject), pointer :: t - type(Material), pointer :: mat - - ! Get pointer to tally - t => tallies(i_tally) - - ! Get pointer to current material. We need this in order to determine what - ! nuclides are in the material - mat => materials(p % material) - - ! ========================================================================== - ! SCORE ALL INDIVIDUAL NUCLIDE REACTION RATES - - NUCLIDE_LOOP: do i = 1, mat % n_nuclides - - ! Determine index in nuclides array and atom density for i-th nuclide in - ! current material - i_nuclide = mat % nuclide(i) - atom_density = mat % atom_density(i) - - ! Determine score for each bin - call score_general(p, t, (i_nuclide-1)*t % n_score_bins, filter_index, & - i_nuclide, atom_density, flux) - - end do NUCLIDE_LOOP - - ! ========================================================================== - ! SCORE TOTAL MATERIAL REACTION RATES - - i_nuclide = -1 - atom_density = ZERO - - ! Determine score for each bin - call score_general(p, t, n_nuclides_total*t % n_score_bins, filter_index, & - i_nuclide, atom_density, flux) - - end subroutine score_all_nuclides - !=============================================================================== ! SCORE_TL_ON_MESH calculate fluxes and reaction rates based on the track-length ! estimate of the flux specifically for tallies that have mesh filters. For @@ -906,9 +1336,11 @@ contains logical :: found_bin ! was a scoring bin found? logical :: start_in_mesh ! starting coordinates inside mesh? logical :: end_in_mesh ! ending coordinates inside mesh? - type(TallyObject), pointer :: t - type(StructuredMesh), pointer :: m - type(Material), pointer :: mat + real(8) :: theta + real(8) :: phi + type(TallyObject), pointer :: t + type(RegularMesh), pointer :: m + type(Material), pointer :: mat t => tallies(i_tally) matching_bins(1:t%n_filters) = 1 @@ -991,6 +1423,40 @@ contains k + 1, p % E) end if + case (FILTER_POLAR) + ! Get theta value + theta = acos(p % coord(1) % uvw(3)) + + ! determine polar angle bin + k = t % filters(i) % n_bins + + ! check if particle is within polar angle bins + if (theta < t % filters(i) % real_bins(1) .or. & + theta > t % filters(i) % real_bins(k + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find polar angle bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + k + 1, theta) + end if + + case (FILTER_AZIMUTHAL) + ! make sure the correct direction vector is used + phi = atan2(p % coord(1) % uvw(2), p % coord(1) % uvw(1)) + + ! determine mu bin + k = t % filters(i) % n_bins + + ! check if particle is within azimuthal angle bins + if (phi < t % filters(i) % real_bins(1) .or. & + phi > t % filters(i) % real_bins(k + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find azimuthal angle bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + k + 1, phi) + end if + end select ! Check if no matching bin was found @@ -1119,6 +1585,118 @@ contains end subroutine score_tl_on_mesh +!=============================================================================== +! SCORE_COLLISION_TALLY calculates fluxes and reaction rates based on the +! 1/Sigma_t estimate of the flux. This is triggered after every collision. It +! is invalid for tallies that require post-collison information because it can +! score reactions that didn't actually occur, and we don't a priori know what +! the outcome will be for reactions that we didn't sample. +!=============================================================================== + + subroutine score_collision_tally(p) + + type(Particle), intent(in) :: p + + integer :: i + integer :: i_tally + integer :: j ! loop index for scoring bins + integer :: k ! loop index for nuclide bins + integer :: filter_index ! single index for single bin + integer :: i_nuclide ! index in nuclides array (from bins) + real(8) :: flux ! collision estimate of flux + real(8) :: atom_density ! atom density of single nuclide + ! in atom/b-cm + logical :: found_bin ! scoring bin found? + type(TallyObject), pointer :: t + type(Material), pointer :: mat + + ! Determine collision estimate of flux + if (survival_biasing) then + ! We need to account for the fact that some weight was already absorbed + flux = (p % last_wgt + p % absorb_wgt) / material_xs % total + else + flux = p % last_wgt / material_xs % total + end if + + ! A loop over all tallies is necessary because we need to simultaneously + ! determine different filter bins for the same tally in order to score to it + + TALLY_LOOP: do i = 1, active_collision_tallies % size() + ! Get index of tally and pointer to tally + i_tally = active_collision_tallies % get_item(i) + t => tallies(i_tally) + + ! ======================================================================= + ! DETERMINE SCORING BIN COMBINATION + + call get_scoring_bins(p, i_tally, found_bin) + if (.not. found_bin) cycle + + ! ======================================================================= + ! CALCULATE RESULTS AND ACCUMULATE TALLY + + ! If we have made it here, we have a scoring combination of bins for this + ! tally -- now we need to determine where in the results array we should + ! be accumulating the tally values + + ! Determine scoring index for this filter combination + filter_index = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1 + + if (t % all_nuclides) then + if (p % material /= MATERIAL_VOID) then + call score_all_nuclides(p, i_tally, flux, filter_index) + end if + else + + NUCLIDE_BIN_LOOP: do k = 1, t % n_nuclide_bins + ! Get index of nuclide in nuclides array + i_nuclide = t % nuclide_bins(k) + + if (i_nuclide > 0) then + if (p % material /= MATERIAL_VOID) then + ! Get pointer to current material + mat => materials(p % material) + + ! Determine if nuclide is actually in material + NUCLIDE_MAT_LOOP: do j = 1, mat % n_nuclides + ! If index of nuclide matches the j-th nuclide listed in the + ! material, break out of the loop + if (i_nuclide == mat % nuclide(j)) exit + + ! If we've reached the last nuclide in the material, it means + ! the specified nuclide to be tallied is not in this material + if (j == mat % n_nuclides) then + cycle NUCLIDE_BIN_LOOP + end if + end do NUCLIDE_MAT_LOOP + + atom_density = mat % atom_density(j) + else + atom_density = ZERO + end if + end if + + ! Determine score for each bin + call score_general(p, t, (k-1)*t % n_score_bins, filter_index, & + i_nuclide, atom_density, flux) + + end do NUCLIDE_BIN_LOOP + end if + + ! If the user has specified that we can assume all tallies are spatially + ! separate, this implies that once a tally has been scored to, we needn't + ! check the others. This cuts down on overhead when there are many + ! tallies specified + + if (assume_separate) exit TALLY_LOOP + + end do TALLY_LOOP + + ! Reset tally map positioning + position = 0 + + end subroutine score_collision_tally + !=============================================================================== ! GET_SCORING_BINS determines a combination of filter bins that should be scored ! for a tally based on the particle's current attributes. @@ -1135,8 +1713,9 @@ contains integer :: n ! number of bins for single filter integer :: offset ! offset for distribcell real(8) :: E ! particle energy - type(TallyObject), pointer :: t - type(StructuredMesh), pointer :: m + real(8) :: theta, phi ! Polar and Azimuthal Angles, respectively + type(TallyObject), pointer :: t + type(RegularMesh), pointer :: m found_bin = .true. t => tallies(i_tally) @@ -1159,7 +1738,9 @@ contains p % coord(p % n_coord) % universe, i_tally) case (FILTER_MATERIAL) - if (p % material /= MATERIAL_VOID) then + if (p % material == MATERIAL_VOID) then + matching_bins(i) = NO_BIN_FOUND + else matching_bins(i) = get_next_bin(FILTER_MATERIAL, & p % material, i_tally) endif @@ -1245,6 +1826,75 @@ contains n + 1, p % E) end if + case (FILTER_DELAYEDGROUP) + + if (survival_biasing .and. t % find_filter(FILTER_ENERGYOUT) <= 0) then + matching_bins(i) = 1 + elseif (active_tracklength_tallies % size() > 0) then + matching_bins(i) = 1 + else + if (p % delayed_group == 0) then + matching_bins = NO_BIN_FOUND + else + matching_bins(i) = p % delayed_group + end if + end if + + case (FILTER_MU) + ! determine mu bin + n = t % filters(i) % n_bins + + ! check if particle is within mu bins + if (p % mu < t % filters(i) % real_bins(1) .or. & + p % mu > t % filters(i) % real_bins(n + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find mu bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + n + 1, p % mu) + end if + + case (FILTER_POLAR) + ! make sure the correct direction vector is used + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + theta = acos(p % coord(1) % uvw(3)) + else + theta = acos(p % last_uvw(3)) + end if + + ! determine polar angle bin + n = t % filters(i) % n_bins + + ! check if particle is within polar angle bins + if (theta < t % filters(i) % real_bins(1) .or. & + theta > t % filters(i) % real_bins(n + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find polar angle bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + n + 1, theta) + end if + + case (FILTER_AZIMUTHAL) + ! make sure the correct direction vector is used + if (t % estimator == ESTIMATOR_TRACKLENGTH) then + phi = atan2(p % coord(1) % uvw(2), p % coord(1) % uvw(1)) + else + phi = atan2(p % last_uvw(2), p % last_uvw(1)) + end if + ! determine mu bin + n = t % filters(i) % n_bins + + ! check if particle is within azimuthal angle bins + if (phi < t % filters(i) % real_bins(1) .or. & + phi > t % filters(i) % real_bins(n + 1)) then + matching_bins(i) = NO_BIN_FOUND + else + ! search to find azimuthal angle bin + matching_bins(i) = binary_search(t % filters(i) % real_bins, & + n + 1, phi) + end if + end select ! If the current filter didn't match, exit this subroutine @@ -1288,8 +1938,8 @@ contains logical :: x_same ! same starting/ending x index (i) logical :: y_same ! same starting/ending y index (j) logical :: z_same ! same starting/ending z index (k) - type(TallyObject), pointer :: t - type(StructuredMesh), pointer :: m + type(TallyObject), pointer :: t + type(RegularMesh), pointer :: m TALLY_LOOP: do i = 1, active_current_tallies % size() ! Copy starting and ending location of particle @@ -1873,6 +2523,8 @@ contains call active_analog_tallies % add(i_user_tallies + i) elseif (user_tallies(i) % estimator == ESTIMATOR_TRACKLENGTH) then call active_tracklength_tallies % add(i_user_tallies + i) + elseif (user_tallies(i) % estimator == ESTIMATOR_COLLISION) then + call active_collision_tallies % add(i_user_tallies + i) end if elseif (user_tallies(i) % type == TALLY_SURFACE_CURRENT) then call active_current_tallies % add(i_user_tallies + i) diff --git a/src/tally_header.F90 b/src/tally_header.F90 index d20c3fea20..18b9219522 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -2,6 +2,7 @@ module tally_header use constants, only: NONE, N_FILTER_TYPES use trigger_header, only: TriggerObject + use, intrinsic :: ISO_C_BINDING implicit none @@ -39,10 +40,10 @@ module tally_header ! TALLYRESULT provides accumulation of results in a particular tally bin !=============================================================================== - type TallyResult - real(8) :: value = 0. - real(8) :: sum = 0. - real(8) :: sum_sq = 0. + type, bind(C) :: TallyResult + real(C_DOUBLE) :: value = 0. + real(C_DOUBLE) :: sum = 0. + real(C_DOUBLE) :: sum_sq = 0. end type TallyResult !=============================================================================== @@ -57,10 +58,6 @@ module tally_header integer :: offset = 0 ! Only used for distribcell filters integer, allocatable :: int_bins(:) real(8), allocatable :: real_bins(:) ! Only used for energy filters - - ! Type-Bound procedures - contains - procedure :: clear => tallyfilter_clear ! Deallocates TallyFilter end type TallyFilter !=============================================================================== @@ -73,7 +70,7 @@ module tally_header ! Basic data integer :: id ! user-defined identifier - character(len=52) :: name = "" ! user-defined name + character(len=104) :: name = "" ! user-defined name integer :: type ! volume, surface current integer :: estimator ! collision, track-length real(8) :: volume ! volume of region @@ -128,81 +125,6 @@ module tally_header ! Tally precision triggers integer :: n_triggers = 0 ! # of triggers type(TriggerObject), allocatable :: triggers(:) ! Array of triggers - - ! Type-Bound procedures - contains - procedure :: clear => tallyobject_clear ! Deallocates TallyObject end type TallyObject - contains - -!=============================================================================== -! TALLYFILTER_CLEAR deallocates a TallyFilter element and sets it to its as -! initialized state. -!=============================================================================== - - subroutine tallyfilter_clear(this) - class(TallyFilter), intent(inout) :: this ! The TallyFilter to be cleared - - this % type = NONE - this % n_bins = 0 - if (allocated(this % int_bins)) & - deallocate(this % int_bins) - if (allocated(this % real_bins)) & - deallocate(this % real_bins) - - end subroutine tallyfilter_clear - -!=============================================================================== -! TALLYOBJECT_CLEAR deallocates a TallyObject element and sets it to its as -! initialized state. -!=============================================================================== - - subroutine tallyobject_clear(this) - class(TallyObject), intent(inout) :: this ! The TallyObject to be cleared - - integer :: i ! Loop Index - - ! This routine will go through each item in TallyObject and set the value - ! to its default, as-initialized values, including deallocations. - this % name = "" - - if (allocated(this % filters)) then - do i = 1, size(this % filters) - call this % filters(i) % clear() - end do - deallocate(this % filters) - end if - - if (allocated(this % stride)) & - deallocate(this % stride) - - this % find_filter = 0 - - this % n_nuclide_bins = 0 - if (allocated(this % nuclide_bins)) & - deallocate(this % nuclide_bins) - this % all_nuclides = .false. - - this % n_score_bins = 0 - if (allocated(this % score_bins)) & - deallocate(this % score_bins) - if (allocated(this % moment_order)) & - deallocate(this % moment_order) - this % n_user_score_bins = 0 - - if (allocated(this % results)) & - deallocate(this % results) - - this % reset = .false. - - this % n_realizations = 0 - - if (allocated(this % triggers)) & - deallocate (this % triggers) - - this % n_triggers = 0 - - end subroutine tallyobject_clear - end module tally_header diff --git a/src/tally_initialize.F90 b/src/tally_initialize.F90 index b7dc5ed98a..73aa18c60c 100644 --- a/src/tally_initialize.F90 +++ b/src/tally_initialize.F90 @@ -38,7 +38,7 @@ contains integer :: j ! loop index for filters integer :: n ! temporary stride integer :: max_n_filters = 0 ! maximum number of filters - type(TallyObject), pointer :: t => null() + type(TallyObject), pointer :: t TALLY_LOOP: do i = 1, n_tallies ! Get pointer to tally @@ -88,7 +88,7 @@ contains integer :: k ! loop index for bins integer :: bin ! filter bin entries integer :: type ! type of tally filter - type(TallyObject), pointer :: t => null() + type(TallyObject), pointer :: t ! allocate tally map array -- note that we don't need a tally map for the ! energy_in and energy_out filters diff --git a/src/timer_header.F90 b/src/timer_header.F90 index 0bf1b7aef5..6b0580f427 100644 --- a/src/timer_header.F90 +++ b/src/timer_header.F90 @@ -29,13 +29,11 @@ contains !=============================================================================== subroutine timer_start(self) - class(Timer), intent(inout) :: self ! Turn timer on and measure starting time self % running = .true. call system_clock(self % start_counts) - end subroutine timer_start !=============================================================================== @@ -43,7 +41,6 @@ contains !=============================================================================== function timer_get_value(self) result(elapsed) - class(Timer), intent(in) :: self ! the timer real(8) :: elapsed ! total elapsed time @@ -58,7 +55,6 @@ contains else elapsed = self % elapsed end if - end function timer_get_value !=============================================================================== @@ -66,30 +62,26 @@ contains !=============================================================================== subroutine timer_stop(self) - class(Timer), intent(inout) :: self ! Check to make sure timer was running if (.not. self % running) return ! Stop timer and add time - self % elapsed = timer_get_value(self) + self % elapsed = self % get_value() self % running = .false. - end subroutine timer_stop !=============================================================================== ! TIMER_RESET resets a timer to have a zero value !=============================================================================== - subroutine timer_reset(self) - + pure subroutine timer_reset(self) class(Timer), intent(inout) :: self self % running = .false. self % start_counts = 0 self % elapsed = ZERO - end subroutine timer_reset end module timer_header diff --git a/src/track_output.F90 b/src/track_output.F90 index fba699e8ef..1665ac25ea 100644 --- a/src/track_output.F90 +++ b/src/track_output.F90 @@ -6,24 +6,36 @@ 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 - integer, private :: n_tracks ! total number of tracks - real(8), private, allocatable :: coords(:,:) ! track coordinates -!$omp threadprivate(n_tracks, coords) + implicit none + private + + type TrackCoordinates + real(8), allocatable :: coords(:,:) + end type TrackCoordinates + + type(TrackCoordinates), allocatable :: tracks(:) +!$omp threadprivate(tracks) + + public :: initialize_particle_track + public :: write_particle_track + public :: add_particle_track + public :: finalize_particle_track contains !=============================================================================== -! INITIALIZE_PARTICLE_TRACK +! INITIALIZE_PARTICLE_TRACK allocates the array to store particle track +! information !=============================================================================== subroutine initialize_particle_track() - n_tracks = 0 + allocate(tracks(1)) end subroutine initialize_particle_track !=============================================================================== @@ -32,23 +44,50 @@ contains subroutine write_particle_track(p) type(Particle), intent(in) :: p - real(8), allocatable :: new_coords(:, :) + integer :: i + integer :: n_tracks + ! Add another column to coords - n_tracks = n_tracks + 1 - if (allocated(coords)) then - allocate(new_coords(3, n_tracks)) - new_coords(:, 1:n_tracks-1) = coords - call move_alloc(FROM=new_coords, TO=coords) + i = size(tracks) + 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) else - allocate(coords(3,1)) + n_tracks = 0 + allocate(tracks(i)%coords(3, 1)) end if ! Write current coordinates into the newest column. - coords(:, n_tracks) = p % coord(1) % xyz + n_tracks = n_tracks + 1 + tracks(i)%coords(:, n_tracks) = p%coord(1)%xyz end subroutine write_particle_track +!=============================================================================== +! ADD_PARTICLE_TRACK creates a new entry in the track coordinates for a +! secondary particle +!=============================================================================== + + subroutine add_particle_track() + type(TrackCoordinates), allocatable :: new_tracks(:) + + integer :: i + + ! Determine current number of particle tracks + i = size(tracks) + + ! Create array one larger than current + allocate(new_tracks(i + 1)) + + ! Copy memory and move allocation + new_tracks(1:i) = tracks(i) + call move_alloc(FROM=new_tracks, TO=tracks) + + end subroutine add_particle_track + !=============================================================================== ! FINALIZE_PARTICLE_TRACK writes the particle track array to disk. !=============================================================================== @@ -56,26 +95,36 @@ 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 :: 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) + end do + !$omp critical (FinalizeParticleTrack) - call binout % file_create(fname) - length = [3, n_tracks] - call binout % write_data(coords, 'coordinates', length=length) - call binout % file_close() + file_id = file_create(fname) + call write_dataset(file_id, 'filetype', 'track') + call write_dataset(file_id, 'revision', REVISION_TRACK) + call write_dataset(file_id, 'n_particles', n_particle_tracks) + call write_dataset(file_id, 'n_coords', n_coords) + do i = 1, n_particle_tracks + call write_dataset(file_id, 'coordinates_' // trim(to_str(i)), & + tracks(i)%coords) + end do + call file_close(file_id) !$omp end critical (FinalizeParticleTrack) - deallocate(coords) + deallocate(tracks) end subroutine finalize_particle_track end module track_output diff --git a/src/tracking.F90 b/src/tracking.F90 index e5faeb209d..2e4503e139 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -13,9 +13,9 @@ module tracking use random_lcg, only: prn use string, only: to_str use tally, only: score_analog_tally, score_tracklength_tally, & - score_surface_current + score_collision_tally, score_surface_current use track_output, only: initialize_particle_track, write_particle_track, & - finalize_particle_track + add_particle_track, finalize_particle_track implicit none @@ -45,20 +45,6 @@ contains call write_message("Simulating Particle " // trim(to_str(p % id))) end if - ! If the cell hasn't been determined based on the particle's location, - ! initiate a search for the current cell - if (p % coord(p % n_coord) % cell == NONE) then - call find_cell(p, found_cell) - - ! Particle couldn't be located - if (.not. found_cell) then - call fatal_error("Could not locate particle " // trim(to_str(p % id))) - end if - - ! set birth cell attribute - p % cell_born = p % coord(p % n_coord) % cell - end if - ! Initialize number of events to zero n_event = 0 @@ -74,7 +60,19 @@ contains call initialize_particle_track() endif - do while (p % alive) + EVENT_LOOP: do + ! If the cell hasn't been determined based on the particle's location, + ! initiate a search for the current cell. This generally happens at the + ! beginning of the history and again for any secondary particles + if (p % coord(p % n_coord) % cell == NONE) then + call find_cell(p, found_cell) + if (.not. found_cell) then + call fatal_error("Could not locate particle " // trim(to_str(p % id))) + end if + + ! set birth cell attribute + if (p % cell_born == NONE) p % cell_born = p % coord(p % n_coord) % cell + end if ! Write particle track. if (p % write_track) call write_particle_track(p) @@ -159,11 +157,13 @@ contains ! has occurred rather than before because we need information on the ! outgoing energy for any tallies with an outgoing energy filter + if (active_collision_tallies % size() > 0) call score_collision_tally(p) if (active_analog_tallies % size() > 0) call score_analog_tally(p) ! Reset banked weight during collision p % n_bank = 0 p % wgt_bank = ZERO + p % n_delayed_bank(:) = 0 ! Reset fission logical p % fission = .false. @@ -197,7 +197,19 @@ contains p % alive = .false. end if - end do + ! Check for secondary particles if this particle is dead + if (.not. p % alive) then + if (p % n_secondary > 0) then + call p % initialize_from_source(p % secondary_bank(p % n_secondary)) + p % n_secondary = p % n_secondary - 1 + + ! Enter new particle in particle track file + if (p % write_track) call add_particle_track() + else + exit EVENT_LOOP + end if + end if + end do EVENT_LOOP ! Finish particle track output. if (p % write_track) then diff --git a/src/trigger.F90 b/src/trigger.F90 index 4a16cd5cab..73cb0c7efe 100644 --- a/src/trigger.F90 +++ b/src/trigger.F90 @@ -9,6 +9,7 @@ module trigger use string, only: to_str use output, only: warning, write_message use mesh, only: mesh_indices_to_bin + use mesh_header, only: RegularMesh use trigger_header, only: TriggerObject use tally, only: TallyObject @@ -91,7 +92,6 @@ contains character(len=52), intent(inout) :: name ! "eigenvalue" or tally score integer :: i ! index in tallies array - integer :: j ! level in tally hierarchy integer :: n ! loop index for nuclides integer :: s ! loop index for triggers integer :: filter_index ! index in results array for filters @@ -166,28 +166,8 @@ contains ! Initialize bins, filter level matching_bins(1:t % n_filters) = 0 - j = 1 - ! Find filter index - FILTER_LOOP: do - find_bin: do - if (t % n_filters == 0) exit find_bin - matching_bins(j) = matching_bins(j) + 1 - if (matching_bins(j) > t % filters(j) % n_bins) then - if (j == 1) exit FILTER_LOOP - matching_bins(j) = 0 - j = j - 1 - else - if (j == t % n_filters) exit find_bin - end if - end do find_bin - - if (t % n_filters > 0) then - filter_index = sum((max(matching_bins(1:t%n_filters),1) - 1) * & - t % stride) + 1 - else - filter_index = 1 - end if + FILTER_LOOP: do filter_index = 1, t % total_filter_bins ! Initialize score index score_index = trigger % score_index @@ -315,7 +295,7 @@ contains real(8) :: std_dev = ZERO ! temporary standard deviration of result type(TallyObject), pointer :: t ! surface current tally type(TriggerObject) :: trigger ! surface current tally trigger - type(StructuredMesh), pointer :: m ! surface current mesh + type(RegularMesh), pointer :: m ! surface current mesh ! Get pointer to mesh i_filter_mesh = t % find_filter(FILTER_MESH) diff --git a/src/trigger_header.F90 b/src/trigger_header.F90 index e137829bd0..96421314cd 100644 --- a/src/trigger_header.F90 +++ b/src/trigger_header.F90 @@ -1,6 +1,6 @@ module trigger_header - use constants, only: NONE, N_FILTER_TYPES + use constants, only: NONE, N_FILTER_TYPES, ZERO implicit none @@ -13,9 +13,9 @@ module trigger_header real(8) :: threshold ! a convergence threshold character(len=52) :: score_name ! the name of the score integer :: score_index ! the index of the score - real(8) :: variance=0.0 ! temp variance container - real(8) :: std_dev =0.0 ! temp std. dev. container - real(8) :: rel_err =0.0 ! temp rel. err. container + real(8) :: variance = ZERO ! temp variance container + real(8) :: std_dev = ZERO ! temp std. dev. container + real(8) :: rel_err = ZERO ! temp rel. err. container end type TriggerObject !=============================================================================== @@ -23,7 +23,7 @@ module trigger_header !=============================================================================== type KTrigger integer :: trigger_type = 0 - real(8) :: threshold = 0 + real(8) :: threshold = ZERO end type KTrigger end module trigger_header diff --git a/src/xml_interface.F90 b/src/xml_interface.F90 index 4ae05ee281..8f0370b152 100644 --- a/src/xml_interface.F90 +++ b/src/xml_interface.F90 @@ -117,7 +117,7 @@ contains type(Node), pointer, intent(out) :: out_ptr logical :: found_ - type(NodeList), pointer :: elem_list => null() + type(NodeList), pointer :: elem_list ! Set found to false found_ = .false. diff --git a/tests/cleanup b/tests/cleanup index 7b81d2d9dd..3369c797ee 100755 --- a/tests/cleanup +++ b/tests/cleanup @@ -5,6 +5,6 @@ # folders. This can occur if a previous error # occurred and the test suite was rerun without # deleting left over binary files. This will -# cause an assertion error in some of the +# cause an assertion error in some of the # tests. -find . \( -name "*.binary" -o -name "*.h5" -o -name "*.ppm" \) -exec rm -f {} \; +find . \( -name "*.h5" -o -name "*.ppm" \) -exec rm -f {} \; diff --git a/tests/input_set.py b/tests/input_set.py new file mode 100644 index 0000000000..87b857f4a9 --- /dev/null +++ b/tests/input_set.py @@ -0,0 +1,571 @@ +import openmc + + +class InputSet(object): + def __init__(self): + self.settings = openmc.SettingsFile() + self.materials = openmc.MaterialsFile() + self.geometry = openmc.GeometryFile() + self.tallies = None + self.plots = None + + def export(self): + self.settings.export_to_xml() + self.materials.export_to_xml() + self.geometry.export_to_xml() + if self.tallies is not None: self.tallies.export_to_xml() + if self.plots is not None: self.plots.export_to_xml() + + def build_default_materials_and_geometry(self): + # Define materials. + fuel = openmc.Material(name='Fuel', material_id=1) + fuel.set_density('g/cm3', 10.062) + fuel.add_nuclide("U-234", 4.9476e-6) + fuel.add_nuclide("U-235", 4.8218e-4) + fuel.add_nuclide("U-236", 9.0402e-5) + fuel.add_nuclide("U-238", 2.1504e-2) + fuel.add_nuclide("Np-237", 7.3733e-6) + fuel.add_nuclide("Pu-238", 1.5148e-6) + fuel.add_nuclide("Pu-239", 1.3955e-4) + fuel.add_nuclide("Pu-240", 3.4405e-5) + fuel.add_nuclide("Pu-241", 2.1439e-5) + fuel.add_nuclide("Pu-242", 3.7422e-6) + fuel.add_nuclide("Am-241", 4.5041e-7) + fuel.add_nuclide("Am-242m", 9.2301e-9) + fuel.add_nuclide("Am-243", 4.7878e-7) + fuel.add_nuclide("Cm-242", 1.0485e-7) + fuel.add_nuclide("Cm-243", 1.4268e-9) + fuel.add_nuclide("Cm-244", 8.8756e-8) + fuel.add_nuclide("Cm-245", 3.5285e-9) + fuel.add_nuclide("Mo-95", 2.6497e-5) + fuel.add_nuclide("Tc-99", 3.2772e-5) + fuel.add_nuclide("Ru-101", 3.0742e-5) + fuel.add_nuclide("Ru-103", 2.3505e-6) + fuel.add_nuclide("Ag-109", 2.0009e-6) + fuel.add_nuclide("Xe-135", 1.0801e-8) + fuel.add_nuclide("Cs-133", 3.4612e-5) + fuel.add_nuclide("Nd-143", 2.6078e-5) + fuel.add_nuclide("Nd-145", 1.9898e-5) + fuel.add_nuclide("Sm-147", 1.6128e-6) + fuel.add_nuclide("Sm-149", 1.1627e-7) + fuel.add_nuclide("Sm-150", 7.1727e-6) + fuel.add_nuclide("Sm-151", 5.4947e-7) + fuel.add_nuclide("Sm-152", 3.0221e-6) + fuel.add_nuclide("Eu-153", 2.6209e-6) + fuel.add_nuclide("Gd-155", 1.5369e-9) + fuel.add_nuclide("O-16", 4.5737e-2) + + clad = openmc.Material(name='Cladding', material_id=2) + clad.set_density('g/cm3', 5.77) + clad.add_nuclide("Zr-90", 0.5145) + clad.add_nuclide("Zr-91", 0.1122) + clad.add_nuclide("Zr-92", 0.1715) + clad.add_nuclide("Zr-94", 0.1738) + clad.add_nuclide("Zr-96", 0.0280) + + cold_water = openmc.Material(name='Cold borated water', material_id=3) + cold_water.set_density('atom/b-cm', 0.07416) + cold_water.add_nuclide("H-1", 2.0) + cold_water.add_nuclide("O-16", 1.0) + cold_water.add_nuclide("B-10", 6.490e-4) + cold_water.add_nuclide("B-11", 2.689e-3) + cold_water.add_s_alpha_beta('HH2O', '71t') + + hot_water = openmc.Material(name='Hot borated water', material_id=4) + hot_water.set_density('atom/b-cm', 0.06614) + hot_water.add_nuclide("H-1", 2.0) + hot_water.add_nuclide("O-16", 1.0) + hot_water.add_nuclide("B-10", 6.490e-4) + hot_water.add_nuclide("B-11", 2.689e-3) + hot_water.add_s_alpha_beta('HH2O', '71t') + + rpv_steel = openmc.Material(name='Reactor pressure vessel steel', + material_id=5) + rpv_steel.set_density('g/cm3', 7.9) + rpv_steel.add_nuclide("Fe-54", 0.05437098, 'wo') + rpv_steel.add_nuclide("Fe-56", 0.88500663, 'wo') + rpv_steel.add_nuclide("Fe-57", 0.0208008, 'wo') + rpv_steel.add_nuclide("Fe-58", 0.00282159, 'wo') + rpv_steel.add_nuclide("Ni-58", 0.0067198, 'wo') + rpv_steel.add_nuclide("Ni-60", 0.0026776, 'wo') + rpv_steel.add_nuclide("Ni-61", 0.0001183, 'wo') + rpv_steel.add_nuclide("Ni-62", 0.0003835, 'wo') + rpv_steel.add_nuclide("Ni-64", 0.0001008, 'wo') + rpv_steel.add_nuclide("Mn-55", 0.01, 'wo') + rpv_steel.add_nuclide("Mo-92", 0.000849, 'wo') + rpv_steel.add_nuclide("Mo-94", 0.0005418, 'wo') + rpv_steel.add_nuclide("Mo-95", 0.0009438, 'wo') + rpv_steel.add_nuclide("Mo-96", 0.0010002, 'wo') + rpv_steel.add_nuclide("Mo-97", 0.0005796, 'wo') + rpv_steel.add_nuclide("Mo-98", 0.0014814, 'wo') + rpv_steel.add_nuclide("Mo-100", 0.0006042, 'wo') + rpv_steel.add_nuclide("Si-28", 0.00367464, 'wo') + rpv_steel.add_nuclide("Si-29", 0.00019336, 'wo') + rpv_steel.add_nuclide("Si-30", 0.000132, 'wo') + rpv_steel.add_nuclide("Cr-50", 0.00010435, 'wo') + rpv_steel.add_nuclide("Cr-52", 0.002092475, 'wo') + rpv_steel.add_nuclide("Cr-53", 0.00024185, 'wo') + rpv_steel.add_nuclide("Cr-54", 6.1325e-05, 'wo') + rpv_steel.add_nuclide("C-Nat", 0.0025, 'wo') + rpv_steel.add_nuclide("Cu-63", 0.0013696, 'wo') + rpv_steel.add_nuclide("Cu-65", 0.0006304, 'wo') + + lower_rad_ref = openmc.Material(name='Lower radial reflector', + material_id=6) + lower_rad_ref.set_density('g/cm3', 4.32) + lower_rad_ref.add_nuclide("H-1", 0.0095661, 'wo') + lower_rad_ref.add_nuclide("O-16", 0.0759107, 'wo') + lower_rad_ref.add_nuclide("B-10", 3.08409e-5, 'wo') + lower_rad_ref.add_nuclide("B-11", 1.40499e-4, 'wo') + lower_rad_ref.add_nuclide("Fe-54", 0.035620772088, 'wo') + lower_rad_ref.add_nuclide("Fe-56", 0.579805982228, 'wo') + lower_rad_ref.add_nuclide("Fe-57", 0.01362750048, 'wo') + lower_rad_ref.add_nuclide("Fe-58", 0.001848545204, 'wo') + lower_rad_ref.add_nuclide("Ni-58", 0.055298376566, 'wo') + lower_rad_ref.add_nuclide("Ni-60", 0.022034425592, 'wo') + lower_rad_ref.add_nuclide("Ni-61", 0.000973510811, 'wo') + lower_rad_ref.add_nuclide("Ni-62", 0.003155886695, 'wo') + lower_rad_ref.add_nuclide("Ni-64", 0.000829500336, 'wo') + lower_rad_ref.add_nuclide("Mn-55", 0.0182870, 'wo') + lower_rad_ref.add_nuclide("Si-28", 0.00839976771, 'wo') + lower_rad_ref.add_nuclide("Si-29", 0.00044199679, 'wo') + lower_rad_ref.add_nuclide("Si-30", 0.0003017355, 'wo') + lower_rad_ref.add_nuclide("Cr-50", 0.007251360806, 'wo') + lower_rad_ref.add_nuclide("Cr-52", 0.145407678031, 'wo') + lower_rad_ref.add_nuclide("Cr-53", 0.016806340306, 'wo') + lower_rad_ref.add_nuclide("Cr-54", 0.004261520857, 'wo') + lower_rad_ref.add_s_alpha_beta('HH2O', '71t') + + upper_rad_ref = openmc.Material(name='Upper radial reflector /' + 'Top plate region', material_id=7) + upper_rad_ref.set_density('g/cm3', 4.28) + upper_rad_ref.add_nuclide("H-1", 0.0086117, 'wo') + upper_rad_ref.add_nuclide("O-16", 0.0683369, 'wo') + upper_rad_ref.add_nuclide("B-10", 2.77638e-5, 'wo') + upper_rad_ref.add_nuclide("B-11", 1.26481e-4, 'wo') + upper_rad_ref.add_nuclide("Fe-54", 0.035953677186, 'wo') + upper_rad_ref.add_nuclide("Fe-56", 0.585224740891, 'wo') + upper_rad_ref.add_nuclide("Fe-57", 0.01375486056, 'wo') + upper_rad_ref.add_nuclide("Fe-58", 0.001865821363, 'wo') + upper_rad_ref.add_nuclide("Ni-58", 0.055815129186, 'wo') + upper_rad_ref.add_nuclide("Ni-60", 0.022240333032, 'wo') + upper_rad_ref.add_nuclide("Ni-61", 0.000982608081, 'wo') + upper_rad_ref.add_nuclide("Ni-62", 0.003185377845, 'wo') + upper_rad_ref.add_nuclide("Ni-64", 0.000837251856, 'wo') + upper_rad_ref.add_nuclide("Mn-55", 0.0184579, 'wo') + upper_rad_ref.add_nuclide("Si-28", 0.00847831314, 'wo') + upper_rad_ref.add_nuclide("Si-29", 0.00044612986, 'wo') + upper_rad_ref.add_nuclide("Si-30", 0.000304557, 'wo') + upper_rad_ref.add_nuclide("Cr-50", 0.00731912987, 'wo') + upper_rad_ref.add_nuclide("Cr-52", 0.146766614995, 'wo') + upper_rad_ref.add_nuclide("Cr-53", 0.01696340737, 'wo') + upper_rad_ref.add_nuclide("Cr-54", 0.004301347765, 'wo') + upper_rad_ref.add_s_alpha_beta('HH2O', '71t') + + bot_plate = openmc.Material(name='Bottom plate region', material_id=8) + bot_plate.set_density('g/cm3', 7.184) + bot_plate.add_nuclide("H-1", 0.0011505, 'wo') + bot_plate.add_nuclide("O-16", 0.0091296, 'wo') + bot_plate.add_nuclide("B-10", 3.70915e-6, 'wo') + bot_plate.add_nuclide("B-11", 1.68974e-5, 'wo') + bot_plate.add_nuclide("Fe-54", 0.03855611055, 'wo') + bot_plate.add_nuclide("Fe-56", 0.627585036425, 'wo') + bot_plate.add_nuclide("Fe-57", 0.014750478, 'wo') + bot_plate.add_nuclide("Fe-58", 0.002000875025, 'wo') + bot_plate.add_nuclide("Ni-58", 0.059855207342, 'wo') + bot_plate.add_nuclide("Ni-60", 0.023850159704, 'wo') + bot_plate.add_nuclide("Ni-61", 0.001053732407, 'wo') + bot_plate.add_nuclide("Ni-62", 0.003415945715, 'wo') + bot_plate.add_nuclide("Ni-64", 0.000897854832, 'wo') + bot_plate.add_nuclide("Mn-55", 0.0197940, 'wo') + bot_plate.add_nuclide("Si-28", 0.00909197802, 'wo') + bot_plate.add_nuclide("Si-29", 0.00047842098, 'wo') + bot_plate.add_nuclide("Si-30", 0.000326601, 'wo') + bot_plate.add_nuclide("Cr-50", 0.007848910646, 'wo') + bot_plate.add_nuclide("Cr-52", 0.157390026871, 'wo') + bot_plate.add_nuclide("Cr-53", 0.018191270146, 'wo') + bot_plate.add_nuclide("Cr-54", 0.004612692337, 'wo') + bot_plate.add_s_alpha_beta('HH2O', '71t') + + bot_nozzle = openmc.Material(name='Bottom nozzle region', material_id=9) + bot_nozzle.set_density('g/cm3', 2.53) + bot_nozzle.add_nuclide("H-1", 0.0245014, 'wo') + bot_nozzle.add_nuclide("O-16", 0.1944274, 'wo') + bot_nozzle.add_nuclide("B-10", 7.89917e-5, 'wo') + bot_nozzle.add_nuclide("B-11", 3.59854e-4, 'wo') + bot_nozzle.add_nuclide("Fe-54", 0.030411411144, 'wo') + bot_nozzle.add_nuclide("Fe-56", 0.495012237964, 'wo') + bot_nozzle.add_nuclide("Fe-57", 0.01163454624, 'wo') + bot_nozzle.add_nuclide("Fe-58", 0.001578204652, 'wo') + bot_nozzle.add_nuclide("Ni-58", 0.047211231662, 'wo') + bot_nozzle.add_nuclide("Ni-60", 0.018811987544, 'wo') + bot_nozzle.add_nuclide("Ni-61", 0.000831139127, 'wo') + bot_nozzle.add_nuclide("Ni-62", 0.002694352115, 'wo') + bot_nozzle.add_nuclide("Ni-64", 0.000708189552, 'wo') + bot_nozzle.add_nuclide("Mn-55", 0.0156126, 'wo') + bot_nozzle.add_nuclide("Si-28", 0.007171335558, 'wo') + bot_nozzle.add_nuclide("Si-29", 0.000377356542, 'wo') + bot_nozzle.add_nuclide("Si-30", 0.0002576079, 'wo') + bot_nozzle.add_nuclide("Cr-50", 0.006190885148, 'wo') + bot_nozzle.add_nuclide("Cr-52", 0.124142524198, 'wo') + bot_nozzle.add_nuclide("Cr-53", 0.014348496148, 'wo') + bot_nozzle.add_nuclide("Cr-54", 0.003638294506, 'wo') + bot_nozzle.add_s_alpha_beta('HH2O', '71t') + + top_nozzle = openmc.Material(name='Top nozzle region', material_id=10) + top_nozzle.set_density('g/cm3', 1.746) + top_nozzle.add_nuclide("H-1", 0.0358870, 'wo') + top_nozzle.add_nuclide("O-16", 0.2847761, 'wo') + top_nozzle.add_nuclide("B-10", 1.15699e-4, 'wo') + top_nozzle.add_nuclide("B-11", 5.27075e-4, 'wo') + top_nozzle.add_nuclide("Fe-54", 0.02644016154, 'wo') + top_nozzle.add_nuclide("Fe-56", 0.43037146399, 'wo') + top_nozzle.add_nuclide("Fe-57", 0.0101152584, 'wo') + top_nozzle.add_nuclide("Fe-58", 0.00137211607, 'wo') + top_nozzle.add_nuclide("Ni-58", 0.04104621835, 'wo') + top_nozzle.add_nuclide("Ni-60", 0.0163554502, 'wo') + top_nozzle.add_nuclide("Ni-61", 0.000722605975, 'wo') + top_nozzle.add_nuclide("Ni-62", 0.002342513875, 'wo') + top_nozzle.add_nuclide("Ni-64", 0.0006157116, 'wo') + top_nozzle.add_nuclide("Mn-55", 0.0135739, 'wo') + top_nozzle.add_nuclide("Si-28", 0.006234853554, 'wo') + top_nozzle.add_nuclide("Si-29", 0.000328078746, 'wo') + top_nozzle.add_nuclide("Si-30", 0.0002239677, 'wo') + top_nozzle.add_nuclide("Cr-50", 0.005382452306, 'wo') + top_nozzle.add_nuclide("Cr-52", 0.107931450781, 'wo') + top_nozzle.add_nuclide("Cr-53", 0.012474806806, 'wo') + top_nozzle.add_nuclide("Cr-54", 0.003163190107, 'wo') + top_nozzle.add_s_alpha_beta('HH2O', '71t') + + top_fa = openmc.Material(name='Top of fuel assemblies', material_id=11) + top_fa.set_density('g/cm3', 3.044) + top_fa.add_nuclide("H-1", 0.0162913, 'wo') + top_fa.add_nuclide("O-16", 0.1292776, 'wo') + top_fa.add_nuclide("B-10", 5.25228e-5, 'wo') + top_fa.add_nuclide("B-11", 2.39272e-4, 'wo') + top_fa.add_nuclide("Zr-90", 0.43313403903, 'wo') + top_fa.add_nuclide("Zr-91", 0.09549277374, 'wo') + top_fa.add_nuclide("Zr-92", 0.14759527104, 'wo') + top_fa.add_nuclide("Zr-94", 0.15280552077, 'wo') + top_fa.add_nuclide("Zr-96", 0.02511169542, 'wo') + top_fa.add_s_alpha_beta('HH2O', '71t') + + bot_fa = openmc.Material(name='Bottom of fuel assemblies', material_id=12) + bot_fa.set_density('g/cm3', 1.762) + bot_fa.add_nuclide("H-1", 0.0292856, 'wo') + bot_fa.add_nuclide("O-16", 0.2323919, 'wo') + bot_fa.add_nuclide("B-10", 9.44159e-5, 'wo') + bot_fa.add_nuclide("B-11", 4.30120e-4, 'wo') + bot_fa.add_nuclide("Zr-90", 0.3741373658, 'wo') + bot_fa.add_nuclide("Zr-91", 0.0824858164, 'wo') + bot_fa.add_nuclide("Zr-92", 0.1274914944, 'wo') + bot_fa.add_nuclide("Zr-94", 0.1319920622, 'wo') + bot_fa.add_nuclide("Zr-96", 0.0216912612, 'wo') + bot_fa.add_s_alpha_beta('HH2O', '71t') + + # Define the materials file. + self.materials.default_xs = '71c' + self.materials.add_materials((fuel, clad, cold_water, hot_water, + rpv_steel, lower_rad_ref, upper_rad_ref, bot_plate, bot_nozzle, + top_nozzle, top_fa, bot_fa)) + + # Define surfaces. + s1 = openmc.ZCylinder(R=0.41, surface_id=1) + s2 = openmc.ZCylinder(R=0.475, surface_id=2) + s3 = openmc.ZCylinder(R=0.56, surface_id=3) + s4 = openmc.ZCylinder(R=0.62, surface_id=4) + s5 = openmc.ZCylinder(R=187.6, surface_id=5) + s6 = openmc.ZCylinder(R=209.0, surface_id=6) + s7 = openmc.ZCylinder(R=229.0, surface_id=7) + s8 = openmc.ZCylinder(R=249.0, surface_id=8) + s8.boundary_type = 'vacuum' + + s31 = openmc.ZPlane(z0=-229.0, surface_id=31) + s31.boundary_type = 'vacuum' + s32 = openmc.ZPlane(z0=-199.0, surface_id=32) + s33 = openmc.ZPlane(z0=-193.0, surface_id=33) + s34 = openmc.ZPlane(z0=-183.0, surface_id=34) + s35 = openmc.ZPlane(z0=0.0, surface_id=35) + s36 = openmc.ZPlane(z0=183.0, surface_id=36) + s37 = openmc.ZPlane(z0=203.0, surface_id=37) + s38 = openmc.ZPlane(z0=215.0, surface_id=38) + s39 = openmc.ZPlane(z0=223.0, surface_id=39) + s39.boundary_type = 'vacuum' + + # Define pin cells. + fuel_cold = openmc.Universe(name='Fuel pin, cladding, cold water', + universe_id=1) + c21 = openmc.Cell(cell_id=21) + c21.region = -s1 + c21.fill = fuel + c22 = openmc.Cell(cell_id=22) + c22.region = +s1 & -s2 + c22.fill = clad + c23 = openmc.Cell(cell_id=23) + c23.region = +s2 + c23.fill = cold_water + fuel_cold.add_cells((c21, c22, c23)) + + tube_cold = openmc.Universe(name='Instrumentation guide tube, ' + 'cold water', universe_id=2) + c24 = openmc.Cell(cell_id=24) + c24.region = -s3 + c24.fill = cold_water + c25 = openmc.Cell(cell_id=25) + c25.region = +s3 & -s4 + c25.fill = clad + c26 = openmc.Cell(cell_id=26) + c26.region = +s4 + c26.fill = cold_water + tube_cold.add_cells((c24, c25, c26)) + + fuel_hot = openmc.Universe(name='Fuel pin, cladding, hot water', + universe_id=3) + c27 = openmc.Cell(cell_id=27) + c27.region = -s1 + c27.fill = fuel + c28 = openmc.Cell(cell_id=28) + c28.region = +s1 & -s2 + c28.fill = clad + c29 = openmc.Cell(cell_id=29) + c29.region = +s2 + c29.fill = hot_water + fuel_hot.add_cells((c27, c28, c29)) + + tube_hot = openmc.Universe(name='Instrumentation guide tube, hot water', + universe_id=4) + c30 = openmc.Cell(cell_id=30) + c30.region = -s3 + c30.fill = hot_water + c31 = openmc.Cell(cell_id=31) + c31.region = +s3 & -s4 + c31.fill = clad + c32 = openmc.Cell(cell_id=32) + c32.region = +s4 + c32.fill = hot_water + tube_hot.add_cells((c30, c31, c32)) + + # Define fuel lattices. + l100 = openmc.RectLattice(name='Fuel assembly (lower half)', + lattice_id=100) + l100.dimension = (17, 17) + l100.lower_left = (-10.71, -10.71) + l100.pitch = (1.26, 1.26) + l100.universes = [ + [fuel_cold]*17, + [fuel_cold]*17, + [fuel_cold]*5 + [tube_cold] + [fuel_cold]*2 + [tube_cold] + + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*5, + [fuel_cold]*3 + [tube_cold] + [fuel_cold]*9 + [tube_cold] + + [fuel_cold]*3, + [fuel_cold]*17, + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2 + [tube_cold] + + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2 + [tube_cold] + + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2, + [fuel_cold]*17, + [fuel_cold]*17, + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2 + [tube_cold] + + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2 + [tube_cold] + + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2, + [fuel_cold]*17, + [fuel_cold]*17, + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2 + [tube_cold] + + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2 + [tube_cold] + + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*2, + [fuel_cold]*17, + [fuel_cold]*3 + [tube_cold] + [fuel_cold]*9 + [tube_cold] + + [fuel_cold]*3, + [fuel_cold]*5 + [tube_cold] + [fuel_cold]*2 + [tube_cold] + + [fuel_cold]*2 + [tube_cold] + [fuel_cold]*5, + [fuel_cold]*17, + [fuel_cold]*17 ] + + l101 = openmc.RectLattice(name='Fuel assembly (upper half)', + lattice_id=101) + l101.dimension = (17, 17) + l101.lower_left = (-10.71, -10.71) + l101.pitch = (1.26, 1.26) + l101.universes = [ + [fuel_hot]*17, + [fuel_hot]*17, + [fuel_hot]*5 + [tube_hot] + [fuel_hot]*2 + [tube_hot] + + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*5, + [fuel_hot]*3 + [tube_hot] + [fuel_hot]*9 + [tube_hot] + + [fuel_hot]*3, + [fuel_hot]*17, + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2 + [tube_hot] + + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2 + [tube_hot] + + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2, + [fuel_hot]*17, + [fuel_hot]*17, + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2 + [tube_hot] + + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2 + [tube_hot] + + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2, + [fuel_hot]*17, + [fuel_hot]*17, + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2 + [tube_hot] + + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2 + [tube_hot] + + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*2, + [fuel_hot]*17, + [fuel_hot]*3 + [tube_hot] + [fuel_hot]*9 + [tube_hot] + + [fuel_hot]*3, + [fuel_hot]*5 + [tube_hot] + [fuel_hot]*2 + [tube_hot] + + [fuel_hot]*2 + [tube_hot] + [fuel_hot]*5, + [fuel_hot]*17, + [fuel_hot]*17 ] + + # Define assemblies. + fa_cw = openmc.Universe(name='Water assembly (cold)', universe_id=5) + c50 = openmc.Cell(cell_id=50) + c50.region = +s34 & -s35 + c50.fill = cold_water + fa_cw.add_cells((c50, )) + + fa_hw = openmc.Universe(name='Water assembly (hot)', universe_id=7) + c70 = openmc.Cell(cell_id=70) + c70.region = +s35 & -s36 + c70.fill = hot_water + fa_hw.add_cells((c70, )) + + fa_cold = openmc.Universe(name='Fuel assembly (cold)', universe_id=6) + c60 = openmc.Cell(cell_id=60) + c60.region = +s34 & -s35 + c60.fill = l100 + fa_cold.add_cells((c60, )) + + fa_hot = openmc.Universe(name='Fuel assembly (hot)', universe_id=8) + c80 = openmc.Cell(cell_id=80) + c80.region = +s35 & -s36 + c80.fill = l101 + fa_hot.add_cells((c80, )) + + # Define core lattices + l200 = openmc.RectLattice(name='Core lattice (lower half)', + lattice_id=200) + l200.dimension = (21, 21) + l200.lower_left = (-224.91, -224.91) + l200.pitch = (21.42, 21.42) + l200.universes = [ + [fa_cw]*21, + [fa_cw]*21, + [fa_cw]*7 + [fa_cold]*7 + [fa_cw]*7, + [fa_cw]*5 + [fa_cold]*11 + [fa_cw]*5, + [fa_cw]*4 + [fa_cold]*13 + [fa_cw]*4, + [fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3, + [fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3, + [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, + [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, + [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, + [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, + [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, + [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, + [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, + [fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3, + [fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3, + [fa_cw]*4 + [fa_cold]*13 + [fa_cw]*4, + [fa_cw]*5 + [fa_cold]*11 + [fa_cw]*5, + [fa_cw]*7 + [fa_cold]*7 + [fa_cw]*7, + [fa_cw]*21, + [fa_cw]*21] + + l201 = openmc.RectLattice(name='Core lattice (lower half)', + lattice_id=201) + l201.dimension = (21, 21) + l201.lower_left = (-224.91, -224.91) + l201.pitch = (21.42, 21.42) + l201.universes = [ + [fa_hw]*21, + [fa_hw]*21, + [fa_hw]*7 + [fa_hot]*7 + [fa_hw]*7, + [fa_hw]*5 + [fa_hot]*11 + [fa_hw]*5, + [fa_hw]*4 + [fa_hot]*13 + [fa_hw]*4, + [fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3, + [fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3, + [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, + [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, + [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, + [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, + [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, + [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, + [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, + [fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3, + [fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3, + [fa_hw]*4 + [fa_hot]*13 + [fa_hw]*4, + [fa_hw]*5 + [fa_hot]*11 + [fa_hw]*5, + [fa_hw]*7 + [fa_hot]*7 + [fa_hw]*7, + [fa_hw]*21, + [fa_hw]*21] + + # Define root universe. + root = openmc.Universe(universe_id=0, name='root universe') + c1 = openmc.Cell(cell_id=1) + c1.region = -s6 & +s34 & -s35 + c1.fill = l200 + + c2 = openmc.Cell(cell_id=2) + c2.region = -s6 & +s35 & -s36 + c2.fill = l201 + + c3 = openmc.Cell(cell_id=3) + c3.region = -s7 & +s31 & -s32 + c3.fill = bot_plate + + c4 = openmc.Cell(cell_id=4) + c4.region = -s5 & +s32 & -s33 + c4.fill = bot_nozzle + + c5 = openmc.Cell(cell_id=5) + c5.region = -s5 & +s33 & -s34 + c5.fill = bot_fa + + c6 = openmc.Cell(cell_id=6) + c6.region = -s5 & +s36 & -s37 + c6.fill = top_fa + + c7 = openmc.Cell(cell_id=7) + c7.region = -s5 & +s37 & -s38 + c7.fill = top_nozzle + + c8 = openmc.Cell(cell_id=8) + c8.region = -s7 & +s38 & -s39 + c8.fill = upper_rad_ref + + c9 = openmc.Cell(cell_id=9) + c9.region = +s6 & -s7 & +s32 & -s38 + c9.fill = bot_nozzle + + c10 = openmc.Cell(cell_id=10) + c10.region = +s7 & -s8 & +s31 & -s39 + c10.fill = rpv_steel + + c11 = openmc.Cell(cell_id=11) + c11.region = +s5 & -s6 & +s32 & -s34 + c11.fill = lower_rad_ref + + c12 = openmc.Cell(cell_id=12) + c12.region = +s5 & -s6 & +s36 & -s38 + c12.fill = upper_rad_ref + + root.add_cells((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)) + + # Define the geometry file. + geometry = openmc.Geometry() + geometry.root_universe = root + + self.geometry.geometry = geometry + + def build_default_settings(self): + self.settings.batches = 10 + self.settings.inactive = 5 + self.settings.particles = 100 + self.settings.set_source_space('box', (-160, -160, -183, 160, 160, 183)) + + def build_defualt_plots(self): + plot = openmc.Plot() + plot.filename = 'mat' + plot.origin = (125, 125, 0) + plot.width = (250, 250) + plot.pixels = (3000, 3000) + plot.color = 'mat' + + self.plots.add_plot(plot) diff --git a/tests/run_tests.py b/tests/run_tests.py index 3550ad7cb1..338732c142 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -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,12 @@ 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: + if os.path.exists(os.path.join(MPI_DIR, 'bin', 'mpifort')): + self.fc = os.path.join(MPI_DIR, 'bin', 'mpifort') + else: + self.fc = os.path.join(MPI_DIR, 'bin', 'mpif90') else: self.fc = FC @@ -164,6 +163,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 +177,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 +270,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 +300,6 @@ if options.list_build_configs: print('Configuration Name: {0}'.format(key)) print(' Debug Flags:..........{0}'.format(tests[key].debug)) print(' Optimization Flags:...{0}'.format(tests[key].optimize)) - print(' HDF5 Active:..........{0}'.format(tests[key].hdf5)) print(' MPI Active:...........{0}'.format(tests[key].mpi)) print(' OpenMP Active:........{0}'.format(tests[key].openmp)) print(' Valgrind Test:........{0}'.format(tests[key].valgrind)) diff --git a/tests/test_basic/geometry.xml b/tests/test_basic/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_basic/geometry.xml +++ b/tests/test_basic/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_basic/results_true.dat b/tests/test_basic/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_basic/results_true.dat +++ b/tests/test_basic/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_basic/test_basic.py b/tests/test_basic/test_basic.py index 6633e59111..2a595f3e66 100755 --- a/tests/test_basic/test_basic.py +++ b/tests/test_basic/test_basic.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_cmfd_feed/geometry.xml b/tests/test_cmfd_feed/geometry.xml index 57c4aa2285..73ea679c4c 100644 --- a/tests/test_cmfd_feed/geometry.xml +++ b/tests/test_cmfd_feed/geometry.xml @@ -4,7 +4,7 @@ 0 - -1 2 -3 4 -5 6 + -1 2 -3 4 -5 6 1 @@ -39,5 +39,5 @@ -1 reflective - + diff --git a/tests/test_cmfd_feed/results_true.dat b/tests/test_cmfd_feed/results_true.dat index a1dd0d815e..9c109db6ab 100644 --- a/tests/test_cmfd_feed/results_true.dat +++ b/tests/test_cmfd_feed/results_true.dat @@ -1,128 +1,128 @@ k-combined: -1.177396E+00 4.883437E-03 +1.168349E+00 1.145333E-02 tally 1: -1.107335E+01 -1.235221E+01 -2.002676E+01 -4.017045E+01 -2.844184E+01 -8.111731E+01 -3.428492E+01 -1.177848E+02 -3.735839E+01 -1.397523E+02 -3.894180E+01 -1.517824E+02 -3.528006E+01 -1.246308E+02 -2.863448E+01 -8.222321E+01 -2.125384E+01 -4.535192E+01 -1.112124E+01 -1.241089E+01 +1.167844E+01 +1.366808E+01 +2.141846E+01 +4.598143E+01 +2.928738E+01 +8.615095E+01 +3.513015E+01 +1.241914E+02 +3.715164E+01 +1.384553E+02 +3.639309E+01 +1.327919E+02 +3.370872E+01 +1.138391E+02 +2.875251E+01 +8.292323E+01 +2.117740E+01 +4.512961E+01 +1.130554E+01 +1.289872E+01 tally 2: -2.243113E+01 -2.535057E+01 -1.557550E+01 -1.222813E+01 -2.164704E+00 -2.389690E-01 -4.049814E+01 -8.218116E+01 -2.854669E+01 -4.085264E+01 -3.934452E+00 -7.833208E-01 -5.706024E+01 -1.633739E+02 -4.049737E+01 -8.234850E+01 -5.231368E+00 -1.386110E+00 -6.798682E+01 -2.320807E+02 -4.819178E+01 -1.166820E+02 -6.247056E+00 -1.968990E+00 -7.449317E+01 -2.782374E+02 -5.315156E+01 -1.417287E+02 -6.667584E+00 -2.250879E+00 -7.530107E+01 -2.849330E+02 -5.378916E+01 -1.454619E+02 -7.071012E+00 -2.522919E+00 -6.820303E+01 -2.335083E+02 -4.850330E+01 -1.181013E+02 -6.241747E+00 -1.973368E+00 -5.831373E+01 -1.704779E+02 -4.149124E+01 -8.633656E+01 -5.385636E+00 -1.468642E+00 -4.184350E+01 -8.792430E+01 -2.971699E+01 -4.435896E+01 -3.784806E+00 -7.343249E-01 -2.202673E+01 -2.444732E+01 -1.531988E+01 -1.183160E+01 -2.073873E+00 -2.272561E-01 +2.339531E+01 +2.755922E+01 +1.646762E+01 +1.365289E+01 +2.146174E+00 +2.369613E-01 +4.309769E+01 +9.312913E+01 +3.054873E+01 +4.681242E+01 +4.076365E+00 +8.462370E-01 +5.840647E+01 +1.715260E+02 +4.161366E+01 +8.713062E+01 +5.382541E+00 +1.473814E+00 +6.927641E+01 +2.411359E+02 +4.943841E+01 +1.228850E+02 +6.282202E+00 +1.990021E+00 +7.308593E+01 +2.678848E+02 +5.202069E+01 +1.357621E+02 +6.826145E+00 +2.353974E+00 +7.117026E+01 +2.543546E+02 +5.068896E+01 +1.290261E+02 +6.342979E+00 +2.033850E+00 +6.615720E+01 +2.193712E+02 +4.725156E+01 +1.119514E+02 +6.024815E+00 +1.833752E+00 +5.738164E+01 +1.651944E+02 +4.081217E+01 +8.360122E+01 +5.326191E+00 +1.435896E+00 +4.208669E+01 +8.911740E+01 +2.994944E+01 +4.517409E+01 +3.905846E+00 +7.855247E-01 +2.273578E+01 +2.615080E+01 +1.603853E+01 +1.303560E+01 +2.160924E+00 +2.473278E-01 tally 3: -1.500439E+01 -1.135466E+01 -9.942586E-01 -5.051831E-02 -2.744453E+01 -3.776958E+01 -1.781992E+00 -1.612021E-01 -3.901013E+01 -7.642401E+01 -2.472924E+00 -3.077607E-01 -4.642527E+01 -1.082730E+02 -2.924369E+00 -4.335819E-01 -5.109083E+01 -1.309660E+02 -3.325865E+00 -5.592642E-01 -5.182512E+01 -1.350762E+02 -3.259912E+00 -5.350517E-01 -4.672480E+01 -1.095974E+02 -3.097309E+00 -4.854729E-01 -3.997405E+01 -8.014326E+01 -2.589176E+00 -3.374615E-01 -2.861624E+01 -4.114210E+01 -1.806237E+00 -1.656944E-01 -1.474531E+01 -1.096355E+01 -9.807860E-01 -4.934364E-02 +1.584939E+01 +1.265206E+01 +1.096930E+00 +6.173135E-02 +2.940258E+01 +4.337818E+01 +1.932931E+00 +1.884749E-01 +4.008186E+01 +8.086427E+01 +2.512704E+00 +3.189987E-01 +4.759648E+01 +1.139252E+02 +3.041630E+00 +4.683237E-01 +5.006181E+01 +1.257467E+02 +3.137042E+00 +4.981005E-01 +4.883211E+01 +1.197646E+02 +3.130686E+00 +4.987337E-01 +4.550029E+01 +1.038199E+02 +2.853740E+00 +4.127265E-01 +3.937822E+01 +7.785807E+01 +2.488983E+00 +3.156421E-01 +2.884912E+01 +4.192640E+01 +1.855316E+00 +1.745109E-01 +1.543635E+01 +1.208459E+01 +1.025635E+00 +5.351565E-02 tally 4: 0.000000E+00 0.000000E+00 @@ -160,8 +160,8 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.050887E+00 -4.698799E-01 +3.119914E+00 +4.908283E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -208,10 +208,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.388951E+00 -1.456464E+00 -2.664528E+00 -3.577345E-01 +5.567786E+00 +1.556825E+00 +2.766088E+00 +3.864023E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -256,10 +256,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.165280E+00 -2.573230E+00 -4.930263E+00 -1.218988E+00 +7.491891E+00 +2.819491E+00 +5.235154E+00 +1.377898E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -304,10 +304,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.550278E+00 -3.668687E+00 -6.985934E+00 -2.450395E+00 +8.810357E+00 +3.898704E+00 +7.233068E+00 +2.630659E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -352,10 +352,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.236725E+00 -4.281659E+00 -8.429932E+00 -3.565265E+00 +9.374583E+00 +4.414420E+00 +8.565683E+00 +3.687428E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -400,10 +400,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.396613E+00 -4.431004E+00 -9.307625E+00 -4.351276E+00 +9.001252E+00 +4.073267E+00 +8.974821E+00 +4.050120E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -448,10 +448,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.721885E+00 -3.821463E+00 -9.438995E+00 -4.479948E+00 +8.236452E+00 +3.401934E+00 +9.042286E+00 +4.102906E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -496,10 +496,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.096946E+00 -2.525113E+00 -8.605114E+00 -3.710134E+00 +7.028546E+00 +2.482380E+00 +8.577643E+00 +3.691947E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -544,10 +544,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.222832E+00 -1.373166E+00 -7.480684E+00 -2.804650E+00 +5.159585E+00 +1.342512E+00 +7.389236E+00 +2.745028E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -592,10 +592,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.726690E+00 -3.773397E-01 -5.470375E+00 -1.504111E+00 +2.762685E+00 +3.914181E-01 +5.471849E+00 +1.509910E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -642,8 +642,8 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.026290E+00 -4.597502E-01 +3.038522E+00 +4.643520E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -662,114 +662,114 @@ k cmfd 0.000000E+00 0.000000E+00 0.000000E+00 -1.150583E+00 -1.159578E+00 -1.162798E+00 -1.171003E+00 -1.162732E+00 -1.165591E+00 -1.166032E+00 -1.165387E+00 -1.165451E+00 -1.170726E+00 -1.170820E+00 -1.167945E+00 -1.166050E+00 -1.165757E+00 -1.167631E+00 -1.168366E+00 +1.180802E+00 +1.162698E+00 +1.162794E+00 +1.159752E+00 +1.152596E+00 +1.151652E+00 +1.148131E+00 +1.151875E+00 +1.151434E+00 +1.158833E+00 +1.160751E+00 +1.155305E+00 +1.155356E+00 +1.158866E+00 +1.161574E+00 +1.154691E+00 cmfd entropy 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.215201E+00 -3.212850E+00 -3.214094E+00 -3.208054E+00 -3.212891E+00 -3.213349E+00 -3.208290E+00 -3.206895E+00 -3.208786E+00 -3.209630E+00 -3.212321E+00 -3.211750E+00 -3.212453E+00 -3.213370E+00 -3.211791E+00 -3.212685E+00 +3.214195E+00 +3.225164E+00 +3.227316E+00 +3.225663E+00 +3.226390E+00 +3.225832E+00 +3.226707E+00 +3.227866E+00 +3.229948E+00 +3.229269E+00 +3.230044E+00 +3.231568E+00 +3.234694E+00 +3.234771E+00 +3.234915E+00 +3.235876E+00 cmfd balance 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -6.348026E-03 -5.102747E-03 -4.043947E-03 -3.952742E-03 -2.533934E-03 -2.215030E-03 -2.945032E-03 -2.597862E-03 -2.300873E-03 -1.991974E-03 -1.679430E-03 -1.636923E-03 -1.581336E-03 -1.431472E-03 -1.419168E-03 -1.256242E-03 +4.742525E-03 +2.646417E-03 +1.981783E-03 +1.856593E-03 +1.797685E-03 +2.122587E-03 +1.200823E-03 +2.177249E-03 +1.442840E-03 +1.477754E-03 +1.236325E-03 +1.048988E-03 +8.395164E-04 +7.380254E-04 +7.742837E-04 +8.235911E-04 cmfd dominance ratio 0.000E+00 0.000E+00 0.000E+00 0.000E+00 - 5.524E-01 - 5.476E-01 - 5.474E-01 - 5.419E-01 - 5.443E-01 - 5.448E-01 - 5.408E-01 - 5.391E-01 - 5.400E-01 - 5.396E-01 - 5.408E-01 - 5.398E-01 - 5.398E-01 - 5.399E-01 - 5.388E-01 - 5.389E-01 + 5.467E-01 + 5.518E-01 + 5.535E-01 + 5.500E-01 + 5.481E-01 + 5.478E-01 + 5.467E-01 + 5.465E-01 + 5.493E-01 + 5.488E-01 + 5.491E-01 + 5.503E-01 + 5.529E-01 + 5.531E-01 + 5.534E-01 + 5.552E-01 cmfd openmc source comparison 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -8.388554E-03 -7.868057E-03 -6.387209E-03 -6.979018E-03 -5.634468E-03 -5.579466E-03 -5.647779E-03 -5.289856E-03 -4.550547E-03 -4.373716E-03 -4.042350E-03 -3.813510E-03 -3.749151E-03 -3.358126E-03 -3.562360E-03 -3.904942E-03 +9.168094E-03 +5.978693E-03 +4.369223E-03 +4.546309E-03 +4.222522E-03 +4.221686E-03 +4.604208E-03 +3.950286E-03 +2.939283E-03 +3.667020E-03 +2.592899E-03 +2.272158E-03 +1.229170E-03 +1.114150E-03 +1.060490E-03 +1.714222E-03 cmfd source -4.142294E-02 -7.484382E-02 -1.050784E-01 -1.256771E-01 -1.444717E-01 -1.420230E-01 -1.350735E-01 -1.118744E-01 -7.755343E-02 -4.198177E-02 +4.724285E-02 +8.305825E-02 +1.081058E-01 +1.314542E-01 +1.357299E-01 +1.359417E-01 +1.240918E-01 +1.087580E-01 +8.111239E-02 +4.450518E-02 diff --git a/tests/test_cmfd_feed/tallies.xml b/tests/test_cmfd_feed/tallies.xml index b20c0ad613..37edcecc2c 100644 --- a/tests/test_cmfd_feed/tallies.xml +++ b/tests/test_cmfd_feed/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -10 -1 -1 10 1 1 10 1 1 diff --git a/tests/test_cmfd_feed/test_cmfd_feed.py b/tests/test_cmfd_feed/test_cmfd_feed.py index a3d2f30310..3bc5f61743 100644 --- a/tests/test_cmfd_feed/test_cmfd_feed.py +++ b/tests/test_cmfd_feed/test_cmfd_feed.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import CMFDTestHarness diff --git a/tests/test_cmfd_nofeed/geometry.xml b/tests/test_cmfd_nofeed/geometry.xml index 57c4aa2285..73ea679c4c 100644 --- a/tests/test_cmfd_nofeed/geometry.xml +++ b/tests/test_cmfd_nofeed/geometry.xml @@ -4,7 +4,7 @@ 0 - -1 2 -3 4 -5 6 + -1 2 -3 4 -5 6 1 @@ -39,5 +39,5 @@ -1 reflective - + diff --git a/tests/test_cmfd_nofeed/results_true.dat b/tests/test_cmfd_nofeed/results_true.dat index da9b802e7e..308dd7d827 100644 --- a/tests/test_cmfd_nofeed/results_true.dat +++ b/tests/test_cmfd_nofeed/results_true.dat @@ -1,128 +1,128 @@ k-combined: -1.170519E+00 8.422960E-03 +1.171115E+00 6.173328E-03 tally 1: -1.078122E+01 -1.170828E+01 -1.999878E+01 -4.018561E+01 -2.812898E+01 -7.936860E+01 -3.362276E+01 -1.133841E+02 -3.714459E+01 -1.382628E+02 -3.828125E+01 -1.470408E+02 -3.599263E+01 -1.299451E+02 -3.090749E+01 -9.596105E+01 -2.144103E+01 -4.630323E+01 -1.143002E+01 -1.314355E+01 +1.151618E+01 +1.331859E+01 +2.120660E+01 +4.514836E+01 +2.759616E+01 +7.639131E+01 +3.216668E+01 +1.036501E+02 +3.664720E+01 +1.345450E+02 +3.771246E+01 +1.424209E+02 +3.523750E+01 +1.245225E+02 +2.973298E+01 +8.860064E+01 +2.152108E+01 +4.647187E+01 +1.169538E+01 +1.375047E+01 tally 2: -2.247115E+01 -2.548076E+01 -1.574700E+01 -1.251937E+01 -2.119907E+00 -2.284737E-01 -4.160187E+01 -8.733627E+01 -2.945600E+01 -4.383448E+01 -4.027136E+00 -8.279807E-01 -5.722117E+01 -1.643758E+02 -4.057100E+01 -8.267151E+01 -5.388803E+00 -1.465180E+00 -6.769175E+01 -2.300722E+02 -4.800300E+01 -1.157663E+02 -6.213554E+00 -1.946061E+00 -7.376629E+01 -2.729166E+02 -5.253400E+01 -1.385018E+02 -6.438590E+00 -2.103693E+00 -7.454128E+01 -2.790080E+02 -5.311800E+01 -1.417584E+02 -6.784745E+00 -2.328936E+00 -6.907125E+01 -2.397912E+02 -4.912000E+01 -1.213330E+02 -6.405754E+00 -2.075535E+00 -6.012056E+01 -1.815248E+02 -4.280600E+01 -9.207864E+01 -5.534450E+00 -1.555396E+00 -4.229808E+01 -8.999380E+01 -3.003200E+01 -4.541718E+01 -3.844618E+00 -7.537006E-01 -2.272774E+01 -2.597695E+01 -1.577800E+01 -1.252728E+01 -2.221451E+00 -2.528223E-01 +2.274639E+01 +2.606952E+01 +1.588200E+01 +1.270445E+01 +2.140989E+00 +2.357207E-01 +4.205792E+01 +8.880940E+01 +2.970000E+01 +4.427086E+01 +3.919645E+00 +7.773724E-01 +5.560960E+01 +1.559764E+02 +3.947900E+01 +7.872700E+01 +5.238942E+00 +1.400918E+00 +6.492259E+01 +2.117369E+02 +4.612200E+01 +1.069035E+02 +5.989449E+00 +1.813201E+00 +7.217377E+01 +2.608499E+02 +5.148500E+01 +1.327923E+02 +6.607336E+00 +2.205529E+00 +7.305896E+01 +2.681514E+02 +5.187500E+01 +1.352457E+02 +6.722921E+00 +2.290262E+00 +6.884269E+01 +2.380550E+02 +4.904800E+01 +1.208314E+02 +6.177320E+00 +1.927173E+00 +5.902100E+01 +1.748370E+02 +4.201000E+01 +8.858460E+01 +5.542381E+00 +1.549108E+00 +4.268091E+01 +9.151405E+01 +3.029500E+01 +4.614050E+01 +3.822093E+00 +7.420139E-01 +2.362279E+01 +2.812041E+01 +1.653100E+01 +1.377737E+01 +2.336090E+00 +2.851840E-01 tally 3: -1.517200E+01 -1.162361E+01 -9.172562E-01 -4.342120E-02 -2.835000E+01 -4.061736E+01 -1.868192E+00 -1.761390E-01 -3.911800E+01 -7.686442E+01 -2.478956E+00 -3.088180E-01 -4.617600E+01 -1.071239E+02 -2.980518E+00 -4.488545E-01 -5.059100E+01 -1.284662E+02 -3.257651E+00 -5.341674E-01 -5.115000E+01 -1.314866E+02 -3.365441E+00 -5.729274E-01 -4.732100E+01 -1.126317E+02 -3.051596E+00 -4.705140E-01 -4.120700E+01 -8.535705E+01 -2.704451E+00 -3.705800E-01 -2.900900E+01 -4.238065E+01 -1.872660E+00 -1.780668E-01 -1.520000E+01 -1.162785E+01 -1.007084E+00 -5.171907E-02 +1.524100E+01 +1.171023E+01 +1.071050E+00 +5.839198E-02 +2.862800E+01 +4.113148E+01 +1.892774E+00 +1.812712E-01 +3.804600E+01 +7.316097E+01 +2.423654E+00 +2.968521E-01 +4.434600E+01 +9.882906E+01 +2.823929E+00 +4.033633E-01 +4.955300E+01 +1.230293E+02 +3.226029E+00 +5.265680E-01 +4.999400E+01 +1.256474E+02 +3.232464E+00 +5.286388E-01 +4.724300E+01 +1.121029E+02 +3.015553E+00 +4.606928E-01 +4.051300E+01 +8.239672E+01 +2.592073E+00 +3.412174E-01 +2.912700E+01 +4.265700E+01 +1.875109E+00 +1.785438E-01 +1.593500E+01 +1.280638E+01 +1.038638E+00 +5.538157E-02 tally 4: 0.000000E+00 0.000000E+00 @@ -160,8 +160,8 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.017000E+00 -4.575810E-01 +3.065000E+00 +4.742170E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -208,10 +208,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.447000E+00 -1.491865E+00 -2.697000E+00 -3.709330E-01 +5.420000E+00 +1.474674E+00 +2.693000E+00 +3.667090E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -256,10 +256,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.403000E+00 -2.751813E+00 -5.151000E+00 -1.334701E+00 +7.243000E+00 +2.637431E+00 +5.092000E+00 +1.305200E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -304,10 +304,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.635000E+00 -3.741143E+00 -7.048000E+00 -2.495310E+00 +8.280000E+00 +3.445670E+00 +6.765000E+00 +2.307253E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -352,10 +352,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.381000E+00 -4.415619E+00 -8.456000E+00 -3.587840E+00 +8.980000E+00 +4.046484E+00 +8.108000E+00 +3.299338E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -400,10 +400,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.297000E+00 -4.334551E+00 -9.198000E+00 -4.240540E+00 +9.016000E+00 +4.079320E+00 +8.962000E+00 +4.034032E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -448,10 +448,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.737000E+00 -3.843559E+00 -9.508000E+00 -4.553256E+00 +8.465000E+00 +3.595665E+00 +9.296000E+00 +4.340524E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -496,10 +496,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.338000E+00 -2.709162E+00 -8.888000E+00 -3.969398E+00 +7.247000E+00 +2.638527E+00 +8.865000E+00 +3.946315E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -544,10 +544,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.354000E+00 -1.442386E+00 -7.584000E+00 -2.887298E+00 +5.179000E+00 +1.353661E+00 +7.492000E+00 +2.817588E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -592,10 +592,10 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.707000E+00 -3.709270E-01 -5.507000E+00 -1.522587E+00 +2.821000E+00 +4.067990E-01 +5.617000E+00 +1.587757E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -642,8 +642,8 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.112000E+00 -4.868600E-01 +3.134000E+00 +4.937920E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -662,114 +662,114 @@ k cmfd 0.000000E+00 0.000000E+00 0.000000E+00 -1.150583E+00 -1.160876E+00 -1.160893E+00 -1.157393E+00 -1.157826E+00 -1.163206E+00 -1.169286E+00 -1.169322E+00 -1.169866E+00 -1.177576E+00 -1.183172E+00 -1.184784E+00 -1.186581E+00 -1.183233E+00 -1.181032E+00 -1.180107E+00 +1.180802E+00 +1.163440E+00 +1.148572E+00 +1.151423E+00 +1.143374E+00 +1.144091E+00 +1.146212E+00 +1.144900E+00 +1.153511E+00 +1.158766E+00 +1.159179E+00 +1.156627E+00 +1.160647E+00 +1.162860E+00 +1.164312E+00 +1.164928E+00 cmfd entropy 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.215201E+00 -3.214833E+00 -3.211409E+00 -3.218241E+00 -3.220068E+00 -3.217667E+00 -3.214425E+00 -3.215427E+00 -3.214339E+00 -3.212343E+00 -3.211075E+00 -3.211281E+00 -3.209704E+00 -3.210597E+00 -3.213481E+00 -3.213943E+00 +3.214195E+00 +3.222259E+00 +3.225989E+00 +3.230436E+00 +3.228875E+00 +3.229003E+00 +3.228502E+00 +3.230397E+00 +3.231417E+00 +3.231192E+00 +3.229995E+00 +3.229396E+00 +3.228730E+00 +3.228091E+00 +3.227600E+00 +3.229723E+00 cmfd balance 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -6.348026E-03 -4.651411E-03 -3.551519E-03 -2.893286E-03 -2.930836E-03 -2.342081E-03 -2.443793E-03 -2.380658E-03 -2.091259E-03 -2.144887E-03 -2.055334E-03 -1.907704E-03 -1.879350E-03 -1.598308E-03 -1.247988E-03 -1.179680E-03 +4.742525E-03 +3.110598E-03 +2.490108E-03 +2.114137E-03 +2.190200E-03 +3.281877E-03 +2.219193E-03 +2.458372E-03 +2.200863E-03 +2.181858E-03 +2.064212E-03 +1.961178E-03 +1.713250E-03 +1.665361E-03 +1.436016E-03 +1.193462E-03 cmfd dominance ratio 0.000E+00 0.000E+00 0.000E+00 0.000E+00 - 5.524E-01 - 5.492E-01 - 5.459E-01 - 5.486E-01 + 5.467E-01 + 5.505E-01 + 5.514E-01 + 5.531E-01 + 5.529E-01 + 5.501E-01 + 5.484E-01 + 5.500E-01 + 5.506E-01 + 5.508E-01 + 5.504E-01 + 5.500E-01 + 5.480E-01 + 5.482E-01 5.475E-01 - 5.455E-01 - 5.433E-01 - 5.425E-01 - 5.412E-01 - 5.404E-01 - 5.399E-01 - 5.400E-01 - 5.401E-01 - 5.414E-01 - 5.433E-01 - 5.437E-01 + 5.493E-01 cmfd openmc source comparison 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -8.388554E-03 -6.525044E-03 -5.810856E-03 -3.651620E-03 -3.448625E-03 -3.805838E-03 -4.064235E-03 -3.244723E-03 -3.963513E-03 -4.186768E-03 -3.785555E-03 -2.732731E-03 -2.308430E-03 -2.074797E-03 -1.581512E-03 -1.729988E-03 +9.168094E-03 +5.976241E-03 +4.426550E-03 +4.107499E-03 +4.957716E-03 +4.026213E-03 +3.986000E-03 +2.702714E-03 +3.619345E-03 +4.909616E-03 +3.355042E-03 +2.945724E-03 +3.010811E-03 +2.965662E-03 +2.673073E-03 +1.669634E-03 cmfd source -3.816410E-02 -7.860013E-02 -1.050204E-01 -1.270331E-01 -1.389768E-01 -1.438216E-01 -1.304530E-01 -1.155470E-01 -7.975741E-02 -4.262650E-02 +4.539734E-02 +8.104913E-02 +1.045143E-01 +1.221516E-01 +1.398002E-01 +1.400323E-01 +1.304628E-01 +1.120006E-01 +8.038230E-02 +4.420934E-02 diff --git a/tests/test_cmfd_nofeed/tallies.xml b/tests/test_cmfd_nofeed/tallies.xml index b20c0ad613..37edcecc2c 100644 --- a/tests/test_cmfd_nofeed/tallies.xml +++ b/tests/test_cmfd_nofeed/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -10 -1 -1 10 1 1 10 1 1 diff --git a/tests/test_cmfd_nofeed/test_cmfd_nofeed.py b/tests/test_cmfd_nofeed/test_cmfd_nofeed.py index a3d2f30310..3bc5f61743 100644 --- a/tests/test_cmfd_nofeed/test_cmfd_nofeed.py +++ b/tests/test_cmfd_nofeed/test_cmfd_nofeed.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import CMFDTestHarness diff --git a/tests/test_complex_cell/geometry.xml b/tests/test_complex_cell/geometry.xml new file mode 100644 index 0000000000..a695396e01 --- /dev/null +++ b/tests/test_complex_cell/geometry.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_complex_cell/materials.xml b/tests/test_complex_cell/materials.xml new file mode 100644 index 0000000000..60ec996735 --- /dev/null +++ b/tests/test_complex_cell/materials.xml @@ -0,0 +1,23 @@ + + + + 71c + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_complex_cell/results_true.dat b/tests/test_complex_cell/results_true.dat new file mode 100644 index 0000000000..97f228e3ee --- /dev/null +++ b/tests/test_complex_cell/results_true.dat @@ -0,0 +1,11 @@ +k-combined: +2.565769E-01 8.980879E-04 +tally 1: +2.584080E+00 +1.335682E+00 +2.763580E+00 +1.528633E+00 +1.007148E+00 +2.031543E-01 +1.113696E-01 +2.485351E-03 diff --git a/tests/test_reflective_cylinder/settings.xml b/tests/test_complex_cell/settings.xml similarity index 100% rename from tests/test_reflective_cylinder/settings.xml rename to tests/test_complex_cell/settings.xml diff --git a/tests/test_filter_cell/tallies.xml b/tests/test_complex_cell/tallies.xml similarity index 60% rename from tests/test_filter_cell/tallies.xml rename to tests/test_complex_cell/tallies.xml index 815b84c145..d1a7d387ee 100644 --- a/tests/test_filter_cell/tallies.xml +++ b/tests/test_complex_cell/tallies.xml @@ -1,9 +1,7 @@ - - + total - - \ No newline at end of file + diff --git a/tests/test_reflective_sphere/test_reflective_sphere.py b/tests/test_complex_cell/test_complex_cell.py old mode 100644 new mode 100755 similarity index 74% rename from tests/test_reflective_sphere/test_reflective_sphere.py rename to tests/test_complex_cell/test_complex_cell.py index 6633e59111..1777db993e --- a/tests/test_reflective_sphere/test_reflective_sphere.py +++ b/tests/test_complex_cell/test_complex_cell.py @@ -6,5 +6,5 @@ from testing_harness import TestHarness if __name__ == '__main__': - harness = TestHarness('statepoint.10.*') + harness = TestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_confidence_intervals/geometry.xml b/tests/test_confidence_intervals/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_confidence_intervals/geometry.xml +++ b/tests/test_confidence_intervals/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_confidence_intervals/test_confidence_intervals.py b/tests/test_confidence_intervals/test_confidence_intervals.py index 1777db993e..ed6addec45 100755 --- a/tests/test_confidence_intervals/test_confidence_intervals.py +++ b/tests/test_confidence_intervals/test_confidence_intervals.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_density_atombcm/geometry.xml b/tests/test_density_atombcm/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_density_atombcm/geometry.xml +++ b/tests/test_density_atombcm/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_density_atombcm/results_true.dat b/tests/test_density_atombcm/results_true.dat index 384fb593eb..2956b53888 100644 --- a/tests/test_density_atombcm/results_true.dat +++ b/tests/test_density_atombcm/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.760126E+00 1.038820E-02 +1.752274E+00 4.032481E-02 diff --git a/tests/test_density_atombcm/test_density_atombcm.py b/tests/test_density_atombcm/test_density_atombcm.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_density_atombcm/test_density_atombcm.py +++ b/tests/test_density_atombcm/test_density_atombcm.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_density_atomcm3/geometry.xml b/tests/test_density_atomcm3/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_density_atomcm3/geometry.xml +++ b/tests/test_density_atomcm3/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_density_atomcm3/results_true.dat b/tests/test_density_atomcm3/results_true.dat index 3feb35ba1e..0bd16fc4de 100644 --- a/tests/test_density_atomcm3/results_true.dat +++ b/tests/test_density_atomcm3/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.092203E+00 1.990176E-02 +1.092376E+00 1.759788E-02 diff --git a/tests/test_density_atomcm3/test_density_atomcm3.py b/tests/test_density_atomcm3/test_density_atomcm3.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_density_atomcm3/test_density_atomcm3.py +++ b/tests/test_density_atomcm3/test_density_atomcm3.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_density_kgm3/geometry.xml b/tests/test_density_kgm3/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_density_kgm3/geometry.xml +++ b/tests/test_density_kgm3/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_density_kgm3/results_true.dat b/tests/test_density_kgm3/results_true.dat index c5942e1a23..6b008101fb 100644 --- a/tests/test_density_kgm3/results_true.dat +++ b/tests/test_density_kgm3/results_true.dat @@ -1,2 +1,2 @@ k-combined: -8.085745E-01 9.674599E-03 +7.994522E-01 1.065745E-02 diff --git a/tests/test_density_kgm3/test_density_kgm3.py b/tests/test_density_kgm3/test_density_kgm3.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_density_kgm3/test_density_kgm3.py +++ b/tests/test_density_kgm3/test_density_kgm3.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_density_sum/geometry.xml b/tests/test_density_sum/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_density_sum/geometry.xml +++ b/tests/test_density_sum/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_density_sum/results_true.dat b/tests/test_density_sum/results_true.dat index 418331925d..9b16f2d988 100644 --- a/tests/test_density_sum/results_true.dat +++ b/tests/test_density_sum/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.319139E-01 1.688777E-02 +3.231215E-01 6.421320E-03 diff --git a/tests/test_density_sum/test_density_sum.py b/tests/test_density_sum/test_density_sum.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_density_sum/test_density_sum.py +++ b/tests/test_density_sum/test_density_sum.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_eigenvalue_genperbatch/geometry.xml b/tests/test_eigenvalue_genperbatch/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_eigenvalue_genperbatch/geometry.xml +++ b/tests/test_eigenvalue_genperbatch/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_eigenvalue_genperbatch/results_true.dat b/tests/test_eigenvalue_genperbatch/results_true.dat index d6aac0453a..9e87c901d9 100644 --- a/tests/test_eigenvalue_genperbatch/results_true.dat +++ b/tests/test_eigenvalue_genperbatch/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.012381E-01 1.890480E-03 +3.015627E-01 5.978844E-03 diff --git a/tests/test_eigenvalue_genperbatch/test_eigenvalue_genperbatch.py b/tests/test_eigenvalue_genperbatch/test_eigenvalue_genperbatch.py index 22752c1894..d6f69fdbb5 100644 --- a/tests/test_eigenvalue_genperbatch/test_eigenvalue_genperbatch.py +++ b/tests/test_eigenvalue_genperbatch/test_eigenvalue_genperbatch.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_eigenvalue_no_inactive/geometry.xml b/tests/test_eigenvalue_no_inactive/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_eigenvalue_no_inactive/geometry.xml +++ b/tests/test_eigenvalue_no_inactive/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_eigenvalue_no_inactive/results_true.dat b/tests/test_eigenvalue_no_inactive/results_true.dat index d7575db1fe..fbbe84cc37 100644 --- a/tests/test_eigenvalue_no_inactive/results_true.dat +++ b/tests/test_eigenvalue_no_inactive/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.066374E-01 7.794575E-03 +3.130246E-01 6.960311E-03 diff --git a/tests/test_eigenvalue_no_inactive/test_eigenvalue_no_inactive.py b/tests/test_eigenvalue_no_inactive/test_eigenvalue_no_inactive.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_eigenvalue_no_inactive/test_eigenvalue_no_inactive.py +++ b/tests/test_eigenvalue_no_inactive/test_eigenvalue_no_inactive.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_energy_grid/geometry.xml b/tests/test_energy_grid/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_energy_grid/geometry.xml +++ b/tests/test_energy_grid/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_energy_grid/results_true.dat b/tests/test_energy_grid/results_true.dat index 05cda2e980..9556a981bc 100644 --- a/tests/test_energy_grid/results_true.dat +++ b/tests/test_energy_grid/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.215828E-01 2.966835E-03 +3.155788E-01 7.559348E-03 diff --git a/tests/test_energy_grid/test_energy_grid.py b/tests/test_energy_grid/test_energy_grid.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_energy_grid/test_energy_grid.py +++ b/tests/test_energy_grid/test_energy_grid.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_entropy/geometry.xml b/tests/test_entropy/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_entropy/geometry.xml +++ b/tests/test_entropy/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_entropy/results_true.dat b/tests/test_entropy/results_true.dat index a3515ba2bb..8b37789c32 100644 --- a/tests/test_entropy/results_true.dat +++ b/tests/test_entropy/results_true.dat @@ -1,13 +1,13 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 entropy: 7.608094E+00 8.167702E+00 8.273634E+00 -8.238974E+00 -8.307173E+00 -8.239618E+00 -8.230443E+00 -8.201657E+00 -8.289158E+00 -8.364683E+00 +8.239452E+00 +8.234598E+00 +8.278421E+00 +8.260773E+00 +8.351860E+00 +8.303719E+00 +8.271058E+00 diff --git a/tests/test_entropy/test_entropy.py b/tests/test_entropy/test_entropy.py index 4657101ad6..113cafcb27 100644 --- a/tests/test_entropy/test_entropy.py +++ b/tests/test_entropy/test_entropy.py @@ -1,8 +1,11 @@ #!/usr/bin/env python +import glob +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness +from openmc.statepoint import StatePoint class EntropyTestHarness(TestHarness): @@ -11,7 +14,6 @@ class EntropyTestHarness(TestHarness): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Write out k-combined. outstr = 'k-combined:\n' @@ -20,7 +22,7 @@ class EntropyTestHarness(TestHarness): # Write out entropy data. outstr += 'entropy:\n' - results = ['{0:12.6E}'.format(x) for x in sp._entropy] + results = ['{0:12.6E}'.format(x) for x in sp.entropy] outstr += '\n'.join(results) + '\n' return outstr diff --git a/tests/test_filter_azimuthal/inputs_true.dat b/tests/test_filter_azimuthal/inputs_true.dat new file mode 100644 index 0000000000..42b6e820be --- /dev/null +++ b/tests/test_filter_azimuthal/inputs_true.dat @@ -0,0 +1 @@ +1d5f81d12f607f4a8436dfb65167e2a2be55dbf86fbc2cc465cec274671be5eaff517d781a4d40e264bb695e3c66c7ff61a650217c99de2ca8c15ca747fe6b80 \ No newline at end of file diff --git a/tests/test_filter_azimuthal/results_true.dat b/tests/test_filter_azimuthal/results_true.dat new file mode 100644 index 0000000000..7883a730d4 --- /dev/null +++ b/tests/test_filter_azimuthal/results_true.dat @@ -0,0 +1,76 @@ +k-combined: +9.903196E-01 4.279617E-02 +tally 1: +4.215917E+01 +3.561920E+02 +4.174788E+01 +3.505184E+02 +4.603223E+01 +4.242918E+02 +4.496760E+01 +4.075599E+02 +4.088099E+01 +3.376516E+02 +tally 2: +4.157239E+01 +3.482158E+02 +4.227810E+01 +3.613293E+02 +4.376107E+01 +3.835007E+02 +4.644205E+01 +4.327195E+02 +4.191554E+01 +3.522147E+02 +tally 3: +4.215917E+01 +3.561920E+02 +4.174788E+01 +3.505184E+02 +4.603223E+01 +4.242918E+02 +4.496402E+01 +4.075053E+02 +4.088458E+01 +3.377000E+02 +tally 4: +1.531988E+01 +4.816326E+01 +9.274393E+00 +1.821174E+01 +1.595868E+01 +5.124238E+01 +1.299895E+00 +6.417145E-01 +1.510024E+01 +4.604170E+01 +8.533361E+00 +1.462765E+01 +1.658141E+01 +5.595629E+01 +1.427417E+00 +6.621807E-01 +1.683102E+01 +5.741400E+01 +9.845257E+00 +2.028406E+01 +1.773179E+01 +6.477077E+01 +1.536972E+00 +6.111079E-01 +1.586070E+01 +5.360975E+01 +9.928220E+00 +2.089005E+01 +1.737609E+01 +6.161847E+01 +1.700608E+00 +8.439708E-01 +1.607027E+01 +5.490113E+01 +7.569336E+00 +1.280955E+01 +1.606086E+01 +5.308665E+01 +9.898901E-01 +3.143027E-01 diff --git a/tests/test_filter_azimuthal/test_filter_azimuthal.py b/tests/test_filter_azimuthal/test_filter_azimuthal.py new file mode 100644 index 0000000000..248ba00120 --- /dev/null +++ b/tests/test_filter_azimuthal/test_filter_azimuthal.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + +class FilterAzimuthalTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt1 = openmc.Filter(type='azimuthal', + bins=(-3.1416, -1.8850, -0.6283, 0.6283, 1.8850, + 3.1416)) + tally1 = openmc.Tally(tally_id=1) + tally1.add_filter(filt1) + tally1.add_score('flux') + tally1.estimator = 'tracklength' + + tally2 = openmc.Tally(tally_id=2) + tally2.add_filter(filt1) + tally2.add_score('flux') + tally2.estimator = 'analog' + + filt3 = openmc.Filter(type='azimuthal', bins=(5,)) + tally3 = openmc.Tally(tally_id=3) + tally3.add_filter(filt3) + tally3.add_score('flux') + tally3.estimator = 'tracklength' + + mesh = openmc.Mesh(mesh_id=1) + mesh.lower_left = [-182.07, -182.07] + mesh.upper_right = [182.07, 182.07] + mesh.dimension = [2, 2] + filt_mesh = openmc.Filter(type='mesh', bins=(1,)) + tally4 = openmc.Tally(tally_id=4) + tally4.add_filter(filt3) + tally4.add_filter(filt_mesh) + tally4.add_score('flux') + tally4.estimator = 'tracklength' + + + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally1) + self._input_set.tallies.add_tally(tally2) + self._input_set.tallies.add_tally(tally3) + self._input_set.tallies.add_tally(tally4) + self._input_set.tallies.add_mesh(mesh) + + super(FilterAzimuthalTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterAzimuthalTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = FilterAzimuthalTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_filter_cell/geometry.xml b/tests/test_filter_cell/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_filter_cell/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_filter_cell/inputs_true.dat b/tests/test_filter_cell/inputs_true.dat new file mode 100644 index 0000000000..2320ff6ab4 --- /dev/null +++ b/tests/test_filter_cell/inputs_true.dat @@ -0,0 +1 @@ +caae173f01f7073d634a68a5c4ce97177423e13596a863976e1c40303dc8c05afed457d5a1aa0ae73627ec953143e4f9c1f45bdbd3b0cca76433062467d59777 \ No newline at end of file diff --git a/tests/test_filter_cell/materials.xml b/tests/test_filter_cell/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_filter_cell/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_filter_cell/results_true.dat b/tests/test_filter_cell/results_true.dat index 0838e7baed..47ff3c281a 100644 --- a/tests/test_filter_cell/results_true.dat +++ b/tests/test_filter_cell/results_true.dat @@ -1,11 +1,11 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: 0.000000E+00 0.000000E+00 -1.517577E+01 -4.747271E+01 -3.151504E+00 -2.051857E+00 -4.536316E+01 -4.258781E+02 +1.767552E+01 +6.295417E+01 +3.863588E+00 +3.013300E+00 +5.356594E+01 +5.839391E+02 diff --git a/tests/test_filter_cell/settings.xml b/tests/test_filter_cell/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_filter_cell/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_filter_cell/test_filter_cell.py b/tests/test_filter_cell/test_filter_cell.py index 1777db993e..d532d59cf8 100644 --- a/tests/test_filter_cell/test_filter_cell.py +++ b/tests/test_filter_cell/test_filter_cell.py @@ -1,10 +1,29 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterCellTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23)) + tally = openmc.Tally(tally_id=1) + tally.add_filter(filt) + tally.add_score('total') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally) + + super(FilterCellTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterCellTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = FilterCellTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_filter_cellborn/geometry.xml b/tests/test_filter_cellborn/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_filter_cellborn/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_filter_cellborn/inputs_true.dat b/tests/test_filter_cellborn/inputs_true.dat new file mode 100644 index 0000000000..5aef4cbb06 --- /dev/null +++ b/tests/test_filter_cellborn/inputs_true.dat @@ -0,0 +1 @@ +2f24eb86cda981982a8db5bb110c72e9cef542c06e15b748c1c7e459f96b0d8ba0978b51dffc006e813cd2e2ae1fa0357336f8322ae263189841afde01f0327b \ No newline at end of file diff --git a/tests/test_filter_cellborn/materials.xml b/tests/test_filter_cellborn/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_filter_cellborn/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_filter_cellborn/results_true.dat b/tests/test_filter_cellborn/results_true.dat index d2fa7f7004..d0ab58f4ed 100644 --- a/tests/test_filter_cellborn/results_true.dat +++ b/tests/test_filter_cellborn/results_true.dat @@ -1,10 +1,10 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: 0.000000E+00 0.000000E+00 -7.449502E+01 -1.145793E+03 +8.921179E+01 +1.601939E+03 0.000000E+00 0.000000E+00 0.000000E+00 diff --git a/tests/test_filter_cellborn/settings.xml b/tests/test_filter_cellborn/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_filter_cellborn/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_filter_cellborn/tallies.xml b/tests/test_filter_cellborn/tallies.xml deleted file mode 100644 index b278b07ff8..0000000000 --- a/tests/test_filter_cellborn/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - total - - - \ No newline at end of file diff --git a/tests/test_filter_cellborn/test_filter_cellborn.py b/tests/test_filter_cellborn/test_filter_cellborn.py index 1777db993e..2fac6a1fcd 100644 --- a/tests/test_filter_cellborn/test_filter_cellborn.py +++ b/tests/test_filter_cellborn/test_filter_cellborn.py @@ -1,10 +1,29 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterCellbornTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cellborn', bins=(10, 21, 22, 23)) + tally = openmc.Tally(tally_id=1) + tally.add_filter(filt) + tally.add_score('total') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally) + + super(FilterCellbornTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterCellbornTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = FilterCellbornTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_filter_delayedgroup/inputs_true.dat b/tests/test_filter_delayedgroup/inputs_true.dat new file mode 100644 index 0000000000..21bce00fd2 --- /dev/null +++ b/tests/test_filter_delayedgroup/inputs_true.dat @@ -0,0 +1 @@ +e771470681d3b4af57a70d148f5eb728df57f1fd7bdb5d6f76ac556b69f10bf0cdd5645fe488f1e17f07cbb72e9fb34af2fd7ede95c8e39c5ffa6ea9b6c5810e \ No newline at end of file diff --git a/tests/test_filter_delayedgroup/results_true.dat b/tests/test_filter_delayedgroup/results_true.dat new file mode 100644 index 0000000000..9db6de2562 --- /dev/null +++ b/tests/test_filter_delayedgroup/results_true.dat @@ -0,0 +1,15 @@ +k-combined: +9.903196E-01 4.279617E-02 +tally 1: +8.141852E-04 +1.337187E-07 +4.849156E-03 +4.744020E-06 +4.460252E-03 +4.015453E-06 +1.028479E-02 +2.136252E-05 +5.002274E-03 +5.056965E-06 +1.974747E-03 +7.882970E-07 diff --git a/tests/test_filter_delayedgroup/test_filter_delayedgroup.py b/tests/test_filter_delayedgroup/test_filter_delayedgroup.py new file mode 100644 index 0000000000..bdad3cc958 --- /dev/null +++ b/tests/test_filter_delayedgroup/test_filter_delayedgroup.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterDelayedgroupTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='delayedgroup', + bins=(1, 2, 3, 4, 5, 6)) + tally = openmc.Tally(tally_id=1) + tally.add_filter(filt) + tally.add_score('delayed-nu-fission') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally) + + super(FilterDelayedgroupTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterDelayedgroupTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = FilterDelayedgroupTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_filter_distribcell/case-1/geometry.xml b/tests/test_filter_distribcell/case-1/geometry.xml index 507559615e..34e636e9fc 100644 --- a/tests/test_filter_distribcell/case-1/geometry.xml +++ b/tests/test_filter_distribcell/case-1/geometry.xml @@ -1,9 +1,9 @@ - - - + + + diff --git a/tests/test_filter_distribcell/case-2/geometry.xml b/tests/test_filter_distribcell/case-2/geometry.xml index b6797d65d0..e3aeedd645 100644 --- a/tests/test_filter_distribcell/case-2/geometry.xml +++ b/tests/test_filter_distribcell/case-2/geometry.xml @@ -1,15 +1,15 @@ - - - - - - - - - + + + + + + + + + 2 2 diff --git a/tests/test_filter_distribcell/case-3/geometry.xml b/tests/test_filter_distribcell/case-3/geometry.xml index b85dd04df9..f6f067aadd 100644 --- a/tests/test_filter_distribcell/case-3/geometry.xml +++ b/tests/test_filter_distribcell/case-3/geometry.xml @@ -21,50 +21,50 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + diff --git a/tests/test_filter_distribcell/case-4/geometry.xml b/tests/test_filter_distribcell/case-4/geometry.xml index 4c2a7fd5e4..c835218bc0 100644 --- a/tests/test_filter_distribcell/case-4/geometry.xml +++ b/tests/test_filter_distribcell/case-4/geometry.xml @@ -1,9 +1,9 @@ - - - - + + + + 1.0 3 diff --git a/tests/test_filter_distribcell/test_filter_distribcell.py b/tests/test_filter_distribcell/test_filter_distribcell.py index 492f03daef..872d29552b 100644 --- a/tests/test_filter_distribcell/test_filter_distribcell.py +++ b/tests/test_filter_distribcell/test_filter_distribcell.py @@ -1,9 +1,10 @@ #!/usr/bin/env python +import glob import hashlib +import os import sys - -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import * @@ -67,9 +68,8 @@ class DistribcellTestHarness(TestHarness): statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ 'exist.' - assert statepoint[0].endswith('binary') \ - or statepoint[0].endswith('h5'), \ - 'Statepoint file is not a binary or hdf5 file.' + assert statepoint[0].endswith('h5'), \ + 'Statepoint file is not a HDF5 file.' if tallies_out_present: assert os.path.exists(os.path.join(os.getcwd(), 'tallies.out')), \ 'Tally output file does not exist.' diff --git a/tests/test_filter_energy/geometry.xml b/tests/test_filter_energy/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_filter_energy/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_filter_energy/inputs_true.dat b/tests/test_filter_energy/inputs_true.dat new file mode 100644 index 0000000000..b120e9fd62 --- /dev/null +++ b/tests/test_filter_energy/inputs_true.dat @@ -0,0 +1 @@ +49835200052ee1a4c9583a7bb4e9430de7d01a6d7a8d4f63ae37be9bbac4fd8c7ed9135ecbc4ab4cb075fd4d77b322265783463dd07c127decceee8c9fe25bfd \ No newline at end of file diff --git a/tests/test_filter_energy/materials.xml b/tests/test_filter_energy/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_filter_energy/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_filter_energy/results_true.dat b/tests/test_filter_energy/results_true.dat index 9e3ab7965b..599e0bf888 100644 --- a/tests/test_filter_energy/results_true.dat +++ b/tests/test_filter_energy/results_true.dat @@ -1,11 +1,11 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -2.687671E+01 -1.475192E+02 -4.148025E+01 -3.443331E+02 -5.223662E+01 -5.466362E+02 -1.050254E+01 -2.218108E+01 +2.844008E+01 +1.619630E+02 +4.425619E+01 +3.938244E+02 +5.527425E+01 +6.120383E+02 +9.799897E+00 +1.957877E+01 diff --git a/tests/test_filter_energy/settings.xml b/tests/test_filter_energy/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_filter_energy/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_filter_energy/tallies.xml b/tests/test_filter_energy/tallies.xml deleted file mode 100644 index 69ce1d593b..0000000000 --- a/tests/test_filter_energy/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - total - - - \ No newline at end of file diff --git a/tests/test_filter_energy/test_filter_energy.py b/tests/test_filter_energy/test_filter_energy.py index 1777db993e..54d1dd4b7f 100644 --- a/tests/test_filter_energy/test_filter_energy.py +++ b/tests/test_filter_energy/test_filter_energy.py @@ -1,10 +1,30 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterEnergyTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='energy', + bins=(0.0, 0.253e-6, 1.0e-3, 1.0, 20.0)) + tally = openmc.Tally(tally_id=1) + tally.add_filter(filt) + tally.add_score('total') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally) + + super(FilterEnergyTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterEnergyTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = FilterEnergyTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_filter_energyout/geometry.xml b/tests/test_filter_energyout/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_filter_energyout/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_filter_energyout/inputs_true.dat b/tests/test_filter_energyout/inputs_true.dat new file mode 100644 index 0000000000..7096648e6c --- /dev/null +++ b/tests/test_filter_energyout/inputs_true.dat @@ -0,0 +1 @@ +183b4a06cbd0930cfa4f28d0c385cf3ae93ab97c171580c2ba9eec0e4b716102ad83f510d62258ef6769c446e72e1d5ba9f630b171ee239ec04c9bbd1e56742e \ No newline at end of file diff --git a/tests/test_filter_energyout/materials.xml b/tests/test_filter_energyout/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_filter_energyout/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_filter_energyout/results_true.dat b/tests/test_filter_energyout/results_true.dat index fa0bfa6466..814385d5a4 100644 --- a/tests/test_filter_energyout/results_true.dat +++ b/tests/test_filter_energyout/results_true.dat @@ -1,11 +1,11 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -2.740000E+01 -1.516786E+02 -4.163000E+01 -3.469463E+02 -5.041000E+01 -5.097599E+02 -6.990000E+00 -9.850700E+00 +2.842000E+01 +1.620214E+02 +4.361000E+01 +3.810139E+02 +5.297000E+01 +5.616595E+02 +6.530000E+00 +8.828900E+00 diff --git a/tests/test_filter_energyout/settings.xml b/tests/test_filter_energyout/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_filter_energyout/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_filter_energyout/tallies.xml b/tests/test_filter_energyout/tallies.xml deleted file mode 100644 index ebec597f13..0000000000 --- a/tests/test_filter_energyout/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - scatter - - - \ No newline at end of file diff --git a/tests/test_filter_energyout/test_filter_energyout.py b/tests/test_filter_energyout/test_filter_energyout.py index 1777db993e..43a8c7d5a9 100644 --- a/tests/test_filter_energyout/test_filter_energyout.py +++ b/tests/test_filter_energyout/test_filter_energyout.py @@ -1,10 +1,30 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterEnergyoutTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='energyout', + bins=(0.0, 0.253e-6, 1.0e-3, 1.0, 20.0)) + tally = openmc.Tally(tally_id=1) + tally.add_filter(filt) + tally.add_score('scatter') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally) + + super(FilterEnergyoutTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterEnergyoutTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = FilterEnergyoutTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_filter_group_transfer/geometry.xml b/tests/test_filter_group_transfer/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_filter_group_transfer/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_filter_group_transfer/inputs_true.dat b/tests/test_filter_group_transfer/inputs_true.dat new file mode 100644 index 0000000000..813bb43c18 --- /dev/null +++ b/tests/test_filter_group_transfer/inputs_true.dat @@ -0,0 +1 @@ +461a6a4ec3b0b6dc7199c09fa8f527e51cc7a1ea4281a708f8b7bcdbb12f7162027928dfcef68a24eaf6c06037a68e151df9aac9eac6ce56617466f2f5270b71 \ No newline at end of file diff --git a/tests/test_filter_group_transfer/materials.xml b/tests/test_filter_group_transfer/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_filter_group_transfer/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_filter_group_transfer/results_true.dat b/tests/test_filter_group_transfer/results_true.dat index 2222558273..c41451e776 100644 --- a/tests/test_filter_group_transfer/results_true.dat +++ b/tests/test_filter_group_transfer/results_true.dat @@ -1,54 +1,54 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -2.470000E+01 -1.233286E+02 +2.576000E+01 +1.331666E+02 0.000000E+00 0.000000E+00 7.000000E-02 -2.100000E-03 +1.300000E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -8.590851E-01 -1.552999E-01 +1.050675E+00 +2.274991E-01 0.000000E+00 0.000000E+00 -2.474615E+00 -1.227479E+00 -2.700000E+00 -1.469800E+00 +2.070821E+00 +8.886068E-01 +2.660000E+00 +1.422000E+00 0.000000E+00 0.000000E+00 -3.712000E+01 -2.758636E+02 +3.897000E+01 +3.042635E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.370712E-01 -2.596756E-02 +4.352932E-01 +4.705717E-02 0.000000E+00 0.000000E+00 -9.771334E-01 -1.963983E-01 +1.018668E+00 +2.090017E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.440000E+00 -3.947400E+00 +4.570000E+00 +4.182700E+00 0.000000E+00 0.000000E+00 -4.688000E+01 -4.409726E+02 -2.867366E-02 -2.783031E-04 +4.968000E+01 +4.940534E+02 +6.537406E-02 +1.230788E-03 0.000000E+00 0.000000E+00 -1.080794E-01 -2.580055E-03 +8.678070E-02 +2.482037E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -57,11 +57,11 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.530000E+00 -2.494900E+00 -1.572766E-01 -5.137814E-03 -6.990000E+00 -9.850700E+00 -3.134136E-01 -2.138680E-02 +3.290000E+00 +2.178900E+00 +1.610879E-01 +5.883677E-03 +6.530000E+00 +8.828900E+00 +3.151783E-01 +2.052521E-02 diff --git a/tests/test_filter_group_transfer/settings.xml b/tests/test_filter_group_transfer/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_filter_group_transfer/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_filter_group_transfer/tallies.xml b/tests/test_filter_group_transfer/tallies.xml deleted file mode 100644 index 64a6fa5e10..0000000000 --- a/tests/test_filter_group_transfer/tallies.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - scatter nu-fission - - - \ No newline at end of file diff --git a/tests/test_filter_group_transfer/test_filter_group_transfer.py b/tests/test_filter_group_transfer/test_filter_group_transfer.py index 1777db993e..cbea5e0a7f 100644 --- a/tests/test_filter_group_transfer/test_filter_group_transfer.py +++ b/tests/test_filter_group_transfer/test_filter_group_transfer.py @@ -1,10 +1,34 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterGroupTransferTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt1 = openmc.Filter(type='energy', + bins=(0.0, 0.253e-6, 1.0e-3, 1.0, 20.0)) + filt2 = openmc.Filter(type='energyout', + bins=(0.0, 0.253e-6, 1.0e-3, 1.0, 20.0)) + tally = openmc.Tally(tally_id=1) + tally.add_filter(filt1) + tally.add_filter(filt2) + tally.add_score('scatter') + tally.add_score('nu-fission') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally) + + super(FilterGroupTransferTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterGroupTransferTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = FilterGroupTransferTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_filter_material/geometry.xml b/tests/test_filter_material/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_filter_material/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_filter_material/inputs_true.dat b/tests/test_filter_material/inputs_true.dat new file mode 100644 index 0000000000..aaa4a4939f --- /dev/null +++ b/tests/test_filter_material/inputs_true.dat @@ -0,0 +1 @@ +2fbd0986abff08126680925284929cf67bdad0cd564775197b78065ce3b0e6ad8094f5ca4d14ea69347db69a6cdcc9796a095178ae9b14a927b101f32f3cd0ec \ No newline at end of file diff --git a/tests/test_filter_material/materials.xml b/tests/test_filter_material/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_filter_material/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_filter_material/results_true.dat b/tests/test_filter_material/results_true.dat index 3d15ea4322..d2b23e2901 100644 --- a/tests/test_filter_material/results_true.dat +++ b/tests/test_filter_material/results_true.dat @@ -1,11 +1,11 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -2.819256E+01 -1.591068E+02 -6.599750E+00 -8.721650E+00 -5.383171E+01 -5.950793E+02 -4.140672E+01 -3.649396E+02 +2.868239E+01 +1.648549E+02 +6.779424E+00 +9.202676E+00 +6.446222E+01 +8.387204E+02 +3.367496E+01 +2.349072E+02 diff --git a/tests/test_filter_material/settings.xml b/tests/test_filter_material/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_filter_material/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_filter_material/tallies.xml b/tests/test_filter_material/tallies.xml deleted file mode 100644 index 4b8d1ce8f0..0000000000 --- a/tests/test_filter_material/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - total - - - \ No newline at end of file diff --git a/tests/test_filter_material/test_filter_material.py b/tests/test_filter_material/test_filter_material.py index 1777db993e..8e42d8c9a2 100644 --- a/tests/test_filter_material/test_filter_material.py +++ b/tests/test_filter_material/test_filter_material.py @@ -1,10 +1,29 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterMaterialTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='material', bins=(1, 2, 3, 4)) + tally = openmc.Tally(tally_id=1) + tally.add_filter(filt) + tally.add_score('total') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally) + + super(FilterMaterialTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterMaterialTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = FilterMaterialTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_filter_mesh_2d/geometry.xml b/tests/test_filter_mesh_2d/geometry.xml index b85dd04df9..f6f067aadd 100644 --- a/tests/test_filter_mesh_2d/geometry.xml +++ b/tests/test_filter_mesh_2d/geometry.xml @@ -21,50 +21,50 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + diff --git a/tests/test_filter_mesh_2d/results_true.dat b/tests/test_filter_mesh_2d/results_true.dat index 01aea5afe2..21946086b9 100644 --- a/tests/test_filter_mesh_2d/results_true.dat +++ b/tests/test_filter_mesh_2d/results_true.dat @@ -1,5 +1,5 @@ k-combined: -1.093844E+00 1.626801E-02 +1.005983E+00 2.248579E-02 tally 1: 0.000000E+00 0.000000E+00 @@ -45,8 +45,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.751430E-01 -7.658753E-01 +3.228098E-02 +1.042062E-03 +3.222708E-01 +1.038585E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -73,14 +75,26 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +8.182335E-01 +3.748630E-01 +2.711997E-01 +5.338821E-02 +3.359680E-01 +5.168399E-02 0.000000E+00 0.000000E+00 -1.287286E-01 -1.657106E-02 -7.512292E-01 -1.499955E-01 -2.231206E+00 -1.531548E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.706070E-01 +1.373496E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -95,120 +109,106 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -6.855163E-02 -4.699326E-03 -6.967594E-02 -4.854737E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.993440E-02 -9.986884E-03 -1.978123E-01 -3.912972E-02 -8.758664E-02 -7.671419E-03 -4.204632E-01 -7.722514E-02 -2.486465E+00 -1.923132E+00 -1.697091E-01 -1.631523E-02 -0.000000E+00 -0.000000E+00 +3.931419E-01 +9.002841E-02 +1.092722E+00 +3.733055E-01 +2.384227E+00 +1.926937E+00 +9.101131E-01 +3.634496E-01 +3.284661E-01 +1.078900E-01 0.000000E+00 0.000000E+00 6.885295E-02 4.740728E-03 0.000000E+00 0.000000E+00 -6.175782E-01 -2.022672E-01 -1.204200E-02 -8.137904E-05 -2.136417E-01 -1.678274E-02 -2.932366E-01 -4.285227E-02 -6.387464E-01 -1.526040E-01 +2.419633E-02 +5.854622E-04 +9.286912E-02 +7.247209E-03 +5.629729E-01 +9.281109E-02 +7.345786E-01 +1.755550E-01 +1.219449E-01 +1.487057E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.062751E+00 -3.899247E-01 -1.264401E+00 -5.654864E-01 -1.615537E+00 -5.605431E-01 -4.267750E-01 -1.013728E-01 -2.024264E+00 -9.373843E-01 -1.122195E-01 -7.011342E-03 -8.223839E-01 -2.170405E-01 -1.239203E+00 -4.165595E-01 -1.169828E+00 -4.406334E-01 -1.373464E+00 -6.398480E-01 -2.824398E+00 -2.991665E+00 -6.158518E-01 -1.951901E-01 -7.188149E-01 -1.091668E-01 -7.595527E-01 -2.108412E-01 -5.784902E-01 -1.362812E-01 -7.167515E-01 -3.225769E-01 -2.081496E-02 -4.332627E-04 -9.212853E-01 -2.277306E-01 -1.266470E+00 -6.777774E-01 +1.983303E-01 +3.797884E-02 +4.840974E-02 +1.266547E-03 +1.183485E+00 +4.184814E-01 +3.027254E-01 +8.598449E-02 +9.889868E-01 +4.608531E-01 +8.698103E-01 +4.598559E-01 +1.332831E+00 +4.809984E-01 +1.564949E+00 +5.782651E-01 +1.143572E+00 +4.399439E-01 +1.326651E+00 +6.376565E-01 +1.716813E+00 +1.314280E+00 +7.673229E-01 +2.364966E-01 +2.539284E+00 +1.945563E+00 +1.263219E+00 +4.919339E-01 +5.430042E-01 +1.300266E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.553587E-01 +1.738170E-01 +2.048487E+00 +1.239856E+00 3.761862E-01 8.452912E-02 -1.350273E-02 -1.823238E-04 -3.348203E-01 -6.603737E-02 -2.382593E-01 -2.884302E-02 -1.548117E+00 -7.256982E-01 -9.635803E-01 -4.452538E-01 -1.030188E+00 -3.496685E-01 -7.053043E-01 -2.814424E-01 -1.260458E-01 -8.365754E-03 -1.484515E+00 -7.183840E-01 -1.887042E+00 -1.143800E+00 -3.798783E+00 -4.487065E+00 -2.274180E+00 -1.991784E+00 -1.903719E-01 -3.237886E-02 -0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 +9.675232E-02 +9.361012E-03 +2.319594E-01 +2.331698E-02 +1.573495E+00 +6.394722E-01 +4.432570E-01 +1.005943E-01 +9.353148E-01 +3.125416E-01 +8.359366E-01 +2.985072E-01 +1.657665E+00 +9.207020E-01 +3.737550E+00 +3.558505E+00 +1.742376E+00 +8.732217E-01 +5.153816E+00 +6.543973E+00 +1.653035E+00 +1.061068E+00 +9.963191E-01 +3.716347E-01 +2.282805E-01 +2.383414E-02 +8.749983E-01 +2.714666E-01 1.728411E-01 1.190218E-02 9.250054E-02 @@ -219,28 +219,28 @@ tally 1: 1.711154E-02 3.218800E-01 7.906855E-02 -9.721141E-01 -3.463278E-01 -8.364857E-01 -2.612988E-01 -6.317454E-01 -1.837078E-01 -2.134394E-01 -1.710045E-02 -3.743814E-02 -1.401614E-03 -1.314651E+00 -7.700853E-01 -7.389940E-01 -2.322340E-01 -6.147456E-01 -1.001719E-01 -3.157573E+00 -2.794673E+00 -6.671644E-01 -1.996570E-01 -0.000000E+00 -0.000000E+00 +1.057036E+00 +3.778638E-01 +9.231639E-01 +2.991795E-01 +3.375678E-01 +1.041383E-01 +1.181686E-01 +8.023920E-03 +4.912969E-01 +2.073894E-01 +9.395786E-01 +4.653730E-01 +6.998437E-01 +2.917085E-01 +3.074214E+00 +2.819088E+00 +2.570673E+00 +1.358321E+00 +1.108912E+00 +3.843307E-01 +4.950896E-02 +2.451137E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -255,24 +255,24 @@ tally 1: 7.670183E-03 0.000000E+00 0.000000E+00 -9.451595E-01 -2.560533E-01 -2.255990E+00 -1.237092E+00 -9.318430E-01 -2.664794E-01 -5.320317E-01 -2.267827E-01 -9.971891E-01 -5.070904E-01 -7.088786E-02 -5.025089E-03 -3.601108E-02 -1.296798E-03 -3.683352E+00 -3.243246E+00 -3.708141E+00 -3.629996E+00 +6.469411E-01 +1.789549E-01 +7.829878E-01 +2.033989E-01 +8.994770E-01 +2.351438E-01 +4.712797E-01 +7.213659E-02 +2.133532E+00 +9.765422E-01 +4.533607E-01 +1.511497E-01 +1.878729E+00 +2.099266E+00 +4.287190E+00 +4.748691E+00 +1.961229E+00 +1.085868E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -285,28 +285,28 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.238471E-01 -1.533812E-02 -2.580606E+00 -1.878196E+00 -2.843921E+00 -1.997749E+00 -1.145124E+00 -4.571704E-01 -1.135664E+00 -4.319756E-01 +1.061692E-01 +1.127190E-02 +1.912282E-01 +3.656822E-02 +3.289827E-01 +1.075283E-01 +1.750908E+00 +8.092384E-01 +2.156426E+00 +9.498067E-01 +1.480596E+00 +6.002164E-01 +3.249216E-01 +1.005106E-01 8.875810E-02 7.878000E-03 -7.494206E-02 -5.616313E-03 -1.007353E+00 -3.619658E-01 -1.649444E+00 -7.918743E-01 +2.458176E-01 +4.377921E-02 +2.766784E+00 +2.677426E+00 +2.703501E+00 +2.548083E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -319,28 +319,28 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.286351E-01 -1.805028E-01 -1.595058E+00 -6.351621E-01 -1.568755E+00 -6.468874E-01 -2.301331E+00 -1.845232E+00 -4.577930E-01 -1.589685E-01 +1.981880E-01 +3.927848E-02 +2.789456E-01 +5.304261E-02 +3.897689E-01 +9.413685E-02 +9.140885E-01 +2.822974E-01 +1.887726E+00 +7.592780E-01 +1.841624E+00 +1.680236E+00 +4.059938E-01 +1.562853E-01 2.897077E-01 8.393057E-02 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -1.772980E-01 -3.143459E-02 +2.445051E-01 +5.978276E-02 +2.234657E-01 +2.716625E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -353,24 +353,24 @@ tally 1: 0.000000E+00 4.783335E-02 2.288029E-03 -8.744336E-01 -2.611835E-01 -1.754522E+00 -1.459573E+00 -3.549403E-01 -6.365363E-02 -1.843261E+00 -9.517219E-01 -1.009556E+00 -4.611770E-01 -1.540221E+00 -7.611324E-01 -8.030427E-01 -2.255596E-01 +5.606011E-01 +1.607491E-01 +1.908325E+00 +1.505641E+00 +1.255795E-01 +1.541635E-02 +7.395548E-01 +2.274416E-01 +5.986733E-01 +9.576988E-02 +1.095026E+00 +4.872910E-01 +1.043470E+00 +3.153965E-01 1.004973E+00 6.046910E-01 -1.664911E-01 -2.771927E-02 +1.724071E-01 +2.775427E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -385,114 +385,114 @@ tally 1: 0.000000E+00 5.470039E-01 2.992133E-01 -4.902613E-01 -1.163360E-01 +4.313918E-01 +1.128703E-01 1.088037E+00 6.007745E-01 1.013469E+00 5.646900E-01 -5.529904E-01 -2.308161E-01 -3.523818E-01 -1.241729E-01 -2.031343E-01 -4.126355E-02 -2.664927E+00 -2.323850E+00 -2.601166E+00 -1.593528E+00 -1.726764E+00 -6.491827E-01 -7.083106E-02 -3.090181E-03 +4.738741E-01 +2.245567E-01 +6.086518E-02 +3.704570E-03 +1.126662E+00 +4.675322E-01 +1.008459E+00 +4.616352E-01 +1.309592E+00 +5.665211E-01 +1.334050E+00 +5.264819E-01 +7.324996E-01 +2.577124E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +3.227736E-01 +1.041828E-01 +9.218244E-01 +2.000301E-01 +2.119900E+00 +1.123846E+00 +4.366404E-02 +1.015133E-03 0.000000E+00 0.000000E+00 -2.213571E-01 -2.455759E-02 -1.471329E+00 -7.001977E-01 -6.348345E-01 -1.603344E-01 -0.000000E+00 -0.000000E+00 -7.240936E-01 -1.701659E-01 -1.280272E+00 -3.624213E-01 -9.794833E-01 -4.411714E-01 +2.309730E-01 +2.570742E-02 +1.270911E+00 +4.617932E-01 +1.107069E+00 +4.574496E-01 1.269137E-01 1.610709E-02 -1.120245E-01 -1.254949E-02 +2.207099E-01 +4.871286E-02 +9.075694E-02 +8.236821E-03 +1.046380E-01 +7.875036E-03 +2.836364E-01 +3.508209E-02 +4.509177E-01 +7.393615E-02 +1.077505E+00 +3.209541E-01 +1.204982E-02 +1.451982E-04 0.000000E+00 0.000000E+00 -8.072240E-01 -2.272369E-01 -3.032594E-01 -5.076695E-02 -7.265258E-01 -1.893670E-01 -2.902123E-01 -3.514713E-02 +0.000000E+00 +0.000000E+00 +2.502937E-01 +5.035125E-02 +1.367234E+00 +5.128884E-01 +5.563575E-01 +2.510519E-01 +3.174809E-01 +1.007941E-01 +9.152129E-01 +2.609325E-01 +9.040668E-01 +2.263595E-01 +7.868812E-01 +2.436310E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -8.608891E-02 -4.586038E-03 -1.319691E+00 -5.856361E-01 -7.752262E-01 -3.101466E-01 -2.606443E-01 -6.793546E-02 -3.686503E-01 -6.346661E-02 -6.935008E-01 -1.992259E-01 -1.591064E+00 -6.804860E-01 -2.418186E-01 -5.847626E-02 0.000000E+00 0.000000E+00 -5.946272E-02 -3.535814E-03 -3.120645E-02 -9.738427E-04 -7.515014E-02 -5.647544E-03 -8.673868E-01 -3.013632E-01 -2.427216E-01 -2.798481E-02 +3.390904E-01 +4.907887E-02 +6.577001E-01 +2.346964E-01 +1.023735E-01 +8.287220E-03 1.499600E-02 2.248801E-04 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079687E-01 -5.125039E-02 -1.649743E+00 -9.187008E-01 -8.924207E-01 -2.872456E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.137844E-02 -5.984482E-03 +1.395650E-01 +1.947839E-02 +1.040555E+00 +3.043523E-01 +1.426976E+00 +6.218295E-01 +8.342758E-01 +2.539692E-01 +3.101170E-01 +9.617255E-02 +6.319919E-02 +3.629541E-03 +1.292774E-01 +8.674372E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -515,14 +515,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.400001E-01 -3.766524E-01 -2.709865E+00 -1.701203E+00 -2.332406E-01 -4.591958E-02 -9.579949E-02 -9.177542E-03 +9.587357E-01 +4.992769E-01 +1.756477E+00 +7.884472E-01 +2.541705E-01 +4.325743E-02 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -551,10 +551,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.366480E-01 -8.328374E-02 -7.405305E-01 -5.483854E-01 +2.422913E-01 +5.870510E-02 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 diff --git a/tests/test_filter_mesh_2d/tallies.xml b/tests/test_filter_mesh_2d/tallies.xml index e046549de3..de3fa65535 100644 --- a/tests/test_filter_mesh_2d/tallies.xml +++ b/tests/test_filter_mesh_2d/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -182.07 -182.07 182.07 182.07 17 17 @@ -13,4 +13,4 @@ total - \ No newline at end of file + diff --git a/tests/test_filter_mesh_2d/test_filter_mesh_2d.py b/tests/test_filter_mesh_2d/test_filter_mesh_2d.py index 1777db993e..ed6addec45 100644 --- a/tests/test_filter_mesh_2d/test_filter_mesh_2d.py +++ b/tests/test_filter_mesh_2d/test_filter_mesh_2d.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_filter_mesh_3d/geometry.xml b/tests/test_filter_mesh_3d/geometry.xml index b85dd04df9..f6f067aadd 100644 --- a/tests/test_filter_mesh_3d/geometry.xml +++ b/tests/test_filter_mesh_3d/geometry.xml @@ -21,50 +21,50 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + diff --git a/tests/test_filter_mesh_3d/results_true.dat b/tests/test_filter_mesh_3d/results_true.dat index a67c77c034..239a9f01a6 100644 --- a/tests/test_filter_mesh_3d/results_true.dat +++ b/tests/test_filter_mesh_3d/results_true.dat @@ -1,5 +1,5 @@ k-combined: -1.093844E+00 1.626801E-02 +1.005983E+00 2.248579E-02 tally 1: 0.000000E+00 0.000000E+00 @@ -753,12 +753,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +3.228098E-02 +1.042062E-03 0.000000E+00 0.000000E+00 -4.083602E-01 -1.667580E-01 -4.667828E-01 -2.178862E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -789,6 +787,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +3.222708E-01 +1.038585E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1261,14 +1261,18 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.009463E-01 +4.037943E-02 +1.741795E-01 +3.033850E-02 +4.431077E-01 +1.023945E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.287286E-01 -1.657106E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1295,14 +1299,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.269274E-02 -5.149605E-04 -9.624622E-02 -9.263335E-03 -1.387020E-01 -1.620196E-02 -4.935882E-01 -8.865346E-02 +1.699856E-01 +1.749182E-02 +1.012141E-01 +1.024430E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1329,14 +1329,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.467757E+00 -6.282919E-01 -3.159457E-01 -4.516223E-02 -2.050369E-01 -3.908542E-02 -2.424662E-01 -5.878987E-02 +2.427282E-01 +4.346756E-02 +8.576175E-02 +6.594648E-03 +7.478060E-03 +5.592138E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1581,6 +1579,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +6.645869E-02 +4.416757E-03 +3.041483E-01 +9.250621E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1655,8 +1657,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -6.855163E-02 -4.699326E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1687,10 +1687,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -4.206687E-02 -1.769622E-03 -2.760907E-02 -7.622607E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1777,8 +1773,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -9.993440E-02 -9.986884E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1809,10 +1803,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.032141E-03 -6.451529E-05 -1.897802E-01 -3.601652E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1843,8 +1833,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.758664E-02 -7.671419E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1855,6 +1843,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +3.931419E-01 +9.002841E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1875,12 +1865,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -6.797399E-03 -4.620463E-05 -1.681205E-01 -1.033597E-02 -2.455452E-01 -4.194938E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1891,6 +1875,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.775906E-01 +3.153842E-02 +8.691809E-01 +2.255229E-01 +4.595089E-02 +2.111485E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1907,12 +1897,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.983445E-01 -1.408489E-02 -3.095279E-01 -4.471018E-02 -1.669298E+00 -8.584140E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.073032E-01 +5.796376E-03 +6.104378E-01 +1.438907E-01 +1.357192E+00 +7.800106E-01 3.092946E-01 4.828943E-02 0.000000E+00 @@ -1943,14 +1943,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.234167E-01 -1.523167E-02 -4.629242E-02 -1.083563E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +5.051275E-01 +9.608655E-02 +4.049856E-01 +1.640133E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2005,6 +2001,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.816781E-02 +3.300694E-04 +3.102983E-01 +9.628505E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2115,16 +2115,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.728847E-01 -2.988911E-02 -3.848345E-01 -1.480976E-01 -5.985907E-02 -3.583109E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +2.419633E-02 +5.854622E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2149,8 +2145,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.914572E-03 -1.532387E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2163,12 +2157,18 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.098236E-02 +1.206123E-04 +5.047052E-02 +2.547273E-03 0.000000E+00 0.000000E+00 -8.127433E-03 -6.605517E-05 0.000000E+00 0.000000E+00 +1.065577E-02 +7.244766E-05 +2.076046E-02 +4.309969E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2185,30 +2185,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.026040E-02 -4.104838E-04 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.065355E-02 -1.134982E-04 -2.799724E-03 -7.838457E-06 -0.000000E+00 -0.000000E+00 -1.799280E-01 -1.619126E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +1.209931E-01 +7.784762E-03 +1.059137E-01 +1.121770E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +1.883880E-01 +1.626283E-02 +1.476781E-01 +2.180883E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2231,10 +2225,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +5.464783E-03 +2.986386E-05 +4.827060E-01 +1.236578E-01 +2.938269E-02 +8.633425E-04 1.103939E-01 1.218681E-02 -1.828427E-01 -1.294521E-02 +1.066312E-01 +7.137023E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2265,10 +2265,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.028489E-01 -8.403390E-02 -3.358975E-01 -5.596699E-02 +6.448951E-03 +4.158897E-05 +1.154960E-01 +1.333932E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2353,10 +2353,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.843200E-01 -4.652895E-02 -7.784310E-01 -2.074140E-01 +1.230857E-01 +1.515010E-02 +7.524451E-02 +5.162294E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2387,10 +2387,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.580039E-01 -1.495118E-02 -1.106397E+00 -4.900888E-01 +5.738188E-03 +3.292680E-05 +1.158207E-02 +1.341443E-04 +3.108948E-02 +9.665557E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2419,14 +2421,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +8.670560E-01 +3.010896E-01 +2.777708E-01 +4.851013E-02 +3.865801E-02 +1.326182E-03 0.000000E+00 0.000000E+00 -6.311586E-01 -1.452469E-01 -8.935124E-01 -2.041594E-01 -9.086642E-02 -7.846733E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2453,8 +2455,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.240497E-01 -1.538832E-02 9.205825E-02 8.474722E-03 2.106671E-01 @@ -2487,12 +2487,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -6.706461E-01 -1.626955E-01 -9.690652E-01 -2.037373E-01 -1.260082E-01 -1.587806E-02 +2.518202E-01 +6.341342E-02 +3.500938E-01 +5.019217E-02 +1.285282E-01 +1.588441E-02 2.585446E-01 6.684532E-02 0.000000E+00 @@ -2523,8 +2523,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.960309E-02 -3.842813E-04 +3.653135E-01 +1.287514E-01 +2.216045E-03 +4.910856E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2543,10 +2545,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -9.261638E-02 -4.454613E-03 +5.022807E-01 +1.147015E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2577,12 +2577,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.905316E-02 -6.249402E-03 -6.679360E-01 -1.650894E-01 -7.539474E-02 -5.684366E-03 +0.000000E+00 +0.000000E+00 +1.172250E+00 +3.690965E-01 +1.605816E-01 +1.294116E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2613,10 +2613,10 @@ tally 1: 0.000000E+00 5.892971E-02 3.472710E-03 -1.107212E+00 -3.413570E-01 -7.306165E-02 -5.338004E-03 +1.338644E+00 +4.668912E-01 +1.673747E-01 +1.423295E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2627,8 +2627,8 @@ tally 1: 0.000000E+00 1.452260E-01 2.109060E-02 -6.184555E-01 -1.333723E-01 +5.921989E-01 +1.326829E-01 3.816328E-02 1.456436E-03 9.153520E-02 @@ -2663,8 +2663,8 @@ tally 1: 6.125553E-04 7.610286E-01 2.001560E-01 -4.985084E-01 -1.084317E-01 +4.516947E-01 +1.062402E-01 8.917764E-02 4.968510E-03 0.000000E+00 @@ -2693,24 +2693,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.736533E-01 -3.015548E-02 -1.425017E+00 -8.058899E-01 -9.850395E-01 -5.477477E-01 0.000000E+00 0.000000E+00 +1.101299E+00 +7.922298E-01 +4.529165E-02 +2.051333E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +5.702227E-01 +1.629185E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.406884E-01 -5.793092E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2727,28 +2725,26 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.047508E-02 -4.966737E-03 -7.482142E-02 -5.598244E-03 -1.212516E-02 -1.470196E-04 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.428465E-01 -5.897443E-02 0.000000E+00 0.000000E+00 -2.031988E-01 -4.128976E-02 -1.238475E-02 -1.533819E-04 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +2.749741E-01 +3.841679E-02 +1.876567E-01 +2.180115E-02 +4.802267E-02 +2.306177E-03 +2.219757E-01 +2.083367E-02 +3.469381E-02 +1.203661E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2763,26 +2759,26 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.198784E-01 -1.437083E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.380516E-01 -4.157334E-02 -7.271496E-02 -5.287466E-03 -1.248706E-01 -9.290399E-03 -6.329934E-02 -4.006806E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +9.220451E-03 +8.501673E-05 +2.421186E-01 +2.296140E-02 +5.301518E-01 +1.266721E-01 +1.676517E+00 +1.032348E+00 +8.127651E-02 +4.329985E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2805,12 +2801,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.932483E-01 -3.411782E-02 -7.125726E-02 -5.077597E-03 -1.721584E-01 -1.580114E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.516265E-01 +6.305270E-02 +3.999873E-02 +1.599899E-03 +5.487047E-01 +1.292105E-01 3.228887E-01 1.042571E-01 0.000000E+00 @@ -2839,12 +2839,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.935296E-02 -3.745370E-04 -4.914514E-02 -2.415245E-03 -3.076980E-01 -3.868177E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.407100E-01 +4.223910E-02 2.022942E-01 4.092294E-02 0.000000E+00 @@ -2875,10 +2875,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.698116E-02 -5.106926E-03 -6.397704E-01 -2.487693E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2901,10 +2897,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.219865E-02 -1.488072E-04 -8.616309E-03 -7.424078E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2931,12 +2923,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.457861E-01 -1.063058E-02 -7.360906E-01 -1.562063E-01 -3.940865E-02 -1.553041E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2947,6 +2933,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +7.553587E-01 +1.738170E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2965,12 +2953,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.452849E-02 -4.309152E-03 -3.655566E-01 -3.753615E-02 -8.473380E-02 -7.179817E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2981,6 +2963,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +0.000000E+00 +0.000000E+00 +6.145563E-02 +3.776795E-03 +2.005189E-01 +2.429212E-02 +5.673596E-01 +1.649938E-01 +4.875014E-01 +2.376576E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 7.157679E-01 3.770273E-01 1.588325E-02 @@ -3031,8 +3031,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.350273E-02 -1.823238E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3065,8 +3063,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.380680E-01 -5.667635E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3121,10 +3121,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.227568E-02 -6.769287E-03 -2.170015E-02 -4.708966E-04 +0.000000E+00 +0.000000E+00 +9.767592E-02 +5.284927E-03 1.342835E-01 1.803205E-02 0.000000E+00 @@ -3155,12 +3155,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.298723E-01 -8.434738E-03 -1.192701E+00 -5.059301E-01 -5.555691E-02 -3.086570E-03 +6.575074E-02 +4.323159E-03 +1.123042E+00 +4.745625E-01 +2.147144E-01 +2.841768E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3169,10 +3169,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.271892E-02 -5.288041E-03 -6.134910E-01 -2.517865E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.138141E-01 +1.295364E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3189,12 +3191,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -2.698309E-01 -5.659690E-02 -7.539545E-03 -5.684475E-05 +2.478967E-01 +2.397512E-02 +8.154628E-02 +5.533841E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3203,12 +3203,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.063682E-01 -2.953689E-02 -7.099357E-01 -1.432662E-01 -2.190760E-02 -4.799429E-04 +1.673829E-01 +2.801704E-02 +6.238670E-01 +1.323614E-01 +1.087831E-01 +8.027300E-03 3.528173E-02 1.244801E-03 0.000000E+00 @@ -3221,8 +3221,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.669518E-02 -3.214344E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3239,10 +3239,10 @@ tally 1: 0.000000E+00 3.125593E-03 9.769332E-06 -5.487602E-01 -2.355803E-01 -7.840909E-02 -6.147986E-03 +5.982046E-01 +2.380250E-01 +1.595969E-01 +1.273945E-02 7.500945E-02 5.626417E-03 0.000000E+00 @@ -3273,22 +3273,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -4.849728E-02 -2.351986E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +2.004455E-02 +4.017842E-04 +1.241994E+00 +5.276343E-01 +3.956269E-01 +6.857794E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -6.355630E-02 -4.039404E-03 -1.399218E-02 -1.957812E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3313,18 +3313,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.567716E-02 -2.424343E-03 -3.815100E-01 -7.061468E-02 -1.998464E-01 -3.993860E-02 -2.952749E-01 -4.970731E-02 -3.559995E-01 -4.240327E-02 -4.275883E-02 -1.828318E-03 +2.517820E-01 +4.088147E-02 +5.984204E-01 +1.119676E-01 +1.600304E+00 +1.060307E+00 +6.251595E-01 +1.631053E-01 +5.084364E-01 +8.750385E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3349,18 +3347,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.056649E-01 -2.528092E-02 -2.212242E-01 -4.870093E-02 -8.268043E-01 -2.499121E-01 -5.858178E-01 -1.482815E-01 -4.753061E-02 -2.259158E-03 0.000000E+00 0.000000E+00 +1.482851E-01 +2.198847E-02 +8.661057E-02 +3.979426E-03 +5.328694E-01 +1.185445E-01 +9.819716E-02 +6.261752E-03 +1.971175E-01 +3.885531E-02 +5.055466E-01 +1.332461E-01 +1.737497E-01 +3.018896E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3381,22 +3383,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.448612E-01 +3.179981E-02 +1.336292E+00 +6.509631E-01 +1.788953E+00 +9.402141E-01 +6.484030E-01 +1.952075E-01 +1.239995E-01 +9.457065E-03 +5.379761E-01 +9.948097E-02 +3.422476E-01 +3.688467E-02 +1.310833E-01 +9.116867E-03 0.000000E+00 0.000000E+00 -1.275494E-01 -1.626884E-02 -8.930936E-01 -4.412573E-01 -1.069465E+00 -3.083849E-01 -5.312952E-01 -1.686403E-01 -3.756270E-01 -7.982176E-02 -6.071797E-01 -1.008227E-01 -1.945731E-01 -2.288397E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3415,24 +3419,20 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -2.147490E-02 -4.611712E-04 -3.020948E-01 -4.980152E-02 -6.199369E-01 -1.339903E-01 -6.953972E-01 -2.667255E-01 -5.032688E-01 -1.089400E-01 -8.876085E-02 -2.663780E-03 +1.452794E-01 +7.962998E-03 +4.950124E-01 +1.019817E-01 +5.154252E-01 +1.349222E-01 +2.369650E-01 +5.615241E-02 +3.458235E-02 +1.195939E-03 1.129905E-02 1.276685E-04 -3.194782E-02 -1.020663E-03 +2.144713E-01 +2.715780E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3453,18 +3453,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -4.936255E-03 -2.436661E-05 -1.854356E-01 -3.062993E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3475,6 +3463,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +6.439196E-02 +4.146324E-03 +9.319271E-01 +3.289332E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3483,6 +3475,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +8.887911E-02 +4.077886E-03 +1.394014E-01 +1.214028E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3513,6 +3509,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +3.093347E-01 +4.640925E-02 +5.656636E-01 +1.123158E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3735,10 +3735,10 @@ tally 1: 0.000000E+00 1.203590E-02 1.448628E-04 -9.089783E-01 -3.025426E-01 -4.101062E-02 -1.363081E-03 +8.166865E-01 +2.864876E-01 +2.182247E-01 +3.276791E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3769,10 +3769,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.394140E-02 -5.731908E-04 -2.225881E-01 -4.954545E-02 +3.880416E-02 +7.940924E-04 +2.944035E-01 +5.470290E-02 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3781,8 +3783,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.901226E-02 -3.614661E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3797,10 +3797,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.232218E-03 -2.737611E-05 -2.699331E-01 -7.286389E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3833,8 +3833,8 @@ tally 1: 0.000000E+00 3.625873E-02 1.314696E-03 -9.527085E-02 -9.076535E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3859,14 +3859,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +1.282000E-01 +1.643523E-02 +8.992357E-04 +8.086249E-07 +4.549792E-02 +2.070061E-03 +2.792616E-01 +7.798705E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3891,16 +3891,16 @@ tally 1: 2.325049E-04 0.000000E+00 0.000000E+00 -5.591708E-01 -3.126720E-01 -3.457017E-02 -1.195097E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +2.186688E-01 +4.781605E-02 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3929,18 +3929,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.005099E-01 -4.873543E-02 -2.482142E-01 -4.941861E-02 -1.464043E-02 -2.143420E-04 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +2.799587E-02 +7.837689E-04 0.000000E+00 0.000000E+00 +2.165781E-01 +4.136640E-02 +1.206583E-01 +1.455843E-02 +3.350979E-02 +1.122906E-03 +1.254721E-01 +1.574324E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3957,6 +3961,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.255610E-02 +1.576557E-04 +2.059029E-01 +2.931063E-02 +9.625207E-02 +9.264462E-03 +4.926052E-01 +1.231087E-01 +3.607423E-01 +6.495313E-02 +2.101048E-01 +2.385810E-02 +7.843494E-01 +1.955825E-01 +9.077784E-01 +3.297447E-01 +3.922359E-03 +1.538490E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3965,18 +3987,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.139114E-01 -1.297580E-02 -1.219324E-01 -1.125290E-02 -6.096339E-02 -3.716535E-03 -2.370045E-02 -5.617113E-04 -2.338106E-01 -2.733856E-02 -6.042735E-02 -3.651465E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3987,8 +3997,20 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +6.913074E-02 +1.799353E-03 +1.249107E-02 +1.560268E-04 0.000000E+00 0.000000E+00 +1.115404E+00 +4.366528E-01 +3.732357E-01 +4.158215E-02 +3.846227E-01 +8.126419E-02 +6.157885E-01 +1.590298E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -3997,22 +4019,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.026371E-02 -4.106181E-04 -1.407747E-01 -1.661272E-02 -2.901913E-01 -8.421099E-02 -1.716410E+00 -1.502067E+00 -2.139592E-01 -1.215205E-02 -3.926381E-01 -8.132843E-02 -2.213252E-01 -2.664541E-02 -1.620099E-01 -2.624722E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4031,22 +4037,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.163882E-01 -1.978213E-01 -4.192042E-02 -1.757322E-03 -0.000000E+00 -0.000000E+00 -8.855834E-03 -7.842579E-05 -0.000000E+00 -0.000000E+00 +5.663121E-01 +1.953137E-01 +4.644811E-01 +1.590726E-01 +5.000400E-02 +1.273713E-03 +2.811483E-02 +7.904436E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4055,6 +4053,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +4.950896E-02 +2.451137E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4339,10 +4339,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.248694E-01 -4.178173E-02 -2.015109E-01 -2.180554E-02 +0.000000E+00 +0.000000E+00 +1.281618E-01 +1.642545E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4373,12 +4373,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.775166E-01 -3.538689E-01 -1.077083E+00 -2.861243E-01 -3.389587E-01 -8.732863E-02 +1.429077E-02 +2.042262E-04 +5.105813E-01 +9.939542E-02 +1.956841E-01 +3.829226E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4407,14 +4407,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.278622E-01 -9.618710E-03 -4.878786E-01 -1.035002E-01 -2.623630E-01 -2.385512E-02 -5.373920E-02 -2.887901E-03 +2.524256E-01 +3.390159E-02 +5.341258E-01 +7.612387E-02 +1.129256E-01 +5.367542E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4439,16 +4439,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -7.796193E-03 -6.078062E-05 -2.370024E-01 -5.617015E-02 -2.378547E-01 -5.657486E-02 -0.000000E+00 -0.000000E+00 +1.789538E-02 +3.202447E-04 +1.070161E-01 +1.145246E-02 +2.004171E-01 +4.016700E-02 +9.277615E-02 +4.350522E-03 +3.796585E-03 +1.441406E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4475,10 +4475,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.812701E-02 +7.911289E-04 0.000000E+00 0.000000E+00 -4.102160E-02 -1.682772E-03 +7.255598E-01 +2.637695E-01 +4.236781E-01 +1.206021E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4507,10 +4511,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.088786E-02 -5.025089E-03 0.000000E+00 0.000000E+00 +3.455666E-01 +1.088929E-01 +1.077941E-01 +5.813092E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4535,8 +4541,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +8.759532E-03 +7.672939E-05 +3.873698E-01 +1.500554E-01 +3.320720E-02 +5.664804E-04 +9.751133E-01 +4.762440E-01 +3.549373E-01 +1.259805E-01 0.000000E+00 0.000000E+00 +4.558589E-03 +2.078073E-05 +1.147837E-01 +1.317530E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4551,12 +4571,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.601108E-02 -1.296798E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +1.491942E-01 +1.942842E-02 +1.215608E-02 +7.465030E-05 +9.749153E-01 +3.525441E-01 +1.238276E+00 +4.724746E-01 +7.559328E-01 +1.539006E-01 +7.550630E-01 +2.671451E-01 +4.016529E-01 +1.049033E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4577,24 +4609,20 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.772849E-01 -3.142995E-02 -1.629085E+00 -7.553358E-01 -5.130574E-01 -1.026482E-01 -5.456703E-01 -1.139540E-01 -5.551969E-01 -1.452833E-01 -2.630569E-01 -2.654789E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +1.915923E-01 +1.106962E-02 +1.039274E+00 +3.820648E-01 +6.748249E-01 +1.513006E-01 +5.553735E-02 +3.084397E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4611,18 +4639,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.711181E-02 -7.588468E-03 -2.593229E-01 -4.929782E-02 -2.365670E-01 -1.635697E-02 -1.481640E+00 -5.785514E-01 -1.000401E+00 -2.814448E-01 -6.430985E-01 -1.924484E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4817,6 +4833,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.061692E-01 +1.127190E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4849,6 +4867,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.912282E-01 +3.656822E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4899,6 +4919,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +3.289827E-01 +1.075283E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4919,10 +4941,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.624881E-02 -2.640238E-04 -1.075983E-01 -1.157740E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4935,6 +4953,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.320797E+00 +4.972727E-01 +4.301105E-01 +6.331514E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4949,16 +4971,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.629487E-02 -3.169112E-03 -8.055202E-02 -6.488629E-03 -1.251664E+00 -7.810326E-01 -1.181564E+00 -3.437055E-01 -1.053167E-02 -1.109161E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4971,6 +4983,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +4.915487E-02 +2.416202E-03 +9.120705E-02 +8.318727E-03 +1.320105E+00 +4.411682E-01 +6.959590E-01 +2.389648E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -4983,26 +5003,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -6.454179E-02 -2.652959E-03 -5.029692E-01 -1.783517E-01 -1.339070E+00 -4.343746E-01 -8.199937E-01 -2.745378E-01 -1.173457E-01 -1.377002E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.736827E-02 -2.243753E-03 5.662623E-02 3.206529E-03 0.000000E+00 @@ -5017,16 +5017,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.166586E-02 +1.360923E-04 +1.891160E-02 +3.576487E-04 +1.256901E+00 +4.792247E-01 +1.364915E-01 +1.696517E-02 0.000000E+00 0.000000E+00 -1.927614E-01 -2.918695E-02 -7.330554E-01 -1.766129E-01 -1.008246E-01 -7.669486E-03 -1.448854E-02 -2.099179E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5055,12 +5055,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -6.565334E-01 -2.186541E-01 -5.729858E-02 -3.283127E-03 -9.691043E-02 -9.391631E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5123,14 +5123,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +6.925951E-02 +4.796880E-03 +1.765581E-01 +2.014257E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -7.494206E-02 -5.616313E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5155,18 +5157,18 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.724677E-02 -3.277192E-03 -1.383438E-01 -1.452928E-02 -2.848872E-02 -8.116069E-04 -3.524549E-01 -5.552654E-02 -4.295071E-01 -9.355140E-02 -1.311425E-03 -1.719836E-06 +1.007236E-01 +1.014525E-02 +3.069376E-01 +6.982061E-02 +1.339942E+00 +5.632235E-01 +8.027545E-01 +2.263816E-01 +1.881835E-01 +3.541303E-02 +2.824222E-02 +7.976228E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5189,26 +5191,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.834417E-02 -2.211153E-03 -1.613421E-01 -2.257097E-02 -1.472879E-01 -2.169372E-02 -4.810374E-01 -8.988575E-02 -6.467051E-01 -1.822459E-01 -1.547275E-01 -2.394060E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 0.000000E+00 0.000000E+00 +6.475515E-01 +1.949499E-01 +8.916929E-01 +2.187649E-01 +9.737449E-01 +4.547148E-01 +1.905118E-01 +3.629474E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5419,6 +5411,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.851330E-02 +8.130086E-04 +1.696747E-01 +2.878950E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5449,6 +5445,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.753509E-02 +7.581810E-04 +2.514105E-01 +5.075004E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5495,12 +5495,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.687121E-01 -2.627261E-02 -1.004106E-01 -1.008228E-02 -3.964673E-02 -1.571863E-03 +0.000000E+00 +0.000000E+00 +6.990313E-02 +4.886448E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5527,14 +5527,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.594872E-01 -9.743264E-02 -8.625384E-01 -2.783049E-01 -3.514218E-03 -1.234973E-05 -1.894941E-01 -2.742554E-02 +6.620581E-01 +1.938858E-01 +4.607570E-02 +1.247203E-03 +0.000000E+00 +0.000000E+00 +2.593018E-02 +6.723742E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5545,8 +5545,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.861976E-01 -3.466955E-02 +3.904410E-02 +1.524442E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5561,12 +5561,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.293501E-01 -5.455683E-02 -2.937497E-01 -8.628891E-02 -6.693709E-01 -1.892115E-01 +3.389223E-01 +5.464846E-02 +1.061647E-01 +1.127094E-02 +1.313508E+00 +4.346493E-01 4.161910E-02 1.732150E-03 0.000000E+00 @@ -5579,8 +5579,8 @@ tally 1: 0.000000E+00 4.016283E-01 1.613053E-01 -4.606785E-01 -1.064675E-01 +5.599819E-01 +9.812234E-02 5.139185E-01 1.322866E-01 2.373992E-01 @@ -5597,10 +5597,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.911517E-01 -3.262245E-02 -3.678584E-01 -7.759535E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5631,8 +5631,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.179923E-02 -2.683160E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5735,6 +5735,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.532915E-01 +2.349830E-02 +0.000000E+00 +0.000000E+00 +2.637807E-03 +6.958026E-06 +9.521605E-03 +9.066095E-05 +7.905417E-02 +6.249562E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5763,20 +5773,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.772980E-01 -3.143459E-02 -0.000000E+00 -0.000000E+00 +5.147382E-02 +2.649554E-03 +1.719918E-01 +1.490049E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -5989,12 +5989,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.231433E-01 -5.413470E-02 -3.993293E-01 -6.467221E-02 -1.519610E-01 -1.155574E-02 +1.305564E-01 +1.704497E-02 +3.518664E-01 +6.212556E-02 +7.817833E-02 +6.111852E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6025,10 +6025,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.649249E-01 -3.073604E-02 -8.553717E-01 -3.211418E-01 +4.740424E-01 +8.028915E-02 +8.000570E-01 +3.176809E-01 5.666391E-01 2.831913E-01 1.643713E-02 @@ -6073,10 +6073,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.186326E-01 -1.190957E-02 -1.107282E-01 -1.226074E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6095,6 +6091,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +9.873816E-02 +9.749225E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 6.179053E-03 @@ -6105,12 +6105,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.475983E-02 -2.178526E-04 -1.747711E+00 -8.535011E-01 -7.461108E-02 -5.566814E-03 +1.154173E-01 +1.332115E-02 +5.192203E-01 +1.359491E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6123,28 +6121,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.833423E-01 -3.201970E-02 -1.016493E-02 -1.033258E-04 -3.086254E-01 -9.524964E-02 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.668929E-02 -7.417426E-04 -1.031629E-01 -8.133494E-03 -2.133233E-01 -4.550684E-02 +3.643669E-01 +3.773661E-02 +1.333650E-01 +1.778623E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6157,28 +6139,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.950700E-01 -3.542385E-02 -1.821781E-01 -3.288596E-02 -2.994706E-01 -3.126060E-02 -3.853993E-01 -1.485326E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.946618E-02 -3.536227E-03 -6.995394E-02 -4.893554E-03 -3.103240E-01 -5.643704E-02 +3.057922E-02 +4.821714E-04 +2.611439E-02 +4.539126E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6189,16 +6153,52 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.934409E-02 -3.268161E-03 -2.618772E-02 -6.857965E-04 0.000000E+00 0.000000E+00 -1.910915E-01 -1.213214E-02 -5.264194E-01 -1.438040E-01 +0.000000E+00 +0.000000E+00 +4.328371E-01 +6.083581E-02 +3.822069E-02 +1.398374E-03 +1.903328E-01 +2.231214E-02 +3.952764E-01 +1.486302E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.256222E-02 +1.578095E-04 +9.794148E-02 +9.592534E-03 +1.849303E-01 +1.553794E-02 +7.480357E-01 +1.929178E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6529,8 +6529,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.886952E-02 -3.465621E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6653,8 +6653,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.911625E-02 -6.259380E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6669,14 +6667,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.747648E-02 -1.404486E-03 -9.038474E-02 -8.169402E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +6.086518E-02 +3.704570E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6685,10 +6681,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.907522E-01 -3.638640E-02 -3.376837E-02 -1.140303E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6703,10 +6695,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.260430E-02 -1.063040E-03 -4.728569E-02 -2.235937E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6715,14 +6703,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +4.249148E-02 +1.805526E-03 +1.045383E+00 +4.214718E-01 +3.878770E-02 +1.504486E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -8.942084E-02 -7.996086E-03 -3.382348E-02 -1.144027E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6737,10 +6727,20 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.663872E-01 -5.237415E-01 -1.495861E+00 -7.117933E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.784801E-02 +7.755114E-04 +6.779315E-01 +3.352682E-01 3.026790E-01 9.161460E-02 0.000000E+00 @@ -6767,16 +6767,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -6.127783E-01 -2.689445E-01 -6.677764E-01 -2.034903E-01 +1.879990E-01 +2.203070E-02 0.000000E+00 0.000000E+00 -1.272042E+00 -5.287947E-01 -4.856872E-02 -2.358920E-03 +0.000000E+00 +0.000000E+00 +9.811002E-01 +4.685901E-01 +1.404927E-01 +1.080893E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6801,12 +6801,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -6.244965E-01 -1.453503E-01 -7.596171E-01 -1.897008E-01 -1.137881E-01 -1.294772E-02 +7.572692E-01 +2.087347E-01 +2.362405E-01 +4.910426E-02 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 1.965530E-01 @@ -6835,12 +6835,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -3.595460E-02 -1.292733E-03 -1.651469E-02 -2.727349E-04 +1.751268E-03 +3.066940E-06 +1.553462E-01 +2.413243E-02 +1.672350E-01 +2.796753E-02 0.000000E+00 0.000000E+00 1.836178E-02 @@ -6941,6 +6941,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +3.696487E-02 +1.366401E-03 +2.858087E-01 +8.168661E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -6969,14 +6973,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.052881E-01 -1.108559E-02 -0.000000E+00 -0.000000E+00 +1.258698E-01 +1.150919E-02 +6.798857E-01 +1.661025E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7007,12 +7007,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.003097E-01 -2.774596E-01 -5.697479E-01 -1.238519E-01 -1.088816E-02 -1.185520E-04 +1.008727E+00 +3.651038E-01 +9.120679E-01 +2.558101E-01 +8.721740E-03 +7.606874E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7039,16 +7039,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.182615E-02 -2.685950E-03 -2.603394E-01 -5.501423E-02 -2.189565E-01 -1.689961E-02 -1.037124E-01 -1.075626E-02 0.000000E+00 0.000000E+00 +2.739345E-02 +7.504010E-04 +1.627060E-02 +2.647323E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7107,12 +7103,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.145166E-01 -1.639307E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +2.309730E-01 +2.570742E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7141,8 +7137,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.237360E+00 -3.492227E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.115905E+00 +4.082126E-01 2.502204E-02 6.261023E-04 0.000000E+00 @@ -7247,12 +7247,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -9.753553E-02 -9.513180E-03 -1.448897E-02 -2.099304E-04 0.000000E+00 0.000000E+00 +2.207099E-01 +4.871286E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7285,6 +7283,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +9.075694E-02 +8.236821E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7315,10 +7315,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.767451E-02 +3.123882E-04 +8.696348E-02 +7.562648E-03 0.000000E+00 0.000000E+00 -8.072240E-01 -2.272369E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7345,16 +7347,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.679628E-02 -1.915958E-04 -2.060666E-01 -4.246344E-02 -9.954401E-04 -9.909010E-07 -7.940105E-02 -6.304526E-03 0.000000E+00 0.000000E+00 +1.690390E-01 +2.753878E-02 +1.145975E-01 +7.543314E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7379,14 +7377,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.430716E-01 -3.335909E-02 -4.349688E-01 -6.259047E-02 -4.848533E-02 -1.782050E-03 0.000000E+00 0.000000E+00 +2.712297E-01 +3.081804E-02 +1.728614E-01 +2.076746E-02 +6.826625E-03 +4.660281E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7415,10 +7413,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.242016E-02 -5.026638E-04 -2.677921E-01 -2.943321E-02 +2.649622E-02 +7.020499E-04 +4.161446E-01 +8.806248E-02 +6.348647E-01 +9.989011E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7451,6 +7451,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.204982E-02 +1.451982E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7551,12 +7553,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.608891E-02 -4.586038E-03 +2.282300E-01 +4.986445E-02 +2.206365E-02 +4.868048E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7587,10 +7587,10 @@ tally 1: 0.000000E+00 1.875562E-01 3.517735E-02 -5.878488E-01 -1.352380E-01 -5.442859E-01 -1.595781E-01 +7.738485E-01 +2.045432E-01 +4.058292E-01 +8.243188E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7623,16 +7623,18 @@ tally 1: 0.000000E+00 4.994213E-01 2.494217E-01 +2.744213E-02 +7.530707E-04 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +2.949405E-02 +7.018464E-04 0.000000E+00 0.000000E+00 -2.758048E-01 -6.072497E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7659,14 +7661,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +8.459022E-03 +7.155505E-05 +3.090219E-01 +9.549453E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.606443E-01 -6.793546E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7681,12 +7685,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +7.226097E-01 +1.395661E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.686503E-01 -6.346661E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7715,14 +7719,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.316493E-01 +1.591047E-02 +6.576990E-01 +1.877309E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.533157E-01 -1.071208E-02 -5.401851E-01 -1.739213E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7749,14 +7753,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +4.546941E-01 +7.107193E-02 +3.321871E-01 +6.515778E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.221279E+00 -4.624743E-01 -3.697846E-01 -6.689364E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7787,10 +7791,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.040339E-01 -4.162983E-02 -3.778476E-02 -1.427688E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7861,8 +7861,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.946272E-02 -3.535814E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7895,8 +7893,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.120645E-02 -9.738427E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7931,6 +7927,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +8.249399E-02 +4.667888E-03 +1.814462E-01 +3.292273E-02 7.515014E-02 5.647544E-03 0.000000E+00 @@ -7957,14 +7957,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.638111E-01 -6.959629E-02 +0.000000E+00 +0.000000E+00 3.109046E-01 8.622176E-02 -2.304832E-01 -3.175419E-02 -6.218789E-02 -3.867333E-03 +2.380422E-01 +3.181133E-02 +1.087532E-01 +6.035666E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -7995,8 +7995,8 @@ tally 1: 0.000000E+00 5.246408E-03 2.752480E-05 -1.779567E-01 -2.094888E-02 +3.760855E-02 +1.251291E-03 5.951856E-02 3.037461E-03 0.000000E+00 @@ -8141,6 +8141,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.395650E-01 +1.947839E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8163,18 +8165,20 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.822292E-01 +4.829456E-02 +6.080756E-02 +3.418907E-03 0.000000E+00 0.000000E+00 -7.333695E-02 -4.658577E-03 -2.790184E-02 -6.568068E-04 -0.000000E+00 -0.000000E+00 -1.525932E-01 -2.328469E-02 +1.804108E-01 +2.405851E-02 5.413665E-02 2.930777E-03 +4.041026E-01 +8.374291E-02 +5.886833E-02 +3.465481E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8197,20 +8201,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +7.093664E-02 +5.032006E-03 5.703113E-02 3.252549E-03 -8.140441E-01 -2.724079E-01 -5.579561E-01 -2.869147E-01 -2.207115E-01 -4.871356E-02 +7.402747E-01 +2.678271E-01 +2.389658E-02 +5.209213E-04 +5.348373E-01 +8.455667E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8239,10 +8239,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.039206E-01 -1.196352E-01 -3.885001E-01 -7.594576E-02 +5.453284E-01 +1.497004E-01 +1.851055E-01 +1.721223E-02 +1.038418E-01 +1.078313E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8261,6 +8263,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +6.010211E-02 +3.612264E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8293,6 +8297,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +6.319919E-02 +3.629541E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8325,14 +8331,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.137844E-02 -5.984482E-03 +1.292774E-01 +8.674372E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8747,14 +8747,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -4.235904E-01 -1.794288E-01 -2.296533E-01 -2.653997E-02 -1.867564E-01 -3.487796E-02 0.000000E+00 0.000000E+00 +4.601224E-01 +1.283387E-01 +4.851011E-01 +1.238875E-01 +1.351214E-02 +1.825779E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8781,12 +8781,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.285152E-02 -5.700776E-03 -1.646014E+00 -6.255979E-01 -9.809995E-01 -3.058040E-01 +7.746478E-03 +6.000792E-05 +1.551243E+00 +5.797918E-01 +1.974875E-01 +1.837196E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8817,10 +8817,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.189281E-01 -4.001687E-02 -1.431247E-02 -2.048469E-04 +2.541705E-01 +4.325743E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -8851,8 +8853,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -9.579949E-02 -9.177542E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -9359,12 +9359,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.668786E-02 +2.784846E-04 +2.256035E-01 +5.089693E-02 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 -2.836882E-01 -8.047901E-02 -5.295973E-02 -2.804733E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -9395,8 +9397,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -7.405305E-01 -5.483854E-01 0.000000E+00 0.000000E+00 0.000000E+00 diff --git a/tests/test_filter_mesh_3d/tallies.xml b/tests/test_filter_mesh_3d/tallies.xml index b2be272799..cd7f925e80 100644 --- a/tests/test_filter_mesh_3d/tallies.xml +++ b/tests/test_filter_mesh_3d/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -182.07 -182.07 -183.00 182.07 182.07 183.00 17 17 17 @@ -13,4 +13,4 @@ total - \ No newline at end of file + diff --git a/tests/test_filter_mesh_3d/test_filter_mesh_3d.py b/tests/test_filter_mesh_3d/test_filter_mesh_3d.py index 1777db993e..ed6addec45 100644 --- a/tests/test_filter_mesh_3d/test_filter_mesh_3d.py +++ b/tests/test_filter_mesh_3d/test_filter_mesh_3d.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_filter_mu/inputs_true.dat b/tests/test_filter_mu/inputs_true.dat new file mode 100644 index 0000000000..b0a607ad34 --- /dev/null +++ b/tests/test_filter_mu/inputs_true.dat @@ -0,0 +1 @@ +cd2aeb24baafe9a904e697955990f6cffb5f25618fdf8c972775715bfe6e92bc259e36fd2b5addff8181439de58ad6f530972ec391e827f46146a2aaace34358 \ No newline at end of file diff --git a/tests/test_filter_mu/results_true.dat b/tests/test_filter_mu/results_true.dat new file mode 100644 index 0000000000..e647a46ec0 --- /dev/null +++ b/tests/test_filter_mu/results_true.dat @@ -0,0 +1,121 @@ +k-combined: +9.903196E-01 4.279617E-02 +tally 1: +1.241000E+01 +3.088870E+01 +1.241000E+01 +3.088870E+01 +1.364000E+01 +3.727140E+01 +1.364000E+01 +3.727140E+01 +3.251000E+01 +2.118597E+02 +3.251000E+01 +2.118597E+02 +7.297000E+01 +1.066904E+03 +7.297000E+01 +1.066904E+03 +tally 2: +9.880000E+00 +1.964520E+01 +9.880000E+00 +1.964520E+01 +1.022000E+01 +2.099620E+01 +1.022000E+01 +2.099620E+01 +1.479000E+01 +4.397670E+01 +1.479000E+01 +4.397670E+01 +3.470000E+01 +2.412094E+02 +3.470000E+01 +2.412094E+02 +6.194000E+01 +7.687326E+02 +6.194000E+01 +7.687326E+02 +tally 3: +3.560000E+00 +2.681800E+00 +3.560000E+00 +2.681800E+00 +1.930000E+00 +7.915000E-01 +1.930000E+00 +7.915000E-01 +3.870000E+00 +3.109100E+00 +3.870000E+00 +3.109100E+00 +3.500000E-01 +3.630000E-02 +3.500000E-01 +3.630000E-02 +3.680000E+00 +2.840200E+00 +3.680000E+00 +2.840200E+00 +2.050000E+00 +8.735000E-01 +2.050000E+00 +8.735000E-01 +3.910000E+00 +3.085100E+00 +3.910000E+00 +3.085100E+00 +3.900000E-01 +3.610000E-02 +3.900000E-01 +3.610000E-02 +5.130000E+00 +5.422100E+00 +5.130000E+00 +5.422100E+00 +3.100000E+00 +1.959200E+00 +3.100000E+00 +1.959200E+00 +5.840000E+00 +6.914600E+00 +5.840000E+00 +6.914600E+00 +5.400000E-01 +8.980000E-02 +5.400000E-01 +8.980000E-02 +1.215000E+01 +3.061010E+01 +1.215000E+01 +3.061010E+01 +7.220000E+00 +1.081680E+01 +7.220000E+00 +1.081680E+01 +1.355000E+01 +3.699090E+01 +1.355000E+01 +3.699090E+01 +1.360000E+00 +5.098000E-01 +1.360000E+00 +5.098000E-01 +2.199000E+01 +9.837430E+01 +2.199000E+01 +9.837430E+01 +1.243000E+01 +3.167470E+01 +1.243000E+01 +3.167470E+01 +2.451000E+01 +1.233915E+02 +2.451000E+01 +1.233915E+02 +2.460000E+00 +1.687000E+00 +2.460000E+00 +1.687000E+00 diff --git a/tests/test_filter_mu/test_filter_mu.py b/tests/test_filter_mu/test_filter_mu.py new file mode 100644 index 0000000000..f59f8c63fd --- /dev/null +++ b/tests/test_filter_mu/test_filter_mu.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterMuTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt1 = openmc.Filter(type='mu', + bins=(-1.0, -0.5, 0.0, 0.5, 1.0)) + tally1 = openmc.Tally(tally_id=1) + tally1.add_filter(filt1) + tally1.add_score('scatter') + tally1.add_score('nu-scatter') + + filt2 = openmc.Filter(type='mu', bins=(5,)) + tally2 = openmc.Tally(tally_id=2) + tally2.add_filter(filt2) + tally2.add_score('scatter') + tally2.add_score('nu-scatter') + + mesh = openmc.Mesh(mesh_id=1) + mesh.lower_left = [-182.07, -182.07] + mesh.upper_right = [182.07, 182.07] + mesh.dimension = [2, 2] + filt_mesh = openmc.Filter(type='mesh', bins=(1,)) + tally3 = openmc.Tally(tally_id=3) + tally3.add_filter(filt2) + tally3.add_filter(filt_mesh) + tally3.add_score('scatter') + tally3.add_score('nu-scatter') + + + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally1) + self._input_set.tallies.add_tally(tally2) + self._input_set.tallies.add_tally(tally3) + self._input_set.tallies.add_mesh(mesh) + + super(FilterMuTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterMuTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = FilterMuTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_filter_polar/inputs_true.dat b/tests/test_filter_polar/inputs_true.dat new file mode 100644 index 0000000000..db67a890f1 --- /dev/null +++ b/tests/test_filter_polar/inputs_true.dat @@ -0,0 +1 @@ +2de29e0a083af0722039ebc246469f26e260d604ab8b76314b2ac472bbd23004e031aec7afe3dbfc4c6112428846cd0cf0c1430e878832b9dab36463d026dee6 \ No newline at end of file diff --git a/tests/test_filter_polar/results_true.dat b/tests/test_filter_polar/results_true.dat new file mode 100644 index 0000000000..2d822630e5 --- /dev/null +++ b/tests/test_filter_polar/results_true.dat @@ -0,0 +1,76 @@ +k-combined: +9.903196E-01 4.279617E-02 +tally 1: +2.127061E+01 +9.220793E+01 +5.602776E+01 +6.373945E+02 +6.367492E+01 +8.138443E+02 +5.529942E+01 +6.140264E+02 +1.951517E+01 +7.668661E+01 +tally 2: +2.075936E+01 +8.757254E+01 +5.524881E+01 +6.153139E+02 +6.475252E+01 +8.402281E+02 +5.446664E+01 +5.961174E+02 +2.074180E+01 +8.681580E+01 +tally 3: +2.128073E+01 +9.230382E+01 +5.601764E+01 +6.371703E+02 +6.367492E+01 +8.138443E+02 +5.529942E+01 +6.140264E+02 +1.951517E+01 +7.668661E+01 +tally 4: +8.088647E+00 +1.396899E+01 +3.960907E+00 +3.249150E+00 +8.430714E+00 +1.435355E+01 +7.192159E-01 +1.641710E-01 +1.974619E+01 +8.105078E+01 +1.212452E+01 +3.016420E+01 +2.228348E+01 +1.050847E+02 +1.748809E+00 +9.501796E-01 +2.257423E+01 +1.038902E+02 +1.351331E+01 +3.969787E+01 +2.507638E+01 +1.283664E+02 +2.193118E+00 +1.424580E+00 +2.192232E+01 +9.859711E+01 +1.096779E+01 +2.506373E+01 +2.074138E+01 +8.670015E+01 +1.469145E+00 +8.072204E-01 +6.850719E+00 +9.425536E+00 +4.584038E+00 +4.399762E+00 +7.176883E+00 +1.090693E+01 +8.244944E-01 +1.794291E-01 diff --git a/tests/test_filter_polar/test_filter_polar.py b/tests/test_filter_polar/test_filter_polar.py new file mode 100644 index 0000000000..db7ed4f6d8 --- /dev/null +++ b/tests/test_filter_polar/test_filter_polar.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + +class FilterPolarTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt1 = openmc.Filter(type='polar', + bins=(0.0, 0.6283, 1.2566, 1.8850, 2.5132, + 3.1416)) + tally1 = openmc.Tally(tally_id=1) + tally1.add_filter(filt1) + tally1.add_score('flux') + tally1.estimator = 'tracklength' + + tally2 = openmc.Tally(tally_id=2) + tally2.add_filter(filt1) + tally2.add_score('flux') + tally2.estimator = 'analog' + + filt3 = openmc.Filter(type='polar', bins=(5,)) + tally3 = openmc.Tally(tally_id=3) + tally3.add_filter(filt3) + tally3.add_score('flux') + tally3.estimator = 'tracklength' + + mesh = openmc.Mesh(mesh_id=1) + mesh.lower_left = [-182.07, -182.07] + mesh.upper_right = [182.07, 182.07] + mesh.dimension = [2, 2] + filt_mesh = openmc.Filter(type='mesh', bins=(1,)) + tally4 = openmc.Tally(tally_id=4) + tally4.add_filter(filt3) + tally4.add_filter(filt_mesh) + tally4.add_score('flux') + tally4.estimator = 'tracklength' + + + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally1) + self._input_set.tallies.add_tally(tally2) + self._input_set.tallies.add_tally(tally3) + self._input_set.tallies.add_tally(tally4) + self._input_set.tallies.add_mesh(mesh) + + super(FilterPolarTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterPolarTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = FilterPolarTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_filter_universe/geometry.xml b/tests/test_filter_universe/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_filter_universe/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_filter_universe/inputs_true.dat b/tests/test_filter_universe/inputs_true.dat new file mode 100644 index 0000000000..7cda1ab848 --- /dev/null +++ b/tests/test_filter_universe/inputs_true.dat @@ -0,0 +1 @@ +51fcaf0aa527d1fd1022e5f312d4d25cd9bacc5fc9792d9f7702ee97cac43700a31f25be767a2cff769c37b5e1cdf3f922467977a9958fa34561e2a102bf8537 \ No newline at end of file diff --git a/tests/test_filter_universe/materials.xml b/tests/test_filter_universe/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_filter_universe/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_filter_universe/results_true.dat b/tests/test_filter_universe/results_true.dat index c63da0083d..f71c4d2c21 100644 --- a/tests/test_filter_universe/results_true.dat +++ b/tests/test_filter_universe/results_true.dat @@ -1,11 +1,11 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -6.369043E+01 -8.385422E+02 -7.330762E+00 -1.137874E+01 -5.011385E+01 -5.251276E+02 -5.132453E+00 -5.801019E+00 +7.510505E+01 +1.143811E+03 +8.792943E+00 +1.575416E+01 +4.214462E+01 +3.642975E+02 +4.335157E+00 +3.864423E+00 diff --git a/tests/test_filter_universe/settings.xml b/tests/test_filter_universe/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_filter_universe/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_filter_universe/tallies.xml b/tests/test_filter_universe/tallies.xml deleted file mode 100644 index bcf16f53a6..0000000000 --- a/tests/test_filter_universe/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - total - - - \ No newline at end of file diff --git a/tests/test_filter_universe/test_filter_universe.py b/tests/test_filter_universe/test_filter_universe.py index 1777db993e..00dd166196 100644 --- a/tests/test_filter_universe/test_filter_universe.py +++ b/tests/test_filter_universe/test_filter_universe.py @@ -1,10 +1,29 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class FilterUniverseTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='universe', bins=(1, 2, 3, 4)) + tally = openmc.Tally(tally_id=1) + tally.add_filter(filt) + tally.add_score('total') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(tally) + + super(FilterUniverseTestHarness, self)._build_inputs() + + def _cleanup(self): + super(FilterUniverseTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = FilterUniverseTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_fixed_source/geometry.xml b/tests/test_fixed_source/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_fixed_source/geometry.xml +++ b/tests/test_fixed_source/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_fixed_source/results_true.dat b/tests/test_fixed_source/results_true.dat index 99eb15e10d..0940301886 100644 --- a/tests/test_fixed_source/results_true.dat +++ b/tests/test_fixed_source/results_true.dat @@ -1,6 +1,6 @@ tally 1: -4.483337E+02 -2.017057E+04 +4.538791E+02 +2.073271E+04 leakage: -9.820000E+00 -9.648000E+00 +9.830000E+00 +9.663900E+00 diff --git a/tests/test_fixed_source/test_fixed_source.py b/tests/test_fixed_source/test_fixed_source.py index e96a3ad8fe..12dbb8d769 100644 --- a/tests/test_fixed_source/test_fixed_source.py +++ b/tests/test_fixed_source/test_fixed_source.py @@ -1,8 +1,12 @@ #!/usr/bin/env python +import glob +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +import numpy as np +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness +from openmc.statepoint import StatePoint class FixedSourceTestHarness(TestHarness): @@ -11,26 +15,26 @@ class FixedSourceTestHarness(TestHarness): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Write out tally data. outstr = '' if self._tallies: tally_num = 1 - for tally_ind in sp._tallies: - tally = sp._tallies[tally_ind] - results = np.zeros((tally._sum.size*2, )) - results[0::2] = tally._sum.ravel() - results[1::2] = tally._sum_sq.ravel() + for tally_ind in sp.tallies: + tally = sp.tallies[tally_ind] + results = np.zeros((tally.sum.size*2, )) + results[0::2] = tally.sum.ravel() + results[1::2] = tally.sum_sq.ravel() results = ['{0:12.6E}'.format(x) for x in results] outstr += 'tally ' + str(tally_num) + ':\n' outstr += '\n'.join(results) + '\n' tally_num += 1 + gt = sp.global_tallies outstr += 'leakage:\n' - outstr += '{0:12.6E}'.format(sp._global_tallies[3][0]) + '\n' - outstr += '{0:12.6E}'.format(sp._global_tallies[3][1]) + '\n' + outstr += '{0:12.6E}'.format(gt[gt['name'] == b'leakage'][0]['sum']) + '\n' + outstr += '{0:12.6E}'.format(gt[gt['name'] == b'leakage'][0]['sum_sq']) + '\n' return outstr diff --git a/tests/test_infinite_cell/geometry.xml b/tests/test_infinite_cell/geometry.xml index e3f63354c6..90bd2233be 100644 --- a/tests/test_infinite_cell/geometry.xml +++ b/tests/test_infinite_cell/geometry.xml @@ -1,7 +1,7 @@ - + @@ -13,5 +13,5 @@ - + diff --git a/tests/test_infinite_cell/results_true.dat b/tests/test_infinite_cell/results_true.dat index 45eaa4f917..0b8d929518 100644 --- a/tests/test_infinite_cell/results_true.dat +++ b/tests/test_infinite_cell/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.998895E-02 2.846817E-04 +9.788797E-02 1.378250E-03 diff --git a/tests/test_infinite_cell/test_infinite_cell.py b/tests/test_infinite_cell/test_infinite_cell.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_infinite_cell/test_infinite_cell.py +++ b/tests/test_infinite_cell/test_infinite_cell.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_lattice/geometry.xml b/tests/test_lattice/geometry.xml index 89af5f1968..809cd6fbb1 100644 --- a/tests/test_lattice/geometry.xml +++ b/tests/test_lattice/geometry.xml @@ -40,11 +40,11 @@ - - - - - + + + + + @@ -85,38 +85,38 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/tests/test_lattice/test_lattice.py b/tests/test_lattice/test_lattice.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_lattice/test_lattice.py +++ b/tests/test_lattice/test_lattice.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_lattice_hex/geometry.xml b/tests/test_lattice_hex/geometry.xml index 8b5915dcdb..cfe39849cb 100644 --- a/tests/test_lattice_hex/geometry.xml +++ b/tests/test_lattice_hex/geometry.xml @@ -14,29 +14,29 @@ - - - - - - - + + + + + + + - - - + + + - - - + + + @@ -194,6 +194,6 @@ + region="-1001 -1002 -1003 -1004 -1005 -1006 1007 -1008"/> diff --git a/tests/test_lattice_hex/test_lattice_hex.py b/tests/test_lattice_hex/test_lattice_hex.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_lattice_hex/test_lattice_hex.py +++ b/tests/test_lattice_hex/test_lattice_hex.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_lattice_mixed/geometry.xml b/tests/test_lattice_mixed/geometry.xml index 524e4d9289..41aa05d411 100644 --- a/tests/test_lattice_mixed/geometry.xml +++ b/tests/test_lattice_mixed/geometry.xml @@ -15,29 +15,29 @@ - - - - - - - + + + + + + + - - - + + + - - - + + + @@ -151,6 +151,6 @@ + region="-1001 -1002 -1003 -1004 -1005 -1006 1007 -1008"/> diff --git a/tests/test_lattice_mixed/results_true.dat b/tests/test_lattice_mixed/results_true.dat index d23feb91f0..7cea76ba00 100644 --- a/tests/test_lattice_mixed/results_true.dat +++ b/tests/test_lattice_mixed/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.605085E-01 8.180822E-03 +9.922449E-01 1.281824E-02 diff --git a/tests/test_lattice_mixed/test_lattice_mixed.py b/tests/test_lattice_mixed/test_lattice_mixed.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_lattice_mixed/test_lattice_mixed.py +++ b/tests/test_lattice_mixed/test_lattice_mixed.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_lattice_multiple/geometry.xml b/tests/test_lattice_multiple/geometry.xml index b85dd04df9..f6f067aadd 100644 --- a/tests/test_lattice_multiple/geometry.xml +++ b/tests/test_lattice_multiple/geometry.xml @@ -21,50 +21,50 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + diff --git a/tests/test_lattice_multiple/results_true.dat b/tests/test_lattice_multiple/results_true.dat index f2e3d93c93..6caffdd953 100644 --- a/tests/test_lattice_multiple/results_true.dat +++ b/tests/test_lattice_multiple/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.093844E+00 1.626801E-02 +1.005983E+00 2.248579E-02 diff --git a/tests/test_lattice_multiple/test_lattice_multiple.py b/tests/test_lattice_multiple/test_lattice_multiple.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_lattice_multiple/test_lattice_multiple.py +++ b/tests/test_lattice_multiple/test_lattice_multiple.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_many_scores/geometry.xml b/tests/test_many_scores/geometry.xml index b85dd04df9..f6f067aadd 100644 --- a/tests/test_many_scores/geometry.xml +++ b/tests/test_many_scores/geometry.xml @@ -21,50 +21,50 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + diff --git a/tests/test_many_scores/results_true.dat b/tests/test_many_scores/results_true.dat index 191122f13e..0d5dd6e32e 100644 --- a/tests/test_many_scores/results_true.dat +++ b/tests/test_many_scores/results_true.dat @@ -1,111 +1,113 @@ k-combined: 0.000000E+00 0.000000E+00 tally 1: -2.254760E+01 -1.695439E+02 -1.017400E+01 -3.450623E+01 -8.690000E+00 -2.517771E+01 -8.696000E+00 -2.521248E+01 -5.224881E-01 -9.127522E-02 -8.690000E+00 -2.517771E+01 -9.665236E-01 -3.121401E-01 -5.224881E-01 -9.127522E-02 -5.199964E-01 -9.041516E-02 -8.696000E+00 -2.521248E+01 -9.666447E-01 -3.122176E-01 -5.199964E-01 -9.041516E-02 -9.262308E+00 -2.859762E+01 -8.684000E+00 -2.514296E+01 -1.484000E+00 -7.346160E-01 -1.804688E+00 -1.089100E+00 -1.334833E+02 -5.960573E+03 -2.254760E+01 -1.695439E+02 --6.230152E-02 -1.023784E-02 --2.696818E-01 -8.525477E-02 --1.670294E-01 -4.366614E-02 -1.331953E-02 -8.064039E-05 --2.490295E-01 -2.511425E-02 -8.289978E-02 -2.753446E-03 --1.390686E-01 -1.592673E-02 -1.600203E-01 -1.344513E-02 -1.017400E+01 -3.450623E+01 --6.564301E-02 -2.564587E-03 --1.245391E-01 -1.143479E-02 --5.550309E-02 -9.334547E-03 -4.671277E-02 -1.795787E-03 --9.901000E-02 -4.609654E-03 -2.619012E-02 -3.011793E-04 --7.090362E-02 -2.450750E-03 -4.059073E-02 -8.841300E-04 -8.690000E+00 -2.517771E+01 --2.685052E-02 -2.769798E-04 -4.047919E-03 -3.384947E-03 --1.325869E-01 -8.610169E-03 --1.594962E-02 -5.528670E-04 --1.320550E-02 -1.856248E-04 -1.185337E-02 -3.428536E-04 -2.622196E-02 -3.774884E-04 -2.938463E-02 -6.660370E-04 -8.696000E+00 -2.521248E+01 --2.634867E-02 -2.718345E-04 -4.042613E-03 -3.367272E-03 --1.328903E-01 -8.576852E-03 --1.632965E-02 -5.577169E-04 --1.408565E-02 -1.815109E-04 -1.202519E-02 -3.685250E-04 -2.634054E-02 -3.730853E-04 -2.941341E-02 -6.479457E-04 +2.247257E+01 +1.683779E+02 1.014000E+01 -3.427460E+01 +3.427342E+01 +8.628000E+00 +2.481430E+01 +8.632000E+00 +2.483728E+01 +5.102293E-01 +8.710841E-02 +8.628000E+00 +2.481430E+01 +9.329009E-01 +2.902534E-01 +5.102293E-01 +8.710841E-02 +5.087118E-01 +8.657086E-02 +8.632000E+00 +2.483728E+01 +9.328366E-01 +2.902108E-01 +5.087118E-01 +8.657086E-02 +9.212024E+00 +2.829472E+01 +8.628000E+00 +2.481430E+01 +1.512000E+00 +7.620560E-01 +1.816851E+00 +1.102658E+00 +1.337996E+02 +5.985519E+03 +2.247257E+01 +1.683779E+02 +1.512960E-01 +2.623972E-02 +-3.775020E-01 +1.055377E-01 +1.916133E-01 +4.680798E-02 +2.754367E-02 +3.320008E-04 +2.028374E-02 +1.319357E-02 +8.974271E-03 +1.681081E-03 +1.658978E-01 +1.520448E-02 +2.878360E-01 +5.645480E-02 +1.014000E+01 +3.427342E+01 +4.798897E-02 +1.551226E-03 +-1.818770E-01 +1.492633E-02 +6.340651E-02 +9.011305E-03 +3.395308E-02 +4.612818E-04 +2.640250E-02 +6.434787E-04 +-8.242639E-03 +9.516540E-04 +8.378601E-02 +2.645988E-03 +9.567484E-02 +7.262477E-03 +8.628000E+00 +2.481430E+01 +4.712248E-02 +1.140942E-03 +-6.431930E-02 +4.290580E-03 +9.251642E-02 +8.134201E-03 +1.020119E-04 +1.154184E-04 +2.994164E-02 +3.079076E-04 +2.128844E-02 +2.046549E-04 +-1.637972E-02 +1.459209E-04 +4.629047E-02 +7.823267E-04 +8.632000E+00 +2.483728E+01 +4.651997E-02 +1.133839E-03 +-6.416955E-02 +4.279418E-03 +9.280565E-02 +8.095106E-03 +-2.078094E-04 +1.151292E-04 +3.005568E-02 +3.104764E-04 +2.199519E-02 +2.179172E-04 +-1.660645E-02 +1.451345E-04 +4.607553E-02 +7.673412E-04 +1.014000E+01 +3.427342E+01 +7.652723E-03 +3.578992E-05 diff --git a/tests/test_many_scores/tallies.xml b/tests/test_many_scores/tallies.xml index 1832acf67a..2df5597d04 100644 --- a/tests/test_many_scores/tallies.xml +++ b/tests/test_many_scores/tallies.xml @@ -6,7 +6,7 @@ flux total scatter nu-scatter scatter-2 scatter-p2 nu-scatter-2 nu-scatter-p2 transport n1n absorption nu-fission kappa-fission - flux-y2 total-y2 scatter-y2 nu-scatter-y2 events + flux-y2 total-y2 scatter-y2 nu-scatter-y2 events delayed-nu-fission diff --git a/tests/test_many_scores/test_many_scores.py b/tests/test_many_scores/test_many_scores.py index 66bfe3dfa7..88c3bdfb3d 100644 --- a/tests/test_many_scores/test_many_scores.py +++ b/tests/test_many_scores/test_many_scores.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_mgxs_library_condense/inputs_true.dat b/tests/test_mgxs_library_condense/inputs_true.dat new file mode 100644 index 0000000000..37397c5947 --- /dev/null +++ b/tests/test_mgxs_library_condense/inputs_true.dat @@ -0,0 +1 @@ +35f99f1973b3bf3efcec6c2dddf56d6679a15dab8582ab5336e86e4fdf90967ce91036e5c30c345decb994ab9133a906b82dc8fad0cdd3398a612d9aa05c1c77 \ No newline at end of file diff --git a/tests/test_mgxs_library_condense/results_true.dat b/tests/test_mgxs_library_condense/results_true.dat new file mode 100644 index 0000000000..45891fc300 --- /dev/null +++ b/tests/test_mgxs_library_condense/results_true.dat @@ -0,0 +1,49 @@ + material group in nuclide mean std. dev. +0 1 1 total 0.419289 0.01638 material group in nuclide mean std. dev. +0 1 1 total 0.07774 0.003273 material group in group out nuclide mean std. dev. +0 1 1 1 total 0.352665 0.015654 material group out nuclide mean std. dev. +0 1 1 total 1 0.119622 material group in nuclide mean std. dev. +0 2 1 total 0.247316 0.009562 material group in nuclide mean std. dev. +0 2 1 total 0 0 material group in group out nuclide mean std. dev. +0 2 1 1 total 0.244838 0.009996 material group out nuclide mean std. dev. +0 2 1 total 0 0 material group in nuclide mean std. dev. +0 3 1 total 0.409938 0.042262 material group in nuclide mean std. dev. +0 3 1 total 0 0 material group in group out nuclide mean std. dev. +0 3 1 1 total 0.403354 0.041386 material group out nuclide mean std. dev. +0 3 1 total 0 0 material group in nuclide mean std. dev. +0 4 1 total 0.344007 0.05352 material group in nuclide mean std. dev. +0 4 1 total 0 0 material group in group out nuclide mean std. dev. +0 4 1 1 total 0.340438 0.052067 material group out nuclide mean std. dev. +0 4 1 total 0 0 material group in nuclide mean std. dev. +0 5 1 total 0 0 material group in nuclide mean std. dev. +0 5 1 total 0 0 material group in group out nuclide mean std. dev. +0 5 1 1 total 0 0 material group out nuclide mean std. dev. +0 5 1 total 0 0 material group in nuclide mean std. dev. +0 6 1 total 0 0 material group in nuclide mean std. dev. +0 6 1 total 0 0 material group in group out nuclide mean std. dev. +0 6 1 1 total 0 0 material group out nuclide mean std. dev. +0 6 1 total 0 0 material group in nuclide mean std. dev. +0 7 1 total 0 0 material group in nuclide mean std. dev. +0 7 1 total 0 0 material group in group out nuclide mean std. dev. +0 7 1 1 total 0 0 material group out nuclide mean std. dev. +0 7 1 total 0 0 material group in nuclide mean std. dev. +0 8 1 total 0 0 material group in nuclide mean std. dev. +0 8 1 total 0 0 material group in group out nuclide mean std. dev. +0 8 1 1 total 0 0 material group out nuclide mean std. dev. +0 8 1 total 0 0 material group in nuclide mean std. dev. +0 9 1 total 0.751873 0.559701 material group in nuclide mean std. dev. +0 9 1 total 0 0 material group in group out nuclide mean std. dev. +0 9 1 1 total 0.695491 0.50757 material group out nuclide mean std. dev. +0 9 1 total 0 0 material group in nuclide mean std. dev. +0 10 1 total 0 0 material group in nuclide mean std. dev. +0 10 1 total 0 0 material group in group out nuclide mean std. dev. +0 10 1 1 total 0 0 material group out nuclide mean std. dev. +0 10 1 total 0 0 material group in nuclide mean std. dev. +0 11 1 total 0.457329 0.403578 material group in nuclide mean std. dev. +0 11 1 total 0 0 material group in group out nuclide mean std. dev. +0 11 1 1 total 0.446737 0.392775 material group out nuclide mean std. dev. +0 11 1 total 0 0 material group in nuclide mean std. dev. +0 12 1 total 0.574978 0.38864 material group in nuclide mean std. dev. +0 12 1 total 0 0 material group in group out nuclide mean std. dev. +0 12 1 1 total 0.559478 0.377512 material group out nuclide mean std. dev. +0 12 1 total 0 0 \ No newline at end of file diff --git a/tests/test_mgxs_library_condense/test_mgxs_library_condense.py b/tests/test_mgxs_library_condense/test_mgxs_library_condense.py new file mode 100644 index 0000000000..4c84de2bf6 --- /dev/null +++ b/tests/test_mgxs_library_condense/test_mgxs_library_condense.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +import os +import sys +import glob +import hashlib +sys.path.insert(0, os.pardir) +from testing_harness import PyAPITestHarness +import openmc +import openmc.mgxs + + +class MGXSTestHarness(PyAPITestHarness): + def _build_inputs(self): + + # The openmc.mgxs module needs a summary.h5 file + self._input_set.settings.output = {'summary': True} + + # Generate inputs using parent class routine + super(MGXSTestHarness, self)._build_inputs() + + # Initialize a two-group structure + energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.]) + + # Initialize MGXS Library for a few cross section types + self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry.geometry) + self.mgxs_lib.by_nuclide = False + self.mgxs_lib.mgxs_types = ['transport', 'nu-fission', + 'nu-scatter matrix', 'chi'] + self.mgxs_lib.energy_groups = energy_groups + self.mgxs_lib.domain_type = 'material' + self.mgxs_lib.build_library() + + # Initialize a tallies file + self._input_set.tallies = openmc.TalliesFile() + self.mgxs_lib.add_to_tallies_file(self._input_set.tallies, merge=False) + self._input_set.tallies.export_to_xml() + + def _get_results(self, hash_output=False): + """Digest info in the statepoint and return as a string.""" + + # Read the statepoint file. + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] + sp = openmc.StatePoint(statepoint) + + # Read the summary file. + summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0] + su = openmc.Summary(summary) + sp.link_with_summary(su) + + # Load the MGXS library from the statepoint + self.mgxs_lib.load_from_statepoint(sp) + + # Build a condensed 1-group MGXS Library + one_group = openmc.mgxs.EnergyGroups([0., 20.]) + condense_lib = self.mgxs_lib.get_condensed_library(one_group) + + # Build a string from Pandas Dataframe for each 1-group MGXS + outstr = '' + for domain in condense_lib.domains: + for mgxs_type in condense_lib.mgxs_types: + mgxs = condense_lib.get_mgxs(domain, mgxs_type) + df = mgxs.get_pandas_dataframe() + outstr += df.to_string() + + print(outstr) + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + + def _cleanup(self): + super(MGXSTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = MGXSTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_mgxs_library_hdf5/inputs_true.dat b/tests/test_mgxs_library_hdf5/inputs_true.dat new file mode 100644 index 0000000000..37397c5947 --- /dev/null +++ b/tests/test_mgxs_library_hdf5/inputs_true.dat @@ -0,0 +1 @@ +35f99f1973b3bf3efcec6c2dddf56d6679a15dab8582ab5336e86e4fdf90967ce91036e5c30c345decb994ab9133a906b82dc8fad0cdd3398a612d9aa05c1c77 \ No newline at end of file diff --git a/tests/test_mgxs_library_hdf5/results_true.dat b/tests/test_mgxs_library_hdf5/results_true.dat new file mode 100644 index 0000000000..eec581046d --- /dev/null +++ b/tests/test_mgxs_library_hdf5/results_true.dat @@ -0,0 +1,168 @@ +domain=1 type=transport +[ 0.38437891 0.81208747] +[ 0.01648997 0.07418959] +domain=1 type=nu-fission +[ 0.02127008 0.69604034] +[ 0.0008939 0.05345764] +domain=1 type=nu-scatter matrix +[[ 3.49923892e-01 1.73140769e-04] + [ 1.94810926e-03 3.79607212e-01]] +[[ 0.01664928 0.0001732 ] + [ 0.00195193 0.04007819]] +domain=1 type=chi +[ 1. 0.] +[ 0.11962178 0. ] +domain=2 type=transport +[ 0.24504295 0.26645769] +[ 0.00882749 0.05220872] +domain=2 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=2 type=nu-scatter matrix +[[ 0.24365718 0. ] + [ 0. 0.25478661]] +[[ 0.00908307 0. ] + [ 0. 0.05556256]] +domain=2 type=chi +[ 0. 0.] +[ 0. 0.] +domain=3 type=transport +[ 0.28227749 1.42731974] +[ 0.03724175 0.24712746] +domain=3 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=3 type=nu-scatter matrix +[[ 0.25396726 0.02727268] + [ 0. 1.37652669]] +[[ 0.03617307 0.00180698] + [ 0. 0.2402569 ]] +domain=3 type=chi +[ 0. 0.] +[ 0. 0.] +domain=4 type=transport +[ 0.25572316 1.17976682] +[ 0.05191655 0.22938034] +domain=4 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=4 type=nu-scatter matrix +[[ 0.23297756 0.02228141] + [ 0. 1.14680862]] +[[ 0.04977114 0.00262525] + [ 0. 0.22219839]] +domain=4 type=chi +[ 0. 0.] +[ 0. 0.] +domain=5 type=transport +[ 0. 0.] +[ 0. 0.] +domain=5 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=5 type=nu-scatter matrix +[[ 0. 0.] + [ 0. 0.]] +[[ 0. 0.] + [ 0. 0.]] +domain=5 type=chi +[ 0. 0.] +[ 0. 0.] +domain=6 type=transport +[ 0. 0.] +[ 0. 0.] +domain=6 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=6 type=nu-scatter matrix +[[ 0. 0.] + [ 0. 0.]] +[[ 0. 0.] + [ 0. 0.]] +domain=6 type=chi +[ 0. 0.] +[ 0. 0.] +domain=7 type=transport +[ 0. 0.] +[ 0. 0.] +domain=7 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=7 type=nu-scatter matrix +[[ 0. 0.] + [ 0. 0.]] +[[ 0. 0.] + [ 0. 0.]] +domain=7 type=chi +[ 0. 0.] +[ 0. 0.] +domain=8 type=transport +[ 0. 0.] +[ 0. 0.] +domain=8 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=8 type=nu-scatter matrix +[[ 0. 0.] + [ 0. 0.]] +[[ 0. 0.] + [ 0. 0.]] +domain=8 type=chi +[ 0. 0.] +[ 0. 0.] +domain=9 type=transport +[ 0.50403601 1.68709544] +[ 0.37962374 2.53662237] +domain=9 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=9 type=nu-scatter matrix +[[ 0.50403601 0. ] + [ 0. 1.41795483]] +[[ 0.37962374 0. ] + [ 0. 2.15802716]] +domain=9 type=chi +[ 0. 0.] +[ 0. 0.] +domain=10 type=transport +[ 0. 0.] +[ 0. 0.] +domain=10 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=10 type=nu-scatter matrix +[[ 0. 0.] + [ 0. 0.]] +[[ 0. 0.] + [ 0. 0.]] +domain=10 type=chi +[ 0. 0.] +[ 0. 0.] +domain=11 type=transport +[ 0.30282618 1.00614519] +[ 0.40131081 1.09163785] +domain=11 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=11 type=nu-scatter matrix +[[ 0.27567871 0.02714747] + [ 0. 0.95792921]] +[[ 0.38567601 0.02000859] + [ 0. 1.05195936]] +domain=11 type=chi +[ 0. 0.] +[ 0. 0.] +domain=12 type=transport +[ 0.25593293 1.11334475] +[ 0.26842571 0.98867569] +domain=12 type=nu-fission +[ 0. 0.] +[ 0. 0.] +domain=12 type=nu-scatter matrix +[[ 0.22631045 0.02962248] + [ 0. 1.07168976]] +[[ 0.25487194 0.0177599 ] + [ 0. 0.95829029]] +domain=12 type=chi +[ 0. 0.] +[ 0. 0.] diff --git a/tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py b/tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py new file mode 100644 index 0000000000..642073104b --- /dev/null +++ b/tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +import os +import sys +import glob +import hashlib +import h5py +sys.path.insert(0, os.pardir) +from testing_harness import PyAPITestHarness +import openmc +import openmc.mgxs + + +class MGXSTestHarness(PyAPITestHarness): + def _build_inputs(self): + + # The openmc.mgxs module needs a summary.h5 file + self._input_set.settings.output = {'summary': True} + + # Generate inputs using parent class routine + super(MGXSTestHarness, self)._build_inputs() + + # Initialize a two-group structure + energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.]) + + # Initialize MGXS Library for a few cross section types + self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry.geometry) + self.mgxs_lib.by_nuclide = False + self.mgxs_lib.mgxs_types = ['transport', 'nu-fission', + 'nu-scatter matrix', 'chi'] + self.mgxs_lib.energy_groups = energy_groups + self.mgxs_lib.domain_type = 'material' + self.mgxs_lib.build_library() + + # Initialize a tallies file + self._input_set.tallies = openmc.TalliesFile() + self.mgxs_lib.add_to_tallies_file(self._input_set.tallies, merge=False) + self._input_set.tallies.export_to_xml() + + def _get_results(self, hash_output=False): + """Digest info in the statepoint and return as a string.""" + + # Read the statepoint file. + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] + sp = openmc.StatePoint(statepoint) + + # Read the summary file. + summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0] + su = openmc.Summary(summary) + sp.link_with_summary(su) + + # Load the MGXS library from the statepoint + self.mgxs_lib.load_from_statepoint(sp) + + # Export the MGXS Library to an HDF5 file + self.mgxs_lib.build_hdf5_store(directory='.') + + # Open the MGXS HDF5 file + f = h5py.File('mgxs.h5', 'r') + + # Build a string from the datasets in the HDF5 file + outstr = '' + for domain in self.mgxs_lib.domains: + for mgxs_type in self.mgxs_lib.mgxs_types: + outstr += 'domain={0} type={1}\n'.format(domain.id, mgxs_type) + key = 'material/{0}/{1}/average'.format(domain.id, mgxs_type) + outstr += str(f[key][...]) + '\n' + key = 'material/{0}/{1}/std. dev.'.format(domain.id, mgxs_type) + outstr += str(f[key][...]) + '\n' + + # Close the MGXS HDF5 file + f.close() + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + + def _cleanup(self): + super(MGXSTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + f = os.path.join(os.getcwd(), 'mgxs.h5') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = MGXSTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_mgxs_library_no_nuclides/inputs_true.dat b/tests/test_mgxs_library_no_nuclides/inputs_true.dat new file mode 100644 index 0000000000..37397c5947 --- /dev/null +++ b/tests/test_mgxs_library_no_nuclides/inputs_true.dat @@ -0,0 +1 @@ +35f99f1973b3bf3efcec6c2dddf56d6679a15dab8582ab5336e86e4fdf90967ce91036e5c30c345decb994ab9133a906b82dc8fad0cdd3398a612d9aa05c1c77 \ No newline at end of file diff --git a/tests/test_mgxs_library_no_nuclides/results_true.dat b/tests/test_mgxs_library_no_nuclides/results_true.dat new file mode 100644 index 0000000000..7618512689 --- /dev/null +++ b/tests/test_mgxs_library_no_nuclides/results_true.dat @@ -0,0 +1,121 @@ + material group in nuclide mean std. dev. +1 1 1 total 0.384379 0.01649 +0 1 2 total 0.812087 0.07419 material group in nuclide mean std. dev. +1 1 1 total 0.02127 0.000894 +0 1 2 total 0.69604 0.053458 material group in group out nuclide mean std. dev. +3 1 1 1 total 0.349924 0.016649 +2 1 1 2 total 0.000173 0.000173 +1 1 2 1 total 0.001948 0.001952 +0 1 2 2 total 0.379607 0.040078 material group out nuclide mean std. dev. +1 1 1 total 1 0.119622 +0 1 2 total 0 0.000000 material group in nuclide mean std. dev. +1 2 1 total 0.245043 0.008827 +0 2 2 total 0.266458 0.052209 material group in nuclide mean std. dev. +1 2 1 total 0 0 +0 2 2 total 0 0 material group in group out nuclide mean std. dev. +3 2 1 1 total 0.243657 0.009083 +2 2 1 2 total 0.000000 0.000000 +1 2 2 1 total 0.000000 0.000000 +0 2 2 2 total 0.254787 0.055563 material group out nuclide mean std. dev. +1 2 1 total 0 0 +0 2 2 total 0 0 material group in nuclide mean std. dev. +1 3 1 total 0.282277 0.037242 +0 3 2 total 1.427320 0.247127 material group in nuclide mean std. dev. +1 3 1 total 0 0 +0 3 2 total 0 0 material group in group out nuclide mean std. dev. +3 3 1 1 total 0.253967 0.036173 +2 3 1 2 total 0.027273 0.001807 +1 3 2 1 total 0.000000 0.000000 +0 3 2 2 total 1.376527 0.240257 material group out nuclide mean std. dev. +1 3 1 total 0 0 +0 3 2 total 0 0 material group in nuclide mean std. dev. +1 4 1 total 0.255723 0.051917 +0 4 2 total 1.179767 0.229380 material group in nuclide mean std. dev. +1 4 1 total 0 0 +0 4 2 total 0 0 material group in group out nuclide mean std. dev. +3 4 1 1 total 0.232978 0.049771 +2 4 1 2 total 0.022281 0.002625 +1 4 2 1 total 0.000000 0.000000 +0 4 2 2 total 1.146809 0.222198 material group out nuclide mean std. dev. +1 4 1 total 0 0 +0 4 2 total 0 0 material group in nuclide mean std. dev. +1 5 1 total 0 0 +0 5 2 total 0 0 material group in nuclide mean std. dev. +1 5 1 total 0 0 +0 5 2 total 0 0 material group in group out nuclide mean std. dev. +3 5 1 1 total 0 0 +2 5 1 2 total 0 0 +1 5 2 1 total 0 0 +0 5 2 2 total 0 0 material group out nuclide mean std. dev. +1 5 1 total 0 0 +0 5 2 total 0 0 material group in nuclide mean std. dev. +1 6 1 total 0 0 +0 6 2 total 0 0 material group in nuclide mean std. dev. +1 6 1 total 0 0 +0 6 2 total 0 0 material group in group out nuclide mean std. dev. +3 6 1 1 total 0 0 +2 6 1 2 total 0 0 +1 6 2 1 total 0 0 +0 6 2 2 total 0 0 material group out nuclide mean std. dev. +1 6 1 total 0 0 +0 6 2 total 0 0 material group in nuclide mean std. dev. +1 7 1 total 0 0 +0 7 2 total 0 0 material group in nuclide mean std. dev. +1 7 1 total 0 0 +0 7 2 total 0 0 material group in group out nuclide mean std. dev. +3 7 1 1 total 0 0 +2 7 1 2 total 0 0 +1 7 2 1 total 0 0 +0 7 2 2 total 0 0 material group out nuclide mean std. dev. +1 7 1 total 0 0 +0 7 2 total 0 0 material group in nuclide mean std. dev. +1 8 1 total 0 0 +0 8 2 total 0 0 material group in nuclide mean std. dev. +1 8 1 total 0 0 +0 8 2 total 0 0 material group in group out nuclide mean std. dev. +3 8 1 1 total 0 0 +2 8 1 2 total 0 0 +1 8 2 1 total 0 0 +0 8 2 2 total 0 0 material group out nuclide mean std. dev. +1 8 1 total 0 0 +0 8 2 total 0 0 material group in nuclide mean std. dev. +1 9 1 total 0.504036 0.379624 +0 9 2 total 1.687095 2.536622 material group in nuclide mean std. dev. +1 9 1 total 0 0 +0 9 2 total 0 0 material group in group out nuclide mean std. dev. +3 9 1 1 total 0.504036 0.379624 +2 9 1 2 total 0.000000 0.000000 +1 9 2 1 total 0.000000 0.000000 +0 9 2 2 total 1.417955 2.158027 material group out nuclide mean std. dev. +1 9 1 total 0 0 +0 9 2 total 0 0 material group in nuclide mean std. dev. +1 10 1 total 0 0 +0 10 2 total 0 0 material group in nuclide mean std. dev. +1 10 1 total 0 0 +0 10 2 total 0 0 material group in group out nuclide mean std. dev. +3 10 1 1 total 0 0 +2 10 1 2 total 0 0 +1 10 2 1 total 0 0 +0 10 2 2 total 0 0 material group out nuclide mean std. dev. +1 10 1 total 0 0 +0 10 2 total 0 0 material group in nuclide mean std. dev. +1 11 1 total 0.302826 0.401311 +0 11 2 total 1.006145 1.091638 material group in nuclide mean std. dev. +1 11 1 total 0 0 +0 11 2 total 0 0 material group in group out nuclide mean std. dev. +3 11 1 1 total 0.275679 0.385676 +2 11 1 2 total 0.027147 0.020009 +1 11 2 1 total 0.000000 0.000000 +0 11 2 2 total 0.957929 1.051959 material group out nuclide mean std. dev. +1 11 1 total 0 0 +0 11 2 total 0 0 material group in nuclide mean std. dev. +1 12 1 total 0.255933 0.268426 +0 12 2 total 1.113345 0.988676 material group in nuclide mean std. dev. +1 12 1 total 0 0 +0 12 2 total 0 0 material group in group out nuclide mean std. dev. +3 12 1 1 total 0.226310 0.254872 +2 12 1 2 total 0.029622 0.017760 +1 12 2 1 total 0.000000 0.000000 +0 12 2 2 total 1.071690 0.958290 material group out nuclide mean std. dev. +1 12 1 total 0 0 +0 12 2 total 0 0 \ No newline at end of file diff --git a/tests/test_mgxs_library_no_nuclides/test_mgxs_library_no_nuclides.py b/tests/test_mgxs_library_no_nuclides/test_mgxs_library_no_nuclides.py new file mode 100644 index 0000000000..2afa9039e8 --- /dev/null +++ b/tests/test_mgxs_library_no_nuclides/test_mgxs_library_no_nuclides.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +import os +import sys +import glob +import hashlib +sys.path.insert(0, os.pardir) +from testing_harness import PyAPITestHarness +import openmc +import openmc.mgxs + + +class MGXSTestHarness(PyAPITestHarness): + def _build_inputs(self): + + # The openmc.mgxs module needs a summary.h5 file + self._input_set.settings.output = {'summary': True} + + # Generate inputs using parent class routine + super(MGXSTestHarness, self)._build_inputs() + + # Initialize a two-group structure + energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.]) + + # Initialize MGXS Library for a few cross section types + self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry.geometry) + self.mgxs_lib.by_nuclide = False + self.mgxs_lib.mgxs_types = ['transport', 'nu-fission', + 'nu-scatter matrix', 'chi'] + self.mgxs_lib.energy_groups = energy_groups + self.mgxs_lib.domain_type = 'material' + self.mgxs_lib.build_library() + + # Initialize a tallies file + self._input_set.tallies = openmc.TalliesFile() + self.mgxs_lib.add_to_tallies_file(self._input_set.tallies, merge=False) + self._input_set.tallies.export_to_xml() + + def _get_results(self, hash_output=False): + """Digest info in the statepoint and return as a string.""" + + # Read the statepoint file. + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] + sp = openmc.StatePoint(statepoint) + + # Read the summary file. + summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0] + su = openmc.Summary(summary) + sp.link_with_summary(su) + + # Load the MGXS library from the statepoint + self.mgxs_lib.load_from_statepoint(sp) + + # Build a string from Pandas Dataframe for each MGXS + outstr = '' + for domain in self.mgxs_lib.domains: + for mgxs_type in self.mgxs_lib.mgxs_types: + mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) + df = mgxs.get_pandas_dataframe() + outstr += df.to_string() + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + + def _cleanup(self): + super(MGXSTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = MGXSTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_mgxs_library_nuclides/inputs_true.dat b/tests/test_mgxs_library_nuclides/inputs_true.dat new file mode 100644 index 0000000000..2e299773a3 --- /dev/null +++ b/tests/test_mgxs_library_nuclides/inputs_true.dat @@ -0,0 +1 @@ +7c1deb8a54fbe1a1ce6ef27cea4a11995210ad3e5ecf32bd83d7c80041edf0793378a7325ffe7ebf9c537e9c278fd4545642fec6c1e46b9c5418118f035d5e95 \ No newline at end of file diff --git a/tests/test_mgxs_library_nuclides/results_true.dat b/tests/test_mgxs_library_nuclides/results_true.dat new file mode 100644 index 0000000000..23ac0e423d --- /dev/null +++ b/tests/test_mgxs_library_nuclides/results_true.dat @@ -0,0 +1,1971 @@ + material group in nuclide mean std. dev. +34 1 1 U-234 0.000000 0.000000 +35 1 1 U-235 0.008559 0.001742 +36 1 1 U-236 0.002643 0.000794 +37 1 1 U-238 0.213622 0.010911 +38 1 1 Np-237 0.000000 0.000000 +39 1 1 Pu-238 0.000000 0.000000 +40 1 1 Pu-239 0.005787 0.001050 +41 1 1 Pu-240 0.005702 0.000850 +42 1 1 Pu-241 0.000869 0.000366 +43 1 1 Pu-242 0.000655 0.000537 +44 1 1 Am-241 0.000000 0.000000 +45 1 1 Am-242m 0.000000 0.000000 +46 1 1 Am-243 0.000000 0.000000 +47 1 1 Cm-242 0.000000 0.000000 +48 1 1 Cm-243 0.000000 0.000000 +49 1 1 Cm-244 0.000000 0.000000 +50 1 1 Cm-245 0.000000 0.000000 +51 1 1 Mo-95 0.000302 0.000216 +52 1 1 Tc-99 0.000782 0.000434 +53 1 1 Ru-101 0.000346 0.000212 +54 1 1 Ru-103 0.000000 0.000000 +55 1 1 Ag-109 0.000000 0.000000 +56 1 1 Xe-135 0.000000 0.000000 +57 1 1 Cs-133 0.000189 0.000264 +58 1 1 Nd-143 0.000721 0.000364 +59 1 1 Nd-145 0.000637 0.000253 +60 1 1 Sm-147 0.000009 0.000238 +61 1 1 Sm-149 0.000000 0.000000 +62 1 1 Sm-150 0.000003 0.000243 +63 1 1 Sm-151 0.000000 0.000000 +64 1 1 Sm-152 0.000874 0.000388 +65 1 1 Eu-153 0.000173 0.000173 +66 1 1 Gd-155 0.000000 0.000000 +67 1 1 O-16 0.142506 0.008222 +0 1 2 U-234 0.001948 0.001952 +1 1 2 U-235 0.179956 0.028209 +2 1 2 U-236 0.000000 0.000000 +3 1 2 U-238 0.239279 0.039048 +4 1 2 Np-237 0.000000 0.000000 +5 1 2 Pu-238 0.000000 0.000000 +6 1 2 Pu-239 0.159745 0.015751 +7 1 2 Pu-240 0.007792 0.003677 +8 1 2 Pu-241 0.017533 0.003806 +9 1 2 Pu-242 0.000000 0.000000 +10 1 2 Am-241 0.000000 0.000000 +11 1 2 Am-242m 0.000000 0.000000 +12 1 2 Am-243 0.000000 0.000000 +13 1 2 Cm-242 0.000000 0.000000 +14 1 2 Cm-243 0.000000 0.000000 +15 1 2 Cm-244 0.000000 0.000000 +16 1 2 Cm-245 0.000000 0.000000 +17 1 2 Mo-95 0.002250 0.004232 +18 1 2 Tc-99 0.003544 0.002528 +19 1 2 Ru-101 0.000000 0.000000 +20 1 2 Ru-103 0.000000 0.000000 +21 1 2 Ag-109 0.000000 0.000000 +22 1 2 Xe-135 0.027274 0.004025 +23 1 2 Cs-133 0.000000 0.000000 +24 1 2 Nd-143 0.006532 0.002517 +25 1 2 Nd-145 0.001948 0.001952 +26 1 2 Sm-147 0.000000 0.000000 +27 1 2 Sm-149 0.007792 0.005701 +28 1 2 Sm-150 0.000000 0.000000 +29 1 2 Sm-151 0.000000 0.000000 +30 1 2 Sm-152 0.000000 0.000000 +31 1 2 Eu-153 0.001686 0.001968 +32 1 2 Gd-155 0.000000 0.000000 +33 1 2 O-16 0.154807 0.023798 material group in nuclide mean std. dev. +34 1 1 U-234 6.771527e-06 2.982583e-07 +35 1 1 U-235 9.687933e-03 4.305720e-04 +36 1 1 U-236 6.279974e-05 3.653120e-06 +37 1 1 U-238 6.335930e-03 4.715525e-04 +38 1 1 Np-237 1.237030e-05 6.333955e-07 +39 1 1 Pu-238 7.369063e-06 5.017525e-07 +40 1 1 Pu-239 4.007893e-03 2.607619e-04 +41 1 1 Pu-240 6.479096e-05 3.728060e-06 +42 1 1 Pu-241 1.074454e-03 4.688479e-05 +43 1 1 Pu-242 5.512610e-06 2.976651e-07 +44 1 1 Am-241 1.088373e-06 8.489934e-08 +45 1 1 Am-242m 1.143307e-06 9.912400e-08 +46 1 1 Am-243 7.745526e-07 5.413923e-08 +47 1 1 Cm-242 4.311566e-07 1.922427e-08 +48 1 1 Cm-243 2.363328e-07 2.235666e-08 +49 1 1 Cm-244 2.840125e-07 2.412051e-08 +50 1 1 Cm-245 3.017505e-07 1.594090e-08 +51 1 1 Mo-95 0.000000e+00 0.000000e+00 +52 1 1 Tc-99 0.000000e+00 0.000000e+00 +53 1 1 Ru-101 0.000000e+00 0.000000e+00 +54 1 1 Ru-103 0.000000e+00 0.000000e+00 +55 1 1 Ag-109 0.000000e+00 0.000000e+00 +56 1 1 Xe-135 0.000000e+00 0.000000e+00 +57 1 1 Cs-133 0.000000e+00 0.000000e+00 +58 1 1 Nd-143 0.000000e+00 0.000000e+00 +59 1 1 Nd-145 0.000000e+00 0.000000e+00 +60 1 1 Sm-147 0.000000e+00 0.000000e+00 +61 1 1 Sm-149 0.000000e+00 0.000000e+00 +62 1 1 Sm-150 0.000000e+00 0.000000e+00 +63 1 1 Sm-151 0.000000e+00 0.000000e+00 +64 1 1 Sm-152 0.000000e+00 0.000000e+00 +65 1 1 Eu-153 0.000000e+00 0.000000e+00 +66 1 1 Gd-155 0.000000e+00 0.000000e+00 +67 1 1 O-16 0.000000e+00 0.000000e+00 +0 1 2 U-234 4.267300e-07 3.529845e-08 +1 1 2 U-235 3.629246e-01 2.964548e-02 +2 1 2 U-236 5.921657e-06 4.881464e-07 +3 1 2 U-238 5.196256e-07 4.286610e-08 +4 1 2 Np-237 2.424211e-07 1.741823e-08 +5 1 2 Pu-238 3.255627e-05 2.692686e-06 +6 1 2 Pu-239 2.868384e-01 2.056896e-02 +7 1 2 Pu-240 4.398266e-06 3.658267e-07 +8 1 2 Pu-241 4.607239e-02 3.797176e-03 +9 1 2 Pu-242 8.451967e-08 6.979002e-09 +10 1 2 Am-241 4.678607e-06 3.253889e-07 +11 1 2 Am-242m 1.417675e-04 1.218350e-05 +12 1 2 Am-243 7.648834e-08 6.303843e-09 +13 1 2 Cm-242 9.433314e-07 7.794362e-08 +14 1 2 Cm-243 1.767995e-06 1.454123e-07 +15 1 2 Cm-244 1.533962e-07 1.266951e-08 +16 1 2 Cm-245 1.145063e-05 9.419051e-07 +17 1 2 Mo-95 0.000000e+00 0.000000e+00 +18 1 2 Tc-99 0.000000e+00 0.000000e+00 +19 1 2 Ru-101 0.000000e+00 0.000000e+00 +20 1 2 Ru-103 0.000000e+00 0.000000e+00 +21 1 2 Ag-109 0.000000e+00 0.000000e+00 +22 1 2 Xe-135 0.000000e+00 0.000000e+00 +23 1 2 Cs-133 0.000000e+00 0.000000e+00 +24 1 2 Nd-143 0.000000e+00 0.000000e+00 +25 1 2 Nd-145 0.000000e+00 0.000000e+00 +26 1 2 Sm-147 0.000000e+00 0.000000e+00 +27 1 2 Sm-149 0.000000e+00 0.000000e+00 +28 1 2 Sm-150 0.000000e+00 0.000000e+00 +29 1 2 Sm-151 0.000000e+00 0.000000e+00 +30 1 2 Sm-152 0.000000e+00 0.000000e+00 +31 1 2 Eu-153 0.000000e+00 0.000000e+00 +32 1 2 Gd-155 0.000000e+00 0.000000e+00 +33 1 2 O-16 0.000000e+00 0.000000e+00 material group in group out nuclide mean std. dev. +102 1 1 1 U-234 0.000000 0.000000 +103 1 1 1 U-235 0.002846 0.001185 +104 1 1 1 U-236 0.001951 0.000829 +105 1 1 1 U-238 0.197520 0.011618 +106 1 1 1 Np-237 0.000000 0.000000 +107 1 1 1 Pu-238 0.000000 0.000000 +108 1 1 1 Pu-239 0.001285 0.000461 +109 1 1 1 Pu-240 0.001027 0.000635 +110 1 1 1 Pu-241 0.000004 0.000242 +111 1 1 1 Pu-242 0.000481 0.000372 +112 1 1 1 Am-241 0.000000 0.000000 +113 1 1 1 Am-242m 0.000000 0.000000 +114 1 1 1 Am-243 0.000000 0.000000 +115 1 1 1 Cm-242 0.000000 0.000000 +116 1 1 1 Cm-243 0.000000 0.000000 +117 1 1 1 Cm-244 0.000000 0.000000 +118 1 1 1 Cm-245 0.000000 0.000000 +119 1 1 1 Mo-95 0.000302 0.000216 +120 1 1 1 Tc-99 0.000262 0.000195 +121 1 1 1 Ru-101 0.000000 0.000000 +122 1 1 1 Ru-103 0.000000 0.000000 +123 1 1 1 Ag-109 0.000000 0.000000 +124 1 1 1 Xe-135 0.000000 0.000000 +125 1 1 1 Cs-133 0.000016 0.000234 +126 1 1 1 Nd-143 0.000721 0.000364 +127 1 1 1 Nd-145 0.000463 0.000281 +128 1 1 1 Sm-147 0.000009 0.000238 +129 1 1 1 Sm-149 0.000000 0.000000 +130 1 1 1 Sm-150 0.000003 0.000243 +131 1 1 1 Sm-151 0.000000 0.000000 +132 1 1 1 Sm-152 0.000700 0.000424 +133 1 1 1 Eu-153 0.000000 0.000000 +134 1 1 1 Gd-155 0.000000 0.000000 +135 1 1 1 O-16 0.142333 0.008156 +68 1 1 2 U-234 0.000000 0.000000 +69 1 1 2 U-235 0.000000 0.000000 +70 1 1 2 U-236 0.000000 0.000000 +71 1 1 2 U-238 0.000000 0.000000 +72 1 1 2 Np-237 0.000000 0.000000 +73 1 1 2 Pu-238 0.000000 0.000000 +74 1 1 2 Pu-239 0.000000 0.000000 +75 1 1 2 Pu-240 0.000000 0.000000 +76 1 1 2 Pu-241 0.000000 0.000000 +77 1 1 2 Pu-242 0.000000 0.000000 +78 1 1 2 Am-241 0.000000 0.000000 +79 1 1 2 Am-242m 0.000000 0.000000 +80 1 1 2 Am-243 0.000000 0.000000 +81 1 1 2 Cm-242 0.000000 0.000000 +82 1 1 2 Cm-243 0.000000 0.000000 +83 1 1 2 Cm-244 0.000000 0.000000 +84 1 1 2 Cm-245 0.000000 0.000000 +85 1 1 2 Mo-95 0.000000 0.000000 +86 1 1 2 Tc-99 0.000000 0.000000 +87 1 1 2 Ru-101 0.000000 0.000000 +88 1 1 2 Ru-103 0.000000 0.000000 +89 1 1 2 Ag-109 0.000000 0.000000 +90 1 1 2 Xe-135 0.000000 0.000000 +91 1 1 2 Cs-133 0.000000 0.000000 +92 1 1 2 Nd-143 0.000000 0.000000 +93 1 1 2 Nd-145 0.000000 0.000000 +94 1 1 2 Sm-147 0.000000 0.000000 +95 1 1 2 Sm-149 0.000000 0.000000 +96 1 1 2 Sm-150 0.000000 0.000000 +97 1 1 2 Sm-151 0.000000 0.000000 +98 1 1 2 Sm-152 0.000000 0.000000 +99 1 1 2 Eu-153 0.000000 0.000000 +100 1 1 2 Gd-155 0.000000 0.000000 +101 1 1 2 O-16 0.000173 0.000173 +34 1 2 1 U-234 0.000000 0.000000 +35 1 2 1 U-235 0.000000 0.000000 +36 1 2 1 U-236 0.000000 0.000000 +37 1 2 1 U-238 0.000000 0.000000 +38 1 2 1 Np-237 0.000000 0.000000 +39 1 2 1 Pu-238 0.000000 0.000000 +40 1 2 1 Pu-239 0.000000 0.000000 +41 1 2 1 Pu-240 0.000000 0.000000 +42 1 2 1 Pu-241 0.000000 0.000000 +43 1 2 1 Pu-242 0.000000 0.000000 +44 1 2 1 Am-241 0.000000 0.000000 +45 1 2 1 Am-242m 0.000000 0.000000 +46 1 2 1 Am-243 0.000000 0.000000 +47 1 2 1 Cm-242 0.000000 0.000000 +48 1 2 1 Cm-243 0.000000 0.000000 +49 1 2 1 Cm-244 0.000000 0.000000 +50 1 2 1 Cm-245 0.000000 0.000000 +51 1 2 1 Mo-95 0.000000 0.000000 +52 1 2 1 Tc-99 0.000000 0.000000 +53 1 2 1 Ru-101 0.000000 0.000000 +54 1 2 1 Ru-103 0.000000 0.000000 +55 1 2 1 Ag-109 0.000000 0.000000 +56 1 2 1 Xe-135 0.000000 0.000000 +57 1 2 1 Cs-133 0.000000 0.000000 +58 1 2 1 Nd-143 0.000000 0.000000 +59 1 2 1 Nd-145 0.000000 0.000000 +60 1 2 1 Sm-147 0.000000 0.000000 +61 1 2 1 Sm-149 0.000000 0.000000 +62 1 2 1 Sm-150 0.000000 0.000000 +63 1 2 1 Sm-151 0.000000 0.000000 +64 1 2 1 Sm-152 0.000000 0.000000 +65 1 2 1 Eu-153 0.000000 0.000000 +66 1 2 1 Gd-155 0.000000 0.000000 +67 1 2 1 O-16 0.001948 0.001952 +0 1 2 2 U-234 0.000000 0.000000 +1 1 2 2 U-235 0.010470 0.006106 +2 1 2 2 U-236 0.000000 0.000000 +3 1 2 2 U-238 0.208109 0.039197 +4 1 2 2 Np-237 0.000000 0.000000 +5 1 2 2 Pu-238 0.000000 0.000000 +6 1 2 2 Pu-239 0.000000 0.000000 +7 1 2 2 Pu-240 0.000000 0.000000 +8 1 2 2 Pu-241 0.000000 0.000000 +9 1 2 2 Pu-242 0.000000 0.000000 +10 1 2 2 Am-241 0.000000 0.000000 +11 1 2 2 Am-242m 0.000000 0.000000 +12 1 2 2 Am-243 0.000000 0.000000 +13 1 2 2 Cm-242 0.000000 0.000000 +14 1 2 2 Cm-243 0.000000 0.000000 +15 1 2 2 Cm-244 0.000000 0.000000 +16 1 2 2 Cm-245 0.000000 0.000000 +17 1 2 2 Mo-95 0.000302 0.002551 +18 1 2 2 Tc-99 0.003544 0.002528 +19 1 2 2 Ru-101 0.000000 0.000000 +20 1 2 2 Ru-103 0.000000 0.000000 +21 1 2 2 Ag-109 0.000000 0.000000 +22 1 2 2 Xe-135 0.000000 0.000000 +23 1 2 2 Cs-133 0.000000 0.000000 +24 1 2 2 Nd-143 0.002636 0.002073 +25 1 2 2 Nd-145 0.000000 0.000000 +26 1 2 2 Sm-147 0.000000 0.000000 +27 1 2 2 Sm-149 0.000000 0.000000 +28 1 2 2 Sm-150 0.000000 0.000000 +29 1 2 2 Sm-151 0.000000 0.000000 +30 1 2 2 Sm-152 0.000000 0.000000 +31 1 2 2 Eu-153 0.001686 0.001968 +32 1 2 2 Gd-155 0.000000 0.000000 +33 1 2 2 O-16 0.152859 0.022894 material group out nuclide mean std. dev. +34 1 1 U-234 0 0.000000 +35 1 1 U-235 1 0.127079 +36 1 1 U-236 0 0.000000 +37 1 1 U-238 1 0.153215 +38 1 1 Np-237 0 0.000000 +39 1 1 Pu-238 0 0.000000 +40 1 1 Pu-239 1 0.150979 +41 1 1 Pu-240 0 0.000000 +42 1 1 Pu-241 1 0.203534 +43 1 1 Pu-242 0 0.000000 +44 1 1 Am-241 0 0.000000 +45 1 1 Am-242m 0 0.000000 +46 1 1 Am-243 0 0.000000 +47 1 1 Cm-242 0 0.000000 +48 1 1 Cm-243 0 0.000000 +49 1 1 Cm-244 0 0.000000 +50 1 1 Cm-245 0 0.000000 +51 1 1 Mo-95 0 0.000000 +52 1 1 Tc-99 0 0.000000 +53 1 1 Ru-101 0 0.000000 +54 1 1 Ru-103 0 0.000000 +55 1 1 Ag-109 0 0.000000 +56 1 1 Xe-135 0 0.000000 +57 1 1 Cs-133 0 0.000000 +58 1 1 Nd-143 0 0.000000 +59 1 1 Nd-145 0 0.000000 +60 1 1 Sm-147 0 0.000000 +61 1 1 Sm-149 0 0.000000 +62 1 1 Sm-150 0 0.000000 +63 1 1 Sm-151 0 0.000000 +64 1 1 Sm-152 0 0.000000 +65 1 1 Eu-153 0 0.000000 +66 1 1 Gd-155 0 0.000000 +67 1 1 O-16 0 0.000000 +0 1 2 U-234 0 0.000000 +1 1 2 U-235 0 0.000000 +2 1 2 U-236 0 0.000000 +3 1 2 U-238 0 0.000000 +4 1 2 Np-237 0 0.000000 +5 1 2 Pu-238 0 0.000000 +6 1 2 Pu-239 0 0.000000 +7 1 2 Pu-240 0 0.000000 +8 1 2 Pu-241 0 0.000000 +9 1 2 Pu-242 0 0.000000 +10 1 2 Am-241 0 0.000000 +11 1 2 Am-242m 0 0.000000 +12 1 2 Am-243 0 0.000000 +13 1 2 Cm-242 0 0.000000 +14 1 2 Cm-243 0 0.000000 +15 1 2 Cm-244 0 0.000000 +16 1 2 Cm-245 0 0.000000 +17 1 2 Mo-95 0 0.000000 +18 1 2 Tc-99 0 0.000000 +19 1 2 Ru-101 0 0.000000 +20 1 2 Ru-103 0 0.000000 +21 1 2 Ag-109 0 0.000000 +22 1 2 Xe-135 0 0.000000 +23 1 2 Cs-133 0 0.000000 +24 1 2 Nd-143 0 0.000000 +25 1 2 Nd-145 0 0.000000 +26 1 2 Sm-147 0 0.000000 +27 1 2 Sm-149 0 0.000000 +28 1 2 Sm-150 0 0.000000 +29 1 2 Sm-151 0 0.000000 +30 1 2 Sm-152 0 0.000000 +31 1 2 Eu-153 0 0.000000 +32 1 2 Gd-155 0 0.000000 +33 1 2 O-16 0 0.000000 material group in nuclide mean std. dev. +5 2 1 Zr-90 0.118578 0.008347 +6 2 1 Zr-91 0.040887 0.002988 +7 2 1 Zr-92 0.033882 0.004365 +8 2 1 Zr-94 0.046281 0.005422 +9 2 1 Zr-96 0.005415 0.002113 +0 2 2 Zr-90 0.122479 0.032627 +1 2 2 Zr-91 0.035669 0.009683 +2 2 2 Zr-92 0.049331 0.021936 +3 2 2 Zr-94 0.058978 0.020081 +4 2 2 Zr-96 0.000000 0.000000 material group in nuclide mean std. dev. +5 2 1 Zr-90 0 0 +6 2 1 Zr-91 0 0 +7 2 1 Zr-92 0 0 +8 2 1 Zr-94 0 0 +9 2 1 Zr-96 0 0 +0 2 2 Zr-90 0 0 +1 2 2 Zr-91 0 0 +2 2 2 Zr-92 0 0 +3 2 2 Zr-94 0 0 +4 2 2 Zr-96 0 0 material group in group out nuclide mean std. dev. +15 2 1 1 Zr-90 0.118578 0.008347 +16 2 1 1 Zr-91 0.039963 0.003053 +17 2 1 1 Zr-92 0.033882 0.004365 +18 2 1 1 Zr-94 0.046281 0.005422 +19 2 1 1 Zr-96 0.004953 0.002087 +10 2 1 2 Zr-90 0.000000 0.000000 +11 2 1 2 Zr-91 0.000000 0.000000 +12 2 1 2 Zr-92 0.000000 0.000000 +13 2 1 2 Zr-94 0.000000 0.000000 +14 2 1 2 Zr-96 0.000000 0.000000 +5 2 2 1 Zr-90 0.000000 0.000000 +6 2 2 1 Zr-91 0.000000 0.000000 +7 2 2 1 Zr-92 0.000000 0.000000 +8 2 2 1 Zr-94 0.000000 0.000000 +9 2 2 1 Zr-96 0.000000 0.000000 +0 2 2 2 Zr-90 0.122479 0.032627 +1 2 2 2 Zr-91 0.023998 0.011915 +2 2 2 2 Zr-92 0.049331 0.021936 +3 2 2 2 Zr-94 0.058978 0.020081 +4 2 2 2 Zr-96 0.000000 0.000000 material group out nuclide mean std. dev. +5 2 1 Zr-90 0 0 +6 2 1 Zr-91 0 0 +7 2 1 Zr-92 0 0 +8 2 1 Zr-94 0 0 +9 2 1 Zr-96 0 0 +0 2 2 Zr-90 0 0 +1 2 2 Zr-91 0 0 +2 2 2 Zr-92 0 0 +3 2 2 Zr-94 0 0 +4 2 2 Zr-96 0 0 material group in nuclide mean std. dev. +4 3 1 H-1 0.206179 0.034791 +5 3 1 O-16 0.075190 0.004750 +6 3 1 B-10 0.000741 0.000470 +7 3 1 B-11 0.000167 0.000208 +0 3 2 H-1 1.323003 0.239067 +1 3 2 O-16 0.071243 0.013291 +2 3 2 B-10 0.033075 0.004283 +3 3 2 B-11 0.000000 0.000000 material group in nuclide mean std. dev. +4 3 1 H-1 0 0 +5 3 1 O-16 0 0 +6 3 1 B-10 0 0 +7 3 1 B-11 0 0 +0 3 2 H-1 0 0 +1 3 2 O-16 0 0 +2 3 2 B-10 0 0 +3 3 2 B-11 0 0 material group in group out nuclide mean std. dev. +12 3 1 1 H-1 0.178758 0.033618 +13 3 1 1 O-16 0.075042 0.004782 +14 3 1 1 B-10 0.000000 0.000000 +15 3 1 1 B-11 0.000167 0.000208 +8 3 1 2 H-1 0.027124 0.001806 +9 3 1 2 O-16 0.000148 0.000148 +10 3 1 2 B-10 0.000000 0.000000 +11 3 1 2 B-11 0.000000 0.000000 +4 3 2 1 H-1 0.000000 0.000000 +5 3 2 1 O-16 0.000000 0.000000 +6 3 2 1 B-10 0.000000 0.000000 +7 3 2 1 B-11 0.000000 0.000000 +0 3 2 2 H-1 1.305284 0.235145 +1 3 2 2 O-16 0.071243 0.013291 +2 3 2 2 B-10 0.000000 0.000000 +3 3 2 2 B-11 0.000000 0.000000 material group out nuclide mean std. dev. +4 3 1 H-1 0 0 +5 3 1 O-16 0 0 +6 3 1 B-10 0 0 +7 3 1 B-11 0 0 +0 3 2 H-1 0 0 +1 3 2 O-16 0 0 +2 3 2 B-10 0 0 +3 3 2 B-11 0 0 material group in nuclide mean std. dev. +4 4 1 H-1 0.188813 0.045599 +5 4 1 O-16 0.066636 0.008217 +6 4 1 B-10 0.000232 0.000233 +7 4 1 B-11 0.000042 0.000300 +0 4 2 H-1 1.088920 0.221595 +1 4 2 O-16 0.064481 0.014318 +2 4 2 B-10 0.026367 0.010478 +3 4 2 B-11 0.000000 0.000000 material group in nuclide mean std. dev. +4 4 1 H-1 0 0 +5 4 1 O-16 0 0 +6 4 1 B-10 0 0 +7 4 1 B-11 0 0 +0 4 2 H-1 0 0 +1 4 2 O-16 0 0 +2 4 2 B-10 0 0 +3 4 2 B-11 0 0 material group in group out nuclide mean std. dev. +12 4 1 1 H-1 0.166764 0.043861 +13 4 1 1 O-16 0.066172 0.007943 +14 4 1 1 B-10 0.000000 0.000000 +15 4 1 1 B-11 0.000042 0.000300 +8 4 1 2 H-1 0.021817 0.002327 +9 4 1 2 O-16 0.000464 0.000466 +10 4 1 2 B-10 0.000000 0.000000 +11 4 1 2 B-11 0.000000 0.000000 +4 4 2 1 H-1 0.000000 0.000000 +5 4 2 1 O-16 0.000000 0.000000 +6 4 2 1 B-10 0.000000 0.000000 +7 4 2 1 B-11 0.000000 0.000000 +0 4 2 2 H-1 1.082328 0.222438 +1 4 2 2 O-16 0.064481 0.014318 +2 4 2 2 B-10 0.000000 0.000000 +3 4 2 2 B-11 0.000000 0.000000 material group out nuclide mean std. dev. +4 4 1 H-1 0 0 +5 4 1 O-16 0 0 +6 4 1 B-10 0 0 +7 4 1 B-11 0 0 +0 4 2 H-1 0 0 +1 4 2 O-16 0 0 +2 4 2 B-10 0 0 +3 4 2 B-11 0 0 material group in nuclide mean std. dev. +27 5 1 Fe-54 0 0 +28 5 1 Fe-56 0 0 +29 5 1 Fe-57 0 0 +30 5 1 Fe-58 0 0 +31 5 1 Ni-58 0 0 +32 5 1 Ni-60 0 0 +33 5 1 Ni-61 0 0 +34 5 1 Ni-62 0 0 +35 5 1 Ni-64 0 0 +36 5 1 Mn-55 0 0 +37 5 1 Mo-92 0 0 +38 5 1 Mo-94 0 0 +39 5 1 Mo-95 0 0 +40 5 1 Mo-96 0 0 +41 5 1 Mo-97 0 0 +42 5 1 Mo-98 0 0 +43 5 1 Mo-100 0 0 +44 5 1 Si-28 0 0 +45 5 1 Si-29 0 0 +46 5 1 Si-30 0 0 +47 5 1 Cr-50 0 0 +48 5 1 Cr-52 0 0 +49 5 1 Cr-53 0 0 +50 5 1 Cr-54 0 0 +51 5 1 C-Nat 0 0 +52 5 1 Cu-63 0 0 +53 5 1 Cu-65 0 0 +0 5 2 Fe-54 0 0 +1 5 2 Fe-56 0 0 +2 5 2 Fe-57 0 0 +3 5 2 Fe-58 0 0 +4 5 2 Ni-58 0 0 +5 5 2 Ni-60 0 0 +6 5 2 Ni-61 0 0 +7 5 2 Ni-62 0 0 +8 5 2 Ni-64 0 0 +9 5 2 Mn-55 0 0 +10 5 2 Mo-92 0 0 +11 5 2 Mo-94 0 0 +12 5 2 Mo-95 0 0 +13 5 2 Mo-96 0 0 +14 5 2 Mo-97 0 0 +15 5 2 Mo-98 0 0 +16 5 2 Mo-100 0 0 +17 5 2 Si-28 0 0 +18 5 2 Si-29 0 0 +19 5 2 Si-30 0 0 +20 5 2 Cr-50 0 0 +21 5 2 Cr-52 0 0 +22 5 2 Cr-53 0 0 +23 5 2 Cr-54 0 0 +24 5 2 C-Nat 0 0 +25 5 2 Cu-63 0 0 +26 5 2 Cu-65 0 0 material group in nuclide mean std. dev. +27 5 1 Fe-54 0 0 +28 5 1 Fe-56 0 0 +29 5 1 Fe-57 0 0 +30 5 1 Fe-58 0 0 +31 5 1 Ni-58 0 0 +32 5 1 Ni-60 0 0 +33 5 1 Ni-61 0 0 +34 5 1 Ni-62 0 0 +35 5 1 Ni-64 0 0 +36 5 1 Mn-55 0 0 +37 5 1 Mo-92 0 0 +38 5 1 Mo-94 0 0 +39 5 1 Mo-95 0 0 +40 5 1 Mo-96 0 0 +41 5 1 Mo-97 0 0 +42 5 1 Mo-98 0 0 +43 5 1 Mo-100 0 0 +44 5 1 Si-28 0 0 +45 5 1 Si-29 0 0 +46 5 1 Si-30 0 0 +47 5 1 Cr-50 0 0 +48 5 1 Cr-52 0 0 +49 5 1 Cr-53 0 0 +50 5 1 Cr-54 0 0 +51 5 1 C-Nat 0 0 +52 5 1 Cu-63 0 0 +53 5 1 Cu-65 0 0 +0 5 2 Fe-54 0 0 +1 5 2 Fe-56 0 0 +2 5 2 Fe-57 0 0 +3 5 2 Fe-58 0 0 +4 5 2 Ni-58 0 0 +5 5 2 Ni-60 0 0 +6 5 2 Ni-61 0 0 +7 5 2 Ni-62 0 0 +8 5 2 Ni-64 0 0 +9 5 2 Mn-55 0 0 +10 5 2 Mo-92 0 0 +11 5 2 Mo-94 0 0 +12 5 2 Mo-95 0 0 +13 5 2 Mo-96 0 0 +14 5 2 Mo-97 0 0 +15 5 2 Mo-98 0 0 +16 5 2 Mo-100 0 0 +17 5 2 Si-28 0 0 +18 5 2 Si-29 0 0 +19 5 2 Si-30 0 0 +20 5 2 Cr-50 0 0 +21 5 2 Cr-52 0 0 +22 5 2 Cr-53 0 0 +23 5 2 Cr-54 0 0 +24 5 2 C-Nat 0 0 +25 5 2 Cu-63 0 0 +26 5 2 Cu-65 0 0 material group in group out nuclide mean std. dev. +81 5 1 1 Fe-54 0 0 +82 5 1 1 Fe-56 0 0 +83 5 1 1 Fe-57 0 0 +84 5 1 1 Fe-58 0 0 +85 5 1 1 Ni-58 0 0 +86 5 1 1 Ni-60 0 0 +87 5 1 1 Ni-61 0 0 +88 5 1 1 Ni-62 0 0 +89 5 1 1 Ni-64 0 0 +90 5 1 1 Mn-55 0 0 +91 5 1 1 Mo-92 0 0 +92 5 1 1 Mo-94 0 0 +93 5 1 1 Mo-95 0 0 +94 5 1 1 Mo-96 0 0 +95 5 1 1 Mo-97 0 0 +96 5 1 1 Mo-98 0 0 +97 5 1 1 Mo-100 0 0 +98 5 1 1 Si-28 0 0 +99 5 1 1 Si-29 0 0 +100 5 1 1 Si-30 0 0 +101 5 1 1 Cr-50 0 0 +102 5 1 1 Cr-52 0 0 +103 5 1 1 Cr-53 0 0 +104 5 1 1 Cr-54 0 0 +105 5 1 1 C-Nat 0 0 +106 5 1 1 Cu-63 0 0 +107 5 1 1 Cu-65 0 0 +54 5 1 2 Fe-54 0 0 +55 5 1 2 Fe-56 0 0 +56 5 1 2 Fe-57 0 0 +57 5 1 2 Fe-58 0 0 +58 5 1 2 Ni-58 0 0 +59 5 1 2 Ni-60 0 0 +60 5 1 2 Ni-61 0 0 +61 5 1 2 Ni-62 0 0 +62 5 1 2 Ni-64 0 0 +63 5 1 2 Mn-55 0 0 +64 5 1 2 Mo-92 0 0 +65 5 1 2 Mo-94 0 0 +66 5 1 2 Mo-95 0 0 +67 5 1 2 Mo-96 0 0 +68 5 1 2 Mo-97 0 0 +69 5 1 2 Mo-98 0 0 +70 5 1 2 Mo-100 0 0 +71 5 1 2 Si-28 0 0 +72 5 1 2 Si-29 0 0 +73 5 1 2 Si-30 0 0 +74 5 1 2 Cr-50 0 0 +75 5 1 2 Cr-52 0 0 +76 5 1 2 Cr-53 0 0 +77 5 1 2 Cr-54 0 0 +78 5 1 2 C-Nat 0 0 +79 5 1 2 Cu-63 0 0 +80 5 1 2 Cu-65 0 0 +27 5 2 1 Fe-54 0 0 +28 5 2 1 Fe-56 0 0 +29 5 2 1 Fe-57 0 0 +30 5 2 1 Fe-58 0 0 +31 5 2 1 Ni-58 0 0 +32 5 2 1 Ni-60 0 0 +33 5 2 1 Ni-61 0 0 +34 5 2 1 Ni-62 0 0 +35 5 2 1 Ni-64 0 0 +36 5 2 1 Mn-55 0 0 +37 5 2 1 Mo-92 0 0 +38 5 2 1 Mo-94 0 0 +39 5 2 1 Mo-95 0 0 +40 5 2 1 Mo-96 0 0 +41 5 2 1 Mo-97 0 0 +42 5 2 1 Mo-98 0 0 +43 5 2 1 Mo-100 0 0 +44 5 2 1 Si-28 0 0 +45 5 2 1 Si-29 0 0 +46 5 2 1 Si-30 0 0 +47 5 2 1 Cr-50 0 0 +48 5 2 1 Cr-52 0 0 +49 5 2 1 Cr-53 0 0 +50 5 2 1 Cr-54 0 0 +51 5 2 1 C-Nat 0 0 +52 5 2 1 Cu-63 0 0 +53 5 2 1 Cu-65 0 0 +0 5 2 2 Fe-54 0 0 +1 5 2 2 Fe-56 0 0 +2 5 2 2 Fe-57 0 0 +3 5 2 2 Fe-58 0 0 +4 5 2 2 Ni-58 0 0 +5 5 2 2 Ni-60 0 0 +6 5 2 2 Ni-61 0 0 +7 5 2 2 Ni-62 0 0 +8 5 2 2 Ni-64 0 0 +9 5 2 2 Mn-55 0 0 +10 5 2 2 Mo-92 0 0 +11 5 2 2 Mo-94 0 0 +12 5 2 2 Mo-95 0 0 +13 5 2 2 Mo-96 0 0 +14 5 2 2 Mo-97 0 0 +15 5 2 2 Mo-98 0 0 +16 5 2 2 Mo-100 0 0 +17 5 2 2 Si-28 0 0 +18 5 2 2 Si-29 0 0 +19 5 2 2 Si-30 0 0 +20 5 2 2 Cr-50 0 0 +21 5 2 2 Cr-52 0 0 +22 5 2 2 Cr-53 0 0 +23 5 2 2 Cr-54 0 0 +24 5 2 2 C-Nat 0 0 +25 5 2 2 Cu-63 0 0 +26 5 2 2 Cu-65 0 0 material group out nuclide mean std. dev. +27 5 1 Fe-54 0 0 +28 5 1 Fe-56 0 0 +29 5 1 Fe-57 0 0 +30 5 1 Fe-58 0 0 +31 5 1 Ni-58 0 0 +32 5 1 Ni-60 0 0 +33 5 1 Ni-61 0 0 +34 5 1 Ni-62 0 0 +35 5 1 Ni-64 0 0 +36 5 1 Mn-55 0 0 +37 5 1 Mo-92 0 0 +38 5 1 Mo-94 0 0 +39 5 1 Mo-95 0 0 +40 5 1 Mo-96 0 0 +41 5 1 Mo-97 0 0 +42 5 1 Mo-98 0 0 +43 5 1 Mo-100 0 0 +44 5 1 Si-28 0 0 +45 5 1 Si-29 0 0 +46 5 1 Si-30 0 0 +47 5 1 Cr-50 0 0 +48 5 1 Cr-52 0 0 +49 5 1 Cr-53 0 0 +50 5 1 Cr-54 0 0 +51 5 1 C-Nat 0 0 +52 5 1 Cu-63 0 0 +53 5 1 Cu-65 0 0 +0 5 2 Fe-54 0 0 +1 5 2 Fe-56 0 0 +2 5 2 Fe-57 0 0 +3 5 2 Fe-58 0 0 +4 5 2 Ni-58 0 0 +5 5 2 Ni-60 0 0 +6 5 2 Ni-61 0 0 +7 5 2 Ni-62 0 0 +8 5 2 Ni-64 0 0 +9 5 2 Mn-55 0 0 +10 5 2 Mo-92 0 0 +11 5 2 Mo-94 0 0 +12 5 2 Mo-95 0 0 +13 5 2 Mo-96 0 0 +14 5 2 Mo-97 0 0 +15 5 2 Mo-98 0 0 +16 5 2 Mo-100 0 0 +17 5 2 Si-28 0 0 +18 5 2 Si-29 0 0 +19 5 2 Si-30 0 0 +20 5 2 Cr-50 0 0 +21 5 2 Cr-52 0 0 +22 5 2 Cr-53 0 0 +23 5 2 Cr-54 0 0 +24 5 2 C-Nat 0 0 +25 5 2 Cu-63 0 0 +26 5 2 Cu-65 0 0 material group in nuclide mean std. dev. +21 6 1 H-1 0 0 +22 6 1 O-16 0 0 +23 6 1 B-10 0 0 +24 6 1 B-11 0 0 +25 6 1 Fe-54 0 0 +26 6 1 Fe-56 0 0 +27 6 1 Fe-57 0 0 +28 6 1 Fe-58 0 0 +29 6 1 Ni-58 0 0 +30 6 1 Ni-60 0 0 +31 6 1 Ni-61 0 0 +32 6 1 Ni-62 0 0 +33 6 1 Ni-64 0 0 +34 6 1 Mn-55 0 0 +35 6 1 Si-28 0 0 +36 6 1 Si-29 0 0 +37 6 1 Si-30 0 0 +38 6 1 Cr-50 0 0 +39 6 1 Cr-52 0 0 +40 6 1 Cr-53 0 0 +41 6 1 Cr-54 0 0 +0 6 2 H-1 0 0 +1 6 2 O-16 0 0 +2 6 2 B-10 0 0 +3 6 2 B-11 0 0 +4 6 2 Fe-54 0 0 +5 6 2 Fe-56 0 0 +6 6 2 Fe-57 0 0 +7 6 2 Fe-58 0 0 +8 6 2 Ni-58 0 0 +9 6 2 Ni-60 0 0 +10 6 2 Ni-61 0 0 +11 6 2 Ni-62 0 0 +12 6 2 Ni-64 0 0 +13 6 2 Mn-55 0 0 +14 6 2 Si-28 0 0 +15 6 2 Si-29 0 0 +16 6 2 Si-30 0 0 +17 6 2 Cr-50 0 0 +18 6 2 Cr-52 0 0 +19 6 2 Cr-53 0 0 +20 6 2 Cr-54 0 0 material group in nuclide mean std. dev. +21 6 1 H-1 0 0 +22 6 1 O-16 0 0 +23 6 1 B-10 0 0 +24 6 1 B-11 0 0 +25 6 1 Fe-54 0 0 +26 6 1 Fe-56 0 0 +27 6 1 Fe-57 0 0 +28 6 1 Fe-58 0 0 +29 6 1 Ni-58 0 0 +30 6 1 Ni-60 0 0 +31 6 1 Ni-61 0 0 +32 6 1 Ni-62 0 0 +33 6 1 Ni-64 0 0 +34 6 1 Mn-55 0 0 +35 6 1 Si-28 0 0 +36 6 1 Si-29 0 0 +37 6 1 Si-30 0 0 +38 6 1 Cr-50 0 0 +39 6 1 Cr-52 0 0 +40 6 1 Cr-53 0 0 +41 6 1 Cr-54 0 0 +0 6 2 H-1 0 0 +1 6 2 O-16 0 0 +2 6 2 B-10 0 0 +3 6 2 B-11 0 0 +4 6 2 Fe-54 0 0 +5 6 2 Fe-56 0 0 +6 6 2 Fe-57 0 0 +7 6 2 Fe-58 0 0 +8 6 2 Ni-58 0 0 +9 6 2 Ni-60 0 0 +10 6 2 Ni-61 0 0 +11 6 2 Ni-62 0 0 +12 6 2 Ni-64 0 0 +13 6 2 Mn-55 0 0 +14 6 2 Si-28 0 0 +15 6 2 Si-29 0 0 +16 6 2 Si-30 0 0 +17 6 2 Cr-50 0 0 +18 6 2 Cr-52 0 0 +19 6 2 Cr-53 0 0 +20 6 2 Cr-54 0 0 material group in group out nuclide mean std. dev. +63 6 1 1 H-1 0 0 +64 6 1 1 O-16 0 0 +65 6 1 1 B-10 0 0 +66 6 1 1 B-11 0 0 +67 6 1 1 Fe-54 0 0 +68 6 1 1 Fe-56 0 0 +69 6 1 1 Fe-57 0 0 +70 6 1 1 Fe-58 0 0 +71 6 1 1 Ni-58 0 0 +72 6 1 1 Ni-60 0 0 +73 6 1 1 Ni-61 0 0 +74 6 1 1 Ni-62 0 0 +75 6 1 1 Ni-64 0 0 +76 6 1 1 Mn-55 0 0 +77 6 1 1 Si-28 0 0 +78 6 1 1 Si-29 0 0 +79 6 1 1 Si-30 0 0 +80 6 1 1 Cr-50 0 0 +81 6 1 1 Cr-52 0 0 +82 6 1 1 Cr-53 0 0 +83 6 1 1 Cr-54 0 0 +42 6 1 2 H-1 0 0 +43 6 1 2 O-16 0 0 +44 6 1 2 B-10 0 0 +45 6 1 2 B-11 0 0 +46 6 1 2 Fe-54 0 0 +47 6 1 2 Fe-56 0 0 +48 6 1 2 Fe-57 0 0 +49 6 1 2 Fe-58 0 0 +50 6 1 2 Ni-58 0 0 +51 6 1 2 Ni-60 0 0 +52 6 1 2 Ni-61 0 0 +53 6 1 2 Ni-62 0 0 +54 6 1 2 Ni-64 0 0 +55 6 1 2 Mn-55 0 0 +56 6 1 2 Si-28 0 0 +57 6 1 2 Si-29 0 0 +58 6 1 2 Si-30 0 0 +59 6 1 2 Cr-50 0 0 +60 6 1 2 Cr-52 0 0 +61 6 1 2 Cr-53 0 0 +62 6 1 2 Cr-54 0 0 +21 6 2 1 H-1 0 0 +22 6 2 1 O-16 0 0 +23 6 2 1 B-10 0 0 +24 6 2 1 B-11 0 0 +25 6 2 1 Fe-54 0 0 +26 6 2 1 Fe-56 0 0 +27 6 2 1 Fe-57 0 0 +28 6 2 1 Fe-58 0 0 +29 6 2 1 Ni-58 0 0 +30 6 2 1 Ni-60 0 0 +31 6 2 1 Ni-61 0 0 +32 6 2 1 Ni-62 0 0 +33 6 2 1 Ni-64 0 0 +34 6 2 1 Mn-55 0 0 +35 6 2 1 Si-28 0 0 +36 6 2 1 Si-29 0 0 +37 6 2 1 Si-30 0 0 +38 6 2 1 Cr-50 0 0 +39 6 2 1 Cr-52 0 0 +40 6 2 1 Cr-53 0 0 +41 6 2 1 Cr-54 0 0 +0 6 2 2 H-1 0 0 +1 6 2 2 O-16 0 0 +2 6 2 2 B-10 0 0 +3 6 2 2 B-11 0 0 +4 6 2 2 Fe-54 0 0 +5 6 2 2 Fe-56 0 0 +6 6 2 2 Fe-57 0 0 +7 6 2 2 Fe-58 0 0 +8 6 2 2 Ni-58 0 0 +9 6 2 2 Ni-60 0 0 +10 6 2 2 Ni-61 0 0 +11 6 2 2 Ni-62 0 0 +12 6 2 2 Ni-64 0 0 +13 6 2 2 Mn-55 0 0 +14 6 2 2 Si-28 0 0 +15 6 2 2 Si-29 0 0 +16 6 2 2 Si-30 0 0 +17 6 2 2 Cr-50 0 0 +18 6 2 2 Cr-52 0 0 +19 6 2 2 Cr-53 0 0 +20 6 2 2 Cr-54 0 0 material group out nuclide mean std. dev. +21 6 1 H-1 0 0 +22 6 1 O-16 0 0 +23 6 1 B-10 0 0 +24 6 1 B-11 0 0 +25 6 1 Fe-54 0 0 +26 6 1 Fe-56 0 0 +27 6 1 Fe-57 0 0 +28 6 1 Fe-58 0 0 +29 6 1 Ni-58 0 0 +30 6 1 Ni-60 0 0 +31 6 1 Ni-61 0 0 +32 6 1 Ni-62 0 0 +33 6 1 Ni-64 0 0 +34 6 1 Mn-55 0 0 +35 6 1 Si-28 0 0 +36 6 1 Si-29 0 0 +37 6 1 Si-30 0 0 +38 6 1 Cr-50 0 0 +39 6 1 Cr-52 0 0 +40 6 1 Cr-53 0 0 +41 6 1 Cr-54 0 0 +0 6 2 H-1 0 0 +1 6 2 O-16 0 0 +2 6 2 B-10 0 0 +3 6 2 B-11 0 0 +4 6 2 Fe-54 0 0 +5 6 2 Fe-56 0 0 +6 6 2 Fe-57 0 0 +7 6 2 Fe-58 0 0 +8 6 2 Ni-58 0 0 +9 6 2 Ni-60 0 0 +10 6 2 Ni-61 0 0 +11 6 2 Ni-62 0 0 +12 6 2 Ni-64 0 0 +13 6 2 Mn-55 0 0 +14 6 2 Si-28 0 0 +15 6 2 Si-29 0 0 +16 6 2 Si-30 0 0 +17 6 2 Cr-50 0 0 +18 6 2 Cr-52 0 0 +19 6 2 Cr-53 0 0 +20 6 2 Cr-54 0 0 material group in nuclide mean std. dev. +21 7 1 H-1 0 0 +22 7 1 O-16 0 0 +23 7 1 B-10 0 0 +24 7 1 B-11 0 0 +25 7 1 Fe-54 0 0 +26 7 1 Fe-56 0 0 +27 7 1 Fe-57 0 0 +28 7 1 Fe-58 0 0 +29 7 1 Ni-58 0 0 +30 7 1 Ni-60 0 0 +31 7 1 Ni-61 0 0 +32 7 1 Ni-62 0 0 +33 7 1 Ni-64 0 0 +34 7 1 Mn-55 0 0 +35 7 1 Si-28 0 0 +36 7 1 Si-29 0 0 +37 7 1 Si-30 0 0 +38 7 1 Cr-50 0 0 +39 7 1 Cr-52 0 0 +40 7 1 Cr-53 0 0 +41 7 1 Cr-54 0 0 +0 7 2 H-1 0 0 +1 7 2 O-16 0 0 +2 7 2 B-10 0 0 +3 7 2 B-11 0 0 +4 7 2 Fe-54 0 0 +5 7 2 Fe-56 0 0 +6 7 2 Fe-57 0 0 +7 7 2 Fe-58 0 0 +8 7 2 Ni-58 0 0 +9 7 2 Ni-60 0 0 +10 7 2 Ni-61 0 0 +11 7 2 Ni-62 0 0 +12 7 2 Ni-64 0 0 +13 7 2 Mn-55 0 0 +14 7 2 Si-28 0 0 +15 7 2 Si-29 0 0 +16 7 2 Si-30 0 0 +17 7 2 Cr-50 0 0 +18 7 2 Cr-52 0 0 +19 7 2 Cr-53 0 0 +20 7 2 Cr-54 0 0 material group in nuclide mean std. dev. +21 7 1 H-1 0 0 +22 7 1 O-16 0 0 +23 7 1 B-10 0 0 +24 7 1 B-11 0 0 +25 7 1 Fe-54 0 0 +26 7 1 Fe-56 0 0 +27 7 1 Fe-57 0 0 +28 7 1 Fe-58 0 0 +29 7 1 Ni-58 0 0 +30 7 1 Ni-60 0 0 +31 7 1 Ni-61 0 0 +32 7 1 Ni-62 0 0 +33 7 1 Ni-64 0 0 +34 7 1 Mn-55 0 0 +35 7 1 Si-28 0 0 +36 7 1 Si-29 0 0 +37 7 1 Si-30 0 0 +38 7 1 Cr-50 0 0 +39 7 1 Cr-52 0 0 +40 7 1 Cr-53 0 0 +41 7 1 Cr-54 0 0 +0 7 2 H-1 0 0 +1 7 2 O-16 0 0 +2 7 2 B-10 0 0 +3 7 2 B-11 0 0 +4 7 2 Fe-54 0 0 +5 7 2 Fe-56 0 0 +6 7 2 Fe-57 0 0 +7 7 2 Fe-58 0 0 +8 7 2 Ni-58 0 0 +9 7 2 Ni-60 0 0 +10 7 2 Ni-61 0 0 +11 7 2 Ni-62 0 0 +12 7 2 Ni-64 0 0 +13 7 2 Mn-55 0 0 +14 7 2 Si-28 0 0 +15 7 2 Si-29 0 0 +16 7 2 Si-30 0 0 +17 7 2 Cr-50 0 0 +18 7 2 Cr-52 0 0 +19 7 2 Cr-53 0 0 +20 7 2 Cr-54 0 0 material group in group out nuclide mean std. dev. +63 7 1 1 H-1 0 0 +64 7 1 1 O-16 0 0 +65 7 1 1 B-10 0 0 +66 7 1 1 B-11 0 0 +67 7 1 1 Fe-54 0 0 +68 7 1 1 Fe-56 0 0 +69 7 1 1 Fe-57 0 0 +70 7 1 1 Fe-58 0 0 +71 7 1 1 Ni-58 0 0 +72 7 1 1 Ni-60 0 0 +73 7 1 1 Ni-61 0 0 +74 7 1 1 Ni-62 0 0 +75 7 1 1 Ni-64 0 0 +76 7 1 1 Mn-55 0 0 +77 7 1 1 Si-28 0 0 +78 7 1 1 Si-29 0 0 +79 7 1 1 Si-30 0 0 +80 7 1 1 Cr-50 0 0 +81 7 1 1 Cr-52 0 0 +82 7 1 1 Cr-53 0 0 +83 7 1 1 Cr-54 0 0 +42 7 1 2 H-1 0 0 +43 7 1 2 O-16 0 0 +44 7 1 2 B-10 0 0 +45 7 1 2 B-11 0 0 +46 7 1 2 Fe-54 0 0 +47 7 1 2 Fe-56 0 0 +48 7 1 2 Fe-57 0 0 +49 7 1 2 Fe-58 0 0 +50 7 1 2 Ni-58 0 0 +51 7 1 2 Ni-60 0 0 +52 7 1 2 Ni-61 0 0 +53 7 1 2 Ni-62 0 0 +54 7 1 2 Ni-64 0 0 +55 7 1 2 Mn-55 0 0 +56 7 1 2 Si-28 0 0 +57 7 1 2 Si-29 0 0 +58 7 1 2 Si-30 0 0 +59 7 1 2 Cr-50 0 0 +60 7 1 2 Cr-52 0 0 +61 7 1 2 Cr-53 0 0 +62 7 1 2 Cr-54 0 0 +21 7 2 1 H-1 0 0 +22 7 2 1 O-16 0 0 +23 7 2 1 B-10 0 0 +24 7 2 1 B-11 0 0 +25 7 2 1 Fe-54 0 0 +26 7 2 1 Fe-56 0 0 +27 7 2 1 Fe-57 0 0 +28 7 2 1 Fe-58 0 0 +29 7 2 1 Ni-58 0 0 +30 7 2 1 Ni-60 0 0 +31 7 2 1 Ni-61 0 0 +32 7 2 1 Ni-62 0 0 +33 7 2 1 Ni-64 0 0 +34 7 2 1 Mn-55 0 0 +35 7 2 1 Si-28 0 0 +36 7 2 1 Si-29 0 0 +37 7 2 1 Si-30 0 0 +38 7 2 1 Cr-50 0 0 +39 7 2 1 Cr-52 0 0 +40 7 2 1 Cr-53 0 0 +41 7 2 1 Cr-54 0 0 +0 7 2 2 H-1 0 0 +1 7 2 2 O-16 0 0 +2 7 2 2 B-10 0 0 +3 7 2 2 B-11 0 0 +4 7 2 2 Fe-54 0 0 +5 7 2 2 Fe-56 0 0 +6 7 2 2 Fe-57 0 0 +7 7 2 2 Fe-58 0 0 +8 7 2 2 Ni-58 0 0 +9 7 2 2 Ni-60 0 0 +10 7 2 2 Ni-61 0 0 +11 7 2 2 Ni-62 0 0 +12 7 2 2 Ni-64 0 0 +13 7 2 2 Mn-55 0 0 +14 7 2 2 Si-28 0 0 +15 7 2 2 Si-29 0 0 +16 7 2 2 Si-30 0 0 +17 7 2 2 Cr-50 0 0 +18 7 2 2 Cr-52 0 0 +19 7 2 2 Cr-53 0 0 +20 7 2 2 Cr-54 0 0 material group out nuclide mean std. dev. +21 7 1 H-1 0 0 +22 7 1 O-16 0 0 +23 7 1 B-10 0 0 +24 7 1 B-11 0 0 +25 7 1 Fe-54 0 0 +26 7 1 Fe-56 0 0 +27 7 1 Fe-57 0 0 +28 7 1 Fe-58 0 0 +29 7 1 Ni-58 0 0 +30 7 1 Ni-60 0 0 +31 7 1 Ni-61 0 0 +32 7 1 Ni-62 0 0 +33 7 1 Ni-64 0 0 +34 7 1 Mn-55 0 0 +35 7 1 Si-28 0 0 +36 7 1 Si-29 0 0 +37 7 1 Si-30 0 0 +38 7 1 Cr-50 0 0 +39 7 1 Cr-52 0 0 +40 7 1 Cr-53 0 0 +41 7 1 Cr-54 0 0 +0 7 2 H-1 0 0 +1 7 2 O-16 0 0 +2 7 2 B-10 0 0 +3 7 2 B-11 0 0 +4 7 2 Fe-54 0 0 +5 7 2 Fe-56 0 0 +6 7 2 Fe-57 0 0 +7 7 2 Fe-58 0 0 +8 7 2 Ni-58 0 0 +9 7 2 Ni-60 0 0 +10 7 2 Ni-61 0 0 +11 7 2 Ni-62 0 0 +12 7 2 Ni-64 0 0 +13 7 2 Mn-55 0 0 +14 7 2 Si-28 0 0 +15 7 2 Si-29 0 0 +16 7 2 Si-30 0 0 +17 7 2 Cr-50 0 0 +18 7 2 Cr-52 0 0 +19 7 2 Cr-53 0 0 +20 7 2 Cr-54 0 0 material group in nuclide mean std. dev. +21 8 1 H-1 0 0 +22 8 1 O-16 0 0 +23 8 1 B-10 0 0 +24 8 1 B-11 0 0 +25 8 1 Fe-54 0 0 +26 8 1 Fe-56 0 0 +27 8 1 Fe-57 0 0 +28 8 1 Fe-58 0 0 +29 8 1 Ni-58 0 0 +30 8 1 Ni-60 0 0 +31 8 1 Ni-61 0 0 +32 8 1 Ni-62 0 0 +33 8 1 Ni-64 0 0 +34 8 1 Mn-55 0 0 +35 8 1 Si-28 0 0 +36 8 1 Si-29 0 0 +37 8 1 Si-30 0 0 +38 8 1 Cr-50 0 0 +39 8 1 Cr-52 0 0 +40 8 1 Cr-53 0 0 +41 8 1 Cr-54 0 0 +0 8 2 H-1 0 0 +1 8 2 O-16 0 0 +2 8 2 B-10 0 0 +3 8 2 B-11 0 0 +4 8 2 Fe-54 0 0 +5 8 2 Fe-56 0 0 +6 8 2 Fe-57 0 0 +7 8 2 Fe-58 0 0 +8 8 2 Ni-58 0 0 +9 8 2 Ni-60 0 0 +10 8 2 Ni-61 0 0 +11 8 2 Ni-62 0 0 +12 8 2 Ni-64 0 0 +13 8 2 Mn-55 0 0 +14 8 2 Si-28 0 0 +15 8 2 Si-29 0 0 +16 8 2 Si-30 0 0 +17 8 2 Cr-50 0 0 +18 8 2 Cr-52 0 0 +19 8 2 Cr-53 0 0 +20 8 2 Cr-54 0 0 material group in nuclide mean std. dev. +21 8 1 H-1 0 0 +22 8 1 O-16 0 0 +23 8 1 B-10 0 0 +24 8 1 B-11 0 0 +25 8 1 Fe-54 0 0 +26 8 1 Fe-56 0 0 +27 8 1 Fe-57 0 0 +28 8 1 Fe-58 0 0 +29 8 1 Ni-58 0 0 +30 8 1 Ni-60 0 0 +31 8 1 Ni-61 0 0 +32 8 1 Ni-62 0 0 +33 8 1 Ni-64 0 0 +34 8 1 Mn-55 0 0 +35 8 1 Si-28 0 0 +36 8 1 Si-29 0 0 +37 8 1 Si-30 0 0 +38 8 1 Cr-50 0 0 +39 8 1 Cr-52 0 0 +40 8 1 Cr-53 0 0 +41 8 1 Cr-54 0 0 +0 8 2 H-1 0 0 +1 8 2 O-16 0 0 +2 8 2 B-10 0 0 +3 8 2 B-11 0 0 +4 8 2 Fe-54 0 0 +5 8 2 Fe-56 0 0 +6 8 2 Fe-57 0 0 +7 8 2 Fe-58 0 0 +8 8 2 Ni-58 0 0 +9 8 2 Ni-60 0 0 +10 8 2 Ni-61 0 0 +11 8 2 Ni-62 0 0 +12 8 2 Ni-64 0 0 +13 8 2 Mn-55 0 0 +14 8 2 Si-28 0 0 +15 8 2 Si-29 0 0 +16 8 2 Si-30 0 0 +17 8 2 Cr-50 0 0 +18 8 2 Cr-52 0 0 +19 8 2 Cr-53 0 0 +20 8 2 Cr-54 0 0 material group in group out nuclide mean std. dev. +63 8 1 1 H-1 0 0 +64 8 1 1 O-16 0 0 +65 8 1 1 B-10 0 0 +66 8 1 1 B-11 0 0 +67 8 1 1 Fe-54 0 0 +68 8 1 1 Fe-56 0 0 +69 8 1 1 Fe-57 0 0 +70 8 1 1 Fe-58 0 0 +71 8 1 1 Ni-58 0 0 +72 8 1 1 Ni-60 0 0 +73 8 1 1 Ni-61 0 0 +74 8 1 1 Ni-62 0 0 +75 8 1 1 Ni-64 0 0 +76 8 1 1 Mn-55 0 0 +77 8 1 1 Si-28 0 0 +78 8 1 1 Si-29 0 0 +79 8 1 1 Si-30 0 0 +80 8 1 1 Cr-50 0 0 +81 8 1 1 Cr-52 0 0 +82 8 1 1 Cr-53 0 0 +83 8 1 1 Cr-54 0 0 +42 8 1 2 H-1 0 0 +43 8 1 2 O-16 0 0 +44 8 1 2 B-10 0 0 +45 8 1 2 B-11 0 0 +46 8 1 2 Fe-54 0 0 +47 8 1 2 Fe-56 0 0 +48 8 1 2 Fe-57 0 0 +49 8 1 2 Fe-58 0 0 +50 8 1 2 Ni-58 0 0 +51 8 1 2 Ni-60 0 0 +52 8 1 2 Ni-61 0 0 +53 8 1 2 Ni-62 0 0 +54 8 1 2 Ni-64 0 0 +55 8 1 2 Mn-55 0 0 +56 8 1 2 Si-28 0 0 +57 8 1 2 Si-29 0 0 +58 8 1 2 Si-30 0 0 +59 8 1 2 Cr-50 0 0 +60 8 1 2 Cr-52 0 0 +61 8 1 2 Cr-53 0 0 +62 8 1 2 Cr-54 0 0 +21 8 2 1 H-1 0 0 +22 8 2 1 O-16 0 0 +23 8 2 1 B-10 0 0 +24 8 2 1 B-11 0 0 +25 8 2 1 Fe-54 0 0 +26 8 2 1 Fe-56 0 0 +27 8 2 1 Fe-57 0 0 +28 8 2 1 Fe-58 0 0 +29 8 2 1 Ni-58 0 0 +30 8 2 1 Ni-60 0 0 +31 8 2 1 Ni-61 0 0 +32 8 2 1 Ni-62 0 0 +33 8 2 1 Ni-64 0 0 +34 8 2 1 Mn-55 0 0 +35 8 2 1 Si-28 0 0 +36 8 2 1 Si-29 0 0 +37 8 2 1 Si-30 0 0 +38 8 2 1 Cr-50 0 0 +39 8 2 1 Cr-52 0 0 +40 8 2 1 Cr-53 0 0 +41 8 2 1 Cr-54 0 0 +0 8 2 2 H-1 0 0 +1 8 2 2 O-16 0 0 +2 8 2 2 B-10 0 0 +3 8 2 2 B-11 0 0 +4 8 2 2 Fe-54 0 0 +5 8 2 2 Fe-56 0 0 +6 8 2 2 Fe-57 0 0 +7 8 2 2 Fe-58 0 0 +8 8 2 2 Ni-58 0 0 +9 8 2 2 Ni-60 0 0 +10 8 2 2 Ni-61 0 0 +11 8 2 2 Ni-62 0 0 +12 8 2 2 Ni-64 0 0 +13 8 2 2 Mn-55 0 0 +14 8 2 2 Si-28 0 0 +15 8 2 2 Si-29 0 0 +16 8 2 2 Si-30 0 0 +17 8 2 2 Cr-50 0 0 +18 8 2 2 Cr-52 0 0 +19 8 2 2 Cr-53 0 0 +20 8 2 2 Cr-54 0 0 material group out nuclide mean std. dev. +21 8 1 H-1 0 0 +22 8 1 O-16 0 0 +23 8 1 B-10 0 0 +24 8 1 B-11 0 0 +25 8 1 Fe-54 0 0 +26 8 1 Fe-56 0 0 +27 8 1 Fe-57 0 0 +28 8 1 Fe-58 0 0 +29 8 1 Ni-58 0 0 +30 8 1 Ni-60 0 0 +31 8 1 Ni-61 0 0 +32 8 1 Ni-62 0 0 +33 8 1 Ni-64 0 0 +34 8 1 Mn-55 0 0 +35 8 1 Si-28 0 0 +36 8 1 Si-29 0 0 +37 8 1 Si-30 0 0 +38 8 1 Cr-50 0 0 +39 8 1 Cr-52 0 0 +40 8 1 Cr-53 0 0 +41 8 1 Cr-54 0 0 +0 8 2 H-1 0 0 +1 8 2 O-16 0 0 +2 8 2 B-10 0 0 +3 8 2 B-11 0 0 +4 8 2 Fe-54 0 0 +5 8 2 Fe-56 0 0 +6 8 2 Fe-57 0 0 +7 8 2 Fe-58 0 0 +8 8 2 Ni-58 0 0 +9 8 2 Ni-60 0 0 +10 8 2 Ni-61 0 0 +11 8 2 Ni-62 0 0 +12 8 2 Ni-64 0 0 +13 8 2 Mn-55 0 0 +14 8 2 Si-28 0 0 +15 8 2 Si-29 0 0 +16 8 2 Si-30 0 0 +17 8 2 Cr-50 0 0 +18 8 2 Cr-52 0 0 +19 8 2 Cr-53 0 0 +20 8 2 Cr-54 0 0 material group in nuclide mean std. dev. +21 9 1 H-1 0.106160 0.179178 +22 9 1 O-16 0.272020 0.171699 +23 9 1 B-10 0.000000 0.000000 +24 9 1 B-11 0.000000 0.000000 +25 9 1 Fe-54 0.000000 0.000000 +26 9 1 Fe-56 0.000000 0.000000 +27 9 1 Fe-57 0.000000 0.000000 +28 9 1 Fe-58 0.000000 0.000000 +29 9 1 Ni-58 0.000000 0.000000 +30 9 1 Ni-60 0.000000 0.000000 +31 9 1 Ni-61 0.000000 0.000000 +32 9 1 Ni-62 0.000000 0.000000 +33 9 1 Ni-64 0.000000 0.000000 +34 9 1 Mn-55 0.085133 0.082479 +35 9 1 Si-28 0.000000 0.000000 +36 9 1 Si-29 0.000000 0.000000 +37 9 1 Si-30 0.000000 0.000000 +38 9 1 Cr-50 0.000000 0.000000 +39 9 1 Cr-52 0.000000 0.000000 +40 9 1 Cr-53 0.040723 0.079827 +41 9 1 Cr-54 0.000000 0.000000 +0 9 2 H-1 1.417955 2.158027 +1 9 2 O-16 0.000000 0.000000 +2 9 2 B-10 0.269141 0.380622 +3 9 2 B-11 0.000000 0.000000 +4 9 2 Fe-54 0.000000 0.000000 +5 9 2 Fe-56 0.000000 0.000000 +6 9 2 Fe-57 0.000000 0.000000 +7 9 2 Fe-58 0.000000 0.000000 +8 9 2 Ni-58 0.000000 0.000000 +9 9 2 Ni-60 0.000000 0.000000 +10 9 2 Ni-61 0.000000 0.000000 +11 9 2 Ni-62 0.000000 0.000000 +12 9 2 Ni-64 0.000000 0.000000 +13 9 2 Mn-55 0.000000 0.000000 +14 9 2 Si-28 0.000000 0.000000 +15 9 2 Si-29 0.000000 0.000000 +16 9 2 Si-30 0.000000 0.000000 +17 9 2 Cr-50 0.000000 0.000000 +18 9 2 Cr-52 0.000000 0.000000 +19 9 2 Cr-53 0.000000 0.000000 +20 9 2 Cr-54 0.000000 0.000000 material group in nuclide mean std. dev. +21 9 1 H-1 0 0 +22 9 1 O-16 0 0 +23 9 1 B-10 0 0 +24 9 1 B-11 0 0 +25 9 1 Fe-54 0 0 +26 9 1 Fe-56 0 0 +27 9 1 Fe-57 0 0 +28 9 1 Fe-58 0 0 +29 9 1 Ni-58 0 0 +30 9 1 Ni-60 0 0 +31 9 1 Ni-61 0 0 +32 9 1 Ni-62 0 0 +33 9 1 Ni-64 0 0 +34 9 1 Mn-55 0 0 +35 9 1 Si-28 0 0 +36 9 1 Si-29 0 0 +37 9 1 Si-30 0 0 +38 9 1 Cr-50 0 0 +39 9 1 Cr-52 0 0 +40 9 1 Cr-53 0 0 +41 9 1 Cr-54 0 0 +0 9 2 H-1 0 0 +1 9 2 O-16 0 0 +2 9 2 B-10 0 0 +3 9 2 B-11 0 0 +4 9 2 Fe-54 0 0 +5 9 2 Fe-56 0 0 +6 9 2 Fe-57 0 0 +7 9 2 Fe-58 0 0 +8 9 2 Ni-58 0 0 +9 9 2 Ni-60 0 0 +10 9 2 Ni-61 0 0 +11 9 2 Ni-62 0 0 +12 9 2 Ni-64 0 0 +13 9 2 Mn-55 0 0 +14 9 2 Si-28 0 0 +15 9 2 Si-29 0 0 +16 9 2 Si-30 0 0 +17 9 2 Cr-50 0 0 +18 9 2 Cr-52 0 0 +19 9 2 Cr-53 0 0 +20 9 2 Cr-54 0 0 material group in group out nuclide mean std. dev. +63 9 1 1 H-1 0.106160 0.179178 +64 9 1 1 O-16 0.272020 0.171699 +65 9 1 1 B-10 0.000000 0.000000 +66 9 1 1 B-11 0.000000 0.000000 +67 9 1 1 Fe-54 0.000000 0.000000 +68 9 1 1 Fe-56 0.000000 0.000000 +69 9 1 1 Fe-57 0.000000 0.000000 +70 9 1 1 Fe-58 0.000000 0.000000 +71 9 1 1 Ni-58 0.000000 0.000000 +72 9 1 1 Ni-60 0.000000 0.000000 +73 9 1 1 Ni-61 0.000000 0.000000 +74 9 1 1 Ni-62 0.000000 0.000000 +75 9 1 1 Ni-64 0.000000 0.000000 +76 9 1 1 Mn-55 0.085133 0.082479 +77 9 1 1 Si-28 0.000000 0.000000 +78 9 1 1 Si-29 0.000000 0.000000 +79 9 1 1 Si-30 0.000000 0.000000 +80 9 1 1 Cr-50 0.000000 0.000000 +81 9 1 1 Cr-52 0.000000 0.000000 +82 9 1 1 Cr-53 0.040723 0.079827 +83 9 1 1 Cr-54 0.000000 0.000000 +42 9 1 2 H-1 0.000000 0.000000 +43 9 1 2 O-16 0.000000 0.000000 +44 9 1 2 B-10 0.000000 0.000000 +45 9 1 2 B-11 0.000000 0.000000 +46 9 1 2 Fe-54 0.000000 0.000000 +47 9 1 2 Fe-56 0.000000 0.000000 +48 9 1 2 Fe-57 0.000000 0.000000 +49 9 1 2 Fe-58 0.000000 0.000000 +50 9 1 2 Ni-58 0.000000 0.000000 +51 9 1 2 Ni-60 0.000000 0.000000 +52 9 1 2 Ni-61 0.000000 0.000000 +53 9 1 2 Ni-62 0.000000 0.000000 +54 9 1 2 Ni-64 0.000000 0.000000 +55 9 1 2 Mn-55 0.000000 0.000000 +56 9 1 2 Si-28 0.000000 0.000000 +57 9 1 2 Si-29 0.000000 0.000000 +58 9 1 2 Si-30 0.000000 0.000000 +59 9 1 2 Cr-50 0.000000 0.000000 +60 9 1 2 Cr-52 0.000000 0.000000 +61 9 1 2 Cr-53 0.000000 0.000000 +62 9 1 2 Cr-54 0.000000 0.000000 +21 9 2 1 H-1 0.000000 0.000000 +22 9 2 1 O-16 0.000000 0.000000 +23 9 2 1 B-10 0.000000 0.000000 +24 9 2 1 B-11 0.000000 0.000000 +25 9 2 1 Fe-54 0.000000 0.000000 +26 9 2 1 Fe-56 0.000000 0.000000 +27 9 2 1 Fe-57 0.000000 0.000000 +28 9 2 1 Fe-58 0.000000 0.000000 +29 9 2 1 Ni-58 0.000000 0.000000 +30 9 2 1 Ni-60 0.000000 0.000000 +31 9 2 1 Ni-61 0.000000 0.000000 +32 9 2 1 Ni-62 0.000000 0.000000 +33 9 2 1 Ni-64 0.000000 0.000000 +34 9 2 1 Mn-55 0.000000 0.000000 +35 9 2 1 Si-28 0.000000 0.000000 +36 9 2 1 Si-29 0.000000 0.000000 +37 9 2 1 Si-30 0.000000 0.000000 +38 9 2 1 Cr-50 0.000000 0.000000 +39 9 2 1 Cr-52 0.000000 0.000000 +40 9 2 1 Cr-53 0.000000 0.000000 +41 9 2 1 Cr-54 0.000000 0.000000 +0 9 2 2 H-1 1.417955 2.158027 +1 9 2 2 O-16 0.000000 0.000000 +2 9 2 2 B-10 0.000000 0.000000 +3 9 2 2 B-11 0.000000 0.000000 +4 9 2 2 Fe-54 0.000000 0.000000 +5 9 2 2 Fe-56 0.000000 0.000000 +6 9 2 2 Fe-57 0.000000 0.000000 +7 9 2 2 Fe-58 0.000000 0.000000 +8 9 2 2 Ni-58 0.000000 0.000000 +9 9 2 2 Ni-60 0.000000 0.000000 +10 9 2 2 Ni-61 0.000000 0.000000 +11 9 2 2 Ni-62 0.000000 0.000000 +12 9 2 2 Ni-64 0.000000 0.000000 +13 9 2 2 Mn-55 0.000000 0.000000 +14 9 2 2 Si-28 0.000000 0.000000 +15 9 2 2 Si-29 0.000000 0.000000 +16 9 2 2 Si-30 0.000000 0.000000 +17 9 2 2 Cr-50 0.000000 0.000000 +18 9 2 2 Cr-52 0.000000 0.000000 +19 9 2 2 Cr-53 0.000000 0.000000 +20 9 2 2 Cr-54 0.000000 0.000000 material group out nuclide mean std. dev. +21 9 1 H-1 0 0 +22 9 1 O-16 0 0 +23 9 1 B-10 0 0 +24 9 1 B-11 0 0 +25 9 1 Fe-54 0 0 +26 9 1 Fe-56 0 0 +27 9 1 Fe-57 0 0 +28 9 1 Fe-58 0 0 +29 9 1 Ni-58 0 0 +30 9 1 Ni-60 0 0 +31 9 1 Ni-61 0 0 +32 9 1 Ni-62 0 0 +33 9 1 Ni-64 0 0 +34 9 1 Mn-55 0 0 +35 9 1 Si-28 0 0 +36 9 1 Si-29 0 0 +37 9 1 Si-30 0 0 +38 9 1 Cr-50 0 0 +39 9 1 Cr-52 0 0 +40 9 1 Cr-53 0 0 +41 9 1 Cr-54 0 0 +0 9 2 H-1 0 0 +1 9 2 O-16 0 0 +2 9 2 B-10 0 0 +3 9 2 B-11 0 0 +4 9 2 Fe-54 0 0 +5 9 2 Fe-56 0 0 +6 9 2 Fe-57 0 0 +7 9 2 Fe-58 0 0 +8 9 2 Ni-58 0 0 +9 9 2 Ni-60 0 0 +10 9 2 Ni-61 0 0 +11 9 2 Ni-62 0 0 +12 9 2 Ni-64 0 0 +13 9 2 Mn-55 0 0 +14 9 2 Si-28 0 0 +15 9 2 Si-29 0 0 +16 9 2 Si-30 0 0 +17 9 2 Cr-50 0 0 +18 9 2 Cr-52 0 0 +19 9 2 Cr-53 0 0 +20 9 2 Cr-54 0 0 material group in nuclide mean std. dev. +21 10 1 H-1 0 0 +22 10 1 O-16 0 0 +23 10 1 B-10 0 0 +24 10 1 B-11 0 0 +25 10 1 Fe-54 0 0 +26 10 1 Fe-56 0 0 +27 10 1 Fe-57 0 0 +28 10 1 Fe-58 0 0 +29 10 1 Ni-58 0 0 +30 10 1 Ni-60 0 0 +31 10 1 Ni-61 0 0 +32 10 1 Ni-62 0 0 +33 10 1 Ni-64 0 0 +34 10 1 Mn-55 0 0 +35 10 1 Si-28 0 0 +36 10 1 Si-29 0 0 +37 10 1 Si-30 0 0 +38 10 1 Cr-50 0 0 +39 10 1 Cr-52 0 0 +40 10 1 Cr-53 0 0 +41 10 1 Cr-54 0 0 +0 10 2 H-1 0 0 +1 10 2 O-16 0 0 +2 10 2 B-10 0 0 +3 10 2 B-11 0 0 +4 10 2 Fe-54 0 0 +5 10 2 Fe-56 0 0 +6 10 2 Fe-57 0 0 +7 10 2 Fe-58 0 0 +8 10 2 Ni-58 0 0 +9 10 2 Ni-60 0 0 +10 10 2 Ni-61 0 0 +11 10 2 Ni-62 0 0 +12 10 2 Ni-64 0 0 +13 10 2 Mn-55 0 0 +14 10 2 Si-28 0 0 +15 10 2 Si-29 0 0 +16 10 2 Si-30 0 0 +17 10 2 Cr-50 0 0 +18 10 2 Cr-52 0 0 +19 10 2 Cr-53 0 0 +20 10 2 Cr-54 0 0 material group in nuclide mean std. dev. +21 10 1 H-1 0 0 +22 10 1 O-16 0 0 +23 10 1 B-10 0 0 +24 10 1 B-11 0 0 +25 10 1 Fe-54 0 0 +26 10 1 Fe-56 0 0 +27 10 1 Fe-57 0 0 +28 10 1 Fe-58 0 0 +29 10 1 Ni-58 0 0 +30 10 1 Ni-60 0 0 +31 10 1 Ni-61 0 0 +32 10 1 Ni-62 0 0 +33 10 1 Ni-64 0 0 +34 10 1 Mn-55 0 0 +35 10 1 Si-28 0 0 +36 10 1 Si-29 0 0 +37 10 1 Si-30 0 0 +38 10 1 Cr-50 0 0 +39 10 1 Cr-52 0 0 +40 10 1 Cr-53 0 0 +41 10 1 Cr-54 0 0 +0 10 2 H-1 0 0 +1 10 2 O-16 0 0 +2 10 2 B-10 0 0 +3 10 2 B-11 0 0 +4 10 2 Fe-54 0 0 +5 10 2 Fe-56 0 0 +6 10 2 Fe-57 0 0 +7 10 2 Fe-58 0 0 +8 10 2 Ni-58 0 0 +9 10 2 Ni-60 0 0 +10 10 2 Ni-61 0 0 +11 10 2 Ni-62 0 0 +12 10 2 Ni-64 0 0 +13 10 2 Mn-55 0 0 +14 10 2 Si-28 0 0 +15 10 2 Si-29 0 0 +16 10 2 Si-30 0 0 +17 10 2 Cr-50 0 0 +18 10 2 Cr-52 0 0 +19 10 2 Cr-53 0 0 +20 10 2 Cr-54 0 0 material group in group out nuclide mean std. dev. +63 10 1 1 H-1 0 0 +64 10 1 1 O-16 0 0 +65 10 1 1 B-10 0 0 +66 10 1 1 B-11 0 0 +67 10 1 1 Fe-54 0 0 +68 10 1 1 Fe-56 0 0 +69 10 1 1 Fe-57 0 0 +70 10 1 1 Fe-58 0 0 +71 10 1 1 Ni-58 0 0 +72 10 1 1 Ni-60 0 0 +73 10 1 1 Ni-61 0 0 +74 10 1 1 Ni-62 0 0 +75 10 1 1 Ni-64 0 0 +76 10 1 1 Mn-55 0 0 +77 10 1 1 Si-28 0 0 +78 10 1 1 Si-29 0 0 +79 10 1 1 Si-30 0 0 +80 10 1 1 Cr-50 0 0 +81 10 1 1 Cr-52 0 0 +82 10 1 1 Cr-53 0 0 +83 10 1 1 Cr-54 0 0 +42 10 1 2 H-1 0 0 +43 10 1 2 O-16 0 0 +44 10 1 2 B-10 0 0 +45 10 1 2 B-11 0 0 +46 10 1 2 Fe-54 0 0 +47 10 1 2 Fe-56 0 0 +48 10 1 2 Fe-57 0 0 +49 10 1 2 Fe-58 0 0 +50 10 1 2 Ni-58 0 0 +51 10 1 2 Ni-60 0 0 +52 10 1 2 Ni-61 0 0 +53 10 1 2 Ni-62 0 0 +54 10 1 2 Ni-64 0 0 +55 10 1 2 Mn-55 0 0 +56 10 1 2 Si-28 0 0 +57 10 1 2 Si-29 0 0 +58 10 1 2 Si-30 0 0 +59 10 1 2 Cr-50 0 0 +60 10 1 2 Cr-52 0 0 +61 10 1 2 Cr-53 0 0 +62 10 1 2 Cr-54 0 0 +21 10 2 1 H-1 0 0 +22 10 2 1 O-16 0 0 +23 10 2 1 B-10 0 0 +24 10 2 1 B-11 0 0 +25 10 2 1 Fe-54 0 0 +26 10 2 1 Fe-56 0 0 +27 10 2 1 Fe-57 0 0 +28 10 2 1 Fe-58 0 0 +29 10 2 1 Ni-58 0 0 +30 10 2 1 Ni-60 0 0 +31 10 2 1 Ni-61 0 0 +32 10 2 1 Ni-62 0 0 +33 10 2 1 Ni-64 0 0 +34 10 2 1 Mn-55 0 0 +35 10 2 1 Si-28 0 0 +36 10 2 1 Si-29 0 0 +37 10 2 1 Si-30 0 0 +38 10 2 1 Cr-50 0 0 +39 10 2 1 Cr-52 0 0 +40 10 2 1 Cr-53 0 0 +41 10 2 1 Cr-54 0 0 +0 10 2 2 H-1 0 0 +1 10 2 2 O-16 0 0 +2 10 2 2 B-10 0 0 +3 10 2 2 B-11 0 0 +4 10 2 2 Fe-54 0 0 +5 10 2 2 Fe-56 0 0 +6 10 2 2 Fe-57 0 0 +7 10 2 2 Fe-58 0 0 +8 10 2 2 Ni-58 0 0 +9 10 2 2 Ni-60 0 0 +10 10 2 2 Ni-61 0 0 +11 10 2 2 Ni-62 0 0 +12 10 2 2 Ni-64 0 0 +13 10 2 2 Mn-55 0 0 +14 10 2 2 Si-28 0 0 +15 10 2 2 Si-29 0 0 +16 10 2 2 Si-30 0 0 +17 10 2 2 Cr-50 0 0 +18 10 2 2 Cr-52 0 0 +19 10 2 2 Cr-53 0 0 +20 10 2 2 Cr-54 0 0 material group out nuclide mean std. dev. +21 10 1 H-1 0 0 +22 10 1 O-16 0 0 +23 10 1 B-10 0 0 +24 10 1 B-11 0 0 +25 10 1 Fe-54 0 0 +26 10 1 Fe-56 0 0 +27 10 1 Fe-57 0 0 +28 10 1 Fe-58 0 0 +29 10 1 Ni-58 0 0 +30 10 1 Ni-60 0 0 +31 10 1 Ni-61 0 0 +32 10 1 Ni-62 0 0 +33 10 1 Ni-64 0 0 +34 10 1 Mn-55 0 0 +35 10 1 Si-28 0 0 +36 10 1 Si-29 0 0 +37 10 1 Si-30 0 0 +38 10 1 Cr-50 0 0 +39 10 1 Cr-52 0 0 +40 10 1 Cr-53 0 0 +41 10 1 Cr-54 0 0 +0 10 2 H-1 0 0 +1 10 2 O-16 0 0 +2 10 2 B-10 0 0 +3 10 2 B-11 0 0 +4 10 2 Fe-54 0 0 +5 10 2 Fe-56 0 0 +6 10 2 Fe-57 0 0 +7 10 2 Fe-58 0 0 +8 10 2 Ni-58 0 0 +9 10 2 Ni-60 0 0 +10 10 2 Ni-61 0 0 +11 10 2 Ni-62 0 0 +12 10 2 Ni-64 0 0 +13 10 2 Mn-55 0 0 +14 10 2 Si-28 0 0 +15 10 2 Si-29 0 0 +16 10 2 Si-30 0 0 +17 10 2 Cr-50 0 0 +18 10 2 Cr-52 0 0 +19 10 2 Cr-53 0 0 +20 10 2 Cr-54 0 0 material group in nuclide mean std. dev. +9 11 1 H-1 0.138558 0.260695 +10 11 1 O-16 0.042575 0.049271 +11 11 1 B-10 0.000000 0.000000 +12 11 1 B-11 0.000000 0.000000 +13 11 1 Zr-90 0.041034 0.049102 +14 11 1 Zr-91 0.027328 0.021092 +15 11 1 Zr-92 0.009788 0.009282 +16 11 1 Zr-94 0.043543 0.036697 +17 11 1 Zr-96 0.000000 0.000000 +0 11 2 H-1 0.824153 0.917955 +1 11 2 O-16 0.041986 0.060727 +2 11 2 B-10 0.048216 0.042726 +3 11 2 B-11 0.000000 0.000000 +4 11 2 Zr-90 0.048596 0.067712 +5 11 2 Zr-91 0.000000 0.000000 +6 11 2 Zr-92 0.000000 0.000000 +7 11 2 Zr-94 0.043195 0.041363 +8 11 2 Zr-96 0.000000 0.000000 material group in nuclide mean std. dev. +9 11 1 H-1 0 0 +10 11 1 O-16 0 0 +11 11 1 B-10 0 0 +12 11 1 B-11 0 0 +13 11 1 Zr-90 0 0 +14 11 1 Zr-91 0 0 +15 11 1 Zr-92 0 0 +16 11 1 Zr-94 0 0 +17 11 1 Zr-96 0 0 +0 11 2 H-1 0 0 +1 11 2 O-16 0 0 +2 11 2 B-10 0 0 +3 11 2 B-11 0 0 +4 11 2 Zr-90 0 0 +5 11 2 Zr-91 0 0 +6 11 2 Zr-92 0 0 +7 11 2 Zr-94 0 0 +8 11 2 Zr-96 0 0 material group in group out nuclide mean std. dev. +27 11 1 1 H-1 0.111411 0.247294 +28 11 1 1 O-16 0.042575 0.049271 +29 11 1 1 B-10 0.000000 0.000000 +30 11 1 1 B-11 0.000000 0.000000 +31 11 1 1 Zr-90 0.041034 0.049102 +32 11 1 1 Zr-91 0.027328 0.021092 +33 11 1 1 Zr-92 0.009788 0.009282 +34 11 1 1 Zr-94 0.043543 0.036697 +35 11 1 1 Zr-96 0.000000 0.000000 +18 11 1 2 H-1 0.027147 0.020009 +19 11 1 2 O-16 0.000000 0.000000 +20 11 1 2 B-10 0.000000 0.000000 +21 11 1 2 B-11 0.000000 0.000000 +22 11 1 2 Zr-90 0.000000 0.000000 +23 11 1 2 Zr-91 0.000000 0.000000 +24 11 1 2 Zr-92 0.000000 0.000000 +25 11 1 2 Zr-94 0.000000 0.000000 +26 11 1 2 Zr-96 0.000000 0.000000 +9 11 2 1 H-1 0.000000 0.000000 +10 11 2 1 O-16 0.000000 0.000000 +11 11 2 1 B-10 0.000000 0.000000 +12 11 2 1 B-11 0.000000 0.000000 +13 11 2 1 Zr-90 0.000000 0.000000 +14 11 2 1 Zr-91 0.000000 0.000000 +15 11 2 1 Zr-92 0.000000 0.000000 +16 11 2 1 Zr-94 0.000000 0.000000 +17 11 2 1 Zr-96 0.000000 0.000000 +0 11 2 2 H-1 0.824153 0.917955 +1 11 2 2 O-16 0.041986 0.060727 +2 11 2 2 B-10 0.000000 0.000000 +3 11 2 2 B-11 0.000000 0.000000 +4 11 2 2 Zr-90 0.048596 0.067712 +5 11 2 2 Zr-91 0.000000 0.000000 +6 11 2 2 Zr-92 0.000000 0.000000 +7 11 2 2 Zr-94 0.043195 0.041363 +8 11 2 2 Zr-96 0.000000 0.000000 material group out nuclide mean std. dev. +9 11 1 H-1 0 0 +10 11 1 O-16 0 0 +11 11 1 B-10 0 0 +12 11 1 B-11 0 0 +13 11 1 Zr-90 0 0 +14 11 1 Zr-91 0 0 +15 11 1 Zr-92 0 0 +16 11 1 Zr-94 0 0 +17 11 1 Zr-96 0 0 +0 11 2 H-1 0 0 +1 11 2 O-16 0 0 +2 11 2 B-10 0 0 +3 11 2 B-11 0 0 +4 11 2 Zr-90 0 0 +5 11 2 Zr-91 0 0 +6 11 2 Zr-92 0 0 +7 11 2 Zr-94 0 0 +8 11 2 Zr-96 0 0 material group in nuclide mean std. dev. +9 12 1 H-1 0.151924 0.200147 +10 12 1 O-16 0.039280 0.026086 +11 12 1 B-10 0.000000 0.000000 +12 12 1 B-11 0.000000 0.000000 +13 12 1 Zr-90 0.017578 0.022079 +14 12 1 Zr-91 0.039984 0.025285 +15 12 1 Zr-92 0.001172 0.006230 +16 12 1 Zr-94 0.001668 0.005966 +17 12 1 Zr-96 0.004328 0.005325 +0 12 2 H-1 0.942412 0.866849 +1 12 2 O-16 0.047438 0.048161 +2 12 2 B-10 0.041655 0.031202 +3 12 2 B-11 0.000000 0.000000 +4 12 2 Zr-90 0.021193 0.017456 +5 12 2 Zr-91 0.007901 0.009268 +6 12 2 Zr-92 0.009422 0.012802 +7 12 2 Zr-94 0.043324 0.027551 +8 12 2 Zr-96 0.000000 0.000000 material group in nuclide mean std. dev. +9 12 1 H-1 0 0 +10 12 1 O-16 0 0 +11 12 1 B-10 0 0 +12 12 1 B-11 0 0 +13 12 1 Zr-90 0 0 +14 12 1 Zr-91 0 0 +15 12 1 Zr-92 0 0 +16 12 1 Zr-94 0 0 +17 12 1 Zr-96 0 0 +0 12 2 H-1 0 0 +1 12 2 O-16 0 0 +2 12 2 B-10 0 0 +3 12 2 B-11 0 0 +4 12 2 Zr-90 0 0 +5 12 2 Zr-91 0 0 +6 12 2 Zr-92 0 0 +7 12 2 Zr-94 0 0 +8 12 2 Zr-96 0 0 material group in group out nuclide mean std. dev. +27 12 1 1 H-1 0.122301 0.187298 +28 12 1 1 O-16 0.039280 0.026086 +29 12 1 1 B-10 0.000000 0.000000 +30 12 1 1 B-11 0.000000 0.000000 +31 12 1 1 Zr-90 0.017578 0.022079 +32 12 1 1 Zr-91 0.039984 0.025285 +33 12 1 1 Zr-92 0.001172 0.006230 +34 12 1 1 Zr-94 0.001668 0.005966 +35 12 1 1 Zr-96 0.004328 0.005325 +18 12 1 2 H-1 0.029622 0.017760 +19 12 1 2 O-16 0.000000 0.000000 +20 12 1 2 B-10 0.000000 0.000000 +21 12 1 2 B-11 0.000000 0.000000 +22 12 1 2 Zr-90 0.000000 0.000000 +23 12 1 2 Zr-91 0.000000 0.000000 +24 12 1 2 Zr-92 0.000000 0.000000 +25 12 1 2 Zr-94 0.000000 0.000000 +26 12 1 2 Zr-96 0.000000 0.000000 +9 12 2 1 H-1 0.000000 0.000000 +10 12 2 1 O-16 0.000000 0.000000 +11 12 2 1 B-10 0.000000 0.000000 +12 12 2 1 B-11 0.000000 0.000000 +13 12 2 1 Zr-90 0.000000 0.000000 +14 12 2 1 Zr-91 0.000000 0.000000 +15 12 2 1 Zr-92 0.000000 0.000000 +16 12 2 1 Zr-94 0.000000 0.000000 +17 12 2 1 Zr-96 0.000000 0.000000 +0 12 2 2 H-1 0.942412 0.866849 +1 12 2 2 O-16 0.047438 0.048161 +2 12 2 2 B-10 0.000000 0.000000 +3 12 2 2 B-11 0.000000 0.000000 +4 12 2 2 Zr-90 0.021193 0.017456 +5 12 2 2 Zr-91 0.007901 0.009268 +6 12 2 2 Zr-92 0.009422 0.012802 +7 12 2 2 Zr-94 0.043324 0.027551 +8 12 2 2 Zr-96 0.000000 0.000000 material group out nuclide mean std. dev. +9 12 1 H-1 0 0 +10 12 1 O-16 0 0 +11 12 1 B-10 0 0 +12 12 1 B-11 0 0 +13 12 1 Zr-90 0 0 +14 12 1 Zr-91 0 0 +15 12 1 Zr-92 0 0 +16 12 1 Zr-94 0 0 +17 12 1 Zr-96 0 0 +0 12 2 H-1 0 0 +1 12 2 O-16 0 0 +2 12 2 B-10 0 0 +3 12 2 B-11 0 0 +4 12 2 Zr-90 0 0 +5 12 2 Zr-91 0 0 +6 12 2 Zr-92 0 0 +7 12 2 Zr-94 0 0 +8 12 2 Zr-96 0 0 \ No newline at end of file diff --git a/tests/test_mgxs_library_nuclides/test_mgxs_library_nuclides.py b/tests/test_mgxs_library_nuclides/test_mgxs_library_nuclides.py new file mode 100644 index 0000000000..173043cf04 --- /dev/null +++ b/tests/test_mgxs_library_nuclides/test_mgxs_library_nuclides.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +import os +import sys +import glob +import hashlib +sys.path.insert(0, os.pardir) +from testing_harness import PyAPITestHarness +import openmc +import openmc.mgxs + + +class MGXSTestHarness(PyAPITestHarness): + def _build_inputs(self): + + # The openmc.mgxs module needs a summary.h5 file + self._input_set.settings.output = {'summary': True} + + # Generate inputs using parent class routine + super(MGXSTestHarness, self)._build_inputs() + + # Initialize a two-group structure + energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.]) + + # Initialize MGXS Library for a few cross section types + self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry.geometry) + self.mgxs_lib.by_nuclide = True + self.mgxs_lib.mgxs_types = ['transport', 'nu-fission', + 'nu-scatter matrix', 'chi'] + self.mgxs_lib.energy_groups = energy_groups + self.mgxs_lib.domain_type = 'material' + self.mgxs_lib.build_library() + + # Initialize a tallies file + self._input_set.tallies = openmc.TalliesFile() + self.mgxs_lib.add_to_tallies_file(self._input_set.tallies, merge=False) + self._input_set.tallies.export_to_xml() + + def _get_results(self, hash_output=False): + """Digest info in the statepoint and return as a string.""" + + # Read the statepoint file. + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] + sp = openmc.StatePoint(statepoint) + + # Read the summary file. + summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0] + su = openmc.Summary(summary) + sp.link_with_summary(su) + + # Load the MGXS library from the statepoint + self.mgxs_lib.load_from_statepoint(sp) + + # Build a string from Pandas Dataframe for each MGXS + outstr = '' + for domain in self.mgxs_lib.domains: + for mgxs_type in self.mgxs_lib.mgxs_types: + mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) + df = mgxs.get_pandas_dataframe() + outstr += df.to_string() + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + + def _cleanup(self): + super(MGXSTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = MGXSTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_natural_element/geometry.xml b/tests/test_natural_element/geometry.xml index 2d427d8cb3..b6b4bd817b 100644 --- a/tests/test_natural_element/geometry.xml +++ b/tests/test_natural_element/geometry.xml @@ -45,50 +45,50 @@ - - + + - - + + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - + + + diff --git a/tests/test_natural_element/results_true.dat b/tests/test_natural_element/results_true.dat index 4b132ea37d..1c8668e128 100644 --- a/tests/test_natural_element/results_true.dat +++ b/tests/test_natural_element/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.053229E+00 9.241274E-02 +1.013112E+00 2.551515E-02 diff --git a/tests/test_natural_element/test_natural_element.py b/tests/test_natural_element/test_natural_element.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_natural_element/test_natural_element.py +++ b/tests/test_natural_element/test_natural_element.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_output/geometry.xml b/tests/test_output/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_output/geometry.xml +++ b/tests/test_output/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_output/results_true.dat b/tests/test_output/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_output/results_true.dat +++ b/tests/test_output/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_output/test_output.py b/tests/test_output/test_output.py index 1f51742ba2..8e36ead808 100644 --- a/tests/test_output/test_output.py +++ b/tests/test_output/test_output.py @@ -1,8 +1,10 @@ #!/usr/bin/env python +import glob +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness class OutputTestHarness(TestHarness): @@ -14,8 +16,8 @@ class OutputTestHarness(TestHarness): # Check for the summary. summary = glob.glob(os.path.join(os.getcwd(), 'summary.*')) assert len(summary) == 1, 'Either multiple or no summary file exists.' - assert summary[0].endswith('out') or summary[0].endswith('h5'),\ - 'Summary file is not a binary or hdf5 file.' + assert summary[0].endswith('h5'),\ + 'Summary file is not a HDF5 file.' # Check for the cross sections. assert os.path.exists(os.path.join(os.getcwd(), 'cross_sections.out')),\ diff --git a/tests/test_particle_restart_eigval/geometry.xml b/tests/test_particle_restart_eigval/geometry.xml index 52fea4df64..c86e016c6e 100644 --- a/tests/test_particle_restart_eigval/geometry.xml +++ b/tests/test_particle_restart_eigval/geometry.xml @@ -4,6 +4,6 @@ - + diff --git a/tests/test_particle_restart_eigval/results_true.dat b/tests/test_particle_restart_eigval/results_true.dat index a93cbb27b2..f343978533 100644 --- a/tests/test_particle_restart_eigval/results_true.dat +++ b/tests/test_particle_restart_eigval/results_true.dat @@ -1,16 +1,16 @@ current batch: -1.200000E+01 +9.000000E+00 current gen: 1.000000E+00 particle id: -6.160000E+02 +5.550000E+02 run mode: -2.000000E+00 +k-eigenvalue particle weight: 1.000000E+00 particle energy: -3.545295E-01 +2.831611E-01 particle xyz: -3.516323E+01 -5.400148E+01 -1.588825E+01 +4.973847E+01 6.971699E+00 -5.201827E+01 particle uvw: -4.129799E-01 7.649720E-01 4.942322E-01 +6.945105E-01 6.295355E-01 -3.483393E-01 diff --git a/tests/test_particle_restart_eigval/test_particle_restart_eigval.py b/tests/test_particle_restart_eigval/test_particle_restart_eigval.py index 64123b2e09..139cb2b9f5 100644 --- a/tests/test_particle_restart_eigval/test_particle_restart_eigval.py +++ b/tests/test_particle_restart_eigval/test_particle_restart_eigval.py @@ -1,10 +1,11 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import ParticleRestartTestHarness if __name__ == '__main__': - harness = ParticleRestartTestHarness('particle_12_616.*') + harness = ParticleRestartTestHarness('particle_9_555.*') harness.main() diff --git a/tests/test_particle_restart_fixed/geometry.xml b/tests/test_particle_restart_fixed/geometry.xml index 52fea4df64..c86e016c6e 100644 --- a/tests/test_particle_restart_fixed/geometry.xml +++ b/tests/test_particle_restart_fixed/geometry.xml @@ -4,6 +4,6 @@ - + diff --git a/tests/test_particle_restart_fixed/results_true.dat b/tests/test_particle_restart_fixed/results_true.dat index ffe7d2cae5..de42a0c68e 100644 --- a/tests/test_particle_restart_fixed/results_true.dat +++ b/tests/test_particle_restart_fixed/results_true.dat @@ -1,16 +1,16 @@ current batch: 7.000000E+00 current gen: -0.000000E+00 -particle id: -6.144000E+03 -run mode: 1.000000E+00 +particle id: +9.280000E+02 +run mode: +fixed source particle weight: 1.000000E+00 particle energy: -5.749729E+00 +4.412022E+00 particle xyz: -8.754675E+00 2.551620E+00 4.394350E-01 +5.572639E+00 -9.139472E+00 -1.974824E+00 particle uvw: --5.971721E-01 -4.845709E-01 6.391999E-01 +1.410422E-01 5.330426E-01 -8.342498E-01 diff --git a/tests/test_particle_restart_fixed/test_particle_restart_fixed.py b/tests/test_particle_restart_fixed/test_particle_restart_fixed.py index 05dcf76a68..5af7454894 100644 --- a/tests/test_particle_restart_fixed/test_particle_restart_fixed.py +++ b/tests/test_particle_restart_fixed/test_particle_restart_fixed.py @@ -1,10 +1,11 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import ParticleRestartTestHarness if __name__ == '__main__': - harness = ParticleRestartTestHarness('particle_7_6144.*') + harness = ParticleRestartTestHarness('particle_7_928.*') harness.main() diff --git a/tests/test_plot_background/geometry.xml b/tests/test_plot_background/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_plot_background/geometry.xml +++ b/tests/test_plot_background/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_plot_background/test_plot_background.py b/tests/test_plot_background/test_plot_background.py index 49cdacb05c..7890eca19d 100644 --- a/tests/test_plot_background/test_plot_background.py +++ b/tests/test_plot_background/test_plot_background.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import PlotTestHarness diff --git a/tests/test_plot_basis/geometry.xml b/tests/test_plot_basis/geometry.xml index ac00ebaf51..83619d9f78 100644 --- a/tests/test_plot_basis/geometry.xml +++ b/tests/test_plot_basis/geometry.xml @@ -6,8 +6,8 @@ - - - + + + diff --git a/tests/test_plot_basis/results_true.dat b/tests/test_plot_basis/results_true.dat index ae588fd4f3..b1d5dc8534 100644 --- a/tests/test_plot_basis/results_true.dat +++ b/tests/test_plot_basis/results_true.dat @@ -1 +1 @@ -6a2400a95ea5baee432dd04a85252818d682004dc80b225b99c4bbc7cfd20d8523bd8e5df8a272df288cb2f300e5eee55f7ffa7b4d28ea64f92b78839ab0e86b \ No newline at end of file +368e0135c136d5c8a2dabb4c8085279dc7ac0bd81b2ec905bdf11ecb5fe99803868631cdff0b3ddec941323bcc661747d4c16edfd4f8d38582155bd6fd7e82e8 \ No newline at end of file diff --git a/tests/test_plot_basis/test_plot_basis.py b/tests/test_plot_basis/test_plot_basis.py index 85e30557d2..d45479e256 100644 --- a/tests/test_plot_basis/test_plot_basis.py +++ b/tests/test_plot_basis/test_plot_basis.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import PlotTestHarness diff --git a/tests/test_plot_colspec/geometry.xml b/tests/test_plot_colspec/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_plot_colspec/geometry.xml +++ b/tests/test_plot_colspec/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_plot_colspec/test_plot_colspec.py b/tests/test_plot_colspec/test_plot_colspec.py index 49cdacb05c..7890eca19d 100644 --- a/tests/test_plot_colspec/test_plot_colspec.py +++ b/tests/test_plot_colspec/test_plot_colspec.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import PlotTestHarness diff --git a/tests/test_plot_mask/geometry.xml b/tests/test_plot_mask/geometry.xml index ac00ebaf51..83619d9f78 100644 --- a/tests/test_plot_mask/geometry.xml +++ b/tests/test_plot_mask/geometry.xml @@ -6,8 +6,8 @@ - - - + + + diff --git a/tests/test_plot_mask/results_true.dat b/tests/test_plot_mask/results_true.dat index 1076324545..a1e323203d 100644 --- a/tests/test_plot_mask/results_true.dat +++ b/tests/test_plot_mask/results_true.dat @@ -1 +1 @@ -d888a734d6e69c5ca92457dc865c4defd8a1d8a1d4a01e0c8e7c528dde25d96df1283da37889dac0857329051958be2f2b491f2fd2bc22c8424a60ec6cda04bd \ No newline at end of file +a7cb65bf40c84c0540d45ff292c398f9ae51b3d9396e88b9b4e5cdf05e8730f409bddb53aec6d396058194c6293c5bd3ef39efd0b0f30f2423f696193c85176c \ No newline at end of file diff --git a/tests/test_plot_mask/test_plot_mask.py b/tests/test_plot_mask/test_plot_mask.py index 85e30557d2..d45479e256 100644 --- a/tests/test_plot_mask/test_plot_mask.py +++ b/tests/test_plot_mask/test_plot_mask.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import PlotTestHarness diff --git a/tests/test_ptables_off/geometry.xml b/tests/test_ptables_off/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_ptables_off/geometry.xml +++ b/tests/test_ptables_off/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_ptables_off/results_true.dat b/tests/test_ptables_off/results_true.dat index 17d6e91453..2d6511cd25 100644 --- a/tests/test_ptables_off/results_true.dat +++ b/tests/test_ptables_off/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.984064E-01 3.464413E-03 +2.998034E-01 5.227986E-03 diff --git a/tests/test_ptables_off/test_ptables_off.py b/tests/test_ptables_off/test_ptables_off.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_ptables_off/test_ptables_off.py +++ b/tests/test_ptables_off/test_ptables_off.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_quadric_surfaces/geometry.xml b/tests/test_quadric_surfaces/geometry.xml new file mode 100644 index 0000000000..98d647a4f6 --- /dev/null +++ b/tests/test_quadric_surfaces/geometry.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tests/test_reflective_cone/materials.xml b/tests/test_quadric_surfaces/materials.xml similarity index 56% rename from tests/test_reflective_cone/materials.xml rename to tests/test_quadric_surfaces/materials.xml index 315c0fa848..0150332b3c 100644 --- a/tests/test_reflective_cone/materials.xml +++ b/tests/test_quadric_surfaces/materials.xml @@ -3,7 +3,8 @@ - + + diff --git a/tests/test_quadric_surfaces/results_true.dat b/tests/test_quadric_surfaces/results_true.dat new file mode 100644 index 0000000000..b2e02fdbb7 --- /dev/null +++ b/tests/test_quadric_surfaces/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +9.706301E-01 4.351374E-02 diff --git a/tests/test_reflective_cone/settings.xml b/tests/test_quadric_surfaces/settings.xml similarity index 79% rename from tests/test_reflective_cone/settings.xml rename to tests/test_quadric_surfaces/settings.xml index af56f56368..9f0e8ed05f 100644 --- a/tests/test_reflective_cone/settings.xml +++ b/tests/test_quadric_surfaces/settings.xml @@ -8,7 +8,7 @@ - + diff --git a/tests/test_reflective_cylinder/test_reflective_cylinder.py b/tests/test_quadric_surfaces/test_quadric_surfaces.py old mode 100644 new mode 100755 similarity index 80% rename from tests/test_reflective_cylinder/test_reflective_cylinder.py rename to tests/test_quadric_surfaces/test_quadric_surfaces.py index 6633e59111..2a595f3e66 --- a/tests/test_reflective_cylinder/test_reflective_cylinder.py +++ b/tests/test_quadric_surfaces/test_quadric_surfaces.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_reflective_cone/geometry.xml b/tests/test_reflective_cone/geometry.xml deleted file mode 100644 index 5453e16155..0000000000 --- a/tests/test_reflective_cone/geometry.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/tests/test_reflective_cone/results_true.dat b/tests/test_reflective_cone/results_true.dat deleted file mode 100644 index 60b34bf66b..0000000000 --- a/tests/test_reflective_cone/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.281477E+00 5.206704E-03 diff --git a/tests/test_reflective_cone/test_reflective_cone.py b/tests/test_reflective_cone/test_reflective_cone.py deleted file mode 100644 index 6633e59111..0000000000 --- a/tests/test_reflective_cone/test_reflective_cone.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python - -import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness - - -if __name__ == '__main__': - harness = TestHarness('statepoint.10.*') - harness.main() diff --git a/tests/test_reflective_cylinder/geometry.xml b/tests/test_reflective_cylinder/geometry.xml deleted file mode 100644 index ce1082f3d6..0000000000 --- a/tests/test_reflective_cylinder/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/test_reflective_cylinder/materials.xml b/tests/test_reflective_cylinder/materials.xml deleted file mode 100644 index 315c0fa848..0000000000 --- a/tests/test_reflective_cylinder/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/test_reflective_cylinder/results_true.dat b/tests/test_reflective_cylinder/results_true.dat deleted file mode 100644 index f98c517889..0000000000 --- a/tests/test_reflective_cylinder/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.276055E+00 3.186526E-03 diff --git a/tests/test_reflective_plane/geometry.xml b/tests/test_reflective_plane/geometry.xml index 4544414365..0dc5c29ab5 100644 --- a/tests/test_reflective_plane/geometry.xml +++ b/tests/test_reflective_plane/geometry.xml @@ -8,6 +8,6 @@ - + diff --git a/tests/test_reflective_plane/results_true.dat b/tests/test_reflective_plane/results_true.dat index 049d45606c..c5ba8e63fb 100644 --- a/tests/test_reflective_plane/results_true.dat +++ b/tests/test_reflective_plane/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.281505E+00 3.254688E-03 +2.276127E+00 4.678320E-03 diff --git a/tests/test_reflective_plane/test_reflective_plane.py b/tests/test_reflective_plane/test_reflective_plane.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_reflective_plane/test_reflective_plane.py +++ b/tests/test_reflective_plane/test_reflective_plane.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_reflective_sphere/geometry.xml b/tests/test_reflective_sphere/geometry.xml deleted file mode 100644 index 5f36d2396f..0000000000 --- a/tests/test_reflective_sphere/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/test_reflective_sphere/materials.xml b/tests/test_reflective_sphere/materials.xml deleted file mode 100644 index 315c0fa848..0000000000 --- a/tests/test_reflective_sphere/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/test_reflective_sphere/results_true.dat b/tests/test_reflective_sphere/results_true.dat deleted file mode 100644 index 47aa5c763e..0000000000 --- a/tests/test_reflective_sphere/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.280812E+00 5.087968E-03 diff --git a/tests/test_reflective_sphere/settings.xml b/tests/test_reflective_sphere/settings.xml deleted file mode 100644 index a6fd5da19e..0000000000 --- a/tests/test_reflective_sphere/settings.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - 10 - 5 - 1000 - - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/test_resonance_scattering/geometry.xml b/tests/test_resonance_scattering/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_resonance_scattering/geometry.xml +++ b/tests/test_resonance_scattering/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_resonance_scattering/results_true.dat b/tests/test_resonance_scattering/results_true.dat index 62b0ac2239..0dda991cac 100644 --- a/tests/test_resonance_scattering/results_true.dat +++ b/tests/test_resonance_scattering/results_true.dat @@ -1,2 +1,2 @@ k-combined: -6.452021E-02 1.738736E-03 +6.842112E-02 8.480934E-04 diff --git a/tests/test_resonance_scattering/test_resonance_scattering.py b/tests/test_resonance_scattering/test_resonance_scattering.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_resonance_scattering/test_resonance_scattering.py +++ b/tests/test_resonance_scattering/test_resonance_scattering.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_rotation/geometry.xml b/tests/test_rotation/geometry.xml index 7306dabdef..2226178771 100644 --- a/tests/test_rotation/geometry.xml +++ b/tests/test_rotation/geometry.xml @@ -5,7 +5,7 @@ - - + + diff --git a/tests/test_rotation/results_true.dat b/tests/test_rotation/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_rotation/results_true.dat +++ b/tests/test_rotation/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_rotation/test_rotation.py b/tests/test_rotation/test_rotation.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_rotation/test_rotation.py +++ b/tests/test_rotation/test_rotation.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_salphabeta/geometry.xml b/tests/test_salphabeta/geometry.xml index ef05988425..f9caa6c883 100644 --- a/tests/test_salphabeta/geometry.xml +++ b/tests/test_salphabeta/geometry.xml @@ -6,8 +6,8 @@ - - - + + + diff --git a/tests/test_salphabeta/results_true.dat b/tests/test_salphabeta/results_true.dat index c2cd683bed..a04ee8fc89 100644 --- a/tests/test_salphabeta/results_true.dat +++ b/tests/test_salphabeta/results_true.dat @@ -1,2 +1,2 @@ k-combined: -8.418898E-01 5.633536E-03 +8.538165E-01 6.355606E-03 diff --git a/tests/test_salphabeta/test_salphabeta.py b/tests/test_salphabeta/test_salphabeta.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_salphabeta/test_salphabeta.py +++ b/tests/test_salphabeta/test_salphabeta.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_salphabeta_multiple/geometry.xml b/tests/test_salphabeta_multiple/geometry.xml index 63f69f7438..13eb601660 100644 --- a/tests/test_salphabeta_multiple/geometry.xml +++ b/tests/test_salphabeta_multiple/geometry.xml @@ -45,52 +45,52 @@ - + - + - - + + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - + + + diff --git a/tests/test_salphabeta_multiple/results_true.dat b/tests/test_salphabeta_multiple/results_true.dat index 57e620610a..593c5adc74 100644 --- a/tests/test_salphabeta_multiple/results_true.dat +++ b/tests/test_salphabeta_multiple/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.686128E-01 5.056987E-02 +9.141547E-01 2.728809E-02 diff --git a/tests/test_salphabeta_multiple/test_salphabeta_multiple.py b/tests/test_salphabeta_multiple/test_salphabeta_multiple.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_salphabeta_multiple/test_salphabeta_multiple.py +++ b/tests/test_salphabeta_multiple/test_salphabeta_multiple.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_score_MT/geometry.xml b/tests/test_score_MT/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_MT/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_MT/inputs_true.dat b/tests/test_score_MT/inputs_true.dat new file mode 100644 index 0000000000..3789a69cba --- /dev/null +++ b/tests/test_score_MT/inputs_true.dat @@ -0,0 +1 @@ +63295b9d510370e65e63a3db627d47d286f5479e53c8eabeda9a5cb25ffe35becb636835aadad11691e34c23292fe11b5f688daee76d76ceac4b5dfd2f9ede4c \ No newline at end of file diff --git a/tests/test_score_MT/materials.xml b/tests/test_score_MT/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_MT/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_MT/results_true.dat b/tests/test_score_MT/results_true.dat index 03b91f89fa..44656963f0 100644 --- a/tests/test_score_MT/results_true.dat +++ b/tests/test_score_MT/results_true.dat @@ -1,5 +1,5 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: 0.000000E+00 0.000000E+00 @@ -9,27 +9,93 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.107640E-02 -4.232516E-05 -1.107640E-02 -4.232516E-05 -3.509526E-01 -2.565440E-02 -1.171523E+00 -2.824070E-01 -5.592851E-04 -1.423656E-07 -5.592851E-04 -1.423656E-07 -3.027322E-02 -1.983924E-04 -1.477313E-02 -4.495633E-05 -8.650696E-08 -7.483455E-15 -8.650696E-08 -7.483455E-15 -1.097403E-04 -3.424171E-09 -6.866942E-02 -9.952916E-04 +1.538090E-03 +1.381456E-06 +1.538090E-03 +1.381456E-06 +3.974412E-01 +3.209809E-02 +1.373550E+00 +3.796357E-01 +5.252455E-06 +2.290531E-11 +5.252455E-06 +2.290531E-11 +3.359792E-02 +2.267331E-04 +2.459115E-02 +1.233078E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.004005E-05 +1.748739E-09 +8.104946E-02 +1.395618E-03 +tally 2: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-01 +9.000000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-02 +2.000000E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +tally 3: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.408027E-03 +1.849607E-06 +1.408027E-03 +1.849607E-06 +3.946436E-01 +3.166261E-02 +1.288136E+00 +3.382059E-01 +2.179241E-05 +4.749090E-10 +2.179241E-05 +4.749090E-10 +3.146594E-02 +2.159308E-04 +4.278352E-02 +4.094478E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.736514E-04 +1.245171E-08 +7.989710E-02 +1.377742E-03 diff --git a/tests/test_score_MT/settings.xml b/tests/test_score_MT/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_MT/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_MT/tallies.xml b/tests/test_score_MT/tallies.xml deleted file mode 100644 index ef7ff8dd82..0000000000 --- a/tests/test_score_MT/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - n2n 16 51 102 - - - \ No newline at end of file diff --git a/tests/test_score_MT/test_score_MT.py b/tests/test_score_MT/test_score_MT.py index 1777db993e..dae86d418c 100644 --- a/tests/test_score_MT/test_score_MT.py +++ b/tests/test_score_MT/test_score_MT.py @@ -1,10 +1,35 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreMTTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('n2n') for t in tallies] + [t.add_score('16') for t in tallies] + [t.add_score('51') for t in tallies] + [t.add_score('102') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreMTTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreMTTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreMTTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_absorption/geometry.xml b/tests/test_score_absorption/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_absorption/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_absorption/inputs_true.dat b/tests/test_score_absorption/inputs_true.dat new file mode 100644 index 0000000000..c4c133600a --- /dev/null +++ b/tests/test_score_absorption/inputs_true.dat @@ -0,0 +1 @@ +482760c362f56e453ce4b466083e77f84a461e636330d7cc2cb1cf7facced678a57a7c785ff9d039b3f575396cb435f99df05d6fa207f553c28ed3ce4f8151b3 \ No newline at end of file diff --git a/tests/test_score_absorption/materials.xml b/tests/test_score_absorption/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_absorption/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_absorption/results_true.dat b/tests/test_score_absorption/results_true.dat index dfdadbae7a..72661f77f4 100644 --- a/tests/test_score_absorption/results_true.dat +++ b/tests/test_score_absorption/results_true.dat @@ -1,20 +1,29 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: 0.000000E+00 0.000000E+00 -2.267589E+00 -1.054691E+00 -1.476133E-02 -4.485759E-05 -3.306896E-01 -2.302248E-02 +2.533174E+00 +1.298118E+00 +2.453769E-02 +1.227715E-04 +3.869051E-01 +3.180828E-02 tally 2: 0.000000E+00 0.000000E+00 -2.290000E+00 -1.070700E+00 +2.540000E+00 +1.293400E+00 +4.000000E-02 +6.000000E-04 +4.000000E-01 +3.600000E-02 +tally 3: 0.000000E+00 0.000000E+00 -3.800000E-01 -3.820000E-02 +2.422314E+00 +1.193460E+00 +4.285618E-02 +4.109734E-04 +3.832282E-01 +3.169516E-02 diff --git a/tests/test_score_absorption/settings.xml b/tests/test_score_absorption/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_absorption/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_absorption/tallies.xml b/tests/test_score_absorption/tallies.xml deleted file mode 100644 index 8cbcef251c..0000000000 --- a/tests/test_score_absorption/tallies.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - absorption - - - - - analog - absorption - - - \ No newline at end of file diff --git a/tests/test_score_absorption/test_score_absorption.py b/tests/test_score_absorption/test_score_absorption.py index 1777db993e..c7e3e130df 100644 --- a/tests/test_score_absorption/test_score_absorption.py +++ b/tests/test_score_absorption/test_score_absorption.py @@ -1,10 +1,32 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreAbsorptionTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('absorption') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreAbsorptionTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreAbsorptionTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreAbsorptionTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_current/geometry.xml b/tests/test_score_current/geometry.xml index b85dd04df9..f6f067aadd 100644 --- a/tests/test_score_current/geometry.xml +++ b/tests/test_score_current/geometry.xml @@ -21,50 +21,50 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + diff --git a/tests/test_score_current/results_true.dat b/tests/test_score_current/results_true.dat index 09d9a8ecf6..936e2d04bc 100644 --- a/tests/test_score_current/results_true.dat +++ b/tests/test_score_current/results_true.dat @@ -1 +1 @@ -8f7125c9686a94f0fdbd76b1667f84b9dab60c068e23d4f2b0105ce058fa533a8a4a221355614add10d54f3b18c14af41891e0fd0593154c73894e5dcb6fe5c2 \ No newline at end of file +1e6945632c55491d4584f4976cc6f5c7340874703cfaf739dd956b7124b4260955efb5b6ba041b32536f9a74572d071e0293dced55a41ea305223f698b734c2a \ No newline at end of file diff --git a/tests/test_score_current/tallies.xml b/tests/test_score_current/tallies.xml index a740949fae..3f496d43a0 100644 --- a/tests/test_score_current/tallies.xml +++ b/tests/test_score_current/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular -182.07 -182.07 -183.00 182.07 182.07 183.00 17 17 17 @@ -19,4 +19,4 @@ current - \ No newline at end of file + diff --git a/tests/test_score_current/test_score_current.py b/tests/test_score_current/test_score_current.py index 64f640b96c..99c2981c2a 100644 --- a/tests/test_score_current/test_score_current.py +++ b/tests/test_score_current/test_score_current.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import HashedTestHarness diff --git a/tests/test_score_delayed_nufission/inputs_true.dat b/tests/test_score_delayed_nufission/inputs_true.dat new file mode 100644 index 0000000000..5a0ec8a211 --- /dev/null +++ b/tests/test_score_delayed_nufission/inputs_true.dat @@ -0,0 +1 @@ +f3c246a1c83b1283163b22069f78231e3f6623fa3c2eb664ce400d0fff07105b6106d0fa8c6dfd49512a7eb676c80e4ee602e19063a9fc453394fe07a94a1bdd \ No newline at end of file diff --git a/tests/test_score_delayed_nufission/results_true.dat b/tests/test_score_delayed_nufission/results_true.dat new file mode 100644 index 0000000000..bc2b8e8a7f --- /dev/null +++ b/tests/test_score_delayed_nufission/results_true.dat @@ -0,0 +1,29 @@ +k-combined: +9.903196E-01 4.279617E-02 +tally 1: +1.711611E-02 +5.967549E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.026930E-02 +2.198717E-05 +tally 2: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.976462E-02 +1.953328E-04 +tally 3: +1.686299E-02 +5.765477E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.061240E-02 +2.305936E-05 diff --git a/tests/test_score_delayed_nufission/test_score_delayed_nufission.py b/tests/test_score_delayed_nufission/test_score_delayed_nufission.py new file mode 100644 index 0000000000..0738520e29 --- /dev/null +++ b/tests/test_score_delayed_nufission/test_score_delayed_nufission.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreDelayedNuFissionTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23, 27)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('delayed-nu-fission') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreDelayedNuFissionTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreDelayedNuFissionTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = ScoreDelayedNuFissionTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_score_events/geometry.xml b/tests/test_score_events/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_events/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_events/inputs_true.dat b/tests/test_score_events/inputs_true.dat new file mode 100644 index 0000000000..bb0fef8e5d --- /dev/null +++ b/tests/test_score_events/inputs_true.dat @@ -0,0 +1 @@ +a97ae7049ac8c30b838987a3e87cbe5ff70b004ee0434e6204931def46c4c099bfef06e74658dab1114cc1035d3f404211a9bc94ef96e9cfb5b788da39d17bbd \ No newline at end of file diff --git a/tests/test_score_events/materials.xml b/tests/test_score_events/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_events/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_events/results_true.dat b/tests/test_score_events/results_true.dat index fd18a5aba1..34b114fbcb 100644 --- a/tests/test_score_events/results_true.dat +++ b/tests/test_score_events/results_true.dat @@ -1,12 +1,12 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -5.627000E+01 -6.565251E+02 -4.892000E+01 -5.009100E+02 +6.520000E+01 +8.551888E+02 +4.035000E+01 +3.351119E+02 tally 2: -1.458000E+01 -4.391620E+01 -1.269000E+01 -3.363670E+01 +1.739000E+01 +6.083290E+01 +1.104000E+01 +2.498260E+01 diff --git a/tests/test_score_events/settings.xml b/tests/test_score_events/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_events/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_events/tallies.xml b/tests/test_score_events/tallies.xml deleted file mode 100644 index ac47f9ec86..0000000000 --- a/tests/test_score_events/tallies.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - events - - - - - - analog - events - - - \ No newline at end of file diff --git a/tests/test_score_events/test_score_events.py b/tests/test_score_events/test_score_events.py index 1777db993e..dce944592e 100644 --- a/tests/test_score_events/test_score_events.py +++ b/tests/test_score_events/test_score_events.py @@ -1,10 +1,31 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreEventsTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 27)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 3)] + [t.add_filter(filt) for t in tallies] + [t.add_score('events') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreEventsTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreEventsTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreEventsTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_fission/geometry.xml b/tests/test_score_fission/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_fission/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_fission/inputs_true.dat b/tests/test_score_fission/inputs_true.dat new file mode 100644 index 0000000000..d90ca274ee --- /dev/null +++ b/tests/test_score_fission/inputs_true.dat @@ -0,0 +1 @@ +5a0461d03b0d9653ee35fded4be23e9b8316e3b7e21d352f822bc1f9763c03e9edab922bdc431f30d2a647c4216d45deba396bf56203027a328b7b28d970e0b8 \ No newline at end of file diff --git a/tests/test_score_fission/materials.xml b/tests/test_score_fission/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_fission/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_fission/results_true.dat b/tests/test_score_fission/results_true.dat index 1a3d333838..2b28cc825c 100644 --- a/tests/test_score_fission/results_true.dat +++ b/tests/test_score_fission/results_true.dat @@ -1,20 +1,29 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -1.089685E+00 -2.438289E-01 +1.156315E+00 +2.733527E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.094323E-01 -1.773090E-01 +6.971594E-01 +1.004973E-01 tally 2: -1.081920E+00 -2.404883E-01 +1.225263E+00 +3.054971E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.945760E-01 -2.073005E-01 +6.475958E-01 +8.567154E-02 +tally 3: +1.131528E+00 +2.612886E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.021712E-01 +1.008605E-01 diff --git a/tests/test_score_fission/settings.xml b/tests/test_score_fission/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_fission/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_fission/tallies.xml b/tests/test_score_fission/tallies.xml deleted file mode 100644 index d56614bdfa..0000000000 --- a/tests/test_score_fission/tallies.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - fission - - - - - analog - fission - - - \ No newline at end of file diff --git a/tests/test_score_fission/test_score_fission.py b/tests/test_score_fission/test_score_fission.py index 1777db993e..4026c0cabf 100644 --- a/tests/test_score_fission/test_score_fission.py +++ b/tests/test_score_fission/test_score_fission.py @@ -1,10 +1,32 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreFissionTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23, 27)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('fission') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreFissionTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreFissionTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreFissionTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_flux/geometry.xml b/tests/test_score_flux/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_flux/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_flux/inputs_true.dat b/tests/test_score_flux/inputs_true.dat new file mode 100644 index 0000000000..2e7358c49e --- /dev/null +++ b/tests/test_score_flux/inputs_true.dat @@ -0,0 +1 @@ +33b7b97f55a337d7001e7927517db6d36d512efec01fa5512c80bbc76b0b581f691a72a3810251aa97491b8cdf25a8ddcc9c9b3e3f54ccc6c315a84e715567d3 \ No newline at end of file diff --git a/tests/test_score_flux/materials.xml b/tests/test_score_flux/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_flux/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_flux/results_true.dat b/tests/test_score_flux/results_true.dat index 9c21a0f3d8..5c366ea8c7 100644 --- a/tests/test_score_flux/results_true.dat +++ b/tests/test_score_flux/results_true.dat @@ -1,15 +1,41 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -3.403102E+01 -2.393236E+02 -1.143060E+01 -2.704386E+01 -5.691243E+01 -6.685581E+02 -2.924945E+01 -1.782032E+02 -9.965051E+00 -2.067319E+01 -4.931805E+01 -5.050490E+02 +3.890713E+01 +3.046363E+02 +1.366220E+01 +3.758161E+01 +6.561669E+01 +8.680729E+02 +2.382728E+01 +1.170590E+02 +8.047875E+00 +1.334796E+01 +4.056568E+01 +3.389623E+02 +tally 2: +3.862543E+01 +2.993190E+02 +1.438678E+01 +4.193571E+01 +6.400634E+01 +8.298077E+02 +2.426423E+01 +1.215124E+02 +7.600812E+00 +1.199814E+01 +4.104875E+01 +3.455300E+02 +tally 3: +3.862543E+01 +2.993190E+02 +1.438678E+01 +4.193571E+01 +6.400634E+01 +8.298077E+02 +2.426423E+01 +1.215124E+02 +7.600812E+00 +1.199814E+01 +4.104875E+01 +3.455300E+02 diff --git a/tests/test_score_flux/settings.xml b/tests/test_score_flux/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_flux/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_flux/tallies.xml b/tests/test_score_flux/tallies.xml deleted file mode 100644 index 30bef71741..0000000000 --- a/tests/test_score_flux/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - flux - - - \ No newline at end of file diff --git a/tests/test_score_flux/test_score_flux.py b/tests/test_score_flux/test_score_flux.py index 1777db993e..1eea55f45f 100644 --- a/tests/test_score_flux/test_score_flux.py +++ b/tests/test_score_flux/test_score_flux.py @@ -1,10 +1,32 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreFluxTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23, 27, 28, 29)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('flux') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreFluxTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreFluxTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreFluxTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_flux_yn/geometry.xml b/tests/test_score_flux_yn/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_flux_yn/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_flux_yn/inputs_true.dat b/tests/test_score_flux_yn/inputs_true.dat new file mode 100644 index 0000000000..c7a1a1b52e --- /dev/null +++ b/tests/test_score_flux_yn/inputs_true.dat @@ -0,0 +1 @@ +b1a63345fc721f87c8fc25babb06741b585ee5dff5f29bb6debfbabb2ad57cb762d98c14e544df998a27bc725fb2704092fcdde54315ff832dff96c3641551d0 \ No newline at end of file diff --git a/tests/test_score_flux_yn/materials.xml b/tests/test_score_flux_yn/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_flux_yn/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_flux_yn/results_true.dat b/tests/test_score_flux_yn/results_true.dat index 8c04c7c898..28a1babb04 100644 --- a/tests/test_score_flux_yn/results_true.dat +++ b/tests/test_score_flux_yn/results_true.dat @@ -1,448 +1,1314 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -3.403102E+01 -2.393236E+02 -1.143060E+01 -2.704386E+01 -5.691243E+01 -6.685581E+02 -2.924945E+01 -1.782032E+02 -9.965051E+00 -2.067319E+01 -4.931805E+01 -5.050490E+02 +3.890713E+01 +3.046363E+02 +1.366220E+01 +3.758161E+01 +6.561669E+01 +8.680729E+02 +2.382728E+01 +1.170590E+02 +8.047875E+00 +1.334796E+01 +4.056568E+01 +3.389623E+02 tally 2: -3.403102E+01 -2.393236E+02 --3.055588E-01 -3.594044E-02 -3.171128E-01 -3.805380E-01 --7.374877E-01 -2.391349E-01 --1.621986E-01 -5.578051E-02 -4.710459E-01 -1.850595E-01 --4.839599E-01 -2.440735E-01 -1.124798E-01 -8.640649E-02 --4.976706E-01 -8.943606E-02 -1.323704E-01 -6.713903E-02 --6.954103E-02 -7.876989E-02 -1.343675E-01 -2.569171E-02 --5.205013E-01 -7.985579E-02 -2.037295E-01 -1.501360E-01 --1.290735E-01 -5.069422E-02 --2.045060E-01 -2.197889E-01 -1.307602E-01 -5.938649E-02 --3.317004E-01 -1.359233E-01 --4.347480E-01 -7.528253E-02 -7.685982E-02 -4.559715E-02 --4.668784E-02 -4.065614E-02 -1.447872E-01 -5.538956E-02 --2.027337E-01 -7.095051E-02 --4.673353E-01 -1.235371E-01 --3.321732E-01 -6.905624E-02 --3.028859E-01 -3.382353E-02 --2.320613E-01 -2.845904E-02 -8.038034E-02 -3.466746E-02 -1.766484E-01 -9.996559E-02 -3.385184E-02 -5.510769E-02 -6.952638E-02 -2.741119E-02 -3.630715E-01 -5.336447E-02 -2.876222E-01 -9.938256E-02 --3.473240E-02 -1.031412E-01 -1.280013E-01 -2.331384E-02 -1.550774E-01 -3.881493E-02 -1.143060E+01 -2.704386E+01 --1.955516E-01 -9.789273E-03 -4.070149E-02 -3.530892E-02 --1.446334E-01 -3.374966E-02 --4.072014E-02 -1.407320E-02 -1.056190E-01 -2.144988E-02 --1.491728E-01 -1.699068E-02 -3.130540E-02 -4.945783E-03 --1.706770E-01 -6.943395E-03 -6.278466E-02 -4.522701E-03 --6.491915E-02 -1.218265E-02 --6.226375E-02 -8.920919E-03 --2.647477E-01 -2.028918E-02 --9.179913E-03 -1.186941E-02 --8.959288E-02 -9.826050E-03 --4.800079E-02 -3.500548E-02 -9.919028E-02 -1.278789E-02 --1.274511E-01 -9.357943E-03 --9.037073E-02 -4.686665E-03 --7.895199E-03 -8.526809E-03 --2.071827E-02 -5.844891E-03 --1.422877E-02 -2.008170E-03 --7.787500E-02 -9.642362E-03 --6.105504E-02 -7.600775E-03 --1.249117E-01 -1.314509E-02 --9.183605E-02 -7.513215E-03 --9.171222E-02 -4.220465E-03 -8.798390E-02 -5.037483E-03 -4.366496E-02 -8.411743E-03 -1.605678E-02 -6.994511E-03 --2.179875E-02 -1.352098E-03 -1.116755E-01 -7.354424E-03 -9.995739E-02 -9.710026E-03 -3.010324E-02 -1.179938E-02 -2.175815E-02 -1.281441E-03 -2.374886E-02 -6.943432E-03 -5.691243E+01 -6.685581E+02 --7.130295E-01 -1.971869E-01 -1.138602E+00 -1.071873E+00 --1.436194E+00 -7.200870E-01 --2.384966E-01 -1.129688E-01 -8.003085E-01 -5.809429E-01 --3.499868E-01 -3.310435E-01 -2.580763E-01 -2.238385E-01 --3.576056E-01 -1.437071E-01 -2.560747E-01 -4.492224E-02 --4.006295E-01 -2.456809E-01 -8.176054E-02 -3.924768E-01 --8.105689E-01 -2.397175E-01 -3.777117E-01 -4.811523E-01 --4.932440E-01 -1.789106E-01 --3.705746E-02 -5.517840E-01 -7.049764E-01 -4.243943E-01 --4.833188E-01 -2.014189E-01 --5.420278E-01 -1.201572E-01 -7.606099E-02 -1.451071E-01 -2.244026E-01 -7.628680E-02 -2.495758E-01 -1.882655E-01 --1.373888E-01 -1.958724E-01 --3.799191E-01 -2.258678E-01 --5.909624E-01 -2.940322E-01 --6.336238E-01 -1.272552E-01 --5.544697E-01 -9.027652E-02 -4.161023E-01 -1.084744E-01 -5.550548E-01 -1.838427E-01 -3.060033E-01 -8.542356E-02 -3.623817E-01 -4.245612E-02 -4.779023E-01 -8.081477E-02 -1.089872E-01 -1.402042E-01 --1.107440E-01 -3.140479E-01 -2.333168E-01 -1.035674E-01 --5.959476E-02 -2.482914E-01 -2.924945E+01 -1.782032E+02 -5.986908E-01 -4.163713E-01 -3.376452E-01 -1.744277E-01 -1.272993E-01 -1.526084E-01 --2.551267E-01 -7.284601E-02 -4.755790E-02 -6.832796E-02 --3.425133E-01 -7.756266E-02 -3.823240E-01 -1.789133E-01 --3.767347E-01 -1.676013E-01 -1.655399E-01 -1.153056E-01 -1.432265E-01 -2.956364E-02 --2.989439E-01 -5.066565E-02 --3.226047E-02 -5.960686E-02 --9.968550E-02 -4.039270E-02 --1.235291E-02 -2.805714E-01 --7.494860E-02 -2.838999E-02 -3.042503E-02 -7.425538E-02 --1.849034E-01 -8.599532E-02 --5.209242E-01 -1.174277E-01 --2.314402E-01 -4.065974E-02 --4.179560E-01 -1.382716E-01 -1.026654E-01 -1.611177E-02 --2.270386E-01 -5.157513E-02 -7.884296E-02 -2.677093E-02 -7.284620E-01 -1.871262E-01 -1.360134E-01 -9.437335E-03 --3.088199E-01 -2.292832E-02 --2.543226E-01 -1.264440E-01 -6.256788E-02 -7.604299E-02 --3.478518E-01 -6.632508E-02 -2.842847E-01 -4.906462E-02 -1.546241E-01 -3.362908E-02 --2.247690E-01 -1.912574E-02 --3.459210E-02 -1.248892E-01 --2.204075E-01 -4.281299E-02 -2.145675E-01 -5.593188E-02 -9.965051E+00 -2.067319E+01 -2.381967E-01 -4.786935E-02 --1.924308E-02 -4.029344E-02 -3.179175E-02 -2.098033E-02 --1.652308E-02 -9.391525E-03 --5.733039E-02 -1.788395E-02 -4.942155E-02 -1.206623E-03 -1.874861E-02 -1.917059E-02 --1.179838E-01 -2.185564E-02 --9.270508E-03 -1.659002E-02 -7.496511E-02 -6.849931E-03 --1.004441E-01 -4.570271E-03 --9.899601E-02 -1.027435E-02 --9.963860E-02 -4.686519E-03 --1.740638E-02 -3.936514E-02 -2.520349E-02 -5.900520E-03 -1.227791E-03 -6.173783E-03 --3.068441E-02 -6.867402E-03 --7.765654E-02 -1.399383E-02 -7.333551E-02 -4.139444E-03 --3.508914E-02 -1.421599E-02 -4.334120E-02 -4.918888E-03 --1.106116E-01 -1.143785E-02 -7.254477E-03 -1.337965E-03 -2.365948E-01 -2.473485E-02 -5.176646E-02 -1.514750E-03 --8.723610E-02 -2.395100E-03 --1.010207E-01 -1.081070E-02 --5.113298E-02 -6.053279E-03 --1.601115E-01 -8.304230E-03 --5.105345E-03 -5.079654E-03 --8.894549E-02 -2.505026E-03 --1.023874E-01 -4.311776E-03 -7.972837E-02 -1.178305E-02 --2.560942E-02 -4.101793E-03 -2.312203E-02 -3.036209E-03 -4.931805E+01 -5.050490E+02 -1.513494E+00 -1.676567E+00 -6.650656E-01 -1.400732E+00 -4.934620E-01 -7.673322E-01 --2.964442E-02 -2.262500E-01 --2.225956E-01 -4.872938E-01 -2.498269E-01 -9.442256E-02 --1.454141E-01 -2.683171E-01 --3.720260E-01 -2.266316E-01 -2.473591E-01 -3.624408E-01 -2.096941E-01 -6.664835E-02 --4.700220E-01 -9.789465E-02 --1.626165E-01 -1.315362E-01 -3.519966E-01 -1.140516E-01 --1.185342E-01 -5.708362E-01 --1.333083E-01 -1.352294E-01 -1.375803E-01 -1.572243E-01 --6.099544E-02 -2.042264E-01 --3.664336E-01 -1.762506E-01 --1.717957E-01 -5.864778E-02 --5.153204E-01 -2.484316E-01 --2.258513E-01 -8.839687E-02 --9.307565E-01 -4.802462E-01 -1.108577E-01 -4.451363E-02 -1.118965E+00 -5.173979E-01 -4.314600E-01 -5.176751E-02 --2.864059E-01 -9.159895E-02 --4.471918E-01 -1.743046E-01 --7.850808E-02 -1.317732E-01 --7.445394E-01 -1.479808E-01 -7.480873E-01 -2.696289E-01 -1.731449E-01 -5.301367E-02 --3.663464E-01 -3.430563E-02 -3.553351E-01 -2.051544E-01 --4.312304E-01 -2.164291E-01 -2.436515E-01 -8.025128E-02 +3.890713E+01 +3.046363E+02 +-1.623579E-01 +4.602199E-02 +4.860074E-01 +5.999399E-01 +-7.895692E-01 +2.803790E-01 +2.525526E-01 +8.261176E-02 +9.103525E-02 +2.246700E-01 +4.583205E-01 +8.444556E-02 +-1.246553E-01 +2.351010E-01 +-3.534581E-01 +1.247916E-01 +-3.700473E-01 +5.215562E-02 +-1.831625E-01 +1.927381E-01 +-1.540114E-01 +1.918221E-02 +-1.266458E-01 +1.455875E-01 +-6.796869E-01 +3.911926E-01 +1.987931E-02 +4.966442E-02 +4.443797E-01 +8.842717E-02 +-1.073855E-01 +4.912428E-02 +-3.999416E-02 +4.440138E-02 +2.857919E-01 +6.935717E-02 +4.174851E-01 +5.485570E-02 +-2.178958E-01 +8.052149E-02 +-1.179644E-02 +6.709330E-02 +8.843286E-01 +2.749681E-01 +2.935079E-01 +3.032897E-02 +-1.809434E-01 +1.902413E-01 +-2.091991E-01 +1.061912E-01 +-7.137275E-02 +4.397656E-02 +2.311558E-01 +4.680679E-02 +9.927573E-02 +1.844111E-01 +-2.821437E-02 +7.293762E-02 +6.224251E-01 +1.028351E-01 +4.136440E-01 +5.198207E-02 +-7.833133E-02 +1.192960E-02 +1.041586E-01 +1.587417E-01 +-3.595677E-01 +3.086335E-01 +-2.096284E-01 +7.881012E-02 +1.366220E+01 +3.758161E+01 +1.461402E-02 +3.260482E-03 +8.325893E-02 +6.248769E-02 +-2.785736E-01 +3.698417E-02 +1.932396E-03 +1.561742E-02 +8.063397E-02 +3.598680E-02 +8.565555E-02 +5.344369E-03 +-3.899905E-02 +2.422867E-02 +-1.215439E-01 +9.193858E-03 +-1.982614E-01 +1.045860E-02 +-7.712629E-02 +2.199979E-02 +3.626484E-02 +9.872078E-04 +-6.305159E-02 +1.645879E-02 +-3.052155E-01 +5.620564E-02 +3.507115E-02 +1.056383E-02 +1.297490E-02 +5.889958E-03 +-1.208752E-02 +7.323602E-03 +-3.441007E-03 +1.841496E-02 +5.543442E-02 +1.186636E-02 +8.000436E-02 +3.703835E-03 +-3.636792E-02 +1.490603E-02 +8.753196E-02 +7.958027E-03 +2.066727E-01 +1.414130E-02 +3.652482E-02 +8.380395E-04 +-1.652432E-01 +1.878732E-02 +-1.375567E-01 +1.302400E-02 +3.692057E-03 +6.312506E-03 +9.016211E-02 +6.699735E-03 +-5.875401E-02 +1.731945E-02 +-3.960008E-02 +3.595906E-03 +1.653510E-01 +9.277293E-03 +4.064973E-02 +2.794606E-03 +-1.729061E-02 +3.219772E-03 +5.764808E-02 +1.861051E-02 +-5.970583E-02 +2.070164E-02 +-6.739411E-02 +1.063341E-02 +6.561669E+01 +8.680729E+02 +-7.938430E-01 +2.994198E-01 +9.278084E-01 +1.861899E+00 +-1.432236E+00 +7.429647E-01 +7.460836E-02 +5.946808E-01 +6.140731E-02 +3.175177E-01 +1.212677E+00 +5.125288E-01 +1.952865E-02 +5.468421E-01 +-2.965796E-01 +1.123288E-01 +-5.334195E-01 +1.589612E-01 +-6.340814E-01 +4.874650E-01 +-4.264003E-02 +9.109571E-03 +-4.323424E-01 +3.370329E-01 +-1.186876E+00 +9.854644E-01 +-2.420825E-01 +1.699455E-01 +2.920627E-02 +6.816643E-02 +-2.684345E-01 +9.799236E-02 +1.281596E-01 +3.092987E-01 +3.746150E-01 +1.242044E-01 +1.035056E+00 +2.589772E-01 +2.005450E-01 +2.074622E-01 +5.412719E-01 +3.193584E-01 +1.070173E+00 +3.266747E-01 +2.657850E-01 +1.599950E-01 +-4.694853E-01 +2.738937E-01 +-7.761977E-01 +2.561652E-01 +3.673179E-02 +9.486916E-02 +3.309909E-01 +1.095243E-01 +1.623761E-01 +2.874582E-01 +2.846296E-01 +2.430397E-01 +7.384842E-01 +2.556480E-01 +3.577508E-01 +1.763210E-01 +-2.917525E-01 +1.875646E-01 +1.634324E-01 +2.952144E-01 +-4.329582E-01 +3.418652E-01 +-2.719362E-01 +2.278925E-01 +2.382728E+01 +1.170590E+02 +-4.718326E-01 +1.961501E-01 +1.612551E-02 +2.815245E-02 +-6.390587E-01 +1.902968E-01 +2.290989E-01 +3.758858E-02 +-1.568179E-01 +1.509162E-01 +-2.363058E-01 +6.671396E-02 +4.350800E-02 +1.031680E-01 +-2.956828E-01 +2.515141E-02 +4.835878E-01 +8.614200E-02 +-5.365970E-02 +8.404087E-02 +6.079969E-02 +3.684343E-02 +-1.313088E-02 +1.488843E-02 +-2.603258E-02 +2.900625E-02 +1.249213E-01 +2.737277E-02 +-4.491422E-01 +9.482600E-02 +-1.095589E-01 +3.711500E-02 +2.248159E-01 +2.815827E-02 +-5.976009E-02 +5.887828E-03 +6.097208E-02 +5.393315E-02 +3.449714E-02 +4.332442E-02 +1.030757E-01 +2.839453E-02 +-4.399117E-01 +8.887569E-02 +-4.564910E-01 +1.172398E-01 +-2.528382E-01 +1.217655E-01 +-3.443316E-01 +4.275616E-02 +5.437008E-02 +2.355567E-02 +5.505588E-02 +5.479129E-02 +-8.326640E-02 +3.095858E-02 +1.888781E-01 +2.884542E-02 +1.981251E-01 +1.520694E-02 +5.279866E-02 +1.020641E-01 +-1.465368E-01 +3.070686E-02 +2.356940E-01 +7.899657E-02 +4.109278E-01 +5.291082E-02 +-2.572510E-01 +3.420895E-02 +8.047875E+00 +1.334796E+01 +-1.707535E-01 +3.290927E-02 +1.024687E-01 +1.308811E-02 +-1.805451E-01 +1.696222E-02 +3.519587E-02 +7.546726E-03 +-1.034933E-01 +2.224207E-02 +-1.580512E-01 +2.369625E-02 +-4.302961E-02 +1.635623E-02 +-2.992903E-02 +5.190220E-03 +2.130862E-01 +1.186351E-02 +-3.321696E-02 +7.972404E-03 +4.992040E-02 +5.667098E-03 +1.261320E-02 +2.436872E-03 +8.314024E-04 +5.360616E-03 +-6.318247E-02 +1.644558E-03 +-1.373600E-01 +1.030707E-02 +1.511677E-03 +3.467685E-03 +1.923485E-02 +8.106508E-04 +-1.180094E-01 +4.381376E-03 +-2.798056E-02 +4.871288E-03 +-7.689499E-02 +7.079493E-03 +-5.842586E-02 +1.380713E-03 +-9.946341E-02 +7.085062E-03 +-8.061825E-02 +8.679468E-03 +-9.229524E-03 +9.187483E-03 +-1.048310E-01 +3.506026E-03 +3.666209E-02 +3.259203E-03 +1.190727E-01 +4.935341E-03 +-7.391655E-02 +2.805554E-03 +2.029126E-02 +2.497736E-03 +2.787185E-02 +5.677987E-04 +6.873108E-02 +1.287727E-02 +-5.262840E-02 +3.190440E-03 +3.910911E-02 +8.661121E-03 +1.076197E-01 +5.456176E-03 +-7.476066E-02 +2.693605E-03 +4.056568E+01 +3.389623E+02 +-6.428633E-01 +6.128893E-01 +4.878518E-01 +2.130257E-01 +-9.548044E-01 +4.556949E-01 +2.234940E-01 +1.006817E-01 +1.080276E-01 +5.980158E-01 +-3.639229E-01 +3.120105E-01 +3.237506E-01 +3.451548E-01 +1.143081E-01 +7.924550E-02 +6.456733E-01 +2.424413E-01 +1.478136E-01 +1.458665E-01 +2.134798E-02 +9.102875E-02 +3.633264E-01 +7.386463E-02 +-2.213946E-01 +1.253249E-01 +-3.153847E-01 +1.094273E-01 +-7.161113E-01 +2.275500E-01 +-2.461979E-01 +1.484452E-01 +2.332886E-01 +9.715521E-02 +-7.029988E-02 +1.835254E-02 +-1.982842E-01 +9.722998E-02 +-2.089693E-01 +2.271404E-01 +7.316104E-02 +3.974665E-02 +-3.266640E-01 +8.054809E-02 +-5.126088E-01 +3.234942E-01 +-3.048753E-01 +3.439501E-01 +-4.872647E-01 +9.473730E-02 +1.590200E-01 +3.613462E-02 +4.641787E-01 +1.671339E-01 +-1.391114E-01 +3.581561E-02 +2.209343E-01 +1.489367E-02 +3.015665E-01 +4.265694E-02 +1.334716E-01 +2.321929E-01 +-3.702914E-01 +1.699549E-01 +8.891532E-02 +1.708595E-01 +6.123686E-01 +1.429184E-01 +-5.891300E-01 +1.085467E-01 +tally 3: +3.862543E+01 +2.993190E+02 +-5.083613E-01 +2.933365E-01 +-4.356793E-01 +6.676831E-01 +-6.093148E-01 +5.685331E-01 +2.512276E-01 +1.308652E-01 +-1.075955E+00 +4.775270E-01 +3.660307E-01 +1.627691E-01 +5.402149E-01 +2.324946E-01 +-3.887573E-01 +1.028105E-01 +4.324152E-01 +1.015147E-01 +3.306993E-02 +8.425069E-02 +2.127456E-01 +5.435453E-02 +2.977294E-01 +1.088039E-01 +-1.055079E+00 +3.590635E-01 +-6.740592E-01 +2.606281E-01 +3.329512E-01 +1.587428E-01 +-1.248691E-01 +1.659045E-01 +2.306000E-01 +1.062057E-01 +9.127791E-02 +2.649459E-01 +2.629881E-01 +4.786229E-02 +2.286813E-01 +2.363629E-02 +6.338613E-01 +1.118828E-01 +7.466647E-01 +1.424535E-01 +7.955161E-02 +1.003327E-02 +1.082691E-01 +2.727882E-02 +-5.295185E-01 +1.335133E-01 +-6.321517E-01 +1.422916E-01 +1.236137E-01 +2.041422E-01 +-5.389265E-02 +1.852888E-01 +3.746082E-01 +5.580885E-02 +1.383528E-01 +2.754456E-01 +5.081204E-01 +1.886515E-01 +-4.022264E-01 +1.417397E-01 +-3.377771E-01 +6.673888E-02 +1.170109E-01 +1.783182E-02 +-2.097916E-01 +7.139323E-02 +1.438678E+01 +4.193571E+01 +-6.547124E-01 +1.780450E-01 +2.207489E-01 +2.115835E-01 +4.952323E-02 +3.039341E-01 +6.681546E-01 +1.389250E-01 +-4.078026E-02 +4.393667E-02 +-8.695509E-01 +2.850853E-01 +-1.792062E-01 +7.367253E-02 +-5.657500E-01 +2.115125E-01 +-8.525189E-02 +2.541971E-02 +5.227867E-02 +2.008468E-02 +6.825349E-02 +5.316522E-02 +3.763076E-01 +7.112554E-02 +-1.279973E-02 +1.883096E-01 +7.775189E-02 +6.874374E-02 +1.119537E-01 +8.467755E-02 +-1.600632E-01 +8.650448E-02 +6.210095E-01 +1.094309E-01 +-9.997484E-02 +3.935353E-02 +-2.300525E-01 +2.351925E-02 +2.486103E-02 +3.125565E-02 +1.289518E-02 +2.879251E-02 +-3.166559E-01 +2.931428E-02 +-1.379285E-02 +2.416257E-02 +1.220552E-02 +5.154030E-02 +-1.431676E-01 +3.434080E-02 +8.148581E-02 +4.218412E-02 +8.541678E-03 +6.396306E-02 +-7.851012E-03 +5.799658E-02 +2.435723E-01 +6.744263E-02 +-2.429877E-01 +6.966516E-02 +-1.638644E-01 +2.058798E-02 +-8.986584E-03 +1.374824E-02 +3.547454E-01 +7.765460E-02 +-1.570173E-01 +6.916960E-02 +-1.056941E-02 +7.626528E-03 +6.400634E+01 +8.298077E+02 +-3.894111E-01 +8.617494E-01 +1.796567E-01 +1.065356E+00 +-1.561037E+00 +7.701475E-01 +-2.237530E-01 +2.259442E-01 +1.109999E+00 +6.179412E-01 +1.636912E+00 +7.887441E-01 +4.661183E-01 +4.191138E-01 +-1.040546E+00 +2.971961E-01 +1.044850E-01 +1.493530E-01 +-4.991935E-01 +3.222404E-01 +-4.205099E-01 +2.734911E-01 +-7.583139E-01 +3.000853E-01 +-3.750811E-01 +1.348273E-01 +-6.355508E-01 +3.666139E-01 +5.233787E-01 +1.292414E-01 +-2.869538E-02 +9.115092E-02 +6.851052E-01 +3.061040E-01 +1.703522E-01 +7.300335E-02 +4.541075E-01 +4.438507E-01 +-2.674857E-01 +4.718588E-01 +3.022517E-02 +1.136781E-01 +5.755596E-01 +2.688162E-01 +2.698373E-01 +1.403188E-01 +8.772347E-01 +3.503562E-01 +-4.258508E-01 +1.400825E-01 +-1.384853E-01 +4.924947E-02 +-1.009402E-01 +2.039230E-01 +-1.339732E-01 +4.772083E-02 +-3.249636E-01 +4.339747E-01 +1.564400E-01 +2.703717E-01 +2.536360E-01 +8.543919E-02 +-3.622063E-01 +7.442240E-02 +-2.074953E-02 +1.355614E-01 +-3.909820E-02 +1.007999E-01 +3.162815E-01 +9.656425E-02 +2.426423E+01 +1.215124E+02 +-9.628829E-01 +3.563586E-01 +2.964625E-01 +9.739638E-02 +-3.680881E-01 +3.484018E-01 +4.339143E-01 +7.590564E-02 +4.633394E-02 +1.080030E-01 +3.091634E-01 +1.246585E-01 +4.520500E-02 +1.095704E-01 +2.479383E-01 +1.138276E-01 +6.457108E-02 +6.833667E-02 +-5.623363E-02 +1.087254E-01 +3.675294E-01 +9.602246E-02 +-1.459951E-01 +9.440544E-02 +-6.817672E-02 +4.978066E-02 +1.076782E-02 +1.697440E-01 +-1.024501E-02 +1.184830E-01 +-1.654178E-01 +1.689209E-02 +-1.006214E-01 +3.392546E-02 +5.070063E-01 +7.598100E-02 +2.251704E-01 +7.867348E-02 +-1.693789E-01 +2.069974E-01 +-2.790249E-01 +2.674643E-02 +3.888604E-01 +3.649330E-02 +7.614452E-02 +7.098023E-02 +1.236282E-02 +5.476895E-02 +-3.151637E-01 +3.543466E-02 +-6.363562E-01 +9.323507E-02 +2.808153E-01 +8.537981E-02 +2.197639E-01 +3.393653E-02 +8.660625E-02 +1.575544E-02 +3.733826E-02 +1.449783E-02 +8.800903E-04 +3.993931E-02 +3.304886E-01 +3.099095E-02 +-4.149186E-02 +5.375091E-02 +2.448819E-01 +9.225028E-02 +-1.230091E-01 +3.865008E-02 +7.600812E+00 +1.199814E+01 +-8.738539E-01 +3.078183E-01 +-2.592305E-01 +1.015952E-01 +-6.391696E-02 +6.657129E-02 +-2.857855E-01 +2.216294E-02 +-3.516811E-01 +3.429194E-02 +4.585144E-02 +6.204056E-02 +-1.599494E-01 +1.684846E-02 +-2.364219E-01 +1.550644E-02 +1.197289E-01 +8.631394E-02 +-1.364517E-01 +5.086560E-02 +-2.213374E-01 +2.779096E-02 +-7.328761E-02 +1.216230E-02 +2.476803E-01 +2.724500E-02 +-6.356296E-02 +2.513244E-02 +-3.886281E-01 +9.479377E-02 +1.006972E-01 +1.352120E-02 +6.932242E-02 +3.192705E-02 +-3.232505E-02 +5.592418E-02 +9.582599E-02 +1.504811E-02 +-2.887999E-01 +3.760482E-02 +-2.372013E-01 +1.868786E-02 +-1.655526E-01 +4.720116E-02 +8.611265E-02 +2.284310E-02 +-2.142116E-01 +2.619080E-02 +-1.811202E-01 +1.457105E-02 +1.430164E-01 +2.016598E-02 +-4.066031E-01 +7.671356E-02 +1.364946E-01 +1.385677E-02 +8.357667E-02 +1.521943E-02 +-2.235270E-02 +1.029570E-02 +-7.920760E-02 +4.227880E-02 +2.622096E-01 +2.327728E-02 +-7.787296E-03 +2.288300E-02 +-1.645219E-02 +5.394704E-02 +7.274557E-02 +1.075570E-02 +4.104875E+01 +3.455300E+02 +-9.827893E-01 +2.751051E-01 +3.227606E-01 +1.213711E-01 +-1.272840E-02 +2.813639E-01 +-1.910394E-01 +5.682320E-02 +4.136260E-01 +2.444497E-01 +-5.123352E-02 +3.867174E-01 +4.424857E-02 +9.651204E-02 +-3.975443E-02 +1.867060E-01 +7.618837E-01 +1.756891E-01 +4.259599E-01 +1.146646E-01 +5.658031E-02 +1.366891E-01 +2.464931E-01 +2.181122E-01 +-1.593998E-01 +2.666678E-01 +-1.928096E-01 +1.216164E-01 +-7.020992E-01 +1.701086E-01 +3.914244E-01 +1.772217E-01 +3.285697E-01 +1.521826E-01 +-2.947923E-02 +8.201284E-02 +-1.346653E-01 +4.498340E-02 +2.112724E-01 +9.923303E-02 +-8.551910E-02 +8.804286E-03 +-3.631005E-01 +1.168145E-01 +-1.840770E-01 +5.714283E-02 +-2.709303E-02 +9.381338E-02 +-2.104005E-02 +4.479215E-02 +4.059493E-01 +8.277066E-02 +2.877400E-01 +8.584721E-02 +4.881128E-02 +1.864179E-01 +8.584545E-02 +4.421744E-02 +-4.392466E-01 +6.260373E-02 +-3.143214E-02 +8.184856E-02 +-5.630973E-01 +1.323469E-01 +-8.010498E-02 +1.096975E-01 +1.818829E-01 +1.717701E-02 +-1.062149E-01 +5.400365E-02 +tally 4: +3.862543E+01 +2.993190E+02 +-5.083613E-01 +2.933365E-01 +-4.356793E-01 +6.676831E-01 +-6.093148E-01 +5.685331E-01 +2.512276E-01 +1.308652E-01 +-1.075955E+00 +4.775270E-01 +3.660307E-01 +1.627691E-01 +5.402149E-01 +2.324946E-01 +-3.887573E-01 +1.028105E-01 +4.324152E-01 +1.015147E-01 +3.306993E-02 +8.425069E-02 +2.127456E-01 +5.435453E-02 +2.977294E-01 +1.088039E-01 +-1.055079E+00 +3.590635E-01 +-6.740592E-01 +2.606281E-01 +3.329512E-01 +1.587428E-01 +-1.248691E-01 +1.659045E-01 +2.306000E-01 +1.062057E-01 +9.127791E-02 +2.649459E-01 +2.629881E-01 +4.786229E-02 +2.286813E-01 +2.363629E-02 +6.338613E-01 +1.118828E-01 +7.466647E-01 +1.424535E-01 +7.955161E-02 +1.003327E-02 +1.082691E-01 +2.727882E-02 +-5.295185E-01 +1.335133E-01 +-6.321517E-01 +1.422916E-01 +1.236137E-01 +2.041422E-01 +-5.389265E-02 +1.852888E-01 +3.746082E-01 +5.580885E-02 +1.383528E-01 +2.754456E-01 +5.081204E-01 +1.886515E-01 +-4.022264E-01 +1.417397E-01 +-3.377771E-01 +6.673888E-02 +1.170109E-01 +1.783182E-02 +-2.097916E-01 +7.139323E-02 +1.438678E+01 +4.193571E+01 +-6.547124E-01 +1.780450E-01 +2.207489E-01 +2.115835E-01 +4.952323E-02 +3.039341E-01 +6.681546E-01 +1.389250E-01 +-4.078026E-02 +4.393667E-02 +-8.695509E-01 +2.850853E-01 +-1.792062E-01 +7.367253E-02 +-5.657500E-01 +2.115125E-01 +-8.525189E-02 +2.541971E-02 +5.227867E-02 +2.008468E-02 +6.825349E-02 +5.316522E-02 +3.763076E-01 +7.112554E-02 +-1.279973E-02 +1.883096E-01 +7.775189E-02 +6.874374E-02 +1.119537E-01 +8.467755E-02 +-1.600632E-01 +8.650448E-02 +6.210095E-01 +1.094309E-01 +-9.997484E-02 +3.935353E-02 +-2.300525E-01 +2.351925E-02 +2.486103E-02 +3.125565E-02 +1.289518E-02 +2.879251E-02 +-3.166559E-01 +2.931428E-02 +-1.379285E-02 +2.416257E-02 +1.220552E-02 +5.154030E-02 +-1.431676E-01 +3.434080E-02 +8.148581E-02 +4.218412E-02 +8.541678E-03 +6.396306E-02 +-7.851012E-03 +5.799658E-02 +2.435723E-01 +6.744263E-02 +-2.429877E-01 +6.966516E-02 +-1.638644E-01 +2.058798E-02 +-8.986584E-03 +1.374824E-02 +3.547454E-01 +7.765460E-02 +-1.570173E-01 +6.916960E-02 +-1.056941E-02 +7.626528E-03 +6.400634E+01 +8.298077E+02 +-3.894111E-01 +8.617494E-01 +1.796567E-01 +1.065356E+00 +-1.561037E+00 +7.701475E-01 +-2.237530E-01 +2.259442E-01 +1.109999E+00 +6.179412E-01 +1.636912E+00 +7.887441E-01 +4.661183E-01 +4.191138E-01 +-1.040546E+00 +2.971961E-01 +1.044850E-01 +1.493530E-01 +-4.991935E-01 +3.222404E-01 +-4.205099E-01 +2.734911E-01 +-7.583139E-01 +3.000853E-01 +-3.750811E-01 +1.348273E-01 +-6.355508E-01 +3.666139E-01 +5.233787E-01 +1.292414E-01 +-2.869538E-02 +9.115092E-02 +6.851052E-01 +3.061040E-01 +1.703522E-01 +7.300335E-02 +4.541075E-01 +4.438507E-01 +-2.674857E-01 +4.718588E-01 +3.022517E-02 +1.136781E-01 +5.755596E-01 +2.688162E-01 +2.698373E-01 +1.403188E-01 +8.772347E-01 +3.503562E-01 +-4.258508E-01 +1.400825E-01 +-1.384853E-01 +4.924947E-02 +-1.009402E-01 +2.039230E-01 +-1.339732E-01 +4.772083E-02 +-3.249636E-01 +4.339747E-01 +1.564400E-01 +2.703717E-01 +2.536360E-01 +8.543919E-02 +-3.622063E-01 +7.442240E-02 +-2.074953E-02 +1.355614E-01 +-3.909820E-02 +1.007999E-01 +3.162815E-01 +9.656425E-02 +2.426423E+01 +1.215124E+02 +-9.628829E-01 +3.563586E-01 +2.964625E-01 +9.739638E-02 +-3.680881E-01 +3.484018E-01 +4.339143E-01 +7.590564E-02 +4.633394E-02 +1.080030E-01 +3.091634E-01 +1.246585E-01 +4.520500E-02 +1.095704E-01 +2.479383E-01 +1.138276E-01 +6.457108E-02 +6.833667E-02 +-5.623363E-02 +1.087254E-01 +3.675294E-01 +9.602246E-02 +-1.459951E-01 +9.440544E-02 +-6.817672E-02 +4.978066E-02 +1.076782E-02 +1.697440E-01 +-1.024501E-02 +1.184830E-01 +-1.654178E-01 +1.689209E-02 +-1.006214E-01 +3.392546E-02 +5.070063E-01 +7.598100E-02 +2.251704E-01 +7.867348E-02 +-1.693789E-01 +2.069974E-01 +-2.790249E-01 +2.674643E-02 +3.888604E-01 +3.649330E-02 +7.614452E-02 +7.098023E-02 +1.236282E-02 +5.476895E-02 +-3.151637E-01 +3.543466E-02 +-6.363562E-01 +9.323507E-02 +2.808153E-01 +8.537981E-02 +2.197639E-01 +3.393653E-02 +8.660625E-02 +1.575544E-02 +3.733826E-02 +1.449783E-02 +8.800903E-04 +3.993931E-02 +3.304886E-01 +3.099095E-02 +-4.149186E-02 +5.375091E-02 +2.448819E-01 +9.225028E-02 +-1.230091E-01 +3.865008E-02 +7.600812E+00 +1.199814E+01 +-8.738539E-01 +3.078183E-01 +-2.592305E-01 +1.015952E-01 +-6.391696E-02 +6.657129E-02 +-2.857855E-01 +2.216294E-02 +-3.516811E-01 +3.429194E-02 +4.585144E-02 +6.204056E-02 +-1.599494E-01 +1.684846E-02 +-2.364219E-01 +1.550644E-02 +1.197289E-01 +8.631394E-02 +-1.364517E-01 +5.086560E-02 +-2.213374E-01 +2.779096E-02 +-7.328761E-02 +1.216230E-02 +2.476803E-01 +2.724500E-02 +-6.356296E-02 +2.513244E-02 +-3.886281E-01 +9.479377E-02 +1.006972E-01 +1.352120E-02 +6.932242E-02 +3.192705E-02 +-3.232505E-02 +5.592418E-02 +9.582599E-02 +1.504811E-02 +-2.887999E-01 +3.760482E-02 +-2.372013E-01 +1.868786E-02 +-1.655526E-01 +4.720116E-02 +8.611265E-02 +2.284310E-02 +-2.142116E-01 +2.619080E-02 +-1.811202E-01 +1.457105E-02 +1.430164E-01 +2.016598E-02 +-4.066031E-01 +7.671356E-02 +1.364946E-01 +1.385677E-02 +8.357667E-02 +1.521943E-02 +-2.235270E-02 +1.029570E-02 +-7.920760E-02 +4.227880E-02 +2.622096E-01 +2.327728E-02 +-7.787296E-03 +2.288300E-02 +-1.645219E-02 +5.394704E-02 +7.274557E-02 +1.075570E-02 +4.104875E+01 +3.455300E+02 +-9.827893E-01 +2.751051E-01 +3.227606E-01 +1.213711E-01 +-1.272840E-02 +2.813639E-01 +-1.910394E-01 +5.682320E-02 +4.136260E-01 +2.444497E-01 +-5.123352E-02 +3.867174E-01 +4.424857E-02 +9.651204E-02 +-3.975443E-02 +1.867060E-01 +7.618837E-01 +1.756891E-01 +4.259599E-01 +1.146646E-01 +5.658031E-02 +1.366891E-01 +2.464931E-01 +2.181122E-01 +-1.593998E-01 +2.666678E-01 +-1.928096E-01 +1.216164E-01 +-7.020992E-01 +1.701086E-01 +3.914244E-01 +1.772217E-01 +3.285697E-01 +1.521826E-01 +-2.947923E-02 +8.201284E-02 +-1.346653E-01 +4.498340E-02 +2.112724E-01 +9.923303E-02 +-8.551910E-02 +8.804286E-03 +-3.631005E-01 +1.168145E-01 +-1.840770E-01 +5.714283E-02 +-2.709303E-02 +9.381338E-02 +-2.104005E-02 +4.479215E-02 +4.059493E-01 +8.277066E-02 +2.877400E-01 +8.584721E-02 +4.881128E-02 +1.864179E-01 +8.584545E-02 +4.421744E-02 +-4.392466E-01 +6.260373E-02 +-3.143214E-02 +8.184856E-02 +-5.630973E-01 +1.323469E-01 +-8.010498E-02 +1.096975E-01 +1.818829E-01 +1.717701E-02 +-1.062149E-01 +5.400365E-02 diff --git a/tests/test_score_flux_yn/settings.xml b/tests/test_score_flux_yn/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_flux_yn/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_flux_yn/tallies.xml b/tests/test_score_flux_yn/tallies.xml deleted file mode 100644 index 71301d0e7f..0000000000 --- a/tests/test_score_flux_yn/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - flux - - - - - flux-y5 - - - diff --git a/tests/test_score_flux_yn/test_score_flux_yn.py b/tests/test_score_flux_yn/test_score_flux_yn.py index 1777db993e..254069226c 100755 --- a/tests/test_score_flux_yn/test_score_flux_yn.py +++ b/tests/test_score_flux_yn/test_score_flux_yn.py @@ -1,10 +1,33 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreFluxYnTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23, 27, 28, 29)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 5)] + [t.add_filter(filt) for t in tallies] + tallies[0].add_score('flux') + [t.add_score('flux-y5') for t in tallies[1:]] + tallies[1].estimator = 'tracklength' + tallies[2].estimator = 'analog' + tallies[3].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreFluxYnTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreFluxYnTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreFluxYnTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_inverse_velocity/inputs_true.dat b/tests/test_score_inverse_velocity/inputs_true.dat new file mode 100644 index 0000000000..0546cf828f --- /dev/null +++ b/tests/test_score_inverse_velocity/inputs_true.dat @@ -0,0 +1 @@ +ba1010f940c50314d61aae9f729b7bb476a6b35c5556fbc689ba3fde70ff50b0ba5dad0db3b38349a1562d67817047090ac450a64d895c8f3393163fe7914763 \ No newline at end of file diff --git a/tests/test_score_inverse_velocity/results_true.dat b/tests/test_score_inverse_velocity/results_true.dat new file mode 100644 index 0000000000..740d31f16b --- /dev/null +++ b/tests/test_score_inverse_velocity/results_true.dat @@ -0,0 +1,29 @@ +k-combined: +9.903196E-01 4.279617E-02 +tally 1: +1.049628E-05 +2.261930E-11 +4.056389E-06 +3.411247E-12 +2.243766E-05 +1.069671E-10 +6.354432E-06 +8.370608E-12 +tally 2: +1.029200E-05 +2.180706E-11 +4.353200E-06 +4.363747E-12 +2.211790E-05 +1.055892E-10 +6.086777E-06 +7.589579E-12 +tally 3: +1.029200E-05 +2.180706E-11 +4.353200E-06 +4.363747E-12 +2.211790E-05 +1.055892E-10 +6.086777E-06 +7.589579E-12 diff --git a/tests/test_score_inverse_velocity/test_score_inversevelocity.py b/tests/test_score_inverse_velocity/test_score_inversevelocity.py new file mode 100644 index 0000000000..787e9df091 --- /dev/null +++ b/tests/test_score_inverse_velocity/test_score_inversevelocity.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreInverseVelocityTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23, 27)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('inverse-velocity') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreInverseVelocityTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreInverseVelocityTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = ScoreInverseVelocityTestHarness('statepoint.10.*', True) + harness.main() diff --git a/tests/test_score_kappafission/geometry.xml b/tests/test_score_kappafission/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_kappafission/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_kappafission/inputs_true.dat b/tests/test_score_kappafission/inputs_true.dat new file mode 100644 index 0000000000..ecb42ddb46 --- /dev/null +++ b/tests/test_score_kappafission/inputs_true.dat @@ -0,0 +1 @@ +57e4aa7550789aec0fcbc4a8917e9d28b1f1ae098a09cde95b757fd87d0dd3924c1bb9d4b23c59cd3793446fb6bbc8af4e1bb46323d70d5e5acd13db1167f545 \ No newline at end of file diff --git a/tests/test_score_kappafission/materials.xml b/tests/test_score_kappafission/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_kappafission/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_kappafission/results_true.dat b/tests/test_score_kappafission/results_true.dat index f9f4c44b9a..976eefa36e 100644 --- a/tests/test_score_kappafission/results_true.dat +++ b/tests/test_score_kappafission/results_true.dat @@ -1,11 +1,29 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -2.135627E+02 -9.364189E+03 +2.266169E+02 +1.049923E+04 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.782510E+02 -6.811324E+03 +1.366590E+02 +3.861651E+03 +tally 2: +2.403775E+02 +1.175130E+04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.270420E+02 +3.297537E+03 +tally 3: +2.217588E+02 +1.003581E+04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.376303E+02 +3.875598E+03 diff --git a/tests/test_score_kappafission/settings.xml b/tests/test_score_kappafission/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_kappafission/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_kappafission/tallies.xml b/tests/test_score_kappafission/tallies.xml deleted file mode 100644 index 1b63fdeeb2..0000000000 --- a/tests/test_score_kappafission/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - kappa-fission - - - \ No newline at end of file diff --git a/tests/test_score_kappafission/test_score_kappafission.py b/tests/test_score_kappafission/test_score_kappafission.py index 1777db993e..2e93b51c46 100644 --- a/tests/test_score_kappafission/test_score_kappafission.py +++ b/tests/test_score_kappafission/test_score_kappafission.py @@ -1,10 +1,32 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreKappaFissionTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23, 27)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('kappa-fission') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreKappaFissionTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreKappaFissionTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreKappaFissionTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_nufission/geometry.xml b/tests/test_score_nufission/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_nufission/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_nufission/inputs_true.dat b/tests/test_score_nufission/inputs_true.dat new file mode 100644 index 0000000000..52f7765fa7 --- /dev/null +++ b/tests/test_score_nufission/inputs_true.dat @@ -0,0 +1 @@ +a42b2e165f59d3f499865d5db1e7db9b4cb25e48290f94080e569a9efc0b437d75cbb5773ac564f6cc95b19521fb7bc97a3eb641b491828c90cd086dc0c06a4b \ No newline at end of file diff --git a/tests/test_score_nufission/materials.xml b/tests/test_score_nufission/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_nufission/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_nufission/results_true.dat b/tests/test_score_nufission/results_true.dat index 21d6586b68..31c6abe9d5 100644 --- a/tests/test_score_nufission/results_true.dat +++ b/tests/test_score_nufission/results_true.dat @@ -1,11 +1,29 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -2.879098E+00 -1.700626E+00 +3.041781E+00 +1.891714E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.401881E+00 -1.235627E+00 +1.835166E+00 +6.963265E-01 +tally 2: +3.341227E+00 +2.322075E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.862652E+00 +7.112121E-01 +tally 3: +2.975121E+00 +1.806644E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.846861E+00 +6.985413E-01 diff --git a/tests/test_score_nufission/settings.xml b/tests/test_score_nufission/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_nufission/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_nufission/tallies.xml b/tests/test_score_nufission/tallies.xml deleted file mode 100644 index d3e6963f3c..0000000000 --- a/tests/test_score_nufission/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - nu-fission - - - \ No newline at end of file diff --git a/tests/test_score_nufission/test_score_nufission.py b/tests/test_score_nufission/test_score_nufission.py index 1777db993e..3d540daac7 100644 --- a/tests/test_score_nufission/test_score_nufission.py +++ b/tests/test_score_nufission/test_score_nufission.py @@ -1,10 +1,32 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreNuFissionTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23, 27)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('nu-fission') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreNuFissionTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreNuFissionTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreNuFissionTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_nuscatter/geometry.xml b/tests/test_score_nuscatter/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_nuscatter/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_nuscatter/inputs_true.dat b/tests/test_score_nuscatter/inputs_true.dat new file mode 100644 index 0000000000..80840f900d --- /dev/null +++ b/tests/test_score_nuscatter/inputs_true.dat @@ -0,0 +1 @@ +764d3ba6b1bc86b462d44151242bd18fa5f0200b831bb7537cf881b728622799eb95a457f88a503487bfd30095c1fa995818d50a6bc41dd182009772c010e82b \ No newline at end of file diff --git a/tests/test_score_nuscatter/materials.xml b/tests/test_score_nuscatter/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_nuscatter/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_nuscatter/results_true.dat b/tests/test_score_nuscatter/results_true.dat index e2be939c75..8f9fcba891 100644 --- a/tests/test_score_nuscatter/results_true.dat +++ b/tests/test_score_nuscatter/results_true.dat @@ -1,11 +1,11 @@ k-combined: -1.093844E+00 1.626801E-02 +1.034954E+00 1.782721E-02 tally 1: 0.000000E+00 0.000000E+00 -1.239000E+01 -3.172630E+01 -3.570000E+00 -2.668900E+00 -4.450000E+01 -4.100412E+02 +2.514000E+01 +6.511880E+01 +6.370000E+00 +4.230900E+00 +8.547000E+01 +7.481913E+02 diff --git a/tests/test_score_nuscatter/settings.xml b/tests/test_score_nuscatter/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_nuscatter/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_nuscatter/tallies.xml b/tests/test_score_nuscatter/tallies.xml deleted file mode 100644 index 08f8fa32cc..0000000000 --- a/tests/test_score_nuscatter/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - nu-scatter - - - \ No newline at end of file diff --git a/tests/test_score_nuscatter/test_score_nuscatter.py b/tests/test_score_nuscatter/test_score_nuscatter.py index 1777db993e..6f33181265 100644 --- a/tests/test_score_nuscatter/test_score_nuscatter.py +++ b/tests/test_score_nuscatter/test_score_nuscatter.py @@ -1,10 +1,34 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreNuScatterTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23)) + t = openmc.Tally(tally_id=1) + t.add_filter(filt) + t.add_score('nu-scatter') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(t) + + self._input_set.build_default_materials_and_geometry() + self._input_set.build_default_settings() + + self._input_set.settings.inactive = 0 + + self._input_set.export() + + def _cleanup(self): + super(ScoreNuScatterTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreNuScatterTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_nuscatter_n/geometry.xml b/tests/test_score_nuscatter_n/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_nuscatter_n/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_nuscatter_n/inputs_true.dat b/tests/test_score_nuscatter_n/inputs_true.dat new file mode 100644 index 0000000000..c63f891d26 --- /dev/null +++ b/tests/test_score_nuscatter_n/inputs_true.dat @@ -0,0 +1 @@ +17541e365f35ebd25134465a02d9a66e46536c4e3f5769da62137ec94ee7c8fb46ef38b9039aa6430261329a4e1b0ce677174323563e5be2f1368dc0c552e312 \ No newline at end of file diff --git a/tests/test_score_nuscatter_n/materials.xml b/tests/test_score_nuscatter_n/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_nuscatter_n/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_nuscatter_n/results_true.dat b/tests/test_score_nuscatter_n/results_true.dat index 9b84b70786..0c1315807f 100644 --- a/tests/test_score_nuscatter_n/results_true.dat +++ b/tests/test_score_nuscatter_n/results_true.dat @@ -1,33 +1,33 @@ k-combined: -1.093844E+00 1.626801E-02 +1.034954E+00 1.782721E-02 tally 1: -1.239000E+01 -3.172630E+01 -1.431689E+00 -4.209133E-01 -6.192790E-01 -1.440589E-01 -4.143123E-01 -5.479770E-02 -2.942906E-01 -3.458523E-02 -3.570000E+00 -2.668900E+00 -3.298388E-01 -4.816449E-02 -3.308381E-01 -3.018261E-02 -5.366444E-02 -7.235974E-03 --7.363858E-02 -7.113489E-03 -4.450000E+01 -4.100412E+02 -2.317316E+01 -1.102855E+02 -8.679054E+00 -1.538963E+01 -7.128469E-01 -1.440027E-01 --1.172445E+00 -3.514659E-01 +2.514000E+01 +6.511880E+01 +2.724740E+00 +8.378120E-01 +1.521255E+00 +2.667071E-01 +7.903706E-01 +1.216244E-01 +5.770120E-01 +5.508594E-02 +6.370000E+00 +4.230900E+00 +8.075261E-01 +9.047897E-02 +5.879624E-01 +4.107777E-02 +2.034636E-01 +8.243025E-03 +-2.744502E-02 +1.515916E-03 +8.547000E+01 +7.481913E+02 +4.446994E+01 +2.016855E+02 +1.664683E+01 +2.837713E+01 +1.373176E+00 +3.329601E-01 +-1.663772E+00 +4.264485E-01 diff --git a/tests/test_score_nuscatter_n/settings.xml b/tests/test_score_nuscatter_n/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_nuscatter_n/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_nuscatter_n/tallies.xml b/tests/test_score_nuscatter_n/tallies.xml deleted file mode 100644 index 90e28227b6..0000000000 --- a/tests/test_score_nuscatter_n/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - nu-scatter nu-scatter-1 nu-scatter-2 nu-scatter-3 nu-scatter-4 - - - diff --git a/tests/test_score_nuscatter_n/test_score_nuscatter_n.py b/tests/test_score_nuscatter_n/test_score_nuscatter_n.py index 1777db993e..40029bd02c 100644 --- a/tests/test_score_nuscatter_n/test_score_nuscatter_n.py +++ b/tests/test_score_nuscatter_n/test_score_nuscatter_n.py @@ -1,10 +1,38 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreNuScatterNTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23)) + t = openmc.Tally(tally_id=1) + t.add_filter(filt) + t.add_score('nu-scatter') + t.add_score('nu-scatter-1') + t.add_score('nu-scatter-2') + t.add_score('nu-scatter-3') + t.add_score('nu-scatter-4') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(t) + + self._input_set.build_default_materials_and_geometry() + self._input_set.build_default_settings() + + self._input_set.settings.inactive = 0 + + self._input_set.export() + + def _cleanup(self): + super(ScoreNuScatterNTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreNuScatterNTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_nuscatter_pn/geometry.xml b/tests/test_score_nuscatter_pn/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_nuscatter_pn/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_nuscatter_pn/inputs_true.dat b/tests/test_score_nuscatter_pn/inputs_true.dat new file mode 100644 index 0000000000..ef53ee8f65 --- /dev/null +++ b/tests/test_score_nuscatter_pn/inputs_true.dat @@ -0,0 +1 @@ +8ae1b048b90a049d9ed42336a0a2e8f7a250a14d889cc15e0c2831ed71617a78b92570480a15f936f2dd623c75f55693e38c69041c3cae24aba082409b51bc9f \ No newline at end of file diff --git a/tests/test_score_nuscatter_pn/materials.xml b/tests/test_score_nuscatter_pn/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_nuscatter_pn/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_nuscatter_pn/results_true.dat b/tests/test_score_nuscatter_pn/results_true.dat index 18a93153ed..603c13e701 100644 --- a/tests/test_score_nuscatter_pn/results_true.dat +++ b/tests/test_score_nuscatter_pn/results_true.dat @@ -1,24 +1,24 @@ k-combined: -1.093844E+00 1.626801E-02 +1.034954E+00 1.782721E-02 tally 1: -1.239000E+01 -3.172630E+01 -1.431689E+00 -4.209133E-01 -6.192790E-01 -1.440589E-01 -4.143123E-01 -5.479770E-02 -2.942906E-01 -3.458523E-02 +2.514000E+01 +6.511880E+01 +2.724740E+00 +8.378120E-01 +1.521255E+00 +2.667071E-01 +7.903706E-01 +1.216244E-01 +5.770120E-01 +5.508594E-02 tally 2: -1.239000E+01 -3.172630E+01 -1.431689E+00 -4.209133E-01 -6.192790E-01 -1.440589E-01 -4.143123E-01 -5.479770E-02 -2.942906E-01 -3.458523E-02 +2.514000E+01 +6.511880E+01 +2.724740E+00 +8.378120E-01 +1.521255E+00 +2.667071E-01 +7.903706E-01 +1.216244E-01 +5.770120E-01 +5.508594E-02 diff --git a/tests/test_score_nuscatter_pn/settings.xml b/tests/test_score_nuscatter_pn/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_nuscatter_pn/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_nuscatter_pn/tallies.xml b/tests/test_score_nuscatter_pn/tallies.xml deleted file mode 100644 index dfad48dda2..0000000000 --- a/tests/test_score_nuscatter_pn/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - nu-scatter-0 nu-scatter-1 nu-scatter-2 nu-scatter-3 nu-scatter-4 - - - - - nu-scatter-p4 - - - diff --git a/tests/test_score_nuscatter_pn/test_score_nuscatter_pn.py b/tests/test_score_nuscatter_pn/test_score_nuscatter_pn.py index 1777db993e..6a69fe054d 100644 --- a/tests/test_score_nuscatter_pn/test_score_nuscatter_pn.py +++ b/tests/test_score_nuscatter_pn/test_score_nuscatter_pn.py @@ -1,10 +1,42 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreNuScatterPNTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, )) + t1 = openmc.Tally(tally_id=1) + t1.add_filter(filt) + t1.add_score('nu-scatter-0') + t1.add_score('nu-scatter-1') + t1.add_score('nu-scatter-2') + t1.add_score('nu-scatter-3') + t1.add_score('nu-scatter-4') + t2 = openmc.Tally(tally_id=2) + t2.add_filter(filt) + t2.add_score('nu-scatter-p4') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(t1) + self._input_set.tallies.add_tally(t2) + + self._input_set.build_default_materials_and_geometry() + self._input_set.build_default_settings() + + self._input_set.settings.inactive = 0 + + self._input_set.export() + + def _cleanup(self): + super(ScoreNuScatterPNTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreNuScatterPNTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_nuscatter_yn/geometry.xml b/tests/test_score_nuscatter_yn/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_nuscatter_yn/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_nuscatter_yn/inputs_true.dat b/tests/test_score_nuscatter_yn/inputs_true.dat new file mode 100644 index 0000000000..632a144031 --- /dev/null +++ b/tests/test_score_nuscatter_yn/inputs_true.dat @@ -0,0 +1 @@ +205e5cac8129797b815f0e79dad6c41a1876157ba69fcffecf67c3603dc36ded5f0168f9961d51fcb7dc7db6d732e7a3e8f82d04947aa0309df56bb8333d4bc9 \ No newline at end of file diff --git a/tests/test_score_nuscatter_yn/materials.xml b/tests/test_score_nuscatter_yn/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_nuscatter_yn/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_nuscatter_yn/results_true.dat b/tests/test_score_nuscatter_yn/results_true.dat index e6ca67827c..2b14a72560 100644 --- a/tests/test_score_nuscatter_yn/results_true.dat +++ b/tests/test_score_nuscatter_yn/results_true.dat @@ -1,38 +1,38 @@ k-combined: -1.093844E+00 1.626801E-02 +1.034954E+00 1.782721E-02 tally 1: -1.239000E+01 -3.172630E+01 +2.514000E+01 +6.511880E+01 tally 2: -1.239000E+01 -3.172630E+01 --1.558408E-01 -1.069360E-02 --4.768057E-02 -2.298561E-02 -7.015981E-02 -1.366523E-02 --2.449791E-02 -5.899048E-03 -9.535825E-02 -6.335188E-03 --9.915129E-03 -2.116965E-03 --2.535001E-03 -2.410993E-03 -1.030312E-01 -1.128648E-02 --4.471182E-02 -6.335010E-03 -4.744793E-02 -2.215754E-03 -6.507318E-02 -2.747856E-03 --8.724368E-02 -3.500811E-03 -5.479971E-03 -2.059588E-04 --1.345855E-01 -5.547202E-03 -8.586379E-02 -3.537507E-03 +2.514000E+01 +6.511880E+01 +2.222467E-01 +2.881247E-02 +3.019176E-01 +3.014833E-02 +-8.459006E-04 +4.773570E-02 +9.596964E-02 +1.009754E-02 +4.314855E-02 +6.207871E-03 +4.607677E-02 +9.205573E-03 +2.345994E-03 +1.243004E-02 +9.577397E-02 +6.605519E-03 +2.821584E-02 +3.834286E-03 +-1.077389E-01 +6.570217E-03 +1.106443E-01 +1.006436E-02 +1.322104E-01 +7.721677E-03 +-1.315548E-02 +5.488918E-04 +-2.792171E-02 +5.816161E-03 +1.994370E-02 +1.169674E-03 diff --git a/tests/test_score_nuscatter_yn/settings.xml b/tests/test_score_nuscatter_yn/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_nuscatter_yn/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_nuscatter_yn/tallies.xml b/tests/test_score_nuscatter_yn/tallies.xml deleted file mode 100644 index b80b37dc8c..0000000000 --- a/tests/test_score_nuscatter_yn/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - nu-scatter-0 - - - - - nu-scatter-y3 - - - diff --git a/tests/test_score_nuscatter_yn/test_score_nuscatter_yn.py b/tests/test_score_nuscatter_yn/test_score_nuscatter_yn.py index 1777db993e..6a6ad54956 100644 --- a/tests/test_score_nuscatter_yn/test_score_nuscatter_yn.py +++ b/tests/test_score_nuscatter_yn/test_score_nuscatter_yn.py @@ -1,10 +1,38 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreNuScatterYNTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, )) + t1 = openmc.Tally(tally_id=1) + t1.add_filter(filt) + t1.add_score('nu-scatter-0') + t2 = openmc.Tally(tally_id=2) + t2.add_filter(filt) + t2.add_score('nu-scatter-y3') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(t1) + self._input_set.tallies.add_tally(t2) + + self._input_set.build_default_materials_and_geometry() + self._input_set.build_default_settings() + + self._input_set.settings.inactive = 0 + + self._input_set.export() + + def _cleanup(self): + super(ScoreNuScatterYNTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreNuScatterYNTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_scatter/geometry.xml b/tests/test_score_scatter/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_scatter/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_scatter/inputs_true.dat b/tests/test_score_scatter/inputs_true.dat new file mode 100644 index 0000000000..35557cd3c5 --- /dev/null +++ b/tests/test_score_scatter/inputs_true.dat @@ -0,0 +1 @@ +b5baba05419ce120bd22d935af9cdd6d206ad5dc5cae5991a9d160c70bb029f2d87040fa4e19f7190de64b908ac6a41a8b28db4a4f3883ec16e529b1449e983d \ No newline at end of file diff --git a/tests/test_score_scatter/materials.xml b/tests/test_score_scatter/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_scatter/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_scatter/results_true.dat b/tests/test_score_scatter/results_true.dat index 9619e0f49d..8d3e0fdc03 100644 --- a/tests/test_score_scatter/results_true.dat +++ b/tests/test_score_scatter/results_true.dat @@ -1,11 +1,29 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: 0.000000E+00 0.000000E+00 -1.290818E+01 -3.438677E+01 -3.136743E+00 -2.032819E+00 -4.503247E+01 -4.196453E+02 +1.514235E+01 +4.620490E+01 +3.839050E+00 +2.975620E+00 +5.317903E+01 +5.754103E+02 +tally 2: +0.000000E+00 +0.000000E+00 +1.485000E+01 +4.439790E+01 +4.120000E+00 +3.438000E+00 +5.173000E+01 +5.467243E+02 +tally 3: +0.000000E+00 +0.000000E+00 +1.496769E+01 +4.502714E+01 +4.117144E+00 +3.431861E+00 +5.174677E+01 +5.469474E+02 diff --git a/tests/test_score_scatter/settings.xml b/tests/test_score_scatter/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_scatter/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_scatter/tallies.xml b/tests/test_score_scatter/tallies.xml deleted file mode 100644 index a4425c0f24..0000000000 --- a/tests/test_score_scatter/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - scatter - - - \ No newline at end of file diff --git a/tests/test_score_scatter/test_score_scatter.py b/tests/test_score_scatter/test_score_scatter.py index 1777db993e..0b2621acd3 100644 --- a/tests/test_score_scatter/test_score_scatter.py +++ b/tests/test_score_scatter/test_score_scatter.py @@ -1,10 +1,32 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreScatterTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('scatter') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreScatterTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreScatterTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreScatterTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_scatter_n/geometry.xml b/tests/test_score_scatter_n/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_scatter_n/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_scatter_n/inputs_true.dat b/tests/test_score_scatter_n/inputs_true.dat new file mode 100644 index 0000000000..e6e3a395bd --- /dev/null +++ b/tests/test_score_scatter_n/inputs_true.dat @@ -0,0 +1 @@ +a153add0502ff0fd4b0670f01679e104be1bb05941e73fb35e426c7f1e41a6144c7eb81fdba0d62ea3f39c7c6798028ff6d5df8c7a50b3e3f9e9bfe72fd48c2f \ No newline at end of file diff --git a/tests/test_score_scatter_n/materials.xml b/tests/test_score_scatter_n/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_scatter_n/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_scatter_n/results_true.dat b/tests/test_score_scatter_n/results_true.dat index 418eabad78..96e56bd6ab 100644 --- a/tests/test_score_scatter_n/results_true.dat +++ b/tests/test_score_scatter_n/results_true.dat @@ -1,33 +1,33 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -1.238000E+01 -3.168320E+01 -1.437080E+00 -4.234943E-01 -6.199204E-01 -1.441510E-01 -4.101424E-01 -5.414561E-02 -2.977431E-01 -3.433685E-02 -3.570000E+00 -2.668900E+00 -3.298388E-01 -4.816449E-02 -3.308381E-01 -3.018261E-02 -5.366444E-02 -7.235974E-03 --7.363858E-02 -7.113489E-03 -4.450000E+01 -4.100412E+02 -2.317316E+01 -1.102855E+02 -8.679054E+00 -1.538963E+01 -7.128469E-01 -1.440027E-01 --1.172445E+00 -3.514659E-01 +1.485000E+01 +4.439790E+01 +1.259515E+00 +3.360064E-01 +7.983154E-01 +1.355632E-01 +3.425460E-01 +2.971972E-02 +2.949225E-01 +3.975603E-02 +4.120000E+00 +3.438000E+00 +6.222571E-01 +8.335984E-02 +1.670136E-01 +1.374768E-02 +-5.819374E-02 +1.091808E-02 +-6.389550E-02 +5.688533E-03 +5.173000E+01 +5.467243E+02 +2.669403E+01 +1.451361E+02 +9.691140E+00 +1.933574E+01 +5.860769E-01 +2.122377E-01 +-1.190340E+00 +3.145785E-01 diff --git a/tests/test_score_scatter_n/settings.xml b/tests/test_score_scatter_n/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_scatter_n/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_scatter_n/tallies.xml b/tests/test_score_scatter_n/tallies.xml deleted file mode 100644 index 0164dea358..0000000000 --- a/tests/test_score_scatter_n/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - scatter scatter-1 scatter-2 scatter-3 scatter-4 - - - \ No newline at end of file diff --git a/tests/test_score_scatter_n/test_score_scatter_n.py b/tests/test_score_scatter_n/test_score_scatter_n.py index 1777db993e..47fd12b2ed 100644 --- a/tests/test_score_scatter_n/test_score_scatter_n.py +++ b/tests/test_score_scatter_n/test_score_scatter_n.py @@ -1,10 +1,33 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreScatterNTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, 22, 23)) + t = openmc.Tally(tally_id=1) + t.add_filter(filt) + t.add_score('scatter') + t.add_score('scatter-1') + t.add_score('scatter-2') + t.add_score('scatter-3') + t.add_score('scatter-4') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(t) + + super(ScoreScatterNTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreScatterNTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreScatterNTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_scatter_pn/geometry.xml b/tests/test_score_scatter_pn/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_scatter_pn/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_scatter_pn/inputs_true.dat b/tests/test_score_scatter_pn/inputs_true.dat new file mode 100644 index 0000000000..3878939c50 --- /dev/null +++ b/tests/test_score_scatter_pn/inputs_true.dat @@ -0,0 +1 @@ +fe56d58827d1803c1a49391711ad682be4a7cbc51519248812554f66e3e46266edc179f4254291a5f455751d3cdc13a17bbd103b9810c8818f36e4d283b503be \ No newline at end of file diff --git a/tests/test_score_scatter_pn/materials.xml b/tests/test_score_scatter_pn/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_scatter_pn/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_scatter_pn/results_true.dat b/tests/test_score_scatter_pn/results_true.dat index d6767ea031..753216a8b7 100644 --- a/tests/test_score_scatter_pn/results_true.dat +++ b/tests/test_score_scatter_pn/results_true.dat @@ -1,24 +1,24 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -1.238000E+01 -3.168320E+01 -1.437080E+00 -4.234943E-01 -6.199204E-01 -1.441510E-01 -4.101424E-01 -5.414561E-02 -2.977431E-01 -3.433685E-02 +1.485000E+01 +4.439790E+01 +1.259515E+00 +3.360064E-01 +7.983154E-01 +1.355632E-01 +3.425460E-01 +2.971972E-02 +2.949225E-01 +3.975603E-02 tally 2: -1.238000E+01 -3.168320E+01 -1.437080E+00 -4.234943E-01 -6.199204E-01 -1.441510E-01 -4.101424E-01 -5.414561E-02 -2.977431E-01 -3.433685E-02 +1.485000E+01 +4.439790E+01 +1.259515E+00 +3.360064E-01 +7.983154E-01 +1.355632E-01 +3.425460E-01 +2.971972E-02 +2.949225E-01 +3.975603E-02 diff --git a/tests/test_score_scatter_pn/settings.xml b/tests/test_score_scatter_pn/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_scatter_pn/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_scatter_pn/tallies.xml b/tests/test_score_scatter_pn/tallies.xml deleted file mode 100644 index 61a7854d68..0000000000 --- a/tests/test_score_scatter_pn/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - scatter-0 scatter-1 scatter-2 scatter-3 scatter-4 - - - - - scatter-p4 - - - \ No newline at end of file diff --git a/tests/test_score_scatter_pn/test_score_scatter_pn.py b/tests/test_score_scatter_pn/test_score_scatter_pn.py index 1777db993e..9186fe5480 100644 --- a/tests/test_score_scatter_pn/test_score_scatter_pn.py +++ b/tests/test_score_scatter_pn/test_score_scatter_pn.py @@ -1,10 +1,38 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreScatterPNTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, )) + t1 = openmc.Tally(tally_id=1) + t1.add_filter(filt) + t1.add_score('scatter-0') + t1.add_score('scatter-1') + t1.add_score('scatter-2') + t1.add_score('scatter-3') + t1.add_score('scatter-4') + t1.estimator = 'analog' + t2 = openmc.Tally(tally_id=2) + t2.add_filter(filt) + t2.add_score('scatter-p4') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(t1) + self._input_set.tallies.add_tally(t2) + + super(ScoreScatterPNTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreScatterPNTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreScatterPNTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_scatter_yn/geometry.xml b/tests/test_score_scatter_yn/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_scatter_yn/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_scatter_yn/inputs_true.dat b/tests/test_score_scatter_yn/inputs_true.dat new file mode 100644 index 0000000000..1ae9f6047d --- /dev/null +++ b/tests/test_score_scatter_yn/inputs_true.dat @@ -0,0 +1 @@ +d80a9e8befab978bc84a231437a2b96c8f6dba81984c9e82a79360feb26bc9875b661131dbaa2deeb66b0aa50a39b2e738303bc40c5c65ee1995cf52f687ae46 \ No newline at end of file diff --git a/tests/test_score_scatter_yn/materials.xml b/tests/test_score_scatter_yn/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_scatter_yn/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_scatter_yn/results_true.dat b/tests/test_score_scatter_yn/results_true.dat index 23f56743bd..fb6b4749d1 100644 --- a/tests/test_score_scatter_yn/results_true.dat +++ b/tests/test_score_scatter_yn/results_true.dat @@ -1,56 +1,56 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: -1.238000E+01 -3.168320E+01 +1.485000E+01 +4.439790E+01 tally 2: -1.238000E+01 -3.168320E+01 --1.570048E-01 -1.067590E-02 --4.730723E-02 -2.307294E-02 -6.490976E-02 -1.426908E-02 --2.426427E-02 -5.909294E-03 -9.534163E-02 -6.333588E-03 --1.023123E-02 -2.132217E-03 --2.609941E-03 -2.406916E-03 -1.035322E-01 -1.128320E-02 --4.271935E-02 -6.478440E-03 -4.721270E-02 -2.212864E-03 -6.453502E-02 -2.750693E-03 --8.681394E-02 -3.493602E-03 -3.052598E-03 -1.842182E-04 --1.350899E-01 -5.564227E-03 -8.846033E-02 -3.537258E-03 -5.729362E-02 -2.064207E-03 -1.780469E-02 -2.838072E-03 --4.570340E-02 -2.812380E-03 -2.213430E-02 -5.564728E-04 --3.159434E-03 -3.500419E-03 --1.547339E-02 -1.929157E-03 -6.653362E-02 -1.421509E-03 -1.226039E-02 -1.144939E-03 -5.785933E-03 -4.218074E-04 +1.485000E+01 +4.439790E+01 +-8.440076E-02 +1.135203E-02 +8.198663E-02 +3.887429E-02 +-1.358080E-01 +2.890416E-02 +-3.544823E-02 +9.843339E-04 +-1.542072E-01 +8.228126E-03 +1.057111E-01 +3.758100E-03 +-1.647870E-02 +4.827841E-03 +1.378297E-01 +1.566876E-02 +4.676778E-02 +4.809366E-03 +1.966204E-02 +7.447981E-04 +1.889258E-02 +6.841953E-04 +1.337703E-02 +1.250077E-03 +-1.044684E-01 +6.969498E-03 +-1.177995E-02 +8.208715E-03 +-1.940058E-04 +5.128759E-03 +-2.165868E-02 +1.335569E-03 +-3.080886E-02 +4.544434E-04 +1.039856E-03 +1.209631E-03 +-1.317068E-02 +1.469722E-03 +-6.432758E-02 +2.106736E-03 +3.323023E-02 +4.513838E-03 +2.683700E-02 +1.146747E-03 +-3.494912E-02 +1.006153E-03 +6.289525E-02 +3.700145E-03 diff --git a/tests/test_score_scatter_yn/settings.xml b/tests/test_score_scatter_yn/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_scatter_yn/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_scatter_yn/tallies.xml b/tests/test_score_scatter_yn/tallies.xml deleted file mode 100644 index 3c46c13d40..0000000000 --- a/tests/test_score_scatter_yn/tallies.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - scatter-0 - analog - - - - - scatter-y4 - - - diff --git a/tests/test_score_scatter_yn/test_score_scatter_yn.py b/tests/test_score_scatter_yn/test_score_scatter_yn.py index 1777db993e..9e6900031f 100644 --- a/tests/test_score_scatter_yn/test_score_scatter_yn.py +++ b/tests/test_score_scatter_yn/test_score_scatter_yn.py @@ -1,10 +1,34 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreScatterYNTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(21, )) + t1 = openmc.Tally(tally_id=1) + t1.add_filter(filt) + t1.add_score('scatter-0') + t1.estimator = 'analog' + t2 = openmc.Tally(tally_id=2) + t2.add_filter(filt) + t2.add_score('scatter-y4') + self._input_set.tallies = openmc.TalliesFile() + self._input_set.tallies.add_tally(t1) + self._input_set.tallies.add_tally(t2) + + super(ScoreScatterYNTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreScatterYNTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreScatterYNTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_total/geometry.xml b/tests/test_score_total/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_total/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_total/inputs_true.dat b/tests/test_score_total/inputs_true.dat new file mode 100644 index 0000000000..c8b979c725 --- /dev/null +++ b/tests/test_score_total/inputs_true.dat @@ -0,0 +1 @@ +8813917cab656135c4eebfdbe5f0d95e6a9409a2b36df1dfb483bdd193a3c0978727918a58399b259b82a7d51ae3f1801148bd978603fec11f27acdbf89520e2 \ No newline at end of file diff --git a/tests/test_score_total/materials.xml b/tests/test_score_total/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_total/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_total/results_true.dat b/tests/test_score_total/results_true.dat index 0838e7baed..9b8a06f807 100644 --- a/tests/test_score_total/results_true.dat +++ b/tests/test_score_total/results_true.dat @@ -1,11 +1,29 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: 0.000000E+00 0.000000E+00 -1.517577E+01 -4.747271E+01 -3.151504E+00 -2.051857E+00 -4.536316E+01 -4.258781E+02 +1.767552E+01 +6.295417E+01 +3.863588E+00 +3.013300E+00 +5.356594E+01 +5.839391E+02 +tally 2: +0.000000E+00 +0.000000E+00 +1.739000E+01 +6.083290E+01 +4.160000E+00 +3.501000E+00 +5.213000E+01 +5.552351E+02 +tally 3: +0.000000E+00 +0.000000E+00 +1.739000E+01 +6.083290E+01 +4.160000E+00 +3.501000E+00 +5.213000E+01 +5.552351E+02 diff --git a/tests/test_score_total/settings.xml b/tests/test_score_total/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_total/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_total/tallies.xml b/tests/test_score_total/tallies.xml deleted file mode 100644 index 815b84c145..0000000000 --- a/tests/test_score_total/tallies.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - total - - - \ No newline at end of file diff --git a/tests/test_score_total/test_score_total.py b/tests/test_score_total/test_score_total.py index 1777db993e..c6f3f335fc 100644 --- a/tests/test_score_total/test_score_total.py +++ b/tests/test_score_total/test_score_total.py @@ -1,10 +1,32 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreTotalTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)] + [t.add_filter(filt) for t in tallies] + [t.add_score('total') for t in tallies] + tallies[0].estimator = 'tracklength' + tallies[1].estimator = 'analog' + tallies[2].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreTotalTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreTotalTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreTotalTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_score_total_yn/geometry.xml b/tests/test_score_total_yn/geometry.xml deleted file mode 100644 index b85dd04df9..0000000000 --- a/tests/test_score_total_yn/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/test_score_total_yn/inputs_true.dat b/tests/test_score_total_yn/inputs_true.dat new file mode 100644 index 0000000000..b2818f8568 --- /dev/null +++ b/tests/test_score_total_yn/inputs_true.dat @@ -0,0 +1 @@ +4dbbd9cec921d2420e7567533c833afbe94335073aa760d1fd937adb695191b3ab7c070ec0d32721dddb4a46054e68322cf6a058420e20e439eb1d44f09f4be4 \ No newline at end of file diff --git a/tests/test_score_total_yn/materials.xml b/tests/test_score_total_yn/materials.xml deleted file mode 100644 index 9c0b74f3f1..0000000000 --- a/tests/test_score_total_yn/materials.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - 71c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/test_score_total_yn/results_true.dat b/tests/test_score_total_yn/results_true.dat index b2dcd39e12..b416b05ec3 100644 --- a/tests/test_score_total_yn/results_true.dat +++ b/tests/test_score_total_yn/results_true.dat @@ -1,14 +1,14 @@ k-combined: -1.093844E+00 1.626801E-02 +9.903196E-01 4.279617E-02 tally 1: 0.000000E+00 0.000000E+00 -1.517577E+01 -4.747271E+01 -3.151504E+00 -2.051857E+00 -4.536316E+01 -4.258781E+02 +1.767552E+01 +6.295417E+01 +3.863588E+00 +3.013300E+00 +5.356594E+01 +5.839391E+02 tally 2: 0.000000E+00 0.000000E+00 @@ -110,106 +110,106 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 -8.795501E-01 -1.600341E-01 --1.530661E-02 -5.215322E-04 -1.571095E-02 -9.166057E-04 -7.226990E-03 -3.683499E-04 --2.456165E-02 -1.571441E-04 -1.387449E-02 -5.600648E-04 --2.186870E-02 -2.081164E-04 --1.106814E-02 -1.065144E-04 --4.579593E-03 -2.008225E-04 -7.573253E-03 -2.493075E-04 --1.505016E-02 -1.451400E-04 -1.503792E-02 -9.539029E-05 --1.183668E-02 -1.741393E-04 -4.060912E-03 -5.890591E-05 -1.789747E-02 -8.239749E-05 --2.168438E-02 -1.555757E-04 --1.045826E-02 -8.108402E-05 -1.227413E-02 -2.502871E-04 --2.806122E-02 -1.886120E-04 --4.918718E-03 -2.129038E-04 --1.014729E-02 -6.914145E-05 --5.873760E-03 -2.229738E-04 -6.666511E-03 -1.394147E-04 --3.245528E-03 -1.550876E-04 --1.037659E-02 -2.163837E-04 -1.517577E+01 -4.747271E+01 --2.463504E-01 -2.376091E-02 -7.930151E-02 -3.516796E-02 --1.611736E-01 -2.658129E-02 --9.124923E-02 -1.181443E-02 -2.766258E-01 -2.310767E-02 --2.269608E-01 -3.593659E-02 --5.345296E-02 -1.169733E-02 --1.838169E-01 -1.625334E-02 --7.883035E-02 -8.514293E-03 --4.922148E-02 -7.767910E-03 -1.144559E-01 -4.638553E-03 --2.027207E-01 -2.158672E-02 -5.449222E-02 -1.287150E-02 -5.384229E-02 -6.688120E-03 --8.231311E-02 -2.743044E-02 -1.172790E-02 -1.089457E-02 --1.545389E-01 -2.655167E-02 --2.290221E-01 -1.443721E-02 -2.773254E-02 -1.070478E-02 --2.522703E-02 -1.136507E-02 --1.287564E-02 -4.969443E-03 -3.471629E-02 -7.559603E-03 --2.261509E-01 -2.383142E-02 --1.463402E-01 -1.526988E-02 +9.780506E-01 +1.942072E-01 +-4.170415E-02 +7.581469E-04 +-2.419728E-03 +6.296241E-04 +-8.163997E-03 +4.785197E-04 +3.971909E-03 +1.363304E-04 +1.585497E-02 +1.295251E-04 +-7.029875E-02 +1.208194E-03 +-1.524070E-02 +2.828843E-04 +-2.141105E-02 +2.953327E-04 +-2.147623E-02 +2.390414E-04 +5.592040E-04 +1.720605E-04 +3.022066E-03 +1.843720E-04 +1.489821E-02 +9.193290E-05 +-1.354668E-02 +2.551940E-04 +-5.692690E-04 +3.013453E-04 +2.324582E-02 +2.170615E-04 +1.883012E-02 +1.045949E-04 +-3.997107E-03 +1.674058E-04 +1.616443E-02 +2.046286E-04 +1.625747E-02 +1.851351E-04 +1.120209E-02 +2.028649E-04 +4.240284E-03 +4.019011E-05 +1.535379E-02 +9.872559E-05 +-8.973926E-03 +1.448680E-04 +-3.933227E-03 +4.305328E-04 +1.767552E+01 +6.295417E+01 +-1.458308E-01 +8.239551E-03 +1.976485E-01 +7.360520E-02 +-2.647182E-01 +5.347815E-02 +1.828025E-01 +1.840743E-02 +1.865994E-01 +2.843407E-02 +-6.438995E-02 +8.898045E-03 +-1.416445E-01 +3.839856E-02 +-3.298894E-01 +2.672141E-02 +-1.462639E-01 +1.225250E-02 +-6.410138E-02 +3.766615E-02 +4.701705E-02 +1.968428E-03 +2.953056E-02 +2.358647E-02 +-1.717672E-01 +5.877351E-02 +1.927497E-02 +1.358953E-02 +1.708870E-01 +1.502033E-02 +4.453803E-02 +1.622532E-02 +-2.076143E-02 +1.850686E-03 +1.111325E-01 +8.415150E-03 +1.249594E-01 +7.491280E-03 +1.381757E-02 +1.537264E-02 +-7.286234E-03 +9.057874E-03 +3.162973E-01 +3.303388E-02 +1.012773E-01 +8.345375E-03 +-5.238963E-02 +3.920421E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -260,56 +260,56 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 -3.151504E+00 -2.051857E+00 --4.923938E-02 -1.416150E-03 --1.041702E-02 -8.114498E-04 --3.212977E-02 -2.419393E-03 -2.557299E-02 -1.124488E-03 -4.083178E-02 -1.351219E-03 --3.910818E-02 -8.908208E-04 -5.659008E-03 -4.488733E-04 --1.625829E-02 -2.325228E-04 -2.554220E-02 -7.666018E-04 --2.251672E-02 -7.703442E-04 --8.302474E-03 -2.748216E-04 --7.692439E-02 -2.167893E-03 -7.267774E-03 -7.781907E-04 -6.821338E-03 -9.518920E-04 --2.203951E-02 -2.214610E-03 -2.052514E-02 -3.756195E-04 --4.158575E-02 -9.330262E-04 --3.000932E-02 -4.584914E-04 --2.247072E-02 -2.519845E-04 -1.589401E-02 -2.302726E-04 --7.793787E-04 -1.588955E-04 --4.634907E-03 -5.395803E-04 --1.193817E-02 -1.674419E-04 --1.682320E-02 -8.389254E-04 +3.863588E+00 +3.013300E+00 +5.075749E-02 +1.018210E-03 +3.445344E-02 +5.778215E-03 +-6.239642E-02 +4.107408E-03 +-1.475495E-02 +7.971898E-04 +5.809323E-02 +3.039895E-03 +-2.510339E-02 +3.529134E-04 +-9.731680E-03 +1.221628E-03 +-5.815144E-02 +1.403261E-03 +-4.936694E-02 +6.481626E-04 +5.141985E-03 +1.343973E-03 +1.515105E-02 +3.044735E-04 +4.474521E-03 +1.155268E-03 +-6.855877E-02 +4.048417E-03 +-2.701967E-05 +1.279041E-03 +2.197636E-02 +2.843662E-04 +-1.780381E-02 +8.441574E-04 +2.916634E-02 +2.530602E-03 +2.289834E-02 +2.201375E-03 +3.283424E-02 +7.615219E-04 +9.623726E-03 +7.614092E-04 +2.808239E-02 +1.500381E-03 +4.835419E-02 +6.933678E-04 +-2.636221E-02 +2.230834E-04 +-4.957463E-02 +1.939266E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -360,53 +360,855 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 -4.536316E+01 -4.258781E+02 --6.747275E-01 -3.006113E-01 -5.302096E-01 -4.167797E-01 --4.347270E-01 -3.702158E-01 --7.344613E-02 -5.940699E-02 -1.081217E+00 -4.070812E-01 --3.172368E-02 -3.124338E-02 -2.656115E-01 -8.561866E-02 --1.286933E-01 -8.347414E-02 -1.258195E-01 -3.329577E-02 --3.751107E-01 -9.007513E-02 -4.283879E-01 -1.067035E-01 --3.467870E-01 -6.788988E-02 -4.218567E-02 -4.465188E-02 -6.876561E-02 -5.655954E-02 --1.116047E-01 -1.073179E-01 -4.077067E-01 -1.148942E-01 --3.218725E-01 -4.739201E-02 --4.297438E-01 -9.739104E-02 -2.199014E-01 -2.328443E-02 -6.007636E-01 -1.194137E-01 --2.194826E-01 -5.017106E-02 -2.266133E-01 -1.131899E-01 -7.161662E-04 -3.345992E-02 --1.987041E-01 -1.381432E-01 +5.356594E+01 +5.839391E+02 +-1.198882E+00 +3.391100E-01 +3.952398E-01 +5.729760E-01 +-1.045726E+00 +4.419194E-01 +2.683170E-01 +1.872580E-01 +5.059349E-01 +2.592209E-01 +4.561651E-01 +1.253696E-01 +-4.273775E-01 +3.509266E-01 +-6.300496E-01 +2.102051E-01 +-3.094705E-01 +1.410278E-01 +-6.840225E-01 +1.971765E-01 +4.123355E-02 +3.962538E-02 +-1.554557E-01 +2.784362E-02 +-4.698631E-01 +1.867413E-01 +-7.016026E-02 +3.059344E-02 +2.922284E-01 +8.680517E-02 +-1.252431E-01 +3.180591E-02 +1.825937E-01 +8.626653E-02 +1.637960E-01 +1.329538E-01 +6.662867E-01 +1.497985E-01 +4.662585E-01 +7.552145E-02 +1.198254E-03 +2.020899E-01 +5.281410E-01 +9.615758E-02 +6.396211E-02 +1.806992E-01 +-1.898620E-01 +1.113751E-01 +tally 3: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.300000E-01 +1.839000E-01 +4.056201E-03 +8.670884E-04 +-2.262959E-02 +2.263780E-03 +-4.568371E-02 +4.078305E-03 +6.023055E-02 +1.099458E-03 +-2.468374E-02 +3.403931E-03 +-8.676202E-02 +2.444658E-03 +2.075016E-02 +5.432442E-03 +1.101095E-02 +3.129947E-04 +8.689134E-03 +2.422445E-03 +-1.097503E-02 +4.670673E-04 +4.979355E-02 +1.791811E-03 +1.769845E-02 +6.074665E-04 +-1.473469E-02 +1.257671E-03 +-1.133757E-02 +1.555143E-03 +1.730195E-02 +1.841949E-03 +-1.191492E-02 +1.859105E-03 +9.038577E-03 +4.401577E-04 +1.770047E-02 +4.158291E-04 +1.492809E-02 +5.488168E-04 +7.970152E-02 +1.597910E-03 +3.741348E-02 +5.704935E-04 +2.078478E-02 +5.379832E-04 +-1.355930E-02 +6.747758E-04 +3.416200E-02 +8.262470E-04 +1.739000E+01 +6.083290E+01 +-2.434171E-01 +3.049063E-02 +-1.278707E-01 +9.585267E-02 +-2.597328E-01 +8.692607E-02 +2.496700E-01 +3.750933E-02 +-1.309937E-01 +4.217907E-02 +-1.863241E-01 +1.738581E-02 +1.292679E-01 +1.799004E-02 +-3.543191E-01 +3.682107E-02 +1.904413E-01 +1.455250E-02 +-7.093238E-02 +1.473997E-02 +1.920412E-01 +1.308864E-02 +1.566093E-01 +1.913492E-02 +-2.499642E-01 +3.036874E-02 +-2.323022E-01 +3.794368E-02 +6.361729E-02 +3.266166E-02 +4.688479E-02 +2.806712E-02 +9.796563E-02 +1.419748E-02 +1.000847E-02 +3.233262E-02 +7.570231E-02 +4.626536E-03 +1.489091E-01 +1.159345E-02 +2.236285E-01 +1.480084E-02 +2.461305E-01 +1.643844E-02 +1.773523E-02 +1.626036E-03 +6.570774E-02 +1.069893E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.160000E+00 +3.501000E+00 +-9.464171E-02 +8.682833E-03 +8.467800E-02 +1.402624E-02 +1.283471E-02 +2.630439E-02 +1.859869E-01 +1.189528E-02 +1.910311E-02 +2.907370E-03 +-2.542253E-01 +2.143851E-02 +-4.021473E-02 +5.812599E-03 +-1.242140E-01 +1.017873E-02 +-2.934198E-02 +2.409920E-03 +5.719767E-02 +2.211520E-03 +3.023903E-02 +2.870625E-03 +1.092479E-01 +6.089989E-03 +1.604743E-02 +1.110224E-02 +3.811062E-03 +5.234112E-03 +5.446762E-02 +5.323411E-03 +-3.868978E-02 +4.949255E-03 +1.384260E-01 +4.903532E-03 +-3.761889E-02 +2.524889E-03 +-6.079772E-02 +2.328339E-03 +1.956623E-03 +4.096814E-03 +1.716402E-03 +2.022751E-03 +-1.108600E-01 +3.227014E-03 +-2.447622E-03 +4.075421E-03 +1.582493E-02 +4.847858E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.213000E+01 +5.552351E+02 +-6.019876E-01 +2.938936E-01 +2.126970E-01 +3.363271E-01 +-6.928646E-01 +3.077152E-01 +-2.976474E-01 +5.830705E-02 +7.804821E-01 +3.967156E-01 +5.737502E-01 +1.090147E-01 +-2.867929E-01 +1.312720E-01 +-4.735578E-01 +6.714577E-02 +-6.340442E-02 +4.240623E-02 +-1.594570E-01 +1.167021E-01 +-5.403124E-02 +6.452745E-02 +-2.670969E-01 +5.822561E-02 +-3.033558E-01 +4.890487E-02 +-3.515557E-01 +5.069681E-02 +2.257462E-01 +4.682933E-02 +-1.449924E-02 +1.625521E-02 +2.809498E-01 +6.883451E-02 +1.904808E-01 +1.004755E-01 +2.570005E-01 +4.301248E-02 +9.493600E-02 +7.708499E-02 +-2.804222E-01 +4.455703E-02 +3.199914E-01 +7.435651E-02 +-2.818069E-04 +7.231318E-02 +3.689494E-01 +1.349712E-01 +tally 4: +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.453374E-01 +1.815824E-01 +-4.552571E-02 +8.689847E-04 +4.192526E-03 +6.095248E-04 +-4.085060E-03 +3.488081E-04 +3.074303E-02 +3.709785E-04 +1.949067E-02 +1.995057E-04 +-7.372260E-02 +1.709765E-03 +-5.140901E-03 +6.268082E-05 +-2.589014E-02 +1.616678E-04 +1.683116E-02 +2.122512E-04 +-1.074659E-02 +1.087471E-04 +3.762844E-03 +3.439135E-05 +1.365793E-02 +5.255161E-05 +5.869374E-05 +4.060049E-04 +-7.715004E-03 +3.629588E-04 +8.240120E-03 +5.192031E-04 +1.662861E-02 +5.038262E-04 +-2.845811E-03 +2.843348E-04 +1.826833E-03 +1.104947E-05 +-5.596885E-04 +1.922661E-05 +1.398723E-02 +1.025178E-04 +1.733988E-02 +1.184228E-04 +1.250057E-02 +1.447801E-04 +-5.450018E-03 +3.725923E-05 +2.390947E-02 +6.837656E-04 +1.739000E+01 +6.083290E+01 +-2.434171E-01 +3.049063E-02 +-1.278707E-01 +9.585267E-02 +-2.597328E-01 +8.692607E-02 +2.496700E-01 +3.750933E-02 +-1.309937E-01 +4.217907E-02 +-1.863241E-01 +1.738581E-02 +1.292679E-01 +1.799004E-02 +-3.543191E-01 +3.682107E-02 +1.904413E-01 +1.455250E-02 +-7.093238E-02 +1.473997E-02 +1.920412E-01 +1.308864E-02 +1.566093E-01 +1.913492E-02 +-2.499642E-01 +3.036874E-02 +-2.323022E-01 +3.794368E-02 +6.361729E-02 +3.266166E-02 +4.688479E-02 +2.806712E-02 +9.796563E-02 +1.419748E-02 +1.000847E-02 +3.233262E-02 +7.570231E-02 +4.626536E-03 +1.489091E-01 +1.159345E-02 +2.236285E-01 +1.480084E-02 +2.461305E-01 +1.643844E-02 +1.773523E-02 +1.626036E-03 +6.570774E-02 +1.069893E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.160000E+00 +3.501000E+00 +-9.464171E-02 +8.682833E-03 +8.467800E-02 +1.402624E-02 +1.283471E-02 +2.630439E-02 +1.859869E-01 +1.189528E-02 +1.910311E-02 +2.907370E-03 +-2.542253E-01 +2.143851E-02 +-4.021473E-02 +5.812599E-03 +-1.242140E-01 +1.017873E-02 +-2.934198E-02 +2.409920E-03 +5.719767E-02 +2.211520E-03 +3.023903E-02 +2.870625E-03 +1.092479E-01 +6.089989E-03 +1.604743E-02 +1.110224E-02 +3.811062E-03 +5.234112E-03 +5.446762E-02 +5.323411E-03 +-3.868978E-02 +4.949255E-03 +1.384260E-01 +4.903532E-03 +-3.761889E-02 +2.524889E-03 +-6.079772E-02 +2.328339E-03 +1.956623E-03 +4.096814E-03 +1.716402E-03 +2.022751E-03 +-1.108600E-01 +3.227014E-03 +-2.447622E-03 +4.075421E-03 +1.582493E-02 +4.847858E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.213000E+01 +5.552351E+02 +-6.019876E-01 +2.938936E-01 +2.126970E-01 +3.363271E-01 +-6.928646E-01 +3.077152E-01 +-2.976474E-01 +5.830705E-02 +7.804821E-01 +3.967156E-01 +5.737502E-01 +1.090147E-01 +-2.867929E-01 +1.312720E-01 +-4.735578E-01 +6.714577E-02 +-6.340442E-02 +4.240623E-02 +-1.594570E-01 +1.167021E-01 +-5.403124E-02 +6.452745E-02 +-2.670969E-01 +5.822561E-02 +-3.033558E-01 +4.890487E-02 +-3.515557E-01 +5.069681E-02 +2.257462E-01 +4.682933E-02 +-1.449924E-02 +1.625521E-02 +2.809498E-01 +6.883451E-02 +1.904808E-01 +1.004755E-01 +2.570005E-01 +4.301248E-02 +9.493600E-02 +7.708499E-02 +-2.804222E-01 +4.455703E-02 +3.199914E-01 +7.435651E-02 +-2.818069E-04 +7.231318E-02 +3.689494E-01 +1.349712E-01 diff --git a/tests/test_score_total_yn/settings.xml b/tests/test_score_total_yn/settings.xml deleted file mode 100644 index 517637a59f..0000000000 --- a/tests/test_score_total_yn/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 10 - 5 - 100 - - - - - - -160 -160 -183 - 160 160 183 - - - - - diff --git a/tests/test_score_total_yn/tallies.xml b/tests/test_score_total_yn/tallies.xml deleted file mode 100644 index ca5dcd2dcb..0000000000 --- a/tests/test_score_total_yn/tallies.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - total - - - - - total-y4 - U-235 total - - - diff --git a/tests/test_score_total_yn/test_score_total_yn.py b/tests/test_score_total_yn/test_score_total_yn.py index 1777db993e..80f947f920 100644 --- a/tests/test_score_total_yn/test_score_total_yn.py +++ b/tests/test_score_total_yn/test_score_total_yn.py @@ -1,10 +1,35 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import TestHarness +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness, PyAPITestHarness +import openmc + + +class ScoreTotalYNTestHarness(PyAPITestHarness): + def _build_inputs(self): + filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23)) + tallies = [openmc.Tally(tally_id=i) for i in range(1, 5)] + [t.add_filter(filt) for t in tallies] + tallies[0].add_score('total') + [t.add_score('total-y4') for t in tallies[1:]] + [t.add_nuclide('U-235') for t in tallies[1:]] + [t.add_nuclide('total') for t in tallies[1:]] + tallies[1].estimator = 'tracklength' + tallies[2].estimator = 'analog' + tallies[3].estimator = 'collision' + self._input_set.tallies = openmc.TalliesFile() + [self._input_set.tallies.add_tally(t) for t in tallies] + + super(ScoreTotalYNTestHarness, self)._build_inputs() + + def _cleanup(self): + super(ScoreTotalYNTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = TestHarness('statepoint.10.*', True) + harness = ScoreTotalYNTestHarness('statepoint.10.*', True) harness.main() diff --git a/tests/test_seed/geometry.xml b/tests/test_seed/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_seed/geometry.xml +++ b/tests/test_seed/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_seed/results_true.dat b/tests/test_seed/results_true.dat index 860e9e9af6..df79ce1ced 100644 --- a/tests/test_seed/results_true.dat +++ b/tests/test_seed/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.984828E-01 5.293550E-03 +2.951164E-01 2.504580E-03 diff --git a/tests/test_seed/test_seed.py b/tests/test_seed/test_seed.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_seed/test_seed.py +++ b/tests/test_seed/test_seed.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_source_angle_mono/geometry.xml b/tests/test_source_angle_mono/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_source_angle_mono/geometry.xml +++ b/tests/test_source_angle_mono/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_source_angle_mono/results_true.dat b/tests/test_source_angle_mono/results_true.dat index 1aca9a5057..42e948758a 100644 --- a/tests/test_source_angle_mono/results_true.dat +++ b/tests/test_source_angle_mono/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.034005E-01 5.499077E-03 +2.964943E-01 1.201478E-02 diff --git a/tests/test_source_angle_mono/test_source_angle_mono.py b/tests/test_source_angle_mono/test_source_angle_mono.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_source_angle_mono/test_source_angle_mono.py +++ b/tests/test_source_angle_mono/test_source_angle_mono.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_source_energy_maxwell/geometry.xml b/tests/test_source_energy_maxwell/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_source_energy_maxwell/geometry.xml +++ b/tests/test_source_energy_maxwell/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_source_energy_maxwell/results_true.dat b/tests/test_source_energy_maxwell/results_true.dat index 349c65ef9c..37b8b36b99 100644 --- a/tests/test_source_energy_maxwell/results_true.dat +++ b/tests/test_source_energy_maxwell/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.008495E-01 6.113736E-03 +2.886671E-01 7.534631E-03 diff --git a/tests/test_source_energy_maxwell/test_source_energy_maxwell.py b/tests/test_source_energy_maxwell/test_source_energy_maxwell.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_source_energy_maxwell/test_source_energy_maxwell.py +++ b/tests/test_source_energy_maxwell/test_source_energy_maxwell.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_source_energy_mono/geometry.xml b/tests/test_source_energy_mono/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_source_energy_mono/geometry.xml +++ b/tests/test_source_energy_mono/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_source_energy_mono/results_true.dat b/tests/test_source_energy_mono/results_true.dat index b7af42bcae..029376bf37 100644 --- a/tests/test_source_energy_mono/results_true.dat +++ b/tests/test_source_energy_mono/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.964207E-01 7.263112E-03 +3.002731E-01 7.561170E-03 diff --git a/tests/test_source_energy_mono/test_source_energy_mono.py b/tests/test_source_energy_mono/test_source_energy_mono.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_source_energy_mono/test_source_energy_mono.py +++ b/tests/test_source_energy_mono/test_source_energy_mono.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_source_file/geometry.xml b/tests/test_source_file/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_source_file/geometry.xml +++ b/tests/test_source_file/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_source_file/results_true.dat b/tests/test_source_file/results_true.dat index 738a15c584..fee61dda26 100644 --- a/tests/test_source_file/results_true.dat +++ b/tests/test_source_file/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.031470E-01 4.441814E-03 +2.962911E-01 4.073420E-03 diff --git a/tests/test_source_file/test_source_file.py b/tests/test_source_file/test_source_file.py index d9aaa9a0fa..6f76438c2a 100644 --- a/tests/test_source_file/test_source_file.py +++ b/tests/test_source_file/test_source_file.py @@ -1,7 +1,9 @@ #!/usr/bin/env python +import glob +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import * @@ -66,15 +68,13 @@ class SourceFileTestHarness(TestHarness): statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ 'exist.' - assert statepoint[0].endswith('binary') \ - or statepoint[0].endswith('h5'), \ - 'Statepoint file is not a binary or hdf5 file.' + assert statepoint[0].endswith('h5'), \ + 'Statepoint file is not a HDF5 file.' source = glob.glob(os.path.join(os.getcwd(), 'source.10.*')) assert len(source) == 1, 'Either multiple or no source files exist.' - assert source[0].endswith('binary') \ - or source[0].endswith('h5'), \ - 'Source file is not a binary or hdf5 file.' + assert source[0].endswith('h5'), \ + 'Source file is not a HDF5 file.' def _run_openmc_restart(self): # Get the name of the source file. diff --git a/tests/test_source_point/geometry.xml b/tests/test_source_point/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_source_point/geometry.xml +++ b/tests/test_source_point/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_source_point/results_true.dat b/tests/test_source_point/results_true.dat index 040f4e188f..fe9a0d78d4 100644 --- a/tests/test_source_point/results_true.dat +++ b/tests/test_source_point/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.025384E-01 4.682677E-03 +3.041148E-01 4.558319E-03 diff --git a/tests/test_source_point/test_source_point.py b/tests/test_source_point/test_source_point.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_source_point/test_source_point.py +++ b/tests/test_source_point/test_source_point.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_sourcepoint_batch/geometry.xml b/tests/test_sourcepoint_batch/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_sourcepoint_batch/geometry.xml +++ b/tests/test_sourcepoint_batch/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py index 8cafb41084..5db0541344 100644 --- a/tests/test_sourcepoint_batch/test_sourcepoint_batch.py +++ b/tests/test_sourcepoint_batch/test_sourcepoint_batch.py @@ -1,32 +1,32 @@ #!/usr/bin/env python +import glob +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness +from openmc.statepoint import StatePoint 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.""" # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() - sp.read_source() # Get the eigenvalue information. outstr = TestHarness._get_results(self) # Add the source information. - xyz = sp._source[0]._xyz + xyz = sp.source[0]['xyz'] outstr += ' '.join(['{0:12.6E}'.format(x) for x in xyz]) outstr += "\n" diff --git a/tests/test_sourcepoint_interval/geometry.xml b/tests/test_sourcepoint_interval/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_sourcepoint_interval/geometry.xml +++ b/tests/test_sourcepoint_interval/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py index 8cafb41084..5db0541344 100644 --- a/tests/test_sourcepoint_interval/test_sourcepoint_interval.py +++ b/tests/test_sourcepoint_interval/test_sourcepoint_interval.py @@ -1,32 +1,32 @@ #!/usr/bin/env python +import glob +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness +from openmc.statepoint import StatePoint 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.""" # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() - sp.read_source() # Get the eigenvalue information. outstr = TestHarness._get_results(self) # Add the source information. - xyz = sp._source[0]._xyz + xyz = sp.source[0]['xyz'] outstr += ' '.join(['{0:12.6E}'.format(x) for x in xyz]) outstr += "\n" diff --git a/tests/test_sourcepoint_latest/geometry.xml b/tests/test_sourcepoint_latest/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_sourcepoint_latest/geometry.xml +++ b/tests/test_sourcepoint_latest/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_sourcepoint_latest/results_true.dat b/tests/test_sourcepoint_latest/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_sourcepoint_latest/results_true.dat +++ b/tests/test_sourcepoint_latest/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_sourcepoint_latest/test_sourcepoint_latest.py b/tests/test_sourcepoint_latest/test_sourcepoint_latest.py index 5ae3984626..724a88fa65 100644 --- a/tests/test_sourcepoint_latest/test_sourcepoint_latest.py +++ b/tests/test_sourcepoint_latest/test_sourcepoint_latest.py @@ -1,8 +1,9 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness class SourcepointTestHarness(TestHarness): @@ -12,9 +13,8 @@ class SourcepointTestHarness(TestHarness): source = glob.glob(os.path.join(os.getcwd(), 'source.*')) assert len(source) == 1, 'Either multiple or no source files ' \ 'exist.' - assert source[0].endswith('binary') \ - or source[0].endswith('h5'), \ - 'Source file is not a binary or hdf5 file.' + assert source[0].endswith('h5'), \ + 'Source file is not a HDF5 file.' if __name__ == '__main__': diff --git a/tests/test_sourcepoint_restart/geometry.xml b/tests/test_sourcepoint_restart/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_sourcepoint_restart/geometry.xml +++ b/tests/test_sourcepoint_restart/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_sourcepoint_restart/results_true.dat b/tests/test_sourcepoint_restart/results_true.dat index 917fc0cdfb..0e4eef9a9d 100644 --- a/tests/test_sourcepoint_restart/results_true.dat +++ b/tests/test_sourcepoint_restart/results_true.dat @@ -1,16 +1,116 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 tally 1: -1.200000E-02 -4.000000E-05 -8.118392E-03 -1.773579E-05 -3.683496E-03 -4.911153E-06 -1.507354E-03 -2.420229E-06 -6.245016E-03 -9.775028E-06 +7.000000E-03 +2.100000E-05 +1.127639E-03 +7.464355E-07 +-1.264355E-03 +1.192757E-06 +8.769846E-04 +1.117508E-06 +3.359153E-03 +4.366438E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.107648E-04 +3.730336E-07 +1.000000E-03 +1.000000E-06 +6.713061E-04 +4.506518E-07 +1.759778E-04 +3.096817E-08 +-2.506458E-04 +6.282332E-08 +6.069794E-04 +3.684240E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.000000E-03 +1.500000E-05 +4.398928E-03 +8.198908E-06 +1.784486E-03 +3.422315E-06 +8.494423E-04 +9.262242E-07 +4.566637E-03 +5.646039E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.069794E-04 +3.684240E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +3.000000E-06 +-1.419189E-03 +9.791601E-07 +-3.125982E-05 +5.086129E-07 +3.291570E-04 +1.943609E-07 +1.525426E-03 +8.346311E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -23,34 +123,254 @@ tally 1: 0.000000E+00 1.000000E-03 1.000000E-06 --6.834146E-04 -4.670555E-07 -2.005832E-04 -4.023363E-08 -2.271406E-04 -5.159283E-08 -1.822902E-03 -3.322972E-06 -3.000000E-03 -9.000000E-06 -2.089393E-03 -4.365565E-06 -1.135864E-03 -1.290186E-06 -8.092128E-04 -6.548254E-07 +-1.542107E-05 +2.378095E-10 +-4.996433E-04 +2.496434E-07 +2.312244E-05 +5.346472E-10 +3.053824E-04 +9.325841E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-02 +8.600000E-05 +3.995253E-03 +1.648172E-05 +3.349403E-03 +1.166653E-05 +4.208940E-03 +7.077664E-06 +1.033905E-02 +2.197265E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.029991E-04 +1.818050E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.600000E-02 +1.620000E-04 +7.996640E-03 +1.882484E-05 +3.921034E-03 +1.157453E-05 +1.644629E-03 +3.217857E-06 +1.159182E-02 +3.534975E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +2.500000E-05 +4.691861E-03 +7.999548E-06 +1.771537E-03 +3.385525E-06 +7.888659E-04 +1.911759E-06 +4.561602E-03 +4.337486E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.107648E-04 +3.730336E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +-3.878617E-04 +1.504367E-07 +-2.743449E-04 +7.526515E-08 +4.359210E-04 +1.900271E-07 +3.034897E-04 +9.210600E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.600000E-02 +5.600000E-05 +4.563082E-03 +6.119552E-06 +1.839038E-03 +1.089339E-06 +1.944879E-03 +2.372975E-06 +8.524215E-03 +1.874218E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.015373E-04 +3.618471E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 1.300000E-02 -5.100000E-05 -4.806354E-03 -1.638996E-05 -2.497355E-03 -3.759321E-06 -2.012128E-03 -2.901025E-06 -6.823095E-03 -1.298557E-05 +5.300000E-05 +6.763364E-03 +1.445064E-05 +2.970216E-03 +3.071874E-06 +2.622002E-03 +3.547897E-06 +5.177618E-03 +8.040228E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -59,8 +379,688 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.993246E-04 -1.796295E-07 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +1.400000E-05 +1.172941E-04 +1.212454E-06 +4.110442E-04 +5.740547E-06 +1.788140E-03 +9.775061E-07 +3.946448E-03 +3.956113E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.109694E-04 +1.866863E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +9.168648E-04 +8.406410E-07 +7.609615E-04 +5.790624E-07 +5.515881E-04 +3.042494E-07 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-02 +2.020000E-04 +1.305502E-02 +4.343057E-05 +8.214305E-03 +2.001202E-05 +3.511762E-03 +1.412559E-05 +1.401995E-02 +4.269615E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.400000E-02 +1.320000E-04 +5.207205E-03 +9.311400E-06 +3.232372E-03 +3.475980E-06 +2.062884E-03 +4.773104E-06 +1.039066E-02 +2.611825E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.171802E-04 +4.646485E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.221939E-03 +7.467452E-07 +1.000000E-03 +1.000000E-06 +9.910929E-04 +9.822652E-07 +9.733978E-04 +9.475032E-07 +9.471508E-04 +8.970946E-07 +0.000000E+00 +0.000000E+00 +1.200000E-02 +5.000000E-05 +2.602864E-03 +4.471106E-06 +4.677566E-03 +1.033338E-05 +3.640584E-03 +3.605122E-06 +4.845169E-03 +8.244364E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +3.700000E-05 +3.786358E-03 +5.908272E-06 +3.416266E-03 +7.032934E-06 +3.353945E-03 +5.140933E-06 +4.261660E-03 +4.981501E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.136905E-04 +1.883305E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.700000E-02 +2.090000E-04 +7.046302E-03 +1.594429E-05 +6.489218E-03 +1.057182E-05 +5.057204E-03 +8.269888E-06 +1.274541E-02 +3.591083E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.503843E-03 +2.261544E-06 +3.000000E-03 +5.000000E-06 +3.434984E-04 +2.731822E-07 +-1.911976E-04 +2.018778E-08 +-5.635206E-04 +2.075189E-07 +2.764973E-03 +3.917274E-06 +2.000000E-03 +2.000000E-06 +1.802029E-03 +1.623906E-06 +1.435858E-03 +1.032682E-06 +9.559957E-04 +4.622600E-07 +0.000000E+00 +0.000000E+00 +2.600000E-02 +1.540000E-04 +1.210267E-02 +4.180540E-05 +5.431699E-03 +2.284317E-05 +6.108638E-03 +1.136078E-05 +1.309420E-02 +3.810504E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.124312E-04 +1.875678E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.044609E-04 +3.653729E-07 +1.000000E-03 +1.000000E-06 +9.341546E-04 +8.726448E-07 +8.089673E-04 +6.544280E-07 +6.367311E-04 +4.054265E-07 +3.022304E-04 +9.134324E-08 +2.100000E-02 +9.900000E-05 +1.206996E-02 +4.033646E-05 +6.345510E-03 +1.603169E-05 +1.976558E-03 +4.386164E-06 +1.001209E-02 +2.316074E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.815901E-03 +1.829916E-06 +2.000000E-03 +2.000000E-06 +1.977802E-03 +1.955858E-06 +1.933788E-03 +1.869841E-06 +1.868714E-03 +1.746332E-06 +0.000000E+00 +0.000000E+00 +1.100000E-02 +3.900000E-05 +2.604154E-03 +9.668124E-06 +1.503936E-04 +1.170450E-06 +5.645599E-04 +1.841604E-06 +5.455481E-03 +1.116233E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.015373E-04 +3.618471E-07 +1.000000E-03 +1.000000E-06 +9.936377E-04 +9.873159E-07 +9.809739E-04 +9.623097E-07 +9.621293E-04 +9.256927E-07 +0.000000E+00 +0.000000E+00 +4.100000E-02 +3.610000E-04 +1.275568E-02 +3.756672E-05 +7.436840E-03 +1.784918E-05 +6.238119E-03 +1.114039E-05 +1.706095E-02 +6.393171E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.510747E-03 +8.216143E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.500000E-02 +1.570000E-04 +4.743361E-03 +1.500512E-05 +2.243747E-03 +1.216909E-05 +6.504387E-04 +5.012686E-06 +1.369930E-02 +4.220232E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.124312E-04 +1.875678E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.205998E-03 +7.272200E-07 +2.000000E-03 +2.000000E-06 +1.935082E-03 +1.872342E-06 +1.808514E-03 +1.635965E-06 +1.626644E-03 +1.325172E-06 +0.000000E+00 +0.000000E+00 +1.800000E-02 +1.180000E-04 +6.144587E-03 +1.810176E-05 +3.517233E-03 +7.894223E-06 +5.434668E-03 +1.689927E-05 +7.002945E-03 +1.633731E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.111025E-04 +2.767076E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.000000E-03 +1.400000E-05 +2.937841E-03 +3.083257E-06 +1.316488E-03 +1.378720E-06 +1.917209E-03 +1.388887E-06 +2.434865E-03 +1.665821E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.100000E-02 +4.290000E-04 +1.555575E-02 +6.845536E-05 +1.492622E-02 +7.523417E-05 +4.779064E-03 +1.568962E-05 +1.858109E-02 +9.770216E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +1.000000E-03 +1.000000E-06 +-7.961895E-04 +6.339178E-07 +4.508767E-04 +2.032898E-07 +-6.751245E-05 +4.557931E-09 +2.105380E-03 +4.432627E-06 +1.000000E-03 +1.000000E-06 +7.706275E-04 +5.938667E-07 +3.908001E-04 +1.527247E-07 +-1.181620E-05 +1.396226E-10 +0.000000E+00 +0.000000E+00 +2.300000E-02 +1.870000E-04 +8.530317E-03 +2.513821E-05 +2.769866E-03 +1.832987E-06 +3.367000E-03 +3.408158E-06 +1.029151E-02 +3.475479E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.300000E-02 +1.110000E-04 +1.493458E-02 +4.520237E-05 +8.130453E-03 +1.434362E-05 +5.917132E-03 +7.829616E-06 +1.005025E-02 +2.033292E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -83,14 +1083,14 @@ tally 1: 0.000000E+00 7.000000E-03 1.100000E-05 --2.517807E-05 -3.415722E-06 -1.479050E-03 -1.509604E-06 --4.624719E-04 -1.787423E-06 -3.839667E-03 -3.396077E-06 +2.102923E-03 +3.237003E-06 +5.338761E-04 +1.665334E-06 +2.177563E-03 +1.210407E-06 +3.049393E-03 +2.236660E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -99,18 +1099,78 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.038170E-04 -9.230477E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.300000E-02 +2.470000E-04 +1.392809E-02 +4.644694E-05 +6.658849E-03 +2.448402E-05 +2.971606E-03 +4.596585E-06 +1.583003E-02 +5.281056E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.146617E-04 +4.615975E-07 1.000000E-03 1.000000E-06 -2.553692E-04 -6.521341E-08 --4.021799E-04 -1.617487E-07 --3.414200E-04 -1.165676E-07 -2.962222E-04 -8.774759E-08 +5.742336E-04 +3.297442E-07 +-5.383652E-06 +2.898371E-11 +-3.879749E-04 +1.505245E-07 +1.213130E-03 +5.521442E-07 +2.000000E-03 +2.000000E-06 +1.895662E-03 +1.796999E-06 +1.695499E-03 +1.439233E-06 +1.415735E-03 +1.008516E-06 +3.007686E-04 +9.046177E-08 +4.000000E-02 +3.460000E-04 +1.325054E-02 +4.611581E-05 +4.279513E-03 +1.445432E-05 +5.681074E-03 +8.701686E-06 +1.883326E-02 +7.820565E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -119,62 +1179,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.962222E-04 -8.774759E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.200000E-02 -1.140000E-04 -1.358164E-03 -1.242643E-05 -1.986239E-05 -5.467378E-06 -1.233135E-03 -7.603089E-06 -9.455567E-03 -1.937818E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +9.052295E-04 +4.558347E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -183,8 +1189,28 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.525429E-03 +8.388512E-07 +3.000000E-03 +3.000000E-06 +2.694249E-03 +2.442268E-06 +2.163402E-03 +1.718872E-06 +1.541834E-03 +1.227757E-06 0.000000E+00 0.000000E+00 +2.000000E-02 +1.000000E-04 +5.928221E-03 +9.217060E-06 +5.152240E-03 +1.183310E-05 +2.057268E-03 +2.929338E-06 +9.478909E-03 +2.313196E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -193,6 +1219,18 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +6.057201E-04 +1.834492E-07 +1.000000E-03 +1.000000E-06 +9.405199E-04 +8.845778E-07 +8.268666E-04 +6.837084E-07 +6.691277E-04 +4.477318E-07 +6.124312E-04 +1.875678E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -201,16 +1239,18 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +6.124312E-04 +1.875678E-07 1.400000E-02 5.200000E-05 -4.571175E-03 -9.190534E-06 -4.041031E-03 -5.995154E-06 -2.577281E-04 -1.101532E-06 -8.329519E-03 -1.844018E-05 +6.537971E-03 +1.724690E-05 +3.839523E-03 +8.693753E-06 +4.048043E-03 +5.450370E-06 +7.581656E-03 +1.459334E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -229,68 +1269,208 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.000000E-03 -1.000000E-05 -4.520960E-04 -2.298902E-06 -4.635765E-04 -2.661361E-07 --3.704326E-04 -7.038297E-08 -2.349751E-03 -4.331174E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.215268E-03 -1.476876E-06 +6.069794E-04 +3.684240E-07 1.000000E-03 1.000000E-06 -9.835700E-04 -9.674099E-07 -9.511149E-04 -9.046195E-07 -9.034334E-04 -8.161919E-07 +5.703488E-04 +3.252978E-07 +-1.205336E-05 +1.452836E-10 +-3.916902E-04 +1.534212E-07 0.000000E+00 0.000000E+00 +3.200000E-02 +2.340000E-04 +1.368605E-02 +4.005184E-05 +6.894848E-03 +1.073483E-05 +5.553663E-03 +7.001843E-06 +1.492310E-02 +4.851599E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.224455E-03 +5.613642E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.800000E-02 +1.860000E-04 +1.044511E-02 +6.915901E-05 +6.444951E-03 +3.586496E-05 +5.196826E-03 +1.312451E-05 +1.156517E-02 +3.164422E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.057201E-04 +1.834492E-07 1.000000E-03 1.000000E-06 -9.302087E-04 -8.652883E-07 -7.979324E-04 -6.366961E-07 -6.169336E-04 -3.806071E-07 -5.774597E-04 -3.334597E-07 +-6.535773E-04 +4.271632E-07 +1.407448E-04 +1.980911E-08 +2.824055E-04 +7.975284E-08 +1.822205E-03 +1.106831E-06 +2.000000E-03 +2.000000E-06 +1.954998E-03 +1.911525E-06 +1.867287E-03 +1.747820E-06 +1.741309E-03 +1.532659E-06 +0.000000E+00 +0.000000E+00 +1.900000E-02 +1.010000E-04 +1.062788E-02 +3.182295E-05 +6.707513E-03 +1.259151E-05 +6.889024E-03 +1.429877E-05 +8.202036E-03 +2.430378E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.306024E-04 +8.660208E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.306024E-04 +8.660208E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +1.500000E-02 +4.500000E-05 +3.192578E-03 +7.201112E-06 +4.457942E-03 +6.346144E-06 +3.572536E-03 +4.921318E-06 +7.292620E-03 +1.123722E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.111025E-04 +2.767076E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.069794E-04 +3.684240E-07 +1.000000E-03 +1.000000E-06 +9.537549E-04 +9.096483E-07 +8.644725E-04 +7.473127E-07 +7.383215E-04 +5.451186E-07 +0.000000E+00 +0.000000E+00 +2.300000E-02 +1.310000E-04 +7.696543E-03 +2.602323E-05 +5.553275E-03 +1.677303E-05 +3.110421E-03 +1.605284E-05 +1.157943E-02 +3.065139E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +1.000000E-03 +1.000000E-06 +-1.849356E-05 +3.420117E-10 +-4.994870E-04 +2.494872E-07 +2.772452E-05 +7.686492E-10 +9.104691E-04 +8.289540E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -301,6 +1481,466 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.600000E-02 +1.460000E-04 +1.097600E-02 +2.696995E-05 +8.425033E-03 +2.480653E-05 +3.259803E-03 +4.519527E-06 +1.278442E-02 +3.571130E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.600000E-02 +6.000000E-05 +2.471171E-03 +8.220215E-06 +2.563821E-04 +8.785791E-07 +1.300883E-03 +3.079168E-06 +7.314002E-03 +1.134821E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.022304E-04 +9.134324E-08 +1.000000E-03 +1.000000E-06 +-5.657444E-04 +3.200667E-07 +-1.989995E-05 +3.960081E-10 +3.959267E-04 +1.567580E-07 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +1.800000E-05 +5.436075E-03 +7.868978E-06 +2.425522E-03 +1.963607E-06 +7.168734E-04 +1.273978E-06 +4.589694E-03 +5.548791E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.100000E-02 +1.070000E-04 +7.539735E-03 +2.068189E-05 +3.936810E-03 +7.972494E-06 +2.420366E-04 +1.148364E-06 +9.428594E-03 +2.131421E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.053824E-04 +9.325841E-08 +2.000000E-03 +2.000000E-06 +1.606787E-04 +1.589809E-06 +1.384713E-03 +1.050316E-06 +7.117279E-04 +6.789060E-07 +9.257840E-04 +4.781566E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.600000E-02 +5.100000E-04 +1.468472E-02 +4.705766E-05 +8.285657E-03 +2.501121E-05 +5.066048E-03 +7.892505E-06 +1.769628E-02 +7.226941E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.216485E-03 +5.564829E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.300000E-02 +1.130000E-04 +9.030313E-03 +2.036594E-05 +5.561323E-03 +2.088769E-05 +3.949070E-03 +5.399490E-06 +1.065996E-02 +2.405722E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.124312E-04 +1.875678E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.044609E-04 +3.653729E-07 +1.000000E-03 +1.000000E-06 +9.969425E-04 +9.938944E-07 +9.908416E-04 +9.817670E-07 +9.817251E-04 +9.637842E-07 +0.000000E+00 +0.000000E+00 +1.300000E-02 +4.300000E-05 +1.119189E-03 +4.668647E-06 +-1.976393E-04 +4.632517E-06 +2.358914E-03 +3.047107E-06 +6.688330E-03 +1.125860E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +1.000000E-03 +1.000000E-06 +-3.353539E-04 +1.124622E-07 +-3.313067E-04 +1.097641E-07 +4.087442E-04 +1.670718E-07 +9.161472E-04 +8.393257E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.600000E-02 +1.980000E-04 +1.024848E-02 +3.100622E-05 +-1.145555E-04 +2.521646E-06 +1.453177E-03 +1.505423E-06 +1.124135E-02 +3.412415E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.029991E-04 +1.818050E-07 +1.000000E-03 +1.000000E-06 +-2.499079E-04 +6.245395E-08 +-4.063191E-04 +1.650952E-07 +3.358425E-04 +1.127902E-07 +6.044609E-04 +3.653729E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.900000E-02 +8.700000E-05 +6.743817E-03 +2.313239E-05 +1.353852E-03 +7.358462E-06 +3.054381E-03 +5.051576E-06 +7.932519E-03 +1.438883E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-02 +9.000000E-05 +4.678519E-03 +8.162854E-06 +2.588181E-03 +7.958110E-06 +2.322176E-03 +3.426024E-06 +8.534070E-03 +1.767419E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.029991E-04 +1.818050E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +3.300000E-05 +7.244624E-03 +1.778235E-05 +2.926133E-03 +9.287629E-06 +9.851866E-04 +6.097573E-06 +3.660351E-03 +3.716102E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.034897E-04 +9.210600E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.053824E-04 +9.325841E-08 +1.000000E-03 +1.000000E-06 +1.744930E-04 +3.044781E-08 +-4.543283E-04 +2.064142E-07 +-2.484572E-04 +6.173098E-08 +0.000000E+00 +0.000000E+00 +1.000000E-02 +2.600000E-05 +3.641369E-03 +6.818931E-06 +2.110606E-03 +2.176630E-06 +1.892973E-03 +1.812944E-06 +5.777456E-03 +9.494012E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.034897E-04 +9.210600E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -322,15 +1962,15 @@ tally 1: 0.000000E+00 0.000000E+00 1.300000E-02 -4.700000E-05 -6.197649E-03 -1.101082E-05 -5.066781E-03 -9.709157E-06 -2.134240E-03 -1.351796E-06 -5.604113E-03 -8.598750E-06 +3.900000E-05 +1.682557E-03 +1.846926E-06 +4.172846E-04 +1.892148E-06 +7.276646E-04 +1.085417E-06 +6.092709E-03 +8.907893E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -339,48 +1979,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -1.000000E-05 --9.379228E-05 -1.179295E-06 -1.623379E-03 -1.703479E-06 --8.659077E-05 -7.366687E-07 -2.943759E-03 -2.593311E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.962222E-04 -8.774759E-08 +3.053824E-04 +9.325841E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -403,14 +2003,14 @@ tally 1: 0.000000E+00 5.000000E-03 7.000000E-06 -2.431919E-03 -1.726875E-06 --5.793826E-04 -1.604970E-07 --1.845208E-03 -8.995877E-07 -1.788227E-03 -8.910514E-07 +1.580450E-03 +1.753085E-06 +3.349602E-04 +3.639488E-07 +2.690006E-04 +2.374932E-07 +1.830811E-03 +9.321096E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -419,6 +2019,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +3.102008E-04 +9.622454E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -447,6 +2049,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +3.034897E-04 +9.210600E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -477,380 +2081,56 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.900000E-02 +1.250000E-04 +2.138118E-03 +8.791773E-06 +2.868574E-03 +9.339641E-06 +5.807501E-04 +1.660344E-06 +8.165982E-03 +2.226036E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.000000E-02 -1.940000E-04 -9.461264E-03 -1.947969E-05 -3.587007E-03 -6.174074E-06 -4.090547E-03 -7.913444E-06 -1.296390E-02 -3.766012E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +3.102008E-04 +9.622454E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -8.793837E-04 -2.578025E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.044609E-04 +3.653729E-07 1.000000E-03 1.000000E-06 --8.123463E-04 -6.599064E-07 -4.898597E-04 -2.399625E-07 --1.216619E-04 -1.480163E-08 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.500000E-02 -6.500000E-05 -3.611706E-03 -1.040980E-05 -9.737058E-04 -4.485811E-06 --7.198322E-05 -1.665155E-06 -7.644305E-03 -1.681345E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.962222E-04 -8.774759E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.962222E-04 -8.774759E-08 -1.000000E-03 -1.000000E-06 -9.957690E-04 -9.915560E-07 -9.873340E-04 -9.748284E-07 -9.747484E-04 -9.501344E-07 -0.000000E+00 -0.000000E+00 -1.300000E-02 -4.500000E-05 -3.079966E-03 -9.332877E-06 -1.443410E-03 -2.514831E-06 -1.111923E-03 -1.429512E-06 -6.483010E-03 -9.477194E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.937562E-04 -2.663195E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.114510E-04 -8.307430E-07 -1.000000E-03 -1.000000E-06 -8.370200E-04 -7.006024E-07 -5.509036E-04 -3.034948E-07 -2.105156E-04 -4.431682E-08 -3.038170E-04 -9.230477E-08 -9.000000E-03 -1.900000E-05 --2.021899E-04 -8.445484E-06 -2.148061E-03 -2.701015E-06 -1.264629E-03 -5.949953E-07 -4.409634E-03 -5.032698E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.962222E-04 -8.774759E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.076340E-04 -3.692191E-07 -1.000000E-03 -1.000000E-06 -9.987845E-04 -9.975704E-07 -9.963556E-04 -9.927245E-07 -9.927178E-04 -9.854887E-07 -0.000000E+00 -0.000000E+00 -3.300000E-02 -2.270000E-04 -1.837920E-02 -7.801676E-05 -1.150357E-02 -2.715434E-05 -5.741625E-03 -6.838179E-06 -1.540397E-02 -4.998202E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -1.000000E-03 -1.000000E-06 -5.247170E-04 -2.753280E-07 --8.700807E-05 -7.570404E-09 --4.259024E-04 -1.813928E-07 -1.196497E-03 -7.159790E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.500000E-02 -1.430000E-04 -8.404687E-03 -2.505155E-05 -6.898191E-03 -1.367706E-05 -3.899114E-03 -3.607028E-06 -1.271358E-02 -3.382031E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-02 -1.940000E-04 -1.736738E-02 -7.398587E-05 -7.729434E-03 -1.773562E-05 -4.523718E-03 -5.898914E-06 -1.567397E-02 -5.134448E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.993246E-04 -1.796295E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.000000E-03 -2.300000E-05 --7.007722E-04 -2.822943E-06 --5.777080E-04 -9.868563E-07 -1.257117E-03 -3.672741E-07 -5.315767E-03 -6.276521E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.400000E-02 -1.220000E-04 -1.229985E-02 -3.184724E-05 -1.060332E-02 -2.381543E-05 -7.803741E-03 -1.463189E-05 -1.117224E-02 -2.961846E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.480499E-03 -6.139848E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.822902E-03 -3.322972E-06 -2.000000E-03 -4.000000E-06 -1.879286E-03 -3.531714E-06 -1.649674E-03 -2.721425E-06 -1.333434E-03 -1.778047E-06 +2.312419E-04 +5.347280E-08 +-4.197908E-04 +1.762243E-07 +-3.159499E-04 +9.982435E-08 0.000000E+00 0.000000E+00 2.100000E-02 -1.010000E-04 -8.226424E-03 -1.799176E-05 -6.115955E-03 -1.432832E-05 -5.108113E-03 -8.009589E-06 -1.030852E-02 -2.790767E-05 +1.070000E-04 +2.216472E-03 +6.388960E-06 +4.896969E-03 +6.428816E-06 +2.155707E-03 +2.884510E-06 +1.038058E-02 +2.477423E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -859,38 +2139,38 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.861614E-04 -2.617623E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.661896E-04 -7.502844E-07 +3.007686E-04 +9.046177E-08 1.000000E-03 1.000000E-06 -8.824739E-04 -7.787602E-07 -6.681402E-04 -4.464114E-07 -3.943779E-04 -1.555340E-07 -2.887299E-04 -8.336493E-08 -2.400000E-02 -1.340000E-04 -5.157290E-03 -7.361769E-06 -3.873191E-03 -7.075290E-06 -8.178477E-04 -5.349982E-06 -1.151979E-02 -2.707490E-05 +7.019813E-04 +4.927778E-07 +2.391667E-04 +5.720072E-08 +-1.881699E-04 +3.540793E-08 +2.131373E-03 +2.696833E-06 +1.000000E-03 +1.000000E-06 +9.937981E-04 +9.876347E-07 +9.814521E-04 +9.632483E-07 +9.630767E-04 +9.275168E-07 +0.000000E+00 +0.000000E+00 +6.000000E-03 +1.000000E-05 +2.774441E-03 +2.455060E-06 +-4.125360E-04 +1.557128E-06 +-9.369606E-04 +2.349382E-06 +3.666415E-03 +4.871762E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -899,8 +2179,20 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -8.880544E-04 -2.629944E-07 +6.057201E-04 +1.834492E-07 +1.000000E-03 +1.000000E-06 +8.429685E-04 +7.105959E-07 +5.658938E-04 +3.202358E-07 +2.330721E-04 +5.432261E-08 +6.015373E-04 +3.618471E-07 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -909,28 +2201,18 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.362820E-03 -2.089719E-06 3.000000E-03 -3.000000E-06 -2.788384E-03 -2.594798E-06 -2.392197E-03 -1.932048E-06 -1.861371E-03 -1.235196E-06 +5.000000E-06 +1.596397E-03 +1.275630E-06 +4.822532E-04 +1.627925E-07 +2.983020E-04 +9.401537E-08 +1.221939E-03 +7.467452E-07 0.000000E+00 0.000000E+00 -1.000000E-02 -3.600000E-05 -1.316990E-03 -3.149836E-06 --3.200310E-04 -2.746500E-07 --1.360513E-03 -1.090571E-06 -4.126370E-03 -6.612189E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -939,8 +2221,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -3.038170E-04 -9.230477E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -961,296 +2241,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.700000E-02 -1.810000E-04 -9.818267E-03 -4.983755E-05 -3.336597E-03 -8.390727E-06 -2.160979E-03 -5.064669E-06 -1.384908E-02 -4.570937E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.925469E-04 -1.756697E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.832949E-04 -7.802099E-07 -1.000000E-03 -1.000000E-06 -2.811985E-04 -7.907261E-08 --3.813911E-04 -1.454592E-07 --3.662100E-04 -1.341098E-07 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.130000E-04 -1.202681E-02 -3.022795E-05 -7.515466E-03 -1.650504E-05 -5.404032E-03 -1.127927E-05 -1.330371E-02 -4.078117E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -3.000000E-03 -3.000000E-06 -2.638441E-04 -1.166669E-06 -2.500034E-04 -9.610467E-07 -1.533129E-03 -8.706796E-07 -1.174177E-03 -5.193538E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.800000E-02 -2.980000E-04 -1.429526E-02 -5.478450E-05 -1.510549E-03 -2.039833E-05 -5.571300E-03 -7.961775E-06 -1.713980E-02 -6.035252E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.804596E-04 -2.584372E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.774597E-04 -3.334597E-07 -2.000000E-03 -4.000000E-06 -1.885369E-03 -3.554618E-06 -1.668235E-03 -2.783008E-06 -1.371259E-03 -1.880351E-06 -2.887299E-04 -8.336493E-08 -1.800000E-02 -7.600000E-05 -1.188269E-02 -3.305188E-05 -6.397672E-03 -1.039477E-05 -5.195583E-03 -8.228666E-06 -6.541819E-03 -1.138522E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.800000E-02 -1.920000E-04 -9.138883E-03 -2.389639E-05 -8.073407E-03 -1.777984E-05 -4.397066E-03 -1.246700E-05 -1.396848E-02 -4.880190E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.184277E-03 -3.507420E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.888633E-04 -3.467599E-07 -1.000000E-03 -1.000000E-06 -9.872275E-04 -9.746182E-07 -9.619273E-04 -9.253040E-07 -9.245834E-04 -8.548545E-07 -0.000000E+00 -0.000000E+00 -2.800000E-02 -1.960000E-04 -9.225605E-03 -2.308636E-05 -5.671475E-03 -8.733020E-06 -2.978790E-03 -7.550647E-06 -1.623921E-02 -6.654244E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 --2.171929E-04 -4.717275E-08 --4.292409E-04 -1.842477E-07 -3.001754E-04 -9.010526E-08 -5.982486E-04 -1.789948E-07 -1.000000E-03 -1.000000E-06 -9.264912E-04 -8.583859E-07 -7.875789E-04 -6.202805E-07 -5.984807E-04 -3.581791E-07 -0.000000E+00 -0.000000E+00 -4.000000E-02 -3.760000E-04 -1.836389E-02 -1.034063E-04 -1.618617E-02 -7.468163E-05 -1.265008E-02 -4.683455E-05 -1.680380E-02 -6.300115E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.481316E-03 -7.904264E-07 -1.000000E-03 -1.000000E-06 --7.356303E-04 -5.411519E-07 -3.117279E-04 -9.717427E-08 -1.082261E-04 -1.171288E-08 -5.888633E-04 -3.467599E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.000000E-03 -2.200000E-05 -1.034121E-03 -5.652456E-07 --8.248086E-04 -1.478042E-06 --7.162554E-04 -2.662167E-07 -4.452971E-03 -6.246366E-06 +4.000000E-05 +-7.915490E-05 +1.150292E-07 +2.293529E-03 +2.932682E-06 +1.356149E-03 +9.471925E-07 +4.579650E-03 +7.918475E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1259,8 +2259,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.899392E-04 -1.740147E-07 +3.022304E-04 +9.134324E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1281,296 +2281,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.700000E-02 -1.650000E-04 -1.022719E-02 -3.691933E-05 -8.344427E-03 -2.163687E-05 -2.493470E-03 -3.777443E-06 -1.562097E-02 -5.500554E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.865227E-04 -7.859225E-07 -1.000000E-03 -1.000000E-06 --2.406040E-04 -5.789029E-08 --4.131646E-04 -1.707050E-07 -3.260844E-04 -1.063311E-07 -2.628743E-03 -4.454101E-06 -1.000000E-03 -1.000000E-06 -8.584065E-04 -7.368618E-07 -6.052926E-04 -3.663792E-07 -2.937076E-04 -8.626413E-08 -2.887299E-04 -8.336493E-08 -2.400000E-02 -1.460000E-04 -1.482825E-02 -6.559075E-05 -7.894674E-03 -1.733357E-05 -4.942543E-03 -5.919157E-06 -9.954930E-03 -2.766286E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.887299E-04 -8.336493E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.114510E-04 -8.307430E-07 -1.000000E-03 -1.000000E-06 -9.637579E-04 -9.288293E-07 -8.932439E-04 -7.978848E-07 -7.922796E-04 -6.277069E-07 -0.000000E+00 -0.000000E+00 -2.800000E-02 -2.080000E-04 -9.690534E-03 -3.443096E-05 -4.888498E-03 -1.094678E-05 -2.994444E-03 -6.032009E-06 -1.236682E-02 -3.585861E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.191871E-03 -5.399087E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.832949E-04 -7.802099E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.000000E-03 -3.100000E-05 -6.119200E-03 -1.291899E-05 -5.129096E-03 -1.114323E-05 -4.761296E-03 -9.710486E-06 -3.829174E-03 -6.324914E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.944316E-04 -8.668999E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.774597E-04 -3.334597E-07 -1.000000E-03 -1.000000E-06 -9.885814E-04 -9.772933E-07 -9.659399E-04 -9.330399E-07 -9.324628E-04 -8.694869E-07 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.270000E-04 -5.315630E-03 -1.185056E-05 -2.837051E-03 -6.724635E-06 -2.570238E-03 -6.855367E-06 -1.266746E-02 -3.785511E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.031416E-04 -4.565438E-07 -1.000000E-03 -1.000000E-06 -9.914618E-04 -9.829965E-07 -9.744947E-04 -9.496400E-07 -9.493160E-04 -9.012008E-07 -0.000000E+00 -0.000000E+00 -9.000000E-03 -2.900000E-05 -2.008698E-03 -7.210242E-06 -1.288698E-03 -6.087002E-07 --5.193923E-04 -4.491465E-07 -3.876462E-03 -4.440238E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.700000E-02 -2.030000E-04 -1.013137E-02 -3.117050E-05 -3.372227E-03 -8.195716E-06 -3.788344E-03 -6.816175E-06 -1.323056E-02 -4.179593E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.183098E-03 -8.764183E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.114510E-04 -8.307430E-07 -1.000000E-03 -1.000000E-06 -8.500688E-04 -7.226169E-07 -5.839254E-04 -3.409689E-07 -2.605821E-04 -6.790302E-08 -0.000000E+00 -0.000000E+00 1.100000E-02 -2.700000E-05 -7.820374E-03 -1.524804E-05 -4.579486E-03 -8.746643E-06 -3.441507E-03 -5.197609E-06 -4.452744E-03 -4.715167E-06 +3.300000E-05 +5.093647E-03 +1.217545E-05 +1.852586E-03 +4.478970E-06 +9.768799E-04 +1.395189E-06 +4.578572E-03 +5.491453E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1579,8 +2299,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.887299E-04 -8.336493E-08 +3.102008E-04 +9.622454E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1589,388 +2309,28 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.774597E-04 -3.334597E-07 +3.053824E-04 +9.325841E-08 1.000000E-03 1.000000E-06 -9.729463E-04 -9.466245E-07 -9.199368E-04 -8.462837E-07 -8.431176E-04 -7.108474E-07 -0.000000E+00 -0.000000E+00 -3.800000E-02 -3.240000E-04 -1.253787E-02 -4.293627E-05 -1.235024E-02 -4.427860E-05 -1.055055E-02 -3.831635E-05 -1.944951E-02 -9.030483E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.944316E-04 -8.668999E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.500000E-04 -5.912427E-03 -8.576381E-06 -6.340156E-03 -2.278116E-05 -1.617551E-03 -6.023906E-06 -1.264835E-02 -3.597963E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.804596E-04 -2.584372E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.230000E-04 -4.119009E-03 -9.246641E-06 -5.235271E-03 -1.144493E-05 --4.185262E-04 -5.960141E-06 -1.208764E-02 -3.425774E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -1.000000E-03 -1.000000E-06 -8.637115E-04 -7.459975E-07 -6.189963E-04 -3.831564E-07 -3.152494E-04 -9.938217E-08 -0.000000E+00 -0.000000E+00 -1.500000E-02 -5.700000E-05 --1.957197E-03 -1.258480E-05 -2.792528E-03 -9.542338E-06 --3.511546E-04 -3.064697E-06 -6.238135E-03 -9.183145E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.200000E-02 -1.080000E-04 -9.763854E-03 -2.367740E-05 -4.590661E-03 -6.936237E-06 -2.901204E-03 -1.887464E-06 -1.005417E-02 -2.274048E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.865227E-04 -7.859225E-07 -1.000000E-03 -1.000000E-06 --2.499079E-04 -6.245395E-08 --4.063191E-04 -1.650952E-07 -3.358425E-04 -1.127902E-07 -1.185094E-03 -7.026788E-07 -1.000000E-03 -1.000000E-06 -9.786988E-04 -9.578514E-07 -9.367771E-04 -8.775513E-07 -8.755719E-04 -7.666261E-07 -3.038170E-04 -9.230477E-08 -2.000000E-02 -9.800000E-05 -7.857549E-03 -1.428798E-05 -5.459113E-03 -9.636925E-06 -1.887884E-03 -1.537243E-06 -1.001700E-02 -2.607271E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.962222E-04 -8.774759E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.800000E-02 -8.200000E-05 -8.495126E-03 -2.651261E-05 -4.998924E-03 -1.299981E-05 -3.448762E-03 -4.943207E-06 -8.610805E-03 -1.917491E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.038562E-04 -4.569667E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -1.200000E-05 -3.227340E-03 -4.394334E-06 -2.414906E-03 -2.934558E-06 -3.208300E-03 -3.506847E-06 -3.262105E-03 -4.123831E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.200000E-02 -5.400000E-05 -4.005144E-03 -5.369960E-06 -4.643787E-03 -9.269182E-06 -2.657135E-03 -3.511892E-06 -4.987572E-03 -8.363876E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +9.817451E-04 +9.638234E-07 +9.457351E-04 +8.944149E-07 +8.929546E-04 +7.973680E-07 0.000000E+00 0.000000E+00 4.000000E-03 -6.000000E-06 -1.406973E-03 -2.042054E-06 -1.350269E-03 -1.571414E-06 -1.514228E-03 -1.025767E-06 -1.776109E-03 -1.051978E-06 +4.000000E-06 +-1.284380E-03 +9.356368E-07 +-5.965448E-04 +6.643272E-07 +3.352677E-04 +2.956621E-07 +1.526686E-03 +6.527074E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2003,374 +2363,14 @@ tally 1: 0.000000E+00 1.000000E-03 1.000000E-06 --9.859558E-04 -9.721088E-07 -9.581632E-04 -9.180766E-07 --9.172070E-04 -8.412686E-07 -1.487277E-03 -7.925940E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -1.300000E-05 -1.259188E-03 -2.542709E-06 -1.153212E-03 -5.113126E-07 -1.180102E-03 -1.512230E-06 -2.952791E-03 -2.256416E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.000000E-03 -2.900000E-05 -3.658677E-03 -5.084397E-06 -1.342768E-03 -7.844439E-07 -1.434698E-03 -1.591990E-06 -4.727265E-03 -6.802376E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.000000E-03 -6.000000E-06 --3.169496E-04 -4.640012E-07 -3.870584E-04 -1.106745E-06 -2.229627E-03 -2.248204E-06 -2.384967E-03 -3.528132E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.887299E-04 -8.336493E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.000000E-03 -2.000000E-06 -1.104635E-03 -1.006490E-06 -5.097352E-04 -1.218176E-06 -8.274440E-04 -9.952021E-07 -8.879520E-04 -4.383151E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.400000E-02 -4.200000E-05 -3.129225E-03 -5.993671E-06 -4.628419E-03 -5.138563E-06 -2.799257E-03 -6.824571E-06 -6.214149E-03 -8.661850E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.962222E-04 -8.774759E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.200000E-02 -3.800000E-05 -4.480587E-03 -8.674795E-06 -3.647946E-03 -4.377407E-06 -3.360220E-03 -5.133585E-06 -7.650887E-03 -1.640283E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.000000E-03 -3.100000E-05 -4.975831E-03 -8.184805E-06 -2.183561E-03 -2.575450E-06 -2.014752E-03 -5.318808E-06 -3.529684E-03 -5.223931E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.832949E-04 -7.802099E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +-3.965739E-04 +1.572709E-07 +-2.640937E-04 +6.974547E-08 +4.389371E-04 +1.926657E-07 +3.053824E-04 +9.325841E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2402,11 +2402,11 @@ tally 1: 0.000000E+00 0.000000E+00 tally 2: -5.604521E-01 -6.286639E-02 -6.095321E-01 -7.435628E-02 -3.539776E+00 -2.507806E+00 -3.963740E+01 -3.144698E+02 +5.720364E-01 +6.548043E-02 +6.217988E-01 +7.736906E-02 +3.624477E+00 +2.628737E+00 +4.047526E+01 +3.278231E+02 diff --git a/tests/test_sourcepoint_restart/tallies.xml b/tests/test_sourcepoint_restart/tallies.xml index 1704f56e1e..67a1b50a94 100644 --- a/tests/test_sourcepoint_restart/tallies.xml +++ b/tests/test_sourcepoint_restart/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular 5 3 4 -10. -5. 0. 10. 4. 9. @@ -20,4 +20,4 @@ fission absorption total flux - \ No newline at end of file + diff --git a/tests/test_sourcepoint_restart/test_sourcepoint_restart.py b/tests/test_sourcepoint_restart/test_sourcepoint_restart.py index 1777db993e..ed6addec45 100644 --- a/tests/test_sourcepoint_restart/test_sourcepoint_restart.py +++ b/tests/test_sourcepoint_restart/test_sourcepoint_restart.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_statepoint_batch/geometry.xml b/tests/test_statepoint_batch/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_statepoint_batch/geometry.xml +++ b/tests/test_statepoint_batch/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_statepoint_batch/results_true.dat b/tests/test_statepoint_batch/results_true.dat index 786fd55461..95b536997e 100644 --- a/tests/test_statepoint_batch/results_true.dat +++ b/tests/test_statepoint_batch/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.109090E-01 5.807935E-03 +3.051173E-01 6.930168E-04 diff --git a/tests/test_statepoint_batch/test_statepoint_batch.py b/tests/test_statepoint_batch/test_statepoint_batch.py index bc5632618f..e1dc167ffd 100644 --- a/tests/test_statepoint_batch/test_statepoint_batch.py +++ b/tests/test_statepoint_batch/test_statepoint_batch.py @@ -1,7 +1,9 @@ #!/usr/bin/env python + +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness class StatepointTestHarness(TestHarness): diff --git a/tests/test_statepoint_interval/geometry.xml b/tests/test_statepoint_interval/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_statepoint_interval/geometry.xml +++ b/tests/test_statepoint_interval/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_statepoint_interval/results_true.dat b/tests/test_statepoint_interval/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_statepoint_interval/results_true.dat +++ b/tests/test_statepoint_interval/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_statepoint_interval/test_statepoint_interval.py b/tests/test_statepoint_interval/test_statepoint_interval.py index b41ee2b7ae..e7a42cdbe7 100644 --- a/tests/test_statepoint_interval/test_statepoint_interval.py +++ b/tests/test_statepoint_interval/test_statepoint_interval.py @@ -1,8 +1,9 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness class StatepointTestHarness(TestHarness): diff --git a/tests/test_statepoint_restart/geometry.xml b/tests/test_statepoint_restart/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_statepoint_restart/geometry.xml +++ b/tests/test_statepoint_restart/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_statepoint_restart/results_true.dat b/tests/test_statepoint_restart/results_true.dat index 378d07639f..7fb39ef0ac 100644 --- a/tests/test_statepoint_restart/results_true.dat +++ b/tests/test_statepoint_restart/results_true.dat @@ -1,16 +1,36 @@ k-combined: 0.000000E+00 0.000000E+00 tally 1: -6.000000E-03 -2.600000E-05 -3.531902E-03 -1.021953E-05 -9.975346E-04 -1.809348E-06 -1.606025E-04 -5.146498E-07 -3.612566E-03 -7.304701E-06 +1.000000E-03 +1.000000E-06 +6.655302E-04 +4.429305E-07 +1.643958E-04 +2.702597E-08 +-2.613362E-04 +6.829663E-08 +9.306024E-04 +8.660208E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -23,2034 +43,174 @@ tally 1: 0.000000E+00 1.000000E-03 1.000000E-06 --6.834146E-04 -4.670555E-07 -2.005832E-04 -4.023363E-08 -2.271406E-04 -5.159283E-08 -1.822902E-03 -3.322972E-06 -3.000000E-03 -9.000000E-06 -2.089393E-03 -4.365565E-06 -1.135864E-03 -1.290186E-06 -8.092128E-04 -6.548254E-07 +3.222834E-05 +1.038666E-09 +-4.984420E-04 +2.484444E-07 +-4.825883E-05 +2.328915E-09 +1.221939E-03 +7.467452E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +-5.510082E-04 +3.036101E-07 +-4.458491E-05 +1.987814E-09 +4.082832E-04 +1.666952E-07 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.000000E-03 +2.000000E-05 +-1.959329E-04 +1.780222E-06 +-1.481510E-03 +1.429609E-06 +2.196341E-04 +1.036368E-06 +3.355616E-03 +5.662237E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 9.000000E-03 4.100000E-05 -5.652386E-03 -1.597604E-05 -2.688047E-03 -3.713200E-06 -2.194373E-03 -2.457094E-06 -4.490780E-03 -1.011172E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.993246E-04 -1.796295E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-03 -5.000000E-06 -2.287185E-05 -1.868964E-06 -1.070450E-03 -8.923889E-07 -6.823621E-04 -7.961600E-07 -1.494157E-03 -1.155142E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.000000E-03 -4.500000E-05 --5.457243E-04 -9.054533E-06 --4.642719E-04 -6.489071E-07 -4.050968E-04 -1.775928E-06 -3.579329E-03 -7.065658E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -2.500000E-05 -3.948480E-03 -7.932459E-06 -1.825370E-03 -1.929280E-06 -9.348098E-04 -5.448323E-07 -4.195272E-03 -8.801845E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.215268E-03 -1.476876E-06 -1.000000E-03 -1.000000E-06 -9.835700E-04 -9.674099E-07 -9.511149E-04 -9.046195E-07 -9.034334E-04 -8.161919E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -2.000000E-05 -2.837861E-03 -4.029451E-06 -2.881422E-03 -5.264923E-06 -6.079138E-04 -2.481989E-07 -2.380679E-03 -3.512909E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 --3.562118E-04 -1.268868E-07 --3.096697E-04 -9.589534E-08 -4.213212E-04 -1.775116E-07 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-03 -5.000000E-06 -1.625863E-03 -1.397973E-06 --7.273518E-05 -2.624738E-08 --9.756535E-04 -5.212160E-07 -9.031416E-04 -4.565438E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -5.200000E-05 -3.200356E-03 -6.305597E-06 -4.448554E-04 -8.305799E-07 --1.337748E-04 -7.137799E-07 -4.794597E-03 -1.149629E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 --8.123463E-04 -6.599064E-07 -4.898597E-04 -2.399625E-07 --1.216619E-04 -1.480163E-08 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -3.600000E-05 -2.521971E-03 -6.360336E-06 -2.020703E-03 -4.083242E-06 -4.407398E-04 -1.942515E-07 -2.955076E-03 -8.732472E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -2.500000E-05 -3.210520E-03 -7.168481E-06 -5.465390E-04 -2.109809E-06 -2.437003E-04 -7.534680E-07 -2.397298E-03 -2.874072E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.993246E-04 -1.796295E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.114510E-04 -8.307430E-07 -1.000000E-03 -1.000000E-06 -8.370200E-04 -7.006024E-07 -5.509036E-04 -3.034948E-07 -2.105156E-04 -4.431682E-08 -3.038170E-04 -9.230477E-08 -3.000000E-03 -5.000000E-06 --5.652293E-04 -2.826536E-07 --4.965795E-04 -1.814108E-07 -4.241721E-04 -1.785027E-07 -1.494157E-03 -1.155142E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.076340E-04 -3.692191E-07 -1.000000E-03 -1.000000E-06 -9.987845E-04 -9.975704E-07 -9.963556E-04 -9.927245E-07 -9.927178E-04 -9.854887E-07 -0.000000E+00 -0.000000E+00 -1.500000E-02 -1.130000E-04 -6.948075E-03 -3.012964E-05 -4.659628E-03 -1.149973E-05 -2.300471E-03 -2.760542E-06 -6.009865E-03 -1.888067E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.076340E-04 -3.692191E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.300000E-02 -8.900000E-05 -3.756467E-03 -7.490548E-06 -3.458886E-03 -8.908312E-06 -1.955536E-03 -1.939721E-06 -5.672810E-03 -1.709769E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.500000E-02 -1.170000E-04 -1.030992E-02 -5.340950E-05 -5.378168E-03 -1.477216E-05 -2.698876E-03 -3.931578E-06 -7.470784E-03 -2.887854E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.993246E-04 -1.796295E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-03 -5.000000E-06 -1.127335E-03 -1.646568E-06 -2.677722E-05 -4.627248E-07 -4.736469E-04 -1.133017E-07 -2.085172E-03 -2.552337E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -2.500000E-05 -4.643996E-03 -1.123518E-05 -5.365579E-03 -1.452653E-05 -3.188541E-03 -5.332163E-06 -2.397298E-03 -2.874072E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.993246E-04 -1.796295E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.822902E-03 -3.322972E-06 -2.000000E-03 -4.000000E-06 -1.879286E-03 -3.531714E-06 -1.649674E-03 -2.721425E-06 -1.333434E-03 -1.778047E-06 -0.000000E+00 -0.000000E+00 -5.000000E-03 -1.300000E-05 -2.119503E-03 -2.510375E-06 -2.082062E-03 -2.331440E-06 -3.351745E-04 -2.838723E-07 -1.510776E-03 -1.564201E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.100000E-02 -7.300000E-05 -3.488060E-03 -6.088204E-06 -4.865073E-04 -2.426361E-07 --1.552382E-03 -3.383588E-06 -3.899764E-03 -7.666624E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.993246E-04 -1.796295E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.076340E-04 -3.692191E-07 -1.000000E-03 -1.000000E-06 -8.964005E-04 -8.035339E-07 -7.053009E-04 -4.974493E-07 -4.561198E-04 -2.080453E-07 -0.000000E+00 -0.000000E+00 -2.000000E-03 -2.000000E-06 -1.915339E-04 -2.525471E-07 --6.211793E-04 -2.122635E-07 --1.146914E-04 -3.101272E-07 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -2.600000E-05 --4.219550E-04 -1.772971E-07 --5.155325E-04 -1.340113E-07 --6.251664E-04 -1.343175E-06 -3.620876E-03 -8.262609E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.000000E-03 -3.400000E-05 -5.071850E-03 -1.313386E-05 -2.724384E-03 -7.394944E-06 -2.290869E-03 -6.048295E-06 -3.620876E-03 -8.262609E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -1.000000E-03 -1.000000E-06 -9.548992E-04 -9.118325E-07 -8.677487E-04 -7.529878E-07 -7.444215E-04 -5.541633E-07 -5.910151E-04 -3.492989E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.300000E-02 -8.500000E-05 -9.564268E-03 -4.579281E-05 -5.459886E-03 -1.501050E-05 -2.874517E-03 -4.642749E-06 -6.592570E-03 -2.173517E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -2.000000E-05 -4.435015E-03 -1.032581E-05 -2.521759E-03 -3.179660E-06 -1.353941E-03 -9.392372E-07 -2.422227E-03 -4.610259E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.300000E-02 -1.090000E-04 -1.100864E-03 -1.263113E-06 -2.894751E-03 -6.130418E-06 --1.408599E-04 -4.071904E-07 -7.537259E-03 -3.418566E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.993246E-04 -1.796295E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.600000E-02 -1.460000E-04 -4.074270E-03 -1.077055E-05 -2.219886E-03 -2.502730E-06 -1.500629E-03 -1.970345E-06 -8.940012E-03 -4.598689E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 --2.171929E-04 -4.717275E-08 --4.292409E-04 -1.842477E-07 -3.001754E-04 -9.010526E-08 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.600000E-02 -1.460000E-04 -4.558047E-03 -2.458088E-05 -4.224970E-03 -1.162419E-05 -3.278961E-03 -7.369638E-06 -7.462474E-03 -2.983182E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.076340E-04 -3.692191E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.000000E-03 -4.000000E-06 --7.774760E-05 -6.044689E-09 --9.888880E-04 -9.778994E-07 -1.150490E-04 -1.323627E-08 -1.510776E-03 -1.564201E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -1.800000E-05 -1.830475E-03 -4.175502E-06 -5.295634E-04 -6.803525E-07 --6.336822E-04 -3.621057E-07 -3.883146E-03 -7.896401E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.865227E-04 -7.859225E-07 -1.000000E-03 -1.000000E-06 --2.406040E-04 -5.789029E-08 --4.131646E-04 -1.707050E-07 -3.260844E-04 -1.063311E-07 -6.076340E-04 -3.692191E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -3.700000E-05 -3.454215E-03 -1.675190E-05 -1.858250E-03 -3.338471E-06 -1.085475E-03 -6.518317E-07 -2.372370E-03 -4.371216E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.114510E-04 -8.307430E-07 -1.000000E-03 -1.000000E-06 -9.637579E-04 -9.288293E-07 -8.932439E-04 -7.978848E-07 -7.922796E-04 -6.277069E-07 -0.000000E+00 -0.000000E+00 -1.000000E-02 -5.000000E-05 -1.718655E-03 -5.820327E-06 -1.009025E-03 -1.093834E-06 -7.699062E-05 -4.576237E-09 -3.587638E-03 -6.586531E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.031416E-04 -4.565438E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 -8.821806E-04 -7.782426E-07 -6.673640E-04 -4.453746E-07 -3.931055E-04 -1.545319E-07 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -2.600000E-05 -1.227695E-03 -5.443406E-06 -2.043844E-04 -8.931431E-07 --1.326053E-03 -9.027914E-07 -2.709425E-03 -4.108894E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.031416E-04 -4.565438E-07 -1.000000E-03 -1.000000E-06 -9.914618E-04 -9.829965E-07 -9.744947E-04 -9.496400E-07 -9.493160E-04 -9.012008E-07 -0.000000E+00 -0.000000E+00 -6.000000E-03 -2.600000E-05 -2.958450E-03 -5.562605E-06 -3.172420E-04 -6.855086E-08 -2.704203E-05 -6.951536E-08 -2.413917E-03 -3.672271E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.038170E-04 -9.230477E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.000000E-03 -1.700000E-05 -1.519186E-03 -1.241308E-06 --2.611610E-04 -2.188069E-06 -3.469316E-04 -8.929955E-07 -3.562710E-03 -9.101691E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.114510E-04 -8.307430E-07 -1.000000E-03 -1.000000E-06 -8.500688E-04 -7.226169E-07 -5.839254E-04 -3.409689E-07 -2.605821E-04 -6.790302E-08 -0.000000E+00 -0.000000E+00 -4.000000E-03 -1.000000E-05 -3.088118E-03 -7.629969E-06 -1.972096E-03 -5.348162E-06 -1.349791E-03 -3.293530E-06 -1.814593E-03 -2.394944E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -5.000000E-05 -5.974452E-03 -2.318079E-05 -3.480849E-03 -1.552533E-05 -3.253745E-03 -8.999790E-06 -4.777978E-03 -1.205544E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.000000E-03 -4.500000E-05 -2.829108E-03 -4.741955E-06 -4.557223E-03 -1.257560E-05 -1.915865E-03 -3.032559E-06 -4.465851E-03 -1.204317E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.000000E-03 -3.400000E-05 -9.777793E-04 -5.838760E-07 -3.108961E-03 -5.045918E-06 -9.790439E-04 -2.045088E-06 -5.377302E-03 -1.508923E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.955076E-04 -8.732472E-08 -1.000000E-03 -1.000000E-06 -8.637115E-04 -7.459975E-07 -6.189963E-04 -3.831564E-07 -3.152494E-04 -9.938217E-08 -0.000000E+00 -0.000000E+00 -8.000000E-03 -4.000000E-05 --2.016521E-03 -3.282699E-06 --2.864647E-04 -5.009517E-06 --1.038509E-03 -9.421948E-07 -3.013242E-03 -5.308856E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.000000E-03 -3.400000E-05 -3.498315E-03 -7.919249E-06 -8.129080E-04 -1.259805E-06 -1.181971E-03 -7.715331E-07 -2.996623E-03 -4.490737E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.865227E-04 -7.859225E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.076340E-04 -3.692191E-07 -1.000000E-03 -1.000000E-06 -9.786988E-04 -9.578514E-07 -9.367771E-04 -8.775513E-07 -8.755719E-04 -7.666261E-07 -3.038170E-04 -9.230477E-08 -8.000000E-03 -5.000000E-05 -2.793720E-03 -4.229256E-06 -2.872177E-03 -4.544501E-06 -1.077428E-03 -9.288883E-07 -3.849908E-03 -1.266706E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -5.800000E-05 -4.954781E-03 -1.712892E-05 -4.126960E-03 -1.107068E-05 -2.518231E-03 -4.154059E-06 -4.819525E-03 -1.335200E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.076340E-04 -3.692191E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.000000E-03 -2.000000E-06 -6.612504E-04 -8.898055E-07 -3.347082E-04 -7.163327E-07 -8.531489E-04 -3.808616E-07 -1.190340E-03 -8.782273E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-03 -5.000000E-06 -4.625274E-04 -1.150077E-06 -5.123029E-04 -8.692268E-07 -8.248357E-04 -5.505055E-07 -1.198649E-03 -7.185180E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 --9.859558E-04 -9.721088E-07 -9.581632E-04 -9.180766E-07 --9.172070E-04 -8.412686E-07 -8.948321E-04 -4.416037E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +5.210818E-03 +1.357783E-05 +1.394382E-03 +9.898987E-07 +2.796067E-04 +6.984712E-07 +3.684681E-03 +7.605759E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2083,14 +243,14 @@ tally 1: 0.000000E+00 4.000000E-03 8.000000E-06 --2.701471E-04 -1.370723E-06 -6.964728E-04 -2.988117E-07 -8.616833E-04 -1.449401E-06 -1.494157E-03 -1.155142E-06 +1.019723E-03 +2.941013E-06 +3.796068E-04 +1.213513E-06 +6.991567E-04 +2.907192E-07 +2.133677E-03 +2.313409E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2121,16 +281,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -4.000000E-03 -1.600000E-05 -6.207788E-04 -3.853663E-07 -1.877009E-04 -3.523162E-08 -9.779406E-04 -9.563678E-07 -2.676187E-03 -4.648130E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2161,16 +311,266 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +3.200000E-05 +7.394988E-04 +4.098659E-07 +4.040769E-04 +3.143715E-07 +1.784935E-04 +3.163907E-07 +2.744646E-03 +3.801137E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.015373E-04 +3.618471E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +4.500000E-05 +4.871111E-03 +1.225810E-05 +2.381697E-03 +2.840243E-06 +2.498800E-03 +3.161161E-06 +3.656384E-03 +6.838240E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +5.000000E-06 +9.405302E-04 +8.589283E-07 +2.623590E-03 +3.990114E-06 +6.768145E-04 +3.652890E-07 +1.212507E-03 +9.103805E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.109694E-04 +1.866863E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +9.168648E-04 +8.406410E-07 +7.609615E-04 +5.790624E-07 +5.515881E-04 +3.042494E-07 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.200000E-02 +8.000000E-05 +6.636635E-03 +2.425315E-05 +4.338045E-03 +1.464490E-05 +3.621511E-03 +1.385488E-05 +7.040297E-03 +2.530812E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-02 +5.800000E-05 +1.624971E-03 +3.694766E-06 +1.160491E-03 +1.280447E-06 +-8.692024E-05 +3.035696E-06 +4.305083E-03 +1.106984E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.221939E-03 +7.467452E-07 +1.000000E-03 +1.000000E-06 +9.910929E-04 +9.822652E-07 +9.733978E-04 +9.475032E-07 +9.471508E-04 +8.970946E-07 +0.000000E+00 +0.000000E+00 2.000000E-03 4.000000E-06 -4.298228E-04 -1.847476E-07 -9.681780E-04 -9.373686E-07 -1.370924E-03 -1.879433E-06 -6.076340E-04 -3.692191E-07 +3.249184E-04 +1.055720E-07 +9.928009E-04 +9.856536E-07 +1.088489E-03 +1.184808E-06 +9.023059E-04 +8.141559E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2203,14 +603,1294 @@ tally 1: 0.000000E+00 1.000000E-03 1.000000E-06 -9.975034E-04 -9.950130E-07 -9.925195E-04 -9.850950E-07 -9.850671E-04 -9.703571E-07 -2.955076E-04 -8.732472E-08 +9.686373E-04 +9.382582E-07 +9.073874E-04 +8.233518E-07 +8.191239E-04 +6.709640E-07 +6.204016E-04 +3.848982E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.500000E-02 +1.530000E-04 +1.597072E-03 +3.005651E-06 +2.949088E-03 +4.679665E-06 +3.631393E-03 +7.090560E-06 +5.460996E-03 +1.769365E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.503843E-03 +2.261544E-06 +2.000000E-03 +4.000000E-06 +-1.555019E-04 +2.418085E-08 +-6.469952E-05 +4.186027E-09 +-1.256495E-04 +1.578779E-08 +2.462742E-03 +3.825930E-06 +2.000000E-03 +2.000000E-06 +1.802029E-03 +1.623906E-06 +1.435858E-03 +1.032682E-06 +9.559957E-04 +4.622600E-07 +0.000000E+00 +0.000000E+00 +1.400000E-02 +1.060000E-04 +3.845354E-03 +1.771893E-05 +7.969986E-04 +1.251583E-05 +2.663540E-03 +3.580311E-06 +7.322201E-03 +2.693121E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-02 +5.800000E-05 +7.529857E-03 +3.304826E-05 +4.385729E-03 +1.180121E-05 +2.219847E-03 +3.711400E-06 +4.549258E-03 +1.248547E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +5.000000E-06 +1.328181E-03 +8.967072E-07 +-4.616880E-04 +2.148940E-07 +-1.029769E-03 +5.645716E-07 +1.522708E-03 +1.199054E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.015373E-04 +3.618471E-07 +1.000000E-03 +1.000000E-06 +9.936377E-04 +9.873159E-07 +9.809739E-04 +9.623097E-07 +9.621293E-04 +9.256927E-07 +0.000000E+00 +0.000000E+00 +2.000000E-02 +2.000000E-04 +7.111929E-03 +2.528978E-05 +1.084601E-03 +1.073353E-06 +1.275976E-03 +2.215783E-06 +7.350498E-03 +2.790619E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.015373E-04 +3.618471E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.000000E-03 +2.500000E-05 +1.990597E-03 +2.484498E-06 +-4.860874E-04 +2.969876E-07 +6.661989E-04 +2.268944E-07 +4.577555E-03 +1.050456E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.015373E-04 +3.618471E-07 +1.000000E-03 +1.000000E-06 +9.615527E-04 +9.245836E-07 +8.868754E-04 +7.865479E-07 +7.802605E-04 +6.088065E-07 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +-3.730183E-04 +1.391426E-07 +-2.912860E-04 +8.484756E-08 +4.297706E-04 +1.847027E-07 +9.306024E-04 +8.660208E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +5.000000E-06 +2.287183E-03 +2.659902E-06 +1.571504E-03 +1.313687E-06 +1.459898E-03 +1.179754E-06 +9.117381E-04 +4.580716E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.200000E-02 +2.600000E-04 +6.732483E-03 +2.695948E-05 +5.717821E-03 +2.889220E-05 +-2.356418E-04 +7.546819E-07 +8.892069E-03 +4.212262E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +1.000000E-03 +1.000000E-06 +-7.961895E-04 +6.339178E-07 +4.508767E-04 +2.032898E-07 +-6.751245E-05 +4.557931E-09 +2.105380E-03 +4.432627E-06 +1.000000E-03 +1.000000E-06 +7.706275E-04 +5.938667E-07 +3.908001E-04 +1.527247E-07 +-1.181620E-05 +1.396226E-10 +0.000000E+00 +0.000000E+00 +1.300000E-02 +1.450000E-04 +5.254317E-03 +2.007625E-05 +1.153872E-03 +6.667482E-07 +1.643586E-03 +1.926972E-06 +5.733468E-03 +2.652835E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +6.100000E-05 +6.423451E-03 +2.063127E-05 +3.306770E-03 +5.779309E-06 +2.784620E-03 +3.970295E-06 +3.976017E-03 +7.971626E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.000000E-03 +8.000000E-06 +6.140550E-04 +1.773047E-06 +-1.620585E-04 +8.222999E-07 +1.423762E-03 +1.013556E-06 +1.832908E-03 +1.680177E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.500000E-02 +1.250000E-04 +4.942916E-03 +1.235885E-05 +1.021964E-03 +5.222106E-07 +9.236822E-04 +1.479238E-06 +7.322201E-03 +2.693121E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +1.000000E-03 +1.000000E-06 +5.742336E-04 +3.297442E-07 +-5.383652E-06 +2.898371E-11 +-3.879749E-04 +1.505245E-07 +3.007686E-04 +9.046177E-08 +1.000000E-03 +1.000000E-06 +9.585989E-04 +9.189118E-07 +8.783677E-04 +7.715298E-07 +7.642712E-04 +5.841105E-07 +3.007686E-04 +9.046177E-08 +1.300000E-02 +8.900000E-05 +5.419508E-03 +1.767227E-05 +2.993901E-03 +4.531596E-06 +2.675067E-03 +3.968688E-06 +5.780629E-03 +1.774150E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.221939E-03 +7.467452E-07 +2.000000E-03 +2.000000E-06 +1.775152E-03 +1.597527E-06 +1.396291E-03 +1.130413E-06 +9.794822E-04 +9.115176E-07 +0.000000E+00 +0.000000E+00 +8.000000E-03 +5.000000E-05 +2.406686E-03 +4.825540E-06 +4.960582E-04 +1.033420E-06 +1.240589E-03 +2.480639E-06 +5.226253E-03 +1.611788E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +9.405199E-04 +8.845778E-07 +8.268666E-04 +6.837084E-07 +6.691277E-04 +4.477318E-07 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +6.000000E-03 +2.600000E-05 +8.982135E-05 +2.560934E-07 +-7.114096E-04 +2.713326E-07 +8.252336E-04 +1.794332E-06 +2.716350E-03 +5.885778E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.300000E-02 +8.900000E-05 +6.195490E-03 +1.953479E-05 +2.111239E-03 +2.311139E-06 +2.268320E-03 +3.353244E-06 +5.808926E-03 +1.694986E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +4.100000E-05 +-8.217874E-04 +4.663323E-07 +7.383083E-04 +5.193896E-06 +8.200240E-04 +3.424935E-07 +3.976017E-03 +7.971626E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.000000E-03 +8.000000E-06 +2.748347E-03 +4.220881E-06 +2.045316E-03 +2.683544E-06 +2.280529E-03 +2.612273E-06 +6.015373E-04 +3.618471E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.306024E-04 +8.660208E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.306024E-04 +8.660208E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +6.000000E-03 +1.800000E-05 +2.626871E-03 +3.665081E-06 +1.681981E-03 +1.510257E-06 +1.862830E-03 +2.103749E-06 +2.735214E-03 +4.122645E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +6.500000E-05 +6.880553E-03 +2.448726E-05 +3.974657E-03 +9.611600E-06 +3.058908E-03 +1.181515E-05 +4.295650E-03 +1.005573E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.200000E-02 +7.200000E-05 +6.025175E-03 +1.856579E-05 +5.884402E-03 +2.141913E-05 +1.752856E-03 +2.842294E-06 +6.401031E-03 +2.082068E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.000000E-03 +1.700000E-05 +3.189581E-03 +6.250530E-06 +1.000837E-03 +5.036982E-07 +-3.117653E-04 +2.901990E-07 +2.754079E-03 +3.853002E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +-5.657444E-04 +3.200667E-07 +-1.989995E-05 +3.960081E-10 +3.959267E-04 +1.567580E-07 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +9.000000E-06 +1.797289E-03 +3.230248E-06 +7.121477E-04 +5.071544E-07 +4.492929E-04 +2.018641E-07 +1.551004E-03 +2.405613E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +6.500000E-05 +6.283851E-03 +1.995229E-05 +1.355416E-03 +1.756870E-06 +-4.317669E-04 +7.579610E-07 +4.267354E-03 +9.253637E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +9.682863E-04 +9.375784E-07 +9.063676E-04 +8.215023E-07 +8.171815E-04 +6.677855E-07 +6.204016E-04 +3.848982E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +1.640000E-04 +7.069243E-03 +2.506156E-05 +4.321329E-03 +1.796567E-05 +2.557673E-03 +3.894493E-06 +6.438760E-03 +2.205150E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.200000E-02 +7.200000E-05 +4.666186E-03 +1.284828E-05 +2.641891E-03 +1.762435E-05 +9.754238E-04 +2.039232E-06 +5.498725E-03 +1.512159E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.000000E-03 +8.000000E-06 +1.714892E-04 +9.981511E-07 +-4.305094E-04 +9.268480E-08 +-2.287903E-04 +5.786188E-08 +2.443878E-03 +2.986981E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +8.500000E-05 +4.472745E-03 +1.447325E-05 +6.072016E-04 +5.846134E-07 +9.336487E-04 +9.381432E-07 +5.169660E-03 +1.440996E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +3.400000E-05 +3.030014E-03 +1.297316E-05 +1.879812E-03 +5.805316E-06 +2.471474E-03 +4.341265E-06 +3.374480E-03 +6.162391E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.000000E-03 +2.900000E-05 +-7.617232E-05 +3.053607E-08 +1.791545E-04 +5.297145E-08 +1.386068E-03 +1.737839E-06 +3.054847E-03 +4.667158E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-03 +4.000000E-06 +1.083160E-03 +1.173236E-06 +-4.570050E-05 +2.088536E-09 +-6.290949E-04 +3.957604E-07 +6.204016E-04 +3.848982E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2243,14 +1923,14 @@ tally 1: 0.000000E+00 6.000000E-03 2.000000E-05 --2.695842E-04 -1.341496E-06 -1.562492E-03 -1.831644E-06 --7.471975E-04 -2.484564E-06 -2.388989E-03 -3.013861E-06 +2.716180E-03 +5.893679E-06 +1.554292E-03 +1.376524E-06 +7.264867E-04 +1.331497E-06 +3.045415E-03 +4.796216E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2281,16 +1961,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.000000E-03 -4.000000E-06 -1.468316E-03 -2.155952E-06 -6.405092E-04 -4.102520E-07 --1.375320E-04 -1.891505E-08 -1.198649E-03 -7.185180E-07 +7.000000E-03 +2.500000E-05 +9.648146E-04 +5.981145E-07 +4.634865E-05 +7.955048E-07 +-1.328560E-04 +3.379815E-07 +3.355616E-03 +5.662237E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2299,8 +1979,328 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.955076E-04 -8.732472E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +5.000000E-06 +1.289998E-03 +8.380263E-07 +-3.762753E-05 +1.288533E-07 +-2.613682E-04 +4.197617E-08 +1.221939E-03 +7.467452E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +8.500000E-05 +3.095504E-03 +7.078598E-06 +-9.175432E-04 +6.837255E-07 +-7.570383E-04 +4.237745E-07 +4.530394E-03 +1.567294E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +7.300000E-05 +3.067467E-03 +5.676919E-06 +2.403624E-03 +2.913670E-06 +1.402382E-03 +1.691430E-06 +5.216821E-03 +1.489979E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.007686E-04 +9.046177E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +5.000000E-06 +1.008832E-03 +8.754929E-07 +-8.318856E-04 +3.573666E-07 +-9.886180E-04 +7.790297E-07 +1.851773E-03 +2.496075E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +8.429685E-04 +7.105959E-07 +5.658938E-04 +3.202358E-07 +2.330721E-04 +5.432261E-08 +6.015373E-04 +3.618471E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +5.000000E-06 +1.596397E-03 +1.275630E-06 +4.822532E-04 +1.627925E-07 +2.983020E-04 +9.401537E-08 +1.221939E-03 +7.467452E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.204016E-04 +3.848982E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +9.000000E-06 +2.576209E-03 +6.636855E-06 +1.844839E-03 +3.403429E-06 +9.997002E-04 +9.994005E-07 +1.240803E-03 +1.539593E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.102008E-04 +9.622454E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2323,14 +2323,14 @@ tally 1: 0.000000E+00 1.000000E-03 1.000000E-06 -9.489856E-04 -9.005736E-07 -8.508605E-04 -7.239635E-07 -7.131001E-04 -5.085118E-07 -2.955076E-04 -8.732472E-08 +1.590395E-04 +2.529356E-08 +-4.620597E-04 +2.134991E-07 +-2.285026E-04 +5.221342E-08 +3.102008E-04 +9.622454E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -2402,11 +2402,11 @@ tally 1: 0.000000E+00 0.000000E+00 tally 2: -2.181843E-01 -2.381339E-02 -2.370439E-01 -2.810520E-02 -1.375356E+00 -9.460863E-01 -1.543948E+01 -1.192513E+02 +2.288800E-01 +2.621372E-02 +2.489848E-01 +3.102301E-02 +1.451035E+00 +1.053707E+00 +1.618797E+01 +1.311489E+02 diff --git a/tests/test_statepoint_restart/tallies.xml b/tests/test_statepoint_restart/tallies.xml index 1704f56e1e..67a1b50a94 100644 --- a/tests/test_statepoint_restart/tallies.xml +++ b/tests/test_statepoint_restart/tallies.xml @@ -2,7 +2,7 @@ - rectangular + regular 5 3 4 -10. -5. 0. 10. 4. 9. @@ -20,4 +20,4 @@ fission absorption total flux - \ No newline at end of file + diff --git a/tests/test_statepoint_restart/test_statepoint_restart.py b/tests/test_statepoint_restart/test_statepoint_restart.py index 0420dbddfa..59b77a8213 100644 --- a/tests/test_statepoint_restart/test_statepoint_restart.py +++ b/tests/test_statepoint_restart/test_statepoint_restart.py @@ -1,8 +1,12 @@ #!/usr/bin/env python +import glob +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness +from openmc.statepoint import StatePoint +from openmc.executor import Executor class StatepointRestartTestHarness(TestHarness): diff --git a/tests/test_statepoint_sourcesep/geometry.xml b/tests/test_statepoint_sourcesep/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_statepoint_sourcesep/geometry.xml +++ b/tests/test_statepoint_sourcesep/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_statepoint_sourcesep/results_true.dat b/tests/test_statepoint_sourcesep/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_statepoint_sourcesep/results_true.dat +++ b/tests/test_statepoint_sourcesep/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py b/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py index 861a04f189..00ded42ec2 100644 --- a/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py +++ b/tests/test_statepoint_sourcesep/test_statepoint_sourcesep.py @@ -1,8 +1,10 @@ #!/usr/bin/env python +import glob +import os import sys -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness class SourcepointTestHarness(TestHarness): @@ -12,9 +14,15 @@ 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.' + + def _cleanup(self): + TestHarness._cleanup(self) + output = glob.glob(os.path.join(os.getcwd(), 'source.*')) + for f in output: + if os.path.exists(f): + os.remove(f) if __name__ == '__main__': diff --git a/tests/test_survival_biasing/geometry.xml b/tests/test_survival_biasing/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_survival_biasing/geometry.xml +++ b/tests/test_survival_biasing/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_survival_biasing/results_true.dat b/tests/test_survival_biasing/results_true.dat index 0f3509e448..a97654cfa2 100644 --- a/tests/test_survival_biasing/results_true.dat +++ b/tests/test_survival_biasing/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.025211E+00 1.372397E-02 +9.997733E-01 2.995572E-02 diff --git a/tests/test_survival_biasing/test_survival_biasing.py b/tests/test_survival_biasing/test_survival_biasing.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_survival_biasing/test_survival_biasing.py +++ b/tests/test_survival_biasing/test_survival_biasing.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_tally_assumesep/geometry.xml b/tests/test_tally_assumesep/geometry.xml index b85dd04df9..f6f067aadd 100644 --- a/tests/test_tally_assumesep/geometry.xml +++ b/tests/test_tally_assumesep/geometry.xml @@ -21,50 +21,50 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + diff --git a/tests/test_tally_assumesep/results_true.dat b/tests/test_tally_assumesep/results_true.dat index a2f3586ae4..4835227f24 100644 --- a/tests/test_tally_assumesep/results_true.dat +++ b/tests/test_tally_assumesep/results_true.dat @@ -1,11 +1,11 @@ k-combined: -1.093844E+00 1.626801E-02 +1.005983E+00 2.248579E-02 tally 1: -1.517577E+01 -4.747271E+01 +1.423676E+01 +4.330937E+01 tally 2: -3.151504E+00 -2.051857E+00 +2.914798E+00 +1.831649E+00 tally 3: -4.536316E+01 -4.258781E+02 +4.088282E+01 +3.662539E+02 diff --git a/tests/test_tally_assumesep/test_tally_assumesep.py b/tests/test_tally_assumesep/test_tally_assumesep.py index 1777db993e..ed6addec45 100644 --- a/tests/test_tally_assumesep/test_tally_assumesep.py +++ b/tests/test_tally_assumesep/test_tally_assumesep.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_tally_nuclides/geometry.xml b/tests/test_tally_nuclides/geometry.xml index 65954a7853..7c3aefe888 100644 --- a/tests/test_tally_nuclides/geometry.xml +++ b/tests/test_tally_nuclides/geometry.xml @@ -4,7 +4,7 @@ - - + + diff --git a/tests/test_tally_nuclides/test_tally_nuclides.py b/tests/test_tally_nuclides/test_tally_nuclides.py index 1777db993e..ed6addec45 100644 --- a/tests/test_tally_nuclides/test_tally_nuclides.py +++ b/tests/test_tally_nuclides/test_tally_nuclides.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_trace/geometry.xml b/tests/test_trace/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_trace/geometry.xml +++ b/tests/test_trace/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_trace/results_true.dat b/tests/test_trace/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_trace/results_true.dat +++ b/tests/test_trace/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_trace/test_trace.py b/tests/test_trace/test_trace.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_trace/test_trace.py +++ b/tests/test_trace/test_trace.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_track_output/geometry.xml b/tests/test_track_output/geometry.xml index 3b5a493115..5b16fe26cd 100644 --- a/tests/test_track_output/geometry.xml +++ b/tests/test_track_output/geometry.xml @@ -15,22 +15,22 @@ - - + + - - - + + + - - + + - + @@ -56,7 +56,7 @@ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - + @@ -80,10 +80,10 @@ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - + + + + @@ -107,10 +107,10 @@ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - + + + + @@ -136,7 +136,7 @@ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - + @@ -160,10 +160,10 @@ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - + + + + @@ -187,10 +187,10 @@ 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - - - - + + + + @@ -214,10 +214,10 @@ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - + + + + @@ -242,10 +242,10 @@ 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - - - - + + + + @@ -269,10 +269,10 @@ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - + + + + @@ -299,7 +299,7 @@ - - + + diff --git a/tests/test_track_output/test_track_output.py b/tests/test_track_output/test_track_output.py index 31d29b7420..9e9ce87adb 100644 --- a/tests/test_track_output/test_track_output.py +++ b/tests/test_track_output/test_track_output.py @@ -1,10 +1,12 @@ #!/usr/bin/env python +import glob +import os +from subprocess import call import shutil import sys - -sys.path.insert(0, '..') -from testing_harness import * +sys.path.insert(0, os.pardir) +from testing_harness import TestHarness class TrackTestHarness(TestHarness): @@ -16,8 +18,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.""" diff --git a/tests/test_translation/geometry.xml b/tests/test_translation/geometry.xml index 1390691dcf..e2cdf23916 100644 --- a/tests/test_translation/geometry.xml +++ b/tests/test_translation/geometry.xml @@ -5,7 +5,7 @@ - - + + diff --git a/tests/test_translation/results_true.dat b/tests/test_translation/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_translation/results_true.dat +++ b/tests/test_translation/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_translation/test_translation.py b/tests/test_translation/test_translation.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_translation/test_translation.py +++ b/tests/test_translation/test_translation.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_trigger_batch_interval/geometry.xml b/tests/test_trigger_batch_interval/geometry.xml index 65954a7853..7c3aefe888 100644 --- a/tests/test_trigger_batch_interval/geometry.xml +++ b/tests/test_trigger_batch_interval/geometry.xml @@ -4,7 +4,7 @@ - - + + diff --git a/tests/test_trigger_batch_interval/results_true.dat b/tests/test_trigger_batch_interval/results_true.dat index 65fa51bb4f..c901e1e54d 100644 --- a/tests/test_trigger_batch_interval/results_true.dat +++ b/tests/test_trigger_batch_interval/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.851940E-01 4.283950E-03 +9.875001E-01 3.961945E-03 tally 1: -1.972289E+01 -2.779778E+01 -4.489781E+00 -1.440247E+00 -4.356175E+00 -1.355797E+00 -1.523311E+01 -1.658397E+01 -1.972289E+01 -2.779778E+01 -4.489781E+00 -1.440247E+00 -4.356175E+00 -1.355797E+00 -1.523311E+01 -1.658397E+01 +2.128147E+01 +3.021699E+01 +4.842434E+00 +1.563989E+00 +4.695086E+00 +1.470132E+00 +1.643904E+01 +1.803258E+01 +2.128147E+01 +3.021699E+01 +4.842434E+00 +1.563989E+00 +4.695086E+00 +1.470132E+00 +1.643904E+01 +1.803258E+01 tally 2: -1.972289E+01 -2.779778E+01 -4.489781E+00 -1.440247E+00 -4.356175E+00 -1.355797E+00 -1.523311E+01 -1.658397E+01 +2.128147E+01 +3.021699E+01 +4.842434E+00 +1.563989E+00 +4.695086E+00 +1.470132E+00 +1.643904E+01 +1.803258E+01 diff --git a/tests/test_trigger_batch_interval/settings.xml b/tests/test_trigger_batch_interval/settings.xml index d7afd9231d..b8e1e9c96a 100644 --- a/tests/test_trigger_batch_interval/settings.xml +++ b/tests/test_trigger_batch_interval/settings.xml @@ -1,15 +1,15 @@ - 10 + 15 5 1000 std_dev - 0.00445 + 0.004 - + true 30 diff --git a/tests/test_trigger_batch_interval/test_trigger_batch_interval.py b/tests/test_trigger_batch_interval/test_trigger_batch_interval.py index d5e176fea9..59b900e503 100644 --- a/tests/test_trigger_batch_interval/test_trigger_batch_interval.py +++ b/tests/test_trigger_batch_interval/test_trigger_batch_interval.py @@ -1,10 +1,11 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness if __name__ == '__main__': - harness = TestHarness('statepoint.19.*', True) + harness = TestHarness('statepoint.20.*', True) harness.main() diff --git a/tests/test_trigger_no_batch_interval/geometry.xml b/tests/test_trigger_no_batch_interval/geometry.xml index 65954a7853..7c3aefe888 100644 --- a/tests/test_trigger_no_batch_interval/geometry.xml +++ b/tests/test_trigger_no_batch_interval/geometry.xml @@ -4,7 +4,7 @@ - - + + diff --git a/tests/test_trigger_no_batch_interval/results_true.dat b/tests/test_trigger_no_batch_interval/results_true.dat index 65fa51bb4f..d06a91646c 100644 --- a/tests/test_trigger_no_batch_interval/results_true.dat +++ b/tests/test_trigger_no_batch_interval/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.851940E-01 4.283950E-03 +9.853099E-01 3.825057E-03 tally 1: -1.972289E+01 -2.779778E+01 -4.489781E+00 -1.440247E+00 -4.356175E+00 -1.355797E+00 -1.523311E+01 -1.658397E+01 -1.972289E+01 -2.779778E+01 -4.489781E+00 -1.440247E+00 -4.356175E+00 -1.355797E+00 -1.523311E+01 -1.658397E+01 +2.409492E+01 +3.417475E+01 +5.477076E+00 +1.765385E+00 +5.309347E+00 +1.658803E+00 +1.861784E+01 +2.040621E+01 +2.409492E+01 +3.417475E+01 +5.477076E+00 +1.765385E+00 +5.309347E+00 +1.658803E+00 +1.861784E+01 +2.040621E+01 tally 2: -1.972289E+01 -2.779778E+01 -4.489781E+00 -1.440247E+00 -4.356175E+00 -1.355797E+00 -1.523311E+01 -1.658397E+01 +2.409492E+01 +3.417475E+01 +5.477076E+00 +1.765385E+00 +5.309347E+00 +1.658803E+00 +1.861784E+01 +2.040621E+01 diff --git a/tests/test_trigger_no_batch_interval/settings.xml b/tests/test_trigger_no_batch_interval/settings.xml index 5ceff1082b..5412af35f9 100644 --- a/tests/test_trigger_no_batch_interval/settings.xml +++ b/tests/test_trigger_no_batch_interval/settings.xml @@ -1,15 +1,15 @@ - 10 + 15 5 1000 std_dev - 0.00445 + 0.004 - + true 30 diff --git a/tests/test_trigger_no_batch_interval/test_trigger_no_batch_interval.py b/tests/test_trigger_no_batch_interval/test_trigger_no_batch_interval.py index d5e176fea9..f9cb68d627 100644 --- a/tests/test_trigger_no_batch_interval/test_trigger_no_batch_interval.py +++ b/tests/test_trigger_no_batch_interval/test_trigger_no_batch_interval.py @@ -1,10 +1,11 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness if __name__ == '__main__': - harness = TestHarness('statepoint.19.*', True) + harness = TestHarness('statepoint.22.*', True) harness.main() diff --git a/tests/test_trigger_no_status/geometry.xml b/tests/test_trigger_no_status/geometry.xml index 65954a7853..7c3aefe888 100644 --- a/tests/test_trigger_no_status/geometry.xml +++ b/tests/test_trigger_no_status/geometry.xml @@ -4,7 +4,7 @@ - - + + diff --git a/tests/test_trigger_no_status/results_true.dat b/tests/test_trigger_no_status/results_true.dat index b9dc78dd03..0b541099b9 100644 --- a/tests/test_trigger_no_status/results_true.dat +++ b/tests/test_trigger_no_status/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.809303E-01 7.264435E-03 +9.906276E-01 1.800527E-03 tally 1: -7.031241E+00 -9.892232E+00 -1.599216E+00 -5.115987E-01 -1.550710E+00 -4.810241E-01 -5.432025E+00 -5.904811E+00 -7.031241E+00 -9.892232E+00 -1.599216E+00 -5.115987E-01 -1.550710E+00 -4.810241E-01 -5.432025E+00 -5.904811E+00 +7.043320E+00 +9.922203E+00 +1.610208E+00 +5.185662E-01 +1.564118E+00 +4.893096E-01 +5.433111E+00 +5.904259E+00 +7.043320E+00 +9.922203E+00 +1.610208E+00 +5.185662E-01 +1.564118E+00 +4.893096E-01 +5.433111E+00 +5.904259E+00 tally 2: -7.031241E+00 -9.892232E+00 -1.599216E+00 -5.115987E-01 -1.550710E+00 -4.810241E-01 -5.432025E+00 -5.904811E+00 +7.043320E+00 +9.922203E+00 +1.610208E+00 +5.185662E-01 +1.564118E+00 +4.893096E-01 +5.433111E+00 +5.904259E+00 diff --git a/tests/test_trigger_no_status/test_trigger_no_status.py b/tests/test_trigger_no_status/test_trigger_no_status.py index 1777db993e..ed6addec45 100644 --- a/tests/test_trigger_no_status/test_trigger_no_status.py +++ b/tests/test_trigger_no_status/test_trigger_no_status.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_trigger_tallies/geometry.xml b/tests/test_trigger_tallies/geometry.xml index 65954a7853..7c3aefe888 100644 --- a/tests/test_trigger_tallies/geometry.xml +++ b/tests/test_trigger_tallies/geometry.xml @@ -4,7 +4,7 @@ - - + + diff --git a/tests/test_trigger_tallies/results_true.dat b/tests/test_trigger_tallies/results_true.dat index 86b1c14d5c..0519260ddc 100644 --- a/tests/test_trigger_tallies/results_true.dat +++ b/tests/test_trigger_tallies/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.824135E-01 6.844127E-03 +9.875396E-01 4.095985E-03 tally 1: -1.408810E+01 -1.985836E+01 -3.199600E+00 -1.024050E+00 -3.102648E+00 -9.629173E-01 -1.088850E+01 -1.186391E+01 -1.408810E+01 -1.985836E+01 -3.199600E+00 -1.024050E+00 -3.102648E+00 -9.629173E-01 -1.088850E+01 -1.186391E+01 +1.415943E+01 +2.006888E+01 +3.225529E+00 +1.040975E+00 +3.128858E+00 +9.794019E-01 +1.093390E+01 +1.196901E+01 +1.415943E+01 +2.006888E+01 +3.225529E+00 +1.040975E+00 +3.128858E+00 +9.794019E-01 +1.093390E+01 +1.196901E+01 tally 2: -1.408810E+01 -1.985836E+01 -3.199600E+00 -1.024050E+00 -3.102648E+00 -9.629173E-01 -1.088850E+01 -1.186391E+01 +1.415943E+01 +2.006888E+01 +3.225529E+00 +1.040975E+00 +3.128858E+00 +9.794019E-01 +1.093390E+01 +1.196901E+01 diff --git a/tests/test_trigger_tallies/settings.xml b/tests/test_trigger_tallies/settings.xml index c6d986ce85..895c0ee72c 100644 --- a/tests/test_trigger_tallies/settings.xml +++ b/tests/test_trigger_tallies/settings.xml @@ -6,10 +6,10 @@ 1000 std_dev - 0.02 + 0.001 - + true 15 diff --git a/tests/test_trigger_tallies/test_trigger_tallies.py b/tests/test_trigger_tallies/test_trigger_tallies.py index 20094827e0..a0b2119dea 100644 --- a/tests/test_trigger_tallies/test_trigger_tallies.py +++ b/tests/test_trigger_tallies/test_trigger_tallies.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_uniform_fs/geometry.xml b/tests/test_uniform_fs/geometry.xml index b9b880d08a..90cf354614 100644 --- a/tests/test_uniform_fs/geometry.xml +++ b/tests/test_uniform_fs/geometry.xml @@ -8,6 +8,6 @@ - + diff --git a/tests/test_uniform_fs/results_true.dat b/tests/test_uniform_fs/results_true.dat index eb3d0e715e..a29a363b25 100644 --- a/tests/test_uniform_fs/results_true.dat +++ b/tests/test_uniform_fs/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.623468E-01 4.795863E-03 +3.546115E-01 2.982307E-03 diff --git a/tests/test_uniform_fs/test_uniform_fs.py b/tests/test_uniform_fs/test_uniform_fs.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_uniform_fs/test_uniform_fs.py +++ b/tests/test_uniform_fs/test_uniform_fs.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_union_energy_grids/geometry.xml b/tests/test_union_energy_grids/geometry.xml index 612e46132e..bc56030e18 100644 --- a/tests/test_union_energy_grids/geometry.xml +++ b/tests/test_union_energy_grids/geometry.xml @@ -3,6 +3,6 @@ - + diff --git a/tests/test_union_energy_grids/results_true.dat b/tests/test_union_energy_grids/results_true.dat index 05cda2e980..9556a981bc 100644 --- a/tests/test_union_energy_grids/results_true.dat +++ b/tests/test_union_energy_grids/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.215828E-01 2.966835E-03 +3.155788E-01 7.559348E-03 diff --git a/tests/test_union_energy_grids/test_union_energy_grids.py b/tests/test_union_energy_grids/test_union_energy_grids.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_union_energy_grids/test_union_energy_grids.py +++ b/tests/test_union_energy_grids/test_union_energy_grids.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_universe/geometry.xml b/tests/test_universe/geometry.xml index a0b8b2f4fc..03f507bec0 100644 --- a/tests/test_universe/geometry.xml +++ b/tests/test_universe/geometry.xml @@ -5,7 +5,7 @@ - - + + diff --git a/tests/test_universe/results_true.dat b/tests/test_universe/results_true.dat index f2dfdeca14..5263a6b7fd 100644 --- a/tests/test_universe/results_true.dat +++ b/tests/test_universe/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.011726E-01 1.841644E-03 +3.021779E-01 3.813358E-03 diff --git a/tests/test_universe/test_universe.py b/tests/test_universe/test_universe.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_universe/test_universe.py +++ b/tests/test_universe/test_universe.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/test_void/geometry.xml b/tests/test_void/geometry.xml index 99b78586a5..48a72c7c31 100644 --- a/tests/test_void/geometry.xml +++ b/tests/test_void/geometry.xml @@ -21,20 +21,20 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/tests/test_void/results_true.dat b/tests/test_void/results_true.dat index 921d07692f..4e99b86760 100644 --- a/tests/test_void/results_true.dat +++ b/tests/test_void/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.069802E+00 2.223092E-02 +1.045350E+00 2.750547E-02 diff --git a/tests/test_void/test_void.py b/tests/test_void/test_void.py index 6633e59111..2a595f3e66 100644 --- a/tests/test_void/test_void.py +++ b/tests/test_void/test_void.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +import os import sys -sys.path.insert(0, '..') +sys.path.insert(0, os.pardir) from testing_harness import TestHarness diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 9405db845c..ed89f76946 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -11,7 +11,8 @@ import sys import numpy as np -sys.path.insert(0, '../..') +sys.path.insert(0, os.path.join(os.pardir, os.pardir)) +from input_set import InputSet from openmc.statepoint import StatePoint from openmc.executor import Executor import openmc.particle_restart as pr @@ -82,9 +83,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.' @@ -94,7 +94,6 @@ class TestHarness(object): # Read the statepoint file. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Write out k-combined. outstr = 'k-combined:\n' @@ -104,11 +103,11 @@ class TestHarness(object): # Write out tally data. if self._tallies: tally_num = 1 - for tally_ind in sp._tallies: - tally = sp._tallies[tally_ind] - results = np.zeros((tally._sum.size*2, )) - results[0::2] = tally._sum.ravel() - results[1::2] = tally._sum_sq.ravel() + for tally_ind in sp.tallies: + tally = sp.tallies[tally_ind] + results = np.zeros((tally.sum.size*2, )) + results[0::2] = tally.sum.ravel() + results[1::2] = tally.sum_sq.ravel() results = ['{0:12.6E}'.format(x) for x in results] outstr += 'tally ' + str(tally_num) + ':\n' @@ -125,7 +124,7 @@ class TestHarness(object): def _write_results(self, results_string): """Write the results to an ASCII file.""" - with open('results_test.dat','w') as fh: + with open('results_test.dat', 'w') as fh: fh.write(results_string) def _overwrite_results(self): @@ -133,12 +132,14 @@ class TestHarness(object): shutil.copyfile('results_test.dat', 'results_true.dat') def _compare_results(self): + """Make sure the current results agree with the _true standard.""" compare = filecmp.cmp('results_test.dat', 'results_true.dat') if not compare: os.rename('results_test.dat', 'results_error.dat') assert compare, 'Results do not agree.' def _cleanup(self): + """Delete statepoints, tally, and test files.""" output = glob.glob(os.path.join(os.getcwd(), 'statepoint.*.*')) output.append(os.path.join(os.getcwd(), 'tallies.out')) output.append(os.path.join(os.getcwd(), 'results_test.dat')) @@ -155,7 +156,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,32 +200,31 @@ 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. statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] sp = StatePoint(statepoint) - sp.read_results() # Write out the eigenvalue and tallies. outstr = TestHarness._get_results(self) # Write out CMFD data. outstr += 'cmfd indices\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._cmfd_indices]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.cmfd_indices]) outstr += '\nk cmfd\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._k_cmfd]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.k_cmfd]) outstr += '\ncmfd entropy\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._cmfd_entropy]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.cmfd_entropy]) outstr += '\ncmfd balance\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._cmfd_balance]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.cmfd_balance]) outstr += '\ncmfd dominance ratio\n' - outstr += '\n'.join(['{0:10.3E}'.format(x) for x in sp._cmfd_dominance]) + outstr += '\n'.join(['{0:10.3E}'.format(x) for x in sp.cmfd_dominance]) outstr += '\ncmfd openmc source comparison\n' - outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp._cmfd_srccmp]) + outstr += '\n'.join(['{0:12.6E}'.format(x) for x in sp.cmfd_srccmp]) outstr += '\ncmfd source\n' - cmfdsrc = np.reshape(sp._cmfd_src, np.product(sp._cmfd_indices), + cmfdsrc = np.reshape(sp.cmfd_src, np.product(sp.cmfd_indices), order='F') outstr += '\n'.join(['{0:12.6E}'.format(x) for x in cmfdsrc]) outstr += '\n' @@ -233,15 +233,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.""" @@ -258,7 +257,7 @@ class ParticleRestartTestHarness(TestHarness): outstr += 'particle id:\n' outstr += "{0:12.6E}\n".format(p.id) outstr += 'run mode:\n' - outstr += "{0:12.6E}\n".format(p.run_mode) + outstr += "{0}\n".format(p.run_mode) outstr += 'particle weight:\n' outstr += "{0:12.6E}\n".format(p.weight) outstr += 'particle energy:\n' @@ -271,3 +270,89 @@ class ParticleRestartTestHarness(TestHarness): p.uvw[2]) return outstr + + +class PyAPITestHarness(TestHarness): + def __init__(self, statepoint_name, tallies_present=False): + TestHarness.__init__(self, statepoint_name, tallies_present) + self._input_set = InputSet() + + def execute_test(self): + """Build input XMLs, run OpenMC, and verify correct results.""" + try: + self._build_inputs() + inputs = self._get_inputs() + self._write_inputs(inputs) + self._compare_inputs() + self._run_openmc() + self._test_output_created() + results = self._get_results() + self._write_results(results) + self._compare_results() + finally: + self._cleanup() + + def update_results(self): + """Update results_true.dat and inputs_true.dat""" + try: + self._build_inputs() + inputs = self._get_inputs() + self._write_inputs(inputs) + self._overwrite_inputs() + self._run_openmc() + self._test_output_created() + results = self._get_results() + self._write_results(results) + self._overwrite_results() + finally: + self._cleanup() + + def _build_inputs(self): + """Write input XML files.""" + self._input_set.build_default_materials_and_geometry() + self._input_set.build_default_settings() + self._input_set.export() + + def _get_inputs(self): + """Return a hash digest of the input XML files.""" + xmls = ('geometry.xml', 'tallies.xml', 'materials.xml', 'settings.xml') + xmls = [os.path.join(os.getcwd(), fname) for fname in xmls] + outstr = '\n'.join([open(fname).read() for fname in xmls + if os.path.exists(fname)]) + + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + def _write_inputs(self, input_digest): + """Write the digest of the input XMLs to an ASCII file.""" + with open('inputs_test.dat', 'w') as fh: + fh.write(input_digest) + + def _overwrite_inputs(self): + """Overwrite inputs_true.dat with inputs_test.dat""" + shutil.copyfile('inputs_test.dat', 'inputs_true.dat') + + def _compare_inputs(self): + """Make sure the current inputs agree with the _true standard.""" + compare = filecmp.cmp('inputs_test.dat', 'inputs_true.dat') + if not compare: + f = open('inputs_test.dat') + for line in f.readlines(): print(line) + f.close() + os.rename('inputs_test.dat', 'inputs_error.dat') + assert compare, 'Input files are broken.' + + def _cleanup(self): + """Delete XMLs, statepoints, tally, and test files.""" + TestHarness._cleanup(self) + output = [os.path.join(os.getcwd(), 'materials.xml')] + output.append(os.path.join(os.getcwd(), 'geometry.xml')) + output.append(os.path.join(os.getcwd(), 'settings.xml')) + output.append(os.path.join(os.getcwd(), 'inputs_test.dat')) + output.append(os.path.join(os.getcwd(), 'summary.h5')) + for f in output: + if os.path.exists(f): + os.remove(f) diff --git a/tests/travis.sh b/tests/travis.sh index fac8d793a6..443e951cc9 100755 --- a/tests/travis.sh +++ b/tests/travis.sh @@ -5,7 +5,7 @@ set -ev # Run all debug tests ./check_source.py if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - ./run_tests.py -C "^basic-debug$|^hdf5-debug$|^mpi-omp-debug$|^phdf5-omp-debug$" -j 2 -s + ./run_tests.py -C "^hdf5-debug$|^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