mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 14:15:42 -04:00
Merge tag 'v0.7.1'
This commit is contained in:
commit
77237af16b
584 changed files with 38731 additions and 34225 deletions
13
.gitignore
vendored
13
.gitignore
vendored
|
|
@ -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
|
||||
.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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
249
CMakeLists.txt
249
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}
|
||||
|
|
|
|||
399
cmake/Modules/FindHDF5.cmake
Normal file
399
cmake/Modules/FindHDF5.cmake
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
#.rst:
|
||||
# FindHDF5
|
||||
# --------
|
||||
#
|
||||
# Find HDF5, a library for reading and writing self describing array data.
|
||||
#
|
||||
#
|
||||
#
|
||||
# This module invokes the HDF5 wrapper compiler that should be installed
|
||||
# alongside HDF5. Depending upon the HDF5 Configuration, the wrapper
|
||||
# compiler is called either h5cc or h5pcc. If this succeeds, the module
|
||||
# will then call the compiler with the -show argument to see what flags
|
||||
# are used when compiling an HDF5 client application.
|
||||
#
|
||||
# The module will optionally accept the COMPONENTS argument. If no
|
||||
# COMPONENTS are specified, then the find module will default to finding
|
||||
# only the HDF5 C library. If one or more COMPONENTS are specified, the
|
||||
# module will attempt to find the language bindings for the specified
|
||||
# components. The only valid components are C, CXX, Fortran, HL, and
|
||||
# Fortran_HL. If the COMPONENTS argument is not given, the module will
|
||||
# attempt to find only the C bindings.
|
||||
#
|
||||
# On UNIX systems, this module will read the variable
|
||||
# HDF5_USE_STATIC_LIBRARIES to determine whether or not to prefer a
|
||||
# static link to a dynamic link for HDF5 and all of it's dependencies.
|
||||
# To use this feature, make sure that the HDF5_USE_STATIC_LIBRARIES
|
||||
# variable is set before the call to find_package.
|
||||
#
|
||||
# To provide the module with a hint about where to find your HDF5
|
||||
# installation, you can set the environment variable HDF5_ROOT. The
|
||||
# Find module will then look in this path when searching for HDF5
|
||||
# executables, paths, and libraries.
|
||||
#
|
||||
# In addition to finding the includes and libraries required to compile
|
||||
# an HDF5 client application, this module also makes an effort to find
|
||||
# tools that come with the HDF5 distribution that may be useful for
|
||||
# regression testing.
|
||||
#
|
||||
# This module will define the following variables:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# HDF5_INCLUDE_DIRS - Location of the hdf5 includes
|
||||
# HDF5_INCLUDE_DIR - Location of the hdf5 includes (deprecated)
|
||||
# HDF5_DEFINITIONS - Required compiler definitions for HDF5
|
||||
# HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings.
|
||||
# HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings
|
||||
# HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings
|
||||
# HDF5_HL_LIBRARIES - Required libraries for the HDF5 high level API
|
||||
# HDF5_Fortran_HL_LIBRARIES - Required libraries for the high level Fortran
|
||||
# bindings.
|
||||
# HDF5_LIBRARIES - Required libraries for all requested bindings
|
||||
# HDF5_FOUND - true if HDF5 was found on the system
|
||||
# HDF5_VERSION - HDF5 version in format Major.Minor.Release
|
||||
# HDF5_LIBRARY_DIRS - the full set of library directories
|
||||
# HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support
|
||||
# HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler
|
||||
# HDF5_CXX_COMPILER_EXECUTABLE - the path to the HDF5 C++ wrapper compiler
|
||||
# HDF5_Fortran_COMPILER_EXECUTABLE - the path to the HDF5 Fortran wrapper compiler
|
||||
# HDF5_DIFF_EXECUTABLE - the path to the HDF5 dataset comparison tool
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2015 Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf
|
||||
# Copyright 2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
# This module is maintained by Will Dicharry <wdicharry@stellarscience.com>.
|
||||
|
||||
include(SelectLibraryConfigurations)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
# List of the valid HDF5 components
|
||||
set( HDF5_VALID_COMPONENTS
|
||||
C
|
||||
CXX
|
||||
Fortran
|
||||
HL
|
||||
Fortran_HL
|
||||
)
|
||||
|
||||
# Validate the list of find components.
|
||||
if( NOT HDF5_FIND_COMPONENTS )
|
||||
set( HDF5_LANGUAGE_BINDINGS "C" )
|
||||
else()
|
||||
# add the extra specified components, ensuring that they are valid.
|
||||
foreach( component ${HDF5_FIND_COMPONENTS} )
|
||||
list( FIND HDF5_VALID_COMPONENTS ${component} component_location )
|
||||
if( ${component_location} EQUAL -1 )
|
||||
message( FATAL_ERROR
|
||||
"\"${component}\" is not a valid HDF5 component." )
|
||||
else()
|
||||
list( APPEND HDF5_LANGUAGE_BINDINGS ${component} )
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Determine whether to search for serial or parallel executable first
|
||||
if(HDF5_PREFER_PARALLEL)
|
||||
set(HDF5_C_COMPILER_NAMES h5pcc h5cc)
|
||||
set(HDF5_CXX_COMPILER_NAMES h5pc++ h5c++)
|
||||
set(HDF5_Fortran_COMPILER_NAMES h5pfc h5fc)
|
||||
else()
|
||||
set(HDF5_C_COMPILER_NAMES h5cc h5pcc)
|
||||
set(HDF5_CXX_COMPILER_NAMES h5c++ h5pc++)
|
||||
set(HDF5_Fortran_COMPILER_NAMES h5fc h5pfc)
|
||||
endif()
|
||||
|
||||
# try to find the HDF5 wrapper compilers
|
||||
find_program( HDF5_C_COMPILER_EXECUTABLE
|
||||
NAMES ${HDF5_C_COMPILER_NAMES}
|
||||
HINTS ENV HDF5_ROOT
|
||||
PATH_SUFFIXES bin Bin
|
||||
DOC "HDF5 Wrapper compiler. Used only to detect HDF5 compile flags." )
|
||||
mark_as_advanced( HDF5_C_COMPILER_EXECUTABLE )
|
||||
|
||||
find_program( HDF5_CXX_COMPILER_EXECUTABLE
|
||||
NAMES ${HDF5_CXX_COMPILER_NAMES}
|
||||
HINTS ENV HDF5_ROOT
|
||||
PATH_SUFFIXES bin Bin
|
||||
DOC "HDF5 C++ Wrapper compiler. Used only to detect HDF5 compile flags." )
|
||||
mark_as_advanced( HDF5_CXX_COMPILER_EXECUTABLE )
|
||||
|
||||
find_program( HDF5_Fortran_COMPILER_EXECUTABLE
|
||||
NAMES ${HDF5_Fortran_COMPILER_NAMES}
|
||||
HINTS ENV HDF5_ROOT
|
||||
PATH_SUFFIXES bin Bin
|
||||
DOC "HDF5 Fortran Wrapper compiler. Used only to detect HDF5 compile flags." )
|
||||
mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE )
|
||||
|
||||
unset(HDF5_C_COMPILER_NAMES)
|
||||
unset(HDF5_CXX_COMPILER_NAMES)
|
||||
unset(HDF5_Fortran_COMPILER_NAMES)
|
||||
|
||||
find_program( HDF5_DIFF_EXECUTABLE
|
||||
NAMES h5diff
|
||||
HINTS ENV HDF5_ROOT
|
||||
PATH_SUFFIXES bin Bin
|
||||
DOC "HDF5 file differencing tool." )
|
||||
mark_as_advanced( HDF5_DIFF_EXECUTABLE )
|
||||
|
||||
# Invoke the HDF5 wrapper compiler. The compiler return value is stored to the
|
||||
# return_value argument, the text output is stored to the output variable.
|
||||
macro( _HDF5_invoke_compiler language output return_value )
|
||||
if( HDF5_${language}_COMPILER_EXECUTABLE )
|
||||
exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE}
|
||||
ARGS -show
|
||||
OUTPUT_VARIABLE ${output}
|
||||
RETURN_VALUE ${return_value}
|
||||
)
|
||||
if( ${${return_value}} EQUAL 0 )
|
||||
# do nothing
|
||||
else()
|
||||
message( STATUS
|
||||
"Unable to determine HDF5 ${language} flags from HDF5 wrapper." )
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Parse a compile line for definitions, includes, library paths, and libraries.
|
||||
macro( _HDF5_parse_compile_line
|
||||
compile_line_var
|
||||
include_paths
|
||||
definitions
|
||||
library_paths
|
||||
libraries )
|
||||
|
||||
# Match the include paths
|
||||
string( REGEX MATCHALL "-I([^\" ]+)" include_path_flags
|
||||
"${${compile_line_var}}"
|
||||
)
|
||||
foreach( IPATH ${include_path_flags} )
|
||||
string( REGEX REPLACE "^-I" "" IPATH ${IPATH} )
|
||||
string( REPLACE "//" "/" IPATH ${IPATH} )
|
||||
list( APPEND ${include_paths} ${IPATH} )
|
||||
endforeach()
|
||||
|
||||
# Match the definitions
|
||||
string( REGEX MATCHALL "-D[^ ]*" definition_flags "${${compile_line_var}}" )
|
||||
foreach( DEF ${definition_flags} )
|
||||
list( APPEND ${definitions} ${DEF} )
|
||||
endforeach()
|
||||
|
||||
# Match the library paths
|
||||
string( REGEX MATCHALL "-L([^\" ]+|\"[^\"]+\")" library_path_flags
|
||||
"${${compile_line_var}}"
|
||||
)
|
||||
|
||||
foreach( LPATH ${library_path_flags} )
|
||||
string( REGEX REPLACE "^-L" "" LPATH ${LPATH} )
|
||||
string( REPLACE "//" "/" LPATH ${LPATH} )
|
||||
list( APPEND ${library_paths} ${LPATH} )
|
||||
endforeach()
|
||||
|
||||
# now search for the library names specified in the compile line (match -l...)
|
||||
# match only -l's preceded by a space or comma
|
||||
# this is to exclude directory names like xxx-linux/
|
||||
string( REGEX MATCHALL "[, ]-l([^\", ]+)" library_name_flags
|
||||
"${${compile_line_var}}" )
|
||||
# strip the -l from all of the library flags and add to the search list
|
||||
foreach( LIB ${library_name_flags} )
|
||||
string( REGEX REPLACE "^[, ]-l" "" LIB ${LIB} )
|
||||
list( APPEND ${libraries} ${LIB} )
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Try to find HDF5 using an installed hdf5-config.cmake
|
||||
if( NOT HDF5_FOUND )
|
||||
find_package( HDF5 QUIET NO_MODULE )
|
||||
if( HDF5_FOUND )
|
||||
set( HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR} )
|
||||
set( HDF5_LIBRARIES )
|
||||
set( HDF5_C_TARGET hdf5 )
|
||||
set( HDF5_CXX_TARGET hdf5_cpp )
|
||||
set( HDF5_HL_TARGET hdf5_hl )
|
||||
set( HDF5_Fortran_TARGET hdf5_fortran )
|
||||
set( HDF5_Fortran_HL_TARGET hdf5_hl_fortran )
|
||||
foreach( _component ${HDF5_LANGUAGE_BINDINGS} )
|
||||
list( FIND HDF5_VALID_COMPONENTS ${_component} _component_location )
|
||||
get_target_property( _comp_location ${HDF5_${_component}_TARGET} LOCATION )
|
||||
if( _comp_location )
|
||||
set( HDF5_${_component}_LIBRARY ${_comp_location} CACHE PATH
|
||||
"HDF5 ${_component} library" )
|
||||
mark_as_advanced( HDF5_${_component}_LIBRARY )
|
||||
list( APPEND HDF5_LIBRARIES ${HDF5_${_component}_LIBRARY} )
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if( NOT HDF5_FOUND )
|
||||
_HDF5_invoke_compiler( C HDF5_C_COMPILE_LINE HDF5_C_RETURN_VALUE )
|
||||
_HDF5_invoke_compiler( CXX HDF5_CXX_COMPILE_LINE HDF5_CXX_RETURN_VALUE )
|
||||
_HDF5_invoke_compiler( Fortran HDF5_Fortran_COMPILE_LINE HDF5_Fortran_RETURN_VALUE )
|
||||
set(HDF5_HL_COMPILE_LINE ${HDF5_C_COMPILE_LINE})
|
||||
set(HDF5_Fortran_HL_COMPILE_LINE ${HDF5_Fortran_COMPILE_LINE})
|
||||
|
||||
# seed the initial lists of libraries to find with items we know we need
|
||||
set( HDF5_C_LIBRARY_NAMES_INIT hdf5 )
|
||||
set( HDF5_HL_LIBRARY_NAMES_INIT hdf5_hl ${HDF5_C_LIBRARY_NAMES_INIT} )
|
||||
set( HDF5_CXX_LIBRARY_NAMES_INIT hdf5_cpp ${HDF5_C_LIBRARY_NAMES_INIT} )
|
||||
set( HDF5_Fortran_LIBRARY_NAMES_INIT hdf5_fortran
|
||||
${HDF5_C_LIBRARY_NAMES_INIT} )
|
||||
set( HDF5_Fortran_HL_LIBRARY_NAMES_INIT hdf5hl_fortran hdf5_hl
|
||||
${HDF5_Fortran_LIBRARY_NAMES_INIT} )
|
||||
|
||||
foreach( LANGUAGE ${HDF5_LANGUAGE_BINDINGS} )
|
||||
if( HDF5_${LANGUAGE}_COMPILE_LINE )
|
||||
_HDF5_parse_compile_line( HDF5_${LANGUAGE}_COMPILE_LINE
|
||||
HDF5_${LANGUAGE}_INCLUDE_FLAGS
|
||||
HDF5_${LANGUAGE}_DEFINITIONS
|
||||
HDF5_${LANGUAGE}_LIBRARY_DIRS
|
||||
HDF5_${LANGUAGE}_LIBRARY_NAMES
|
||||
)
|
||||
|
||||
# take a guess that the includes may be in the 'include' sibling
|
||||
# directory of a library directory.
|
||||
foreach( dir ${HDF5_${LANGUAGE}_LIBRARY_DIRS} )
|
||||
list( APPEND HDF5_${LANGUAGE}_INCLUDE_FLAGS ${dir}/../include )
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# set the definitions for the language bindings.
|
||||
list( APPEND HDF5_DEFINITIONS ${HDF5_${LANGUAGE}_DEFINITIONS} )
|
||||
|
||||
# find the HDF5 include directories
|
||||
if(${LANGUAGE} MATCHES "Fortran")
|
||||
set(HDF5_INCLUDE_FILENAME hdf5.mod)
|
||||
else()
|
||||
set(HDF5_INCLUDE_FILENAME hdf5.h)
|
||||
endif()
|
||||
|
||||
find_path( HDF5_${LANGUAGE}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME}
|
||||
HINTS
|
||||
${HDF5_${LANGUAGE}_INCLUDE_FLAGS}
|
||||
ENV
|
||||
HDF5_ROOT
|
||||
PATHS
|
||||
$ENV{HOME}/.local/include
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
Include
|
||||
)
|
||||
mark_as_advanced( HDF5_${LANGUAGE}_INCLUDE_DIR )
|
||||
list( APPEND HDF5_INCLUDE_DIRS ${HDF5_${LANGUAGE}_INCLUDE_DIR} )
|
||||
|
||||
# find the HDF5 libraries
|
||||
foreach( LIB ${HDF5_${LANGUAGE}_LIBRARY_NAMES_INIT} )
|
||||
if( UNIX AND HDF5_USE_STATIC_LIBRARIES )
|
||||
# According to bug 1643 on the CMake bug tracker, this is the
|
||||
# preferred method for searching for a static library.
|
||||
# See http://www.cmake.org/Bug/view.php?id=1643. We search
|
||||
# first for the full static library name, but fall back to a
|
||||
# generic search on the name if the static search fails.
|
||||
set( THIS_LIBRARY_SEARCH_DEBUG lib${LIB}d.a ${LIB}d )
|
||||
set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a ${LIB} )
|
||||
else()
|
||||
set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d )
|
||||
set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} )
|
||||
endif()
|
||||
find_library( HDF5_${LIB}_LIBRARY_DEBUG
|
||||
NAMES ${THIS_LIBRARY_SEARCH_DEBUG}
|
||||
HINTS ${HDF5_${LANGUAGE}_LIBRARY_DIRS}
|
||||
ENV HDF5_ROOT
|
||||
PATH_SUFFIXES lib Lib )
|
||||
find_library( HDF5_${LIB}_LIBRARY_RELEASE
|
||||
NAMES ${THIS_LIBRARY_SEARCH_RELEASE}
|
||||
HINTS ${HDF5_${LANGUAGE}_LIBRARY_DIRS}
|
||||
ENV HDF5_ROOT
|
||||
PATH_SUFFIXES lib Lib )
|
||||
select_library_configurations( HDF5_${LIB} )
|
||||
list(APPEND HDF5_${LANGUAGE}_LIBRARIES ${HDF5_${LIB}_LIBRARY})
|
||||
endforeach()
|
||||
list( APPEND HDF5_LIBRARY_DIRS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} )
|
||||
|
||||
# When the wrapper lists a library with -l, e.g. -lz, simply use it as
|
||||
# is. If find_library is called for these libraries, you end up with
|
||||
# local libraries that will not be suitable when cross-compiling for the
|
||||
# Intel Xeon Phi.
|
||||
foreach(LIBNAME ${HDF5_${LANGUAGE}_LIBRARY_NAMES})
|
||||
list(APPEND HDF5_${LANGUAGE}_LIBRARIES "-l${LIBNAME}")
|
||||
endforeach()
|
||||
|
||||
# Append the libraries for this language binding to the list of all
|
||||
# required libraries.
|
||||
list(APPEND HDF5_LIBRARIES ${HDF5_${LANGUAGE}_LIBRARIES})
|
||||
endforeach()
|
||||
|
||||
# We may have picked up some duplicates in various lists during the above
|
||||
# process for the language bindings (both the C and C++ bindings depend on
|
||||
# libz for example). Remove the duplicates. It appears that the default
|
||||
# CMake behavior is to remove duplicates from the end of a list. However,
|
||||
# for link lines, this is incorrect since unresolved symbols are searched
|
||||
# for down the link line. Therefore, we reverse the list, remove the
|
||||
# duplicates, and then reverse it again to get the duplicates removed from
|
||||
# the beginning.
|
||||
macro( _remove_duplicates_from_beginning _list_name )
|
||||
list( REVERSE ${_list_name} )
|
||||
list( REMOVE_DUPLICATES ${_list_name} )
|
||||
list( REVERSE ${_list_name} )
|
||||
endmacro()
|
||||
|
||||
if( HDF5_INCLUDE_DIRS )
|
||||
_remove_duplicates_from_beginning( HDF5_INCLUDE_DIRS )
|
||||
endif()
|
||||
if( HDF5_LIBRARY_DIRS )
|
||||
_remove_duplicates_from_beginning( HDF5_LIBRARY_DIRS )
|
||||
endif()
|
||||
|
||||
# If the HDF5 include directory was found, open H5pubconf.h to determine if
|
||||
# HDF5 was compiled with parallel IO support
|
||||
set( HDF5_IS_PARALLEL FALSE )
|
||||
set( HDF5_VERSION "" )
|
||||
foreach( _dir IN LISTS HDF5_INCLUDE_DIRS )
|
||||
foreach(_hdr "${_dir}/H5pubconf.h" "${_dir}/H5pubconf-64.h" "${_dir}/H5pubconf-32.h")
|
||||
if( EXISTS "${_hdr}" )
|
||||
file( STRINGS "${_hdr}"
|
||||
HDF5_HAVE_PARALLEL_DEFINE
|
||||
REGEX "HAVE_PARALLEL 1" )
|
||||
if( HDF5_HAVE_PARALLEL_DEFINE )
|
||||
set( HDF5_IS_PARALLEL TRUE )
|
||||
endif()
|
||||
unset(HDF5_HAVE_PARALLEL_DEFINE)
|
||||
|
||||
file( STRINGS "${_hdr}"
|
||||
HDF5_VERSION_DEFINE
|
||||
REGEX "^[ \t]*#[ \t]*define[ \t]+H5_VERSION[ \t]+" )
|
||||
if( "${HDF5_VERSION_DEFINE}" MATCHES
|
||||
"H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+).*\"" )
|
||||
set( HDF5_VERSION "${CMAKE_MATCH_1}" )
|
||||
endif()
|
||||
unset(HDF5_VERSION_DEFINE)
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL
|
||||
"HDF5 library compiled with parallel IO support" )
|
||||
mark_as_advanced( HDF5_IS_PARALLEL )
|
||||
|
||||
# For backwards compatibility we set HDF5_INCLUDE_DIR to the value of
|
||||
# HDF5_INCLUDE_DIRS
|
||||
if( HDF5_INCLUDE_DIRS )
|
||||
set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" )
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args( HDF5
|
||||
REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS
|
||||
VERSION_VAR HDF5_VERSION
|
||||
)
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,4 @@ as debugging.
|
|||
styleguide
|
||||
workflow
|
||||
xml-parsing
|
||||
statepoint
|
||||
voxel
|
||||
docbuild
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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**,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
------------
|
||||
|
|
|
|||
|
|
@ -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). `<http://dx.doi.org/j.pnucene.2014.12.018>`_
|
||||
|
||||
- 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). `<http://dx.doi.org/10.1016/j.anucene/2014.10.029>`_
|
||||
|
||||
- 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). `<http://dx.doi.org/10.1016/j.anucene.2014.10.029>`_
|
||||
|
||||
- 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). `<http://dx.doi.org/10.1016/jcp.2015.08.013>`_
|
||||
|
||||
- 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). `<http://dx.doi.org/10.1080/00223131.2015.1035353>`_
|
||||
|
||||
- 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). `<http://dx.doi.org/10.1016/j.cpc.2015.05.025>`_
|
||||
|
||||
- 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). `<http://dx.doi.org/10.1016/j.anucene.2014.08.046>`_
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
8
docs/source/pythonapi/energy_groups.rst
Normal file
8
docs/source/pythonapi/energy_groups.rst
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
.. _pythonapi_energy_groups:
|
||||
|
||||
=============
|
||||
Energy Groups
|
||||
=============
|
||||
|
||||
.. automodule:: openmc.mgxs.groups
|
||||
:members:
|
||||
BIN
docs/source/pythonapi/examples/images/mgxs.png
Normal file
BIN
docs/source/pythonapi/examples/images/mgxs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
1195
docs/source/pythonapi/examples/mgxs-part-i.ipynb
Normal file
1195
docs/source/pythonapi/examples/mgxs-part-i.ipynb
Normal file
File diff suppressed because one or more lines are too long
13
docs/source/pythonapi/examples/mgxs-part-i.rst
Normal file
13
docs/source/pythonapi/examples/mgxs-part-i.rst
Normal file
|
|
@ -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.
|
||||
1947
docs/source/pythonapi/examples/mgxs-part-ii.ipynb
Normal file
1947
docs/source/pythonapi/examples/mgxs-part-ii.ipynb
Normal file
File diff suppressed because one or more lines are too long
13
docs/source/pythonapi/examples/mgxs-part-ii.rst
Normal file
13
docs/source/pythonapi/examples/mgxs-part-ii.rst
Normal file
|
|
@ -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.
|
||||
1653
docs/source/pythonapi/examples/mgxs-part-iii.ipynb
Normal file
1653
docs/source/pythonapi/examples/mgxs-part-iii.ipynb
Normal file
File diff suppressed because one or more lines are too long
13
docs/source/pythonapi/examples/mgxs-part-iii.rst
Normal file
13
docs/source/pythonapi/examples/mgxs-part-iii.rst
Normal file
|
|
@ -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.
|
||||
File diff suppressed because one or more lines are too long
1134
docs/source/pythonapi/examples/post-processing.ipynb
Normal file
1134
docs/source/pythonapi/examples/post-processing.ipynb
Normal file
File diff suppressed because one or more lines are too long
13
docs/source/pythonapi/examples/post-processing.rst
Normal file
13
docs/source/pythonapi/examples/post-processing.rst
Normal file
|
|
@ -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.
|
||||
|
|
@ -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": [
|
||||
"<IPython.core.display.Image object>"
|
||||
]
|
||||
|
|
@ -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 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(nu-fission / absorption)</td>\n",
|
||||
" <td>1.042726</td>\n",
|
||||
" <td>0.008661</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> (nu-fission / absorption)</td>\n",
|
||||
" <td> 1.040687</td>\n",
|
||||
" <td> 0.010913</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"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 @@
|
|||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>energy [MeV]</th>\n",
|
||||
" <th>nuclide</th>\n",
|
||||
" <th>score</th>\n",
|
||||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>absorption</td>\n",
|
||||
" <td>0.958874</td>\n",
|
||||
" <td>0.007146</td>\n",
|
||||
" <td> (0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> absorption</td>\n",
|
||||
" <td> 0.959302</td>\n",
|
||||
" <td> 0.010033</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"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 @@
|
|||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>energy [MeV]</th>\n",
|
||||
" <th>nuclide</th>\n",
|
||||
" <th>score</th>\n",
|
||||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>1.09186</td>\n",
|
||||
" <td>0.010424</td>\n",
|
||||
" <td> (0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> nu-fission</td>\n",
|
||||
" <td> 1.09103</td>\n",
|
||||
" <td> 0.012491</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"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 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>0.0e+00 - 6.2e-01</td>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>absorption</td>\n",
|
||||
" <td>0.802921</td>\n",
|
||||
" <td>0.006109</td>\n",
|
||||
" <td> (0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> absorption</td>\n",
|
||||
" <td> 0.803182</td>\n",
|
||||
" <td> 0.008664</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\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 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>0.0e+00 - 6.2e-01</td>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(nu-fission / absorption)</td>\n",
|
||||
" <td>1.240421</td>\n",
|
||||
" <td>0.010978</td>\n",
|
||||
" <td> (0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> (nu-fission / absorption)</td>\n",
|
||||
" <td> 1.237982</td>\n",
|
||||
" <td> 0.014179</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\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 @@
|
|||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>energy [MeV]</th>\n",
|
||||
" <th>cell</th>\n",
|
||||
" <th>nuclide</th>\n",
|
||||
" <th>score</th>\n",
|
||||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(((absorption * nu-fission) * absorption) * (n...</td>\n",
|
||||
" <td>1.042726</td>\n",
|
||||
" <td>0.017538</td>\n",
|
||||
" <td> (0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> (((absorption * nu-fission) * absorption) * (n...</td>\n",
|
||||
" <td> 1.040687</td>\n",
|
||||
" <td> 0.022989</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"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 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(U-238 / total)</td>\n",
|
||||
" <td>(nu-fission / flux)</td>\n",
|
||||
" <td>0.000001</td>\n",
|
||||
" <td>6.985151e-09</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td> (U-238 / total)</td>\n",
|
||||
" <td> (nu-fission / flux)</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> 8.078651e-09</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(U-238 / total)</td>\n",
|
||||
" <td>(scatter / flux)</td>\n",
|
||||
" <td>0.209988</td>\n",
|
||||
" <td>2.206753e-03</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td> (U-238 / total)</td>\n",
|
||||
" <td> (scatter / flux)</td>\n",
|
||||
" <td> 0.209990</td>\n",
|
||||
" <td> 2.449396e-03</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(U-235 / total)</td>\n",
|
||||
" <td>(nu-fission / flux)</td>\n",
|
||||
" <td>0.355276</td>\n",
|
||||
" <td>3.741612e-03</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td> (U-235 / total)</td>\n",
|
||||
" <td> (nu-fission / flux)</td>\n",
|
||||
" <td> 0.356117</td>\n",
|
||||
" <td> 4.364366e-03</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(U-235 / total)</td>\n",
|
||||
" <td>(scatter / flux)</td>\n",
|
||||
" <td>0.005555</td>\n",
|
||||
" <td>5.842517e-05</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td> (U-235 / total)</td>\n",
|
||||
" <td> (scatter / flux)</td>\n",
|
||||
" <td> 0.005555</td>\n",
|
||||
" <td> 6.495710e-05</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>4</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(U-238 / total)</td>\n",
|
||||
" <td>(nu-fission / flux)</td>\n",
|
||||
" <td>0.007229</td>\n",
|
||||
" <td>5.951357e-05</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td> (U-238 / total)</td>\n",
|
||||
" <td> (nu-fission / flux)</td>\n",
|
||||
" <td> 0.007190</td>\n",
|
||||
" <td> 7.596666e-05</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>5</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(U-238 / total)</td>\n",
|
||||
" <td>(scatter / flux)</td>\n",
|
||||
" <td>0.227642</td>\n",
|
||||
" <td>9.496469e-04</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td> (U-238 / total)</td>\n",
|
||||
" <td> (scatter / flux)</td>\n",
|
||||
" <td> 0.227843</td>\n",
|
||||
" <td> 1.024510e-03</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>6</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(U-235 / total)</td>\n",
|
||||
" <td>(nu-fission / flux)</td>\n",
|
||||
" <td>0.008076</td>\n",
|
||||
" <td>5.699123e-05</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td> (U-235 / total)</td>\n",
|
||||
" <td> (nu-fission / flux)</td>\n",
|
||||
" <td> 0.008086</td>\n",
|
||||
" <td> 6.251590e-05</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>7</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(U-235 / total)</td>\n",
|
||||
" <td>(scatter / flux)</td>\n",
|
||||
" <td>0.003369</td>\n",
|
||||
" <td>1.369755e-05</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td> (U-235 / total)</td>\n",
|
||||
" <td> (scatter / flux)</td>\n",
|
||||
" <td> 0.003365</td>\n",
|
||||
" <td> 1.646663e-05</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"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 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>U-238</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>0.000002</td>\n",
|
||||
" <td>1.211808e-08</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td> U-238</td>\n",
|
||||
" <td> nu-fission</td>\n",
|
||||
" <td> 0.000002</td>\n",
|
||||
" <td> 1.450189e-08</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>U-235</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>0.870360</td>\n",
|
||||
" <td>6.496431e-03</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td> U-235</td>\n",
|
||||
" <td> nu-fission</td>\n",
|
||||
" <td> 0.870882</td>\n",
|
||||
" <td> 7.895515e-03</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>U-238</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>0.083226</td>\n",
|
||||
" <td>6.367951e-04</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td> U-238</td>\n",
|
||||
" <td> nu-fission</td>\n",
|
||||
" <td> 0.082484</td>\n",
|
||||
" <td> 8.253437e-04</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>U-235</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>0.092974</td>\n",
|
||||
" <td>5.921990e-04</td>\n",
|
||||
" <td> 10000</td>\n",
|
||||
" <td> (6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td> U-235</td>\n",
|
||||
" <td> nu-fission</td>\n",
|
||||
" <td> 0.092762</td>\n",
|
||||
" <td> 6.444580e-04</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"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 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.0e-08 - 1.1e-07</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>4.638428</td>\n",
|
||||
" <td>0.034134</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.0e-08 - 1.1e-07)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 4.630154</td>\n",
|
||||
" <td> 0.044512</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.1e-07 - 1.2e-06</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>2.050818</td>\n",
|
||||
" <td>0.010745</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.1e-07 - 1.2e-06)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 2.042984</td>\n",
|
||||
" <td> 0.011429</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.2e-06 - 1.3e-05</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>1.656905</td>\n",
|
||||
" <td>0.009480</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.2e-06 - 1.3e-05)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 1.657517</td>\n",
|
||||
" <td> 0.008617</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.3e-05 - 1.4e-04</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>1.870808</td>\n",
|
||||
" <td>0.011883</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.3e-05 - 1.4e-04)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 1.863326</td>\n",
|
||||
" <td> 0.008848</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>4</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.4e-04 - 1.5e-03</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>2.045621</td>\n",
|
||||
" <td>0.011414</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.4e-04 - 1.5e-03)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 2.043916</td>\n",
|
||||
" <td> 0.014195</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>5</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.5e-03 - 1.6e-02</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>2.163297</td>\n",
|
||||
" <td>0.008725</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.5e-03 - 1.6e-02)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 2.134458</td>\n",
|
||||
" <td> 0.007561</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>6</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.6e-02 - 1.7e-01</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>2.202045</td>\n",
|
||||
" <td>0.013500</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.6e-02 - 1.7e-01)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 2.209947</td>\n",
|
||||
" <td> 0.013848</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>7</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.7e-01 - 1.9e+00</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>1.996977</td>\n",
|
||||
" <td>0.010791</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.7e-01 - 1.9e+00)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 2.006967</td>\n",
|
||||
" <td> 0.009368</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>8</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.9e+00 - 2.0e+01</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>0.370890</td>\n",
|
||||
" <td>0.003597</td>\n",
|
||||
" <td> 10002</td>\n",
|
||||
" <td> (1.9e+00 - 2.0e+01)</td>\n",
|
||||
" <td> H-1</td>\n",
|
||||
" <td> scatter</td>\n",
|
||||
" <td> 0.373895</td>\n",
|
||||
" <td> 0.002964</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"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,
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
66
docs/source/pythonapi/mgxs.rst
Normal file
66
docs/source/pythonapi/mgxs.rst
Normal file
|
|
@ -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:
|
||||
8
docs/source/pythonapi/mgxs_library.rst
Normal file
8
docs/source/pythonapi/mgxs_library.rst
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
.. _pythonapi_mgxs_library:
|
||||
|
||||
============
|
||||
MGXS Library
|
||||
============
|
||||
|
||||
.. automodule:: openmc.mgxs.library
|
||||
:members:
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <wbinventor@gmail.com>`_
|
||||
- `Matt Ellis <mellis13@mit.edu>`_
|
||||
- `Sterling Harper <sterlingmharper@mit.edu>`_
|
||||
- `Bryan Herman <bherman@mit.edu>`_
|
||||
- `Nicholas Horelik <nicholas.horelik@gmail.com>`_
|
||||
- `Bryan Herman <hermab53@gmail.com>`_
|
||||
- `Colin Josey <cjosey@mit.edu>`_
|
||||
- `William Lyu <PaleNeutron@users.noreply.github.com>`_
|
||||
- `Adam Nelson <nelsonag@umich.edu>`_
|
||||
- `Paul Romano <paul.k.romano@gmail.com>`_
|
||||
- `Anthony Scopatz <scopatz@gmail.com>`_
|
||||
- `Kelly Rowland <kellylynnerowland@gmail.com>`_
|
||||
- `Sam Shaner <samuelshaner@gmail.com>`_
|
||||
- `Jon Walsh <walshjon@mit.edu>`_
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
|||
<id>1</id>
|
||||
<universe>0</universe>
|
||||
<material>1</material>
|
||||
<surfaces>-1</surfaces>
|
||||
<region>-1</region>
|
||||
</cell>
|
||||
</geometry>
|
||||
|
||||
|
|
@ -764,7 +762,7 @@ could be written as:
|
|||
<!-- This is a comment -->
|
||||
|
||||
<surface id="1" type="sphere" coeffs="0.0 0.0 0.0 5.0" boundary="vacuum" />
|
||||
<cell id="1" universe="0" material="1" surfaces="-1" />
|
||||
<cell id="1" universe="0" material="1" region="-1" />
|
||||
|
||||
</geometry>
|
||||
|
||||
|
|
@ -788,7 +786,8 @@ Each ``<surface>`` 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`".
|
||||
|
||||
|
||||
``<cell>`` Element
|
||||
------------------
|
||||
|
||||
|
|
@ -892,15 +897,29 @@ Each ``<cell>`` 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
|
||||
|
||||
<cell id="1" material="1" region="-3 | ~(5 -2)" />
|
||||
|
||||
.. 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 ``<nuclide>`` and
|
||||
``<element>`` 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 ``<tally>`` 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 ``<tally>`` 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
|
||||
``<filter type="energy" bins="0.0 1.0 20.0" />``, 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
|
||||
|
||||
<filter type="energy" bins="0.0 1.0 20.0" />
|
||||
|
||||
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 ``<filter type="energyout" bins="0.0 1.0 20.0" />``, then
|
||||
two post-collision energy bins will be created, one with energies
|
||||
specified as
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<filter type="energyout" bins="0.0 1.0 20.0" />
|
||||
|
||||
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
|
||||
|
||||
<filter type="mu" bins="-1.0 -0.6 -0.2 0.2 0.6 1.0" />
|
||||
|
||||
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
|
||||
|
||||
<filter type="mu" bins="5" />
|
||||
|
||||
: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
|
||||
|
||||
<filter type="polar" bins="0.0 0.6283 1.2566 1.8850 2.5132 3.1416"/>
|
||||
|
||||
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
|
||||
|
||||
<filter type="polar" bins="5" />
|
||||
|
||||
: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
|
||||
|
||||
<filter type="azimuthal" bins="0.0 3.1416 6.2832" />
|
||||
|
||||
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
|
||||
|
||||
<filter type="azimuthal" bins="2" />
|
||||
|
||||
:mesh:
|
||||
The ``id`` of a structured mesh to be tallied over.
|
||||
|
||||
|
|
@ -1263,6 +1373,15 @@ The ``<tally>`` 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
|
||||
|
||||
<filter type="delayedgroup" bins="1 2 3 4 5 6" />
|
||||
|
||||
: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 ``<tally>`` 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 ``<tally>`` 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 ``<tally>`` 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 ``<mesh>``. 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
-------------
|
||||
|
||||
|
|
|
|||
16
docs/source/usersguide/output/index.rst
Normal file
16
docs/source/usersguide/output/index.rst
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
.. _usersguide_output:
|
||||
|
||||
===================
|
||||
Output File Formats
|
||||
===================
|
||||
|
||||
.. toctree::
|
||||
:numbered:
|
||||
:maxdepth: 3
|
||||
|
||||
statepoint
|
||||
source
|
||||
summary
|
||||
particle_restart
|
||||
track
|
||||
voxel
|
||||
57
docs/source/usersguide/output/particle_restart.rst
Normal file
57
docs/source/usersguide/output/particle_restart.rst
Normal file
|
|
@ -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.
|
||||
19
docs/source/usersguide/output/source.rst
Normal file
19
docs/source/usersguide/output/source.rst
Normal file
|
|
@ -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.
|
||||
259
docs/source/usersguide/output/statepoint.rst
Normal file
259
docs/source/usersguide/output/statepoint.rst
Normal file
|
|
@ -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 <uid>/type** (*char[]*)
|
||||
|
||||
Type of mesh.
|
||||
|
||||
**/tallies/meshes/mesh <uid>/dimension** (*int*)
|
||||
|
||||
Number of mesh cells in each dimension.
|
||||
|
||||
**/tallies/meshes/mesh <uid>/lower_left** (*double[]*)
|
||||
|
||||
Coordinates of lower-left corner of mesh.
|
||||
|
||||
**/tallies/meshes/mesh <uid>/upper_right** (*double[]*)
|
||||
|
||||
Coordinates of upper-right corner of mesh.
|
||||
|
||||
**/tallies/meshes/mesh <uid>/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 <uid>/estimator** (*char[]*)
|
||||
|
||||
Type of tally estimator, either 'analog', 'tracklength', or 'collision'.
|
||||
|
||||
**/tallies/tally <uid>/n_realizations** (*int*)
|
||||
|
||||
Number of realizations.
|
||||
|
||||
**/tallies/tally <uid>/n_filters** (*int*)
|
||||
|
||||
Number of filters used.
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/type** (*char[]*)
|
||||
|
||||
Type of the j-th filter. Can be 'universe', 'material', 'cell', 'cellborn',
|
||||
'surface', 'mesh', 'energy', 'energyout', or 'distribcell'.
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/offset** (*int*)
|
||||
|
||||
Filter offset (used for distribcell filter).
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/n_bins** (*int*)
|
||||
|
||||
Number of bins for the j-th filter.
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/bins** (*int[]* or *double[]*)
|
||||
|
||||
Value for each filter bin of this type.
|
||||
|
||||
**/tallies/tally <uid>/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 <uid>/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 <uid>/score_bins** (*char[][]*)
|
||||
|
||||
Values of specified scores.
|
||||
|
||||
**/tallies/tally <uid>/n_user_scores** (*int*)
|
||||
|
||||
Number of scores without accounting for those added by expansions,
|
||||
e.g. scatter-PN.
|
||||
|
||||
**/tallies/tally <uid>/moment_orders** (*char[][]*)
|
||||
|
||||
Tallying moment orders for Legendre and spherical harmonic tally expansions
|
||||
(*e.g.*, 'P2', 'Y1,2', etc.).
|
||||
|
||||
**/tallies/tally <uid>/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.
|
||||
311
docs/source/usersguide/output/summary.rst
Normal file
311
docs/source/usersguide/output/summary.rst
Normal file
|
|
@ -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 <uid>/index** (*int*)
|
||||
|
||||
Index in cells array used internally in OpenMC.
|
||||
|
||||
**/geometry/cells/cell <uid>/name** (*char[]*)
|
||||
|
||||
Name of the cell.
|
||||
|
||||
**/geometry/cells/cell <uid>/universe** (*int*)
|
||||
|
||||
Universe assigned to the cell. If none is specified, the default
|
||||
universe (0) is assigned.
|
||||
|
||||
**/geometry/cells/cell <uid>/fill_type** (*char[]*)
|
||||
|
||||
Type of fill for the cell. Can be 'normal', 'universe', or 'lattice'.
|
||||
|
||||
**/geometry/cells/cell <uid>/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 <uid>/offset** (*int[]*)
|
||||
|
||||
Offsets used for distribcell tally filter. This dataset is present only if
|
||||
fill_type is set to 'universe'.
|
||||
|
||||
**/geometry/cells/cell <uid>/translation** (*double[3]*)
|
||||
|
||||
Translation applied to the fill universe. This dataset is present only if
|
||||
fill_type is set to 'universe'.
|
||||
|
||||
**/geometry/cells/cell <uid>/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 <uid>/lattice** (*int*)
|
||||
|
||||
Unique ID of the lattice which fills the cell. Only present if fill_type is
|
||||
set to 'lattice'.
|
||||
|
||||
**/geometry/cells/cell <uid>/region** (*char[]*)
|
||||
|
||||
Region specification for the cell.
|
||||
|
||||
**/geometry/surfaces/surface <uid>/index** (*int*)
|
||||
|
||||
Index in surfaces array used internally in OpenMC.
|
||||
|
||||
**/geometry/surfaces/surface <uid>/name** (*char[]*)
|
||||
|
||||
Name of the surface.
|
||||
|
||||
**/geometry/surfaces/surface <uid>/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 <uid>/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 <uid>/boundary_condition** (*char[]*)
|
||||
|
||||
Boundary condition applied to the surface. Can be 'transmission', 'vacuum',
|
||||
'reflective', or 'periodic'.
|
||||
|
||||
**/geometry/universes/universe <uid>/index** (*int*)
|
||||
|
||||
Index in the universes array used internally in OpenMC.
|
||||
|
||||
**/geometry/universes/universe <uid>/cells** (*int[]*)
|
||||
|
||||
Array of unique IDs of cells that appear in the universe.
|
||||
|
||||
**/geometry/lattices/lattice <uid>/index** (*int*)
|
||||
|
||||
Index in the lattices array used internally in OpenMC.
|
||||
|
||||
**/geometry/lattices/lattice <uid>/name** (*char[]*)
|
||||
|
||||
Name of the lattice.
|
||||
|
||||
**/geometry/lattices/lattice <uid>/type** (*char[]*)
|
||||
|
||||
Type of the lattice, either 'rectangular' or 'hexagonal'.
|
||||
|
||||
**/geometry/lattices/lattice <uid>/pitch** (*double[]*)
|
||||
|
||||
Pitch of the lattice.
|
||||
|
||||
**/geometry/lattices/lattice <uid>/outer** (*int*)
|
||||
|
||||
Outer universe assigned to lattice cells outside the defined range.
|
||||
|
||||
**/geometry/lattices/lattice <uid>/offsets** (*int[]*)
|
||||
|
||||
Offsets used for distribcell tally filter.
|
||||
|
||||
**/geometry/lattices/lattice <uid>/universes** (*int[]*)
|
||||
|
||||
Three-dimensional array of universes assigned to each cell of the lattice.
|
||||
|
||||
**/geometry/lattices/lattice <uid>/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 <uid>/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 <uid>/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 <uid>/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 <uid>/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 <uid>/index** (*int*)
|
||||
|
||||
Index in materials array used internally in OpenMC.
|
||||
|
||||
**/materials/material <uid>/name** (*char[]*)
|
||||
|
||||
Name of the material.
|
||||
|
||||
**/materials/material <uid>/atom_density** (*double[]*)
|
||||
|
||||
Total atom density of the material in atom/b-cm.
|
||||
|
||||
**/materials/material <uid>/nuclides** (*char[][]*)
|
||||
|
||||
Array of nuclides present in the material, e.g., 'U-235.71c'.
|
||||
|
||||
**/materials/material <uid>/nuclide_densities** (*double[]*)
|
||||
|
||||
Atom density of each nuclide.
|
||||
|
||||
**/materials/material <uid>/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 <uid>/index** (*int*)
|
||||
|
||||
Index in the meshes array used internally in OpenMC.
|
||||
|
||||
**/tallies/mesh <uid>/type** (*char[]*)
|
||||
|
||||
Type of the mesh. The only valid option is currently 'regular'.
|
||||
|
||||
**/tallies/mesh <uid>/dimension** (*int[]*)
|
||||
|
||||
Number of mesh cells in each direction.
|
||||
|
||||
**/tallies/mesh <uid>/lower_left** (*double[]*)
|
||||
|
||||
Coordinates of the lower-left corner of the mesh.
|
||||
|
||||
**/tallies/mesh <uid>/upper_right** (*double[]*)
|
||||
|
||||
Coordinates of the upper-right corner of the mesh.
|
||||
|
||||
**/tallies/mesh <uid>/width** (*double[]*)
|
||||
|
||||
Width of a single mesh cell in each direction.
|
||||
|
||||
**/tallies/tally <uid>/index** (*int*)
|
||||
|
||||
Index in tallies array used internally in OpenMC.
|
||||
|
||||
**/tallies/tally <uid>/name** (*char[]*)
|
||||
|
||||
Name of the tally.
|
||||
|
||||
**/tallies/tally <uid>/n_filters** (*int*)
|
||||
|
||||
Number of filters applied to the tally.
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/type** (*char[]*)
|
||||
|
||||
Type of the j-th filter. Can be 'universe', 'material', 'cell', 'cellborn',
|
||||
'surface', 'mesh', 'energy', 'energyout', or 'distribcell'.
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/offset** (*int*)
|
||||
|
||||
Filter offset (used for distribcell filter).
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/n_bins** (*int*)
|
||||
|
||||
Number of bins for the j-th filter.
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/bins** (*int[]* or *double[]*)
|
||||
|
||||
Value for each filter bin of this type.
|
||||
|
||||
**/tallies/tally <uid>/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 <uid>/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 <uid>/score_bins** (*char[][]*)
|
||||
|
||||
Scoring bins for the tally.
|
||||
30
docs/source/usersguide/output/track.rst
Normal file
30
docs/source/usersguide/output/track.rst
Normal file
|
|
@ -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.
|
||||
25
docs/source/usersguide/output/voxel.rst
Normal file
25
docs/source/usersguide/output/voxel.rst
Normal file
|
|
@ -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.
|
||||
|
|
@ -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 <pythonapi>`. Both the provided scripts and the Python API rely on a number
|
||||
third-party Python packages, including:
|
||||
|
||||
* [1]_ `Numpy <http://www.numpy.org/>`_
|
||||
* [1]_ `Scipy <http://www.scipy.org/>`_
|
||||
* [2]_ `h5py <http://code.google.com/p/h5py/>`_
|
||||
* [3]_ `Matplotlib <http://matplotlib.org/>`_
|
||||
* [3]_ `Silomesh <https://github.com/nhorelik/silomesh>`_
|
||||
* [3]_ `VTK <http://www.vtk.org/>`_
|
||||
* [1]_ `NumPy <http://www.numpy.org/>`_
|
||||
* [2]_ `h5py <http://www.h5py.org>`_
|
||||
* [3]_ `pandas <http://pandas.pydata.org>`_
|
||||
* [4]_ `matplotlib <http://matplotlib.org/>`_
|
||||
* [4]_ `Silomesh <https://github.com/nhorelik/silomesh>`_
|
||||
* [4]_ `VTK <http://www.vtk.org/>`_
|
||||
* [4]_ `lxml <http://lxml.de>`_
|
||||
|
||||
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 <https://pip.pypa.io>`_
|
||||
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
|
||||
|
||||
<openmc_root>/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
|
||||
|
||||
<openmc_root>/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 <http://www.vtk.org/>`_ with python bindings - On Ubuntu, these are
|
||||
easily obtained with ``sudo apt-get install python-vtk``
|
||||
* `VTK <http://www.vtk.org/>`_ 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 <http://ipython.org/>`_). 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 <notebook_post_processing>` demonstrates how
|
||||
to extract data from a statepoint using the Python API.
|
||||
|
||||
Plotting in 2D
|
||||
--------------
|
||||
|
||||
The :ref:`IPython notebook example <notebook_post_processing>` 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
|
||||
|
||||
<openmc_root>/src/utils/statepoint_3d.py <statepoint_file> -o output.silo
|
||||
<openmc_root>/src/utils/statepoint_3d.py <statepoint_file> --vtk -o output.vtm
|
||||
openmc-statepoint-3d <statepoint_file> -o output.silo
|
||||
openmc-statepoint-3d <statepoint_file> --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 <statepoint_file> --tallies 2,4 --scores 4.1,4.3 -o output.silo
|
||||
statepoint_3d.py <statepoint_file> --filters 2.energyin.1 --vtk -o output.vtm
|
||||
openmc-statepoint-3d <statepoint_file> --tallies 2,4 --scores 4.1,4.3 -o output.silo
|
||||
openmc-statepoint-3d <statepoint_file> --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
|
||||
<http://docs.scipy.org/doc/scipy/reference/tutorial/io.html>`_ 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
|
|||
</track>
|
||||
|
||||
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]:
|
||||
[<SourceSite: xyz=[ 2.21980946 -8.92686048 87.93720485] at E=0.932923263566>,
|
||||
<SourceSite: xyz=[ 2.21980946 -8.92686048 87.93720485] at E=0.349240220512>,
|
||||
<SourceSite: xyz=[-31.21542213 -30.26762771 72.10845757] at E=3.75843584486>,
|
||||
<SourceSite: xyz=[-31.21542213 -30.26762771 72.10845757] at E=0.80550137267>,
|
||||
<SourceSite: xyz=[ 0.18805099 -69.13376508 103.67726838] at E=1.67922461097>,
|
||||
<SourceSite: xyz=[ 0.18805099 -69.13376508 103.67726838] at E=1.16304110199>,
|
||||
<SourceSite: xyz=[ -50.42189115 -9.96571672 123.34077905] at E=0.710937974074>,
|
||||
<SourceSite: xyz=[ -32.80427668 -15.49316628 125.26301151] at E=1.61907104162>,
|
||||
<SourceSite: xyz=[ 53.20376026 -15.38643708 120.58071044] at E=3.33962024907>,
|
||||
<SourceSite: xyz=[ 53.20376026 -15.38643708 120.58071044] at E=1.90185680329>]
|
||||
|
||||
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 <notebook_post_processing>` demontrates how to
|
||||
analyze and plot source information.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
136
examples/python/boxes/build-xml.py
Normal file
136
examples/python/boxes/build-xml.py
Normal file
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
<geometry>
|
||||
|
||||
<!-- Definition of Cells -->
|
||||
<cell id="1" universe="0" fill="37" surfaces="-2" />
|
||||
<cell id="100" universe="37" material="40" surfaces="-1" />
|
||||
<cell id="101" universe="37" material="41" surfaces="1" />
|
||||
<cell id="2" universe="0" material="41" surfaces = "2 -3" />
|
||||
<cell id="1" universe="0" fill="37" region="-2" />
|
||||
<cell id="100" universe="37" material="40" region="-1" />
|
||||
<cell id="101" universe="37" material="41" region="1" />
|
||||
<cell id="2" universe="0" material="41" region="2 -3" />
|
||||
|
||||
<!-- Defition of Surfaces -->
|
||||
<surface id="1" type="z-cylinder" coeffs="0 0 7" />
|
||||
<surface id="2" type="z-cylinder" coeffs="0 0 9" />
|
||||
<surface id="3" type="z-cylinder" coeffs="0 0 11" boundary="vacuum" />
|
||||
|
||||
|
||||
</geometry>
|
||||
|
|
|
|||
39
examples/xml/boxes/geometry.xml
Normal file
39
examples/xml/boxes/geometry.xml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0"?>
|
||||
<geometry>
|
||||
|
||||
<!--
|
||||
This example consists of three nested boxes, and is meant to show how to
|
||||
use Boolean operators to construct complex cell regions.
|
||||
-->
|
||||
|
||||
<surface id="1" type="x-plane" coeffs="-10" boundary="vacuum" />
|
||||
<surface id="2" type="x-plane" coeffs="-7" />
|
||||
<surface id="3" type="x-plane" coeffs="-4" />
|
||||
<surface id="4" type="x-plane" coeffs="4" />
|
||||
<surface id="5" type="x-plane" coeffs="7" />
|
||||
<surface id="6" type="x-plane" coeffs="10" boundary="vacuum" />
|
||||
|
||||
<surface id="11" type="y-plane" coeffs="-10" boundary="vacuum" />
|
||||
<surface id="12" type="y-plane" coeffs="-7" />
|
||||
<surface id="13" type="y-plane" coeffs="-4" />
|
||||
<surface id="14" type="y-plane" coeffs="4" />
|
||||
<surface id="15" type="y-plane" coeffs="7" />
|
||||
<surface id="16" type="y-plane" coeffs="10" boundary="vacuum" />
|
||||
|
||||
<surface id="21" type="z-plane" coeffs="-10" boundary="vacuum" />
|
||||
<surface id="22" type="z-plane" coeffs="-7" />
|
||||
<surface id="23" type="z-plane" coeffs="-4" />
|
||||
<surface id="24" type="z-plane" coeffs="4" />
|
||||
<surface id="25" type="z-plane" coeffs="7" />
|
||||
<surface id="26" type="z-plane" coeffs="10" boundary="vacuum" />
|
||||
|
||||
<!-- Innermost cube -->
|
||||
<cell id="1" material="1" region="3 -4 13 -14 23 -24" />
|
||||
|
||||
<!-- Middle cubic shell -->
|
||||
<cell id="2" material="2" region="2 -5 12 -15 22 -25 (-3 | 4 | -13 | 14 | -23 | 24)" />
|
||||
|
||||
<!-- Outermost cubic shell -->
|
||||
<cell id="3" material="3" region="1 -6 11 -16 21 -26 ~(2 -5 12 -15 22 -25)" />
|
||||
|
||||
</geometry>
|
||||
23
examples/xml/boxes/materials.xml
Normal file
23
examples/xml/boxes/materials.xml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<materials>
|
||||
|
||||
<default_xs>71c</default_xs>
|
||||
|
||||
<material id="1">
|
||||
<density value="4.5" units="g/cc" />
|
||||
<nuclide name="U-235" ao="1.0" />
|
||||
</material>
|
||||
|
||||
<material id="2">
|
||||
<density value="4.5" units="g/cc" />
|
||||
<nuclide name="U-238" ao="1.0" />
|
||||
</material>
|
||||
|
||||
<material id="3">
|
||||
<density value="1.0" units="g/cc" />
|
||||
<nuclide name="O-16" ao="1.0" />
|
||||
<nuclide name="H-1" ao="2.0" />
|
||||
<sab name="HH2O" xs="71t" />
|
||||
</material>
|
||||
|
||||
</materials>
|
||||
9
examples/xml/boxes/plots.xml
Normal file
9
examples/xml/boxes/plots.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0"?>
|
||||
<plots>
|
||||
<plot id="1" type="slice">
|
||||
<color>cell</color>
|
||||
<origin>0. 0. 0.</origin>
|
||||
<width>20. 20.</width>
|
||||
<pixels>200 200</pixels>
|
||||
</plot>
|
||||
</plots>
|
||||
16
examples/xml/boxes/settings.xml
Normal file
16
examples/xml/boxes/settings.xml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0"?>
|
||||
<settings>
|
||||
|
||||
<!-- Parameters for k-eigenvalue calculation -->
|
||||
<eigenvalue>
|
||||
<batches>15</batches>
|
||||
<inactive>5</inactive>
|
||||
<particles>10000</particles>
|
||||
</eigenvalue>
|
||||
|
||||
<!-- Starting source -->
|
||||
<source>
|
||||
<space type="box" parameters="-10. -10. -10. 10. 10. 10." />
|
||||
</source>
|
||||
|
||||
</settings>
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<geometry>
|
||||
|
||||
<cell id="1" fill="6" surfaces="1 -2 3 -4" />
|
||||
<cell id="2" universe="5" fill="4" surfaces="1 -2 3 -4" />
|
||||
<cell id="101" universe="1" material="1" surfaces="-5" />
|
||||
<cell id="102" universe="1" material="2" surfaces="5" />
|
||||
<cell id="201" universe="2" material="1" surfaces="-6" />
|
||||
<cell id="202" universe="2" material="2" surfaces="6" />
|
||||
<cell id="301" universe="3" material="1" surfaces="-7" />
|
||||
<cell id="302" universe="3" material="2" surfaces="7" />
|
||||
<cell id="1" fill="6" region="1 -2 3 -4" />
|
||||
<cell id="2" universe="5" fill="4" region="1 -2 3 -4" />
|
||||
<cell id="101" universe="1" material="1" region="-5" />
|
||||
<cell id="102" universe="1" material="2" region="5" />
|
||||
<cell id="201" universe="2" material="1" region="-6" />
|
||||
<cell id="202" universe="2" material="2" region="6" />
|
||||
<cell id="301" universe="3" material="1" region="-7" />
|
||||
<cell id="302" universe="3" material="2" region="7" />
|
||||
|
||||
<!-- 4 x 4 assembly -->
|
||||
<lattice id="4">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<tallies>
|
||||
|
||||
<mesh id="1">
|
||||
<type>rectangular</type>
|
||||
<type>regular</type>
|
||||
<dimension>4 4</dimension>
|
||||
<lower_left>-2.0 -2.0</lower_left>
|
||||
<width>1.0 1.0</width>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0"?>
|
||||
<geometry>
|
||||
|
||||
<cell id="1" fill="5" surfaces="1 -2 3 -4" />
|
||||
<cell id="101" universe="1" material="1" surfaces="-5" />
|
||||
<cell id="102" universe="1" material="2" surfaces="5" />
|
||||
<cell id="201" universe="2" material="1" surfaces="-6" />
|
||||
<cell id="202" universe="2" material="2" surfaces="6" />
|
||||
<cell id="301" universe="3" material="1" surfaces="-7" />
|
||||
<cell id="302" universe="3" material="2" surfaces="7" />
|
||||
<cell id="1" fill="5" region="1 -2 3 -4" />
|
||||
<cell id="101" universe="1" material="1" region="-5" />
|
||||
<cell id="102" universe="1" material="2" region="5" />
|
||||
<cell id="201" universe="2" material="1" region="-6" />
|
||||
<cell id="202" universe="2" material="2" region="6" />
|
||||
<cell id="301" universe="3" material="1" region="-7" />
|
||||
<cell id="302" universe="3" material="2" region="7" />
|
||||
|
||||
<lattice id="5">
|
||||
<dimension>4 4</dimension>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<tallies>
|
||||
|
||||
<mesh id="1">
|
||||
<type>rectangular</type>
|
||||
<type>regular</type>
|
||||
<dimension>4 4</dimension>
|
||||
<lower_left>-2.0 -2.0</lower_left>
|
||||
<width>1.0 1.0</width>
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@
|
|||
<surface id="6" type="y-plane" coeffs="-0.62992" boundary="reflective" />
|
||||
<surface id="7" type="y-plane" coeffs=" 0.62992" boundary="reflective" />
|
||||
|
||||
<cell id="1" material="1" surfaces=" -1" /> <!-- UO2 Fuel -->
|
||||
<cell id="2" material="2" surfaces="1 -2" /> <!-- Helium gap -->
|
||||
<cell id="3" material="3" surfaces="2 -3" /> <!-- Zircaloy cladding -->
|
||||
<cell id="4" material="4" surfaces="3 4 -5 6 -7" /> <!-- Borated water -->
|
||||
<cell id="1" material="1" region=" -1" /> <!-- UO2 Fuel -->
|
||||
<cell id="2" material="2" region="1 -2" /> <!-- Helium gap -->
|
||||
<cell id="3" material="3" region="2 -3" /> <!-- Zircaloy cladding -->
|
||||
<cell id="4" material="4" region="3 4 -5 6 -7" /> <!-- Borated water -->
|
||||
|
||||
</geometry>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<tallies>
|
||||
|
||||
<mesh id="1" type="rectangular">
|
||||
<mesh id="1" type="regular">
|
||||
<dimension>100 100 1</dimension>
|
||||
<lower_left>-0.62992 -0.62992 -1.e50</lower_left>
|
||||
<upper_right>0.62992 0.62992 1.e50</upper_right>
|
||||
|
|
@ -13,4 +13,4 @@
|
|||
<scores>flux fission nu-fission</scores>
|
||||
</tally>
|
||||
|
||||
</tallies>
|
||||
</tallies>
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@
|
|||
<cell id="1">
|
||||
<universe>0</universe>
|
||||
<material>1</material>
|
||||
<surfaces>1 -2 3 -4 5 -6</surfaces>
|
||||
<region>1 -2 3 -4 5 -6</region>
|
||||
</cell>
|
||||
|
||||
<!-- Defition of Surfaces -->
|
||||
<surface id="1" type="x-plane" coeffs="-1" boundary="vacuum" />
|
||||
<surface id="2" type="x-plane" coeffs="1" boundary="vacuum" />
|
||||
<surface id="3" type="y-plane" coeffs="-1" boundary="reflective" />
|
||||
<surface id="3" type="y-plane" coeffs="-1" boundary="reflective" />
|
||||
<surface id="4" type="y-plane" coeffs="1" boundary="reflective" />
|
||||
<surface id="5" type="z-plane" coeffs="-1" boundary="reflective" />
|
||||
<surface id="5" type="z-plane" coeffs="-1" boundary="reflective" />
|
||||
<surface id="6" type="z-plane" coeffs="1" boundary="reflective" />
|
||||
|
||||
|
||||
</geometry>
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)})
|
||||
279
openmc/cross.py
279
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
524
openmc/filter.py
524
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
3
openmc/mgxs/__init__.py
Normal file
3
openmc/mgxs/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from openmc.mgxs.groups import EnergyGroups
|
||||
from openmc.mgxs.library import Library
|
||||
from openmc.mgxs.mgxs import *
|
||||
238
openmc/mgxs/groups.py
Normal file
238
openmc/mgxs/groups.py
Normal file
|
|
@ -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
|
||||
681
openmc/mgxs/library.py
Normal file
681
openmc/mgxs/library.py
Normal file
|
|
@ -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'))
|
||||
2276
openmc/mgxs/mgxs.py
Normal file
2276
openmc/mgxs/mgxs.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
199
openmc/plots.py
199
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
|
||||
|
|
|
|||
362
openmc/region.py
Normal file
362
openmc/region.py
Normal file
|
|
@ -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)
|
||||
<class 'openmc.region.Intersection'>
|
||||
|
||||
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)
|
||||
<class 'openmc.region.Union'>
|
||||
|
||||
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)
|
||||
<class 'openmc.region.Complement'>
|
||||
|
||||
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
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
1018
openmc/statepoint.py
1018
openmc/statepoint.py
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
<class 'openmc.surface.Halfspace'>
|
||||
|
||||
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)
|
||||
|
|
|
|||
1410
openmc/tallies.py
1410
openmc/tallies.py
File diff suppressed because it is too large
Load diff
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <surface>
|
||||
# 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)
|
||||
|
|
|
|||
|
|
@ -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 = []
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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")
|
||||
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
6
setup.py
6
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': {
|
||||
|
|
|
|||
452
src/ace.F90
452
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue